* General Public License for more details.
*
*/
-
-#include "qla_os.h"
#include "qla_def.h"
+#include <linux/moduleparam.h>
+#include <linux/vmalloc.h>
+#include <linux/smp_lock.h>
+#include <linux/delay.h>
+
+#include <scsi/scsi_tcq.h>
+#include <scsi/scsicam.h>
+#include <scsi/scsi_transport.h>
+#include <scsi/scsi_transport_fc.h>
+
/*
* Driver version
*/
* Module parameter information and variables
*/
int ql2xmaxqdepth;
-module_param(ql2xmaxqdepth, int, 0);
+module_param(ql2xmaxqdepth, int, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(ql2xmaxqdepth,
"Maximum queue depth to report for target devices.");
int ql2xlogintimeout = 20;
-module_param(ql2xlogintimeout, int, 0);
+module_param(ql2xlogintimeout, int, S_IRUGO|S_IRUSR);
MODULE_PARM_DESC(ql2xlogintimeout,
"Login timeout value in seconds.");
int qlport_down_retry;
-module_param(qlport_down_retry, int, 0);
+module_param(qlport_down_retry, int, S_IRUGO|S_IRUSR);
MODULE_PARM_DESC(qlport_down_retry,
"Maximum number of command retries to a port that returns"
"a PORT-DOWN status.");
int ql2xretrycount = 20;
-module_param(ql2xretrycount, int, 0);
+module_param(ql2xretrycount, int, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(ql2xretrycount,
"Maximum number of mid-layer retries allowed for a command. "
"Default value is 20, ");
int displayConfig;
-module_param(displayConfig, int, 0);
+module_param(displayConfig, int, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(displayConfig,
"If 1 then display the configuration used in /etc/modprobe.conf.");
int ql2xplogiabsentdevice;
-module_param(ql2xplogiabsentdevice, int, 0);
+module_param(ql2xplogiabsentdevice, int, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(ql2xplogiabsentdevice,
"Option to enable PLOGI to devices that are not present after "
"a Fabric scan. This is needed for several broken switches."
"Default is 0 - no PLOGI. 1 - perfom PLOGI.");
+int ql2xenablezio = 0;
+module_param(ql2xenablezio, int, S_IRUGO|S_IRUSR);
+MODULE_PARM_DESC(ql2xenablezio,
+ "Option to enable ZIO:If 1 then enable it otherwise"
+ " use the default set in the NVRAM."
+ " Default is 0 : disabled");
+
int ql2xintrdelaytimer = 10;
-module_param(ql2xintrdelaytimer, int, 0);
+module_param(ql2xintrdelaytimer, int, S_IRUGO|S_IRUSR);
MODULE_PARM_DESC(ql2xintrdelaytimer,
"ZIO: Waiting time for Firmware before it generates an "
"interrupt to the host to notify completion of request.");
int ConfigRequired;
-module_param(ConfigRequired, int, 0);
+module_param(ConfigRequired, int, S_IRUGO|S_IRUSR);
MODULE_PARM_DESC(ConfigRequired,
"If 1, then only configured devices passed in through the"
"ql2xopts parameter will be presented to the OS");
int Bind = BIND_BY_PORT_NAME;
-module_param(Bind, int, 0);
+module_param(Bind, int, S_IRUGO|S_IRUSR);
MODULE_PARM_DESC(Bind,
"Target persistent binding method: "
"0 by Portname (default); 1 by PortID; 2 by Nodename. ");
int ql2xsuspendcount = SUSPEND_COUNT;
-module_param(ql2xsuspendcount, int, 0);
+module_param(ql2xsuspendcount, int, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(ql2xsuspendcount,
"Number of 6-second suspend iterations to perform while a "
"target returns a <NOT READY> status. Default is 10 "
"iterations.");
int ql2xdoinitscan = 1;
-module_param(ql2xdoinitscan, int, 0);
+module_param(ql2xdoinitscan, int, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(ql2xdoinitscan,
"Signal mid-layer to perform scan after driver load: 0 -- no "
"signal sent to mid-layer.");
int ql2xloginretrycount = 0;
-module_param(ql2xloginretrycount, int, 0);
+module_param(ql2xloginretrycount, int, S_IRUGO|S_IRUSR);
MODULE_PARM_DESC(ql2xloginretrycount,
"Specify an alternate value for the NVRAM login retry count.");
static void copy_mem_info(struct info_str *, char *, int);
static int copy_info(struct info_str *, char *, ...);
-
-/*
- * List of host adapters
- */
-LIST_HEAD(qla_hostlist);
-rwlock_t qla_hostlist_lock = RW_LOCK_UNLOCKED;
-
static void qla2x00_free_device(scsi_qla_host_t *);
static void qla2x00_config_dma_addressing(scsi_qla_host_t *ha);
* SCSI host template entry points
*/
static int qla2xxx_slave_configure(struct scsi_device * device);
+static int qla2x00_queuecommand(struct scsi_cmnd *cmd,
+ void (*fn)(struct scsi_cmnd *));
static int qla2xxx_eh_abort(struct scsi_cmnd *);
static int qla2xxx_eh_device_reset(struct scsi_cmnd *);
static int qla2xxx_eh_bus_reset(struct scsi_cmnd *);
static int qla2xxx_eh_host_reset(struct scsi_cmnd *);
-static uint8_t qla2x00_loop_reset(scsi_qla_host_t *ha);
+static int qla2x00_loop_reset(scsi_qla_host_t *ha);
static int qla2x00_device_reset(scsi_qla_host_t *, fc_port_t *);
static int qla2x00_proc_info(struct Scsi_Host *, char *, char **,
static void qla2x00_display_fc_names(scsi_qla_host_t *);
-void qla2x00_blink_led(scsi_qla_host_t *);
-
/* TODO Convert to inlines
*
* Timer routines
static __inline__ void
qla2x00_delete_from_done_queue(scsi_qla_host_t *, srb_t *);
-/**************************************************************************
-* sp_put
-*
-* Description:
-* Decrement reference count and call the callback if we're the last
-* owner of the specified sp. Will get the host_lock before calling
-* the callback.
-*
-* Input:
-* ha - pointer to the scsi_qla_host_t where the callback is to occur.
-* sp - pointer to srb_t structure to use.
-*
-* Returns:
-*
-**************************************************************************/
-static inline void
-sp_put(struct scsi_qla_host * ha, srb_t *sp)
-{
- if (atomic_read(&sp->ref_count) == 0) {
- qla_printk(KERN_INFO, ha,
- "%s(): **** SP->ref_count not zero\n",
- __func__);
- DEBUG2(BUG();)
-
- return;
- }
-
- if (!atomic_dec_and_test(&sp->ref_count)) {
- return;
- }
-
- qla2x00_callback(ha, sp->cmd);
-}
-
-/**************************************************************************
-* sp_get
-*
-* Description:
-* Increment reference count of the specified sp.
-*
-* Input:
-* sp - pointer to srb_t structure to use.
-*
-* Returns:
-*
-**************************************************************************/
-static inline void
-sp_get(struct scsi_qla_host * ha, srb_t *sp)
-{
- atomic_inc(&sp->ref_count);
-
- if (atomic_read(&sp->ref_count) > 2) {
- qla_printk(KERN_INFO, ha,
- "%s(): **** SP->ref_count greater than two\n",
- __func__);
- DEBUG2(BUG();)
-
- return;
- }
-}
-
/*
* qla2x00_callback
* Returns the completed SCSI command to LINUX.
(*(cmd)->scsi_done)(cmd);
}
+/**************************************************************************
+* sp_put
+*
+* Description:
+* Decrement reference count and call the callback if we're the last
+* owner of the specified sp. Will get the host_lock before calling
+* the callback.
+*
+* Input:
+* ha - pointer to the scsi_qla_host_t where the callback is to occur.
+* sp - pointer to srb_t structure to use.
+*
+* Returns:
+*
+**************************************************************************/
+static inline void
+sp_put(struct scsi_qla_host * ha, srb_t *sp)
+{
+ if (atomic_read(&sp->ref_count) == 0) {
+ qla_printk(KERN_INFO, ha,
+ "%s(): **** SP->ref_count not zero\n",
+ __func__);
+ DEBUG2(BUG();)
+
+ return;
+ }
+
+ if (!atomic_dec_and_test(&sp->ref_count)) {
+ return;
+ }
+
+ qla2x00_callback(ha, sp->cmd);
+}
+
+/**************************************************************************
+* sp_get
+*
+* Description:
+* Increment reference count of the specified sp.
+*
+* Input:
+* sp - pointer to srb_t structure to use.
+*
+* Returns:
+*
+**************************************************************************/
+static inline void
+sp_get(struct scsi_qla_host * ha, srb_t *sp)
+{
+ atomic_inc(&sp->ref_count);
+
+ if (atomic_read(&sp->ref_count) > 2) {
+ qla_printk(KERN_INFO, ha,
+ "%s(): **** SP->ref_count greater than two\n",
+ __func__);
+ DEBUG2(BUG();)
+
+ return;
+ }
+}
+
static inline void
qla2x00_delete_from_done_queue(scsi_qla_host_t *dest_ha, srb_t *sp)
{
static uint8_t qla2x00_mem_alloc(scsi_qla_host_t *);
static void qla2x00_mem_free(scsi_qla_host_t *ha);
-int qla2x00_allocate_sp_pool( scsi_qla_host_t *ha);
-void qla2x00_free_sp_pool(scsi_qla_host_t *ha);
+static int qla2x00_allocate_sp_pool( scsi_qla_host_t *ha);
+static void qla2x00_free_sp_pool(scsi_qla_host_t *ha);
+static srb_t *qla2x00_get_new_sp(scsi_qla_host_t *ha);
static ssize_t qla2x00_sysfs_read_fw_dump(struct kobject *, char *, loff_t,
size_t);
.write = qla2x00_sysfs_write_nvram,
};
-
-int
-qla2x00_set_info(char *buffer, int length, struct Scsi_Host *shost)
-{
- return (-ENOSYS); /* Currently this is a no-op */
-}
-
/* -------------------------------------------------------------------------- */
struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj,
struct device, kobj)));
int reading;
+ uint32_t dump_size;
if (off != 0)
return (0);
if (ha->fw_dump != NULL && !ha->fw_dump_reading) {
ha->fw_dump_reading = 1;
- ha->fw_dump_buffer = (char *)vmalloc(FW_DUMP_SIZE);
+ dump_size = FW_DUMP_SIZE_1M;
+ if (ha->fw_memory_size < 0x20000)
+ dump_size = FW_DUMP_SIZE_128K;
+ else if (ha->fw_memory_size < 0x80000)
+ dump_size = FW_DUMP_SIZE_512K;
+ ha->fw_dump_buffer = (char *)vmalloc(dump_size);
if (ha->fw_dump_buffer == NULL) {
qla_printk(KERN_WARNING, ha,
"Unable to allocate memory for firmware "
- "dump buffer (%d).\n", FW_DUMP_SIZE);
+ "dump buffer (%d).\n", dump_size);
ha->fw_dump_reading = 0;
return (count);
qla_printk(KERN_INFO, ha,
"Firmware dump ready for read on (%ld).\n",
ha->host_no);
- memset(ha->fw_dump_buffer, 0, FW_DUMP_SIZE);
+ memset(ha->fw_dump_buffer, 0, dump_size);
if (IS_QLA2100(ha) || IS_QLA2200(ha))
qla2100_ascii_fw_dump(ha);
else
/* Write NVRAM. */
spin_lock_irqsave(&ha->hardware_lock, flags);
qla2x00_lock_nvram_access(ha);
+ qla2x00_release_nvram_protection(ha);
witer = (uint16_t *)buf;
for (cnt = 0; cnt < count / 2; cnt++) {
qla2x00_write_nvram_word(ha, cnt+ha->nvram_base,
}
/* -------------------------------------------------------------------------- */
-char *
+static char *
qla2x00_get_pci_info_str(struct scsi_qla_host *ha, char *str)
{
static char *pci_bus_modes[] = {
* interrupt handler may call this routine as part of request-completion
* handling).
**************************************************************************/
-int
+static int
qla2x00_queuecommand(struct scsi_cmnd *cmd, void (*fn)(struct scsi_cmnd *))
{
fc_port_t *fcport;
cmd->host_scribble = (unsigned char *)handle;
/* Bookkeeping information */
- sp->r_start = jiffies; /* time the request was recieved */
+ sp->r_start = jiffies; /* Time the request was recieved. */
sp->u_start = 0;
/* Setup device queue pointers. */
} else
sp->flags |= SRB_TAPE;
-
DEBUG5(printk("scsi(%ld:%2d:%2d): (queuecmd) queue sp = %p, "
"flags=0x%x fo retry=%d, pid=%ld\n",
ha->host_no, t, l, sp, sp->flags, sp->fo_retry_cnt,
spin_lock_irq(ha->host->host_lock);
return (0);
}
+
if (tq && test_bit(TQF_SUSPENDED, &tq->flags) &&
(sp->flags & SRB_TAPE) == 0) {
/* If target suspended put incoming I/O in retry_q. */
was_empty = add_to_pending_queue(ha, sp);
if ((IS_QLA2100(ha) || IS_QLA2200(ha)) && ha->flags.online) {
- unsigned long flags;
- device_reg_t *reg;
- reg = ha->iobase;
-
if (ha->response_ring_ptr->signature != RESPONSE_PROCESSED) {
+ unsigned long flags;
+
spin_lock_irqsave(&ha->hardware_lock, flags);
qla2x00_process_response_queue(ha);
spin_unlock_irqrestore(&ha->hardware_lock, flags);
* In all other cases we'll let an irq pick up our IO and submit it
* to the controller to improve affinity.
*/
- if (smp_processor_id() == ha->last_irq_cpu || was_empty)
+ if (_smp_processor_id() == ha->last_irq_cpu || was_empty)
qla2x00_next(ha);
spin_lock_irq(ha->host->host_lock);
static int
qla2x00_eh_wait_on_command(scsi_qla_host_t *ha, struct scsi_cmnd *cmd)
{
-#define ABORT_WAIT_TIME 10 /* seconds */
+#define ABORT_POLLING_PERIOD HZ
+#define ABORT_WAIT_TIME ((10 * HZ) / (ABORT_POLLING_PERIOD))
int found = 0;
int done = 0;
- srb_t *rp;
+ srb_t *rp = NULL;
struct list_head *list, *temp;
- u_long cpu_flags = 0;
u_long max_wait_time = ABORT_WAIT_TIME;
do {
/* Check on done queue */
- if (!found) {
- spin_lock_irqsave(&ha->list_lock, cpu_flags);
- list_for_each_safe(list, temp, &ha->done_queue) {
- rp = list_entry(list, srb_t, list);
+ spin_lock(&ha->list_lock);
+ list_for_each_safe(list, temp, &ha->done_queue) {
+ rp = list_entry(list, srb_t, list);
- /*
- * Found command. Just exit and wait for the
- * cmd sent to OS.
- */
- if (cmd == rp->cmd) {
- found++;
- DEBUG3(printk("%s: found in done "
- "queue.\n", __func__);)
- break;
- }
+ /*
+ * Found command. Just exit and wait for the cmd sent
+ * to OS.
+ */
+ if (cmd == rp->cmd) {
+ found++;
+ DEBUG3(printk("%s: found in done queue.\n",
+ __func__);)
+ break;
}
- spin_unlock_irqrestore(&ha->list_lock, cpu_flags);
}
+ spin_unlock(&ha->list_lock);
- /* Checking to see if its returned to OS */
- rp = (srb_t *) CMD_SP(cmd);
- if (rp == NULL ) {
+ /* Complete the cmd right away. */
+ if (found) {
+ qla2x00_delete_from_done_queue(ha, rp);
+ sp_put(ha, rp);
done++;
break;
}
spin_unlock_irq(ha->host->host_lock);
set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(2*HZ);
+ schedule_timeout(ABORT_POLLING_PERIOD);
spin_lock_irq(ha->host->host_lock);
} while ((max_wait_time--));
- if (done) {
+ if (done)
DEBUG2(printk(KERN_INFO "%s: found cmd=%p.\n", __func__, cmd));
- } else if (found) {
- /* Immediately return command to the mid-layer */
- qla2x00_delete_from_done_queue(ha, rp);
- sp_put(ha, rp);
- done++;
- }
return (done);
}
* Success (Adapter is online) : 0
* Failed (Adapter is offline/disabled) : 1
*/
-static inline int
+static int
qla2x00_wait_for_hba_online(scsi_qla_host_t *ha)
{
int return_status;
wait_online = jiffies + (MAX_LOOP_TIMEOUT * HZ);
while (((test_bit(ISP_ABORT_NEEDED, &ha->dpc_flags)) ||
test_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags) ||
- test_bit(ISP_ABORT_RETRY, &ha->dpc_flags)) &&
- time_before(jiffies, wait_online)) {
+ test_bit(ISP_ABORT_RETRY, &ha->dpc_flags) ||
+ ha->dpc_active) && time_before(jiffies, wait_online)) {
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(HZ);
+ msleep(1000);
}
- if (ha->flags.online == TRUE)
+ if (ha->flags.online)
return_status = QLA_SUCCESS;
else
- /* Adapter is disabled/offline */
return_status = QLA_FUNCTION_FAILED;
DEBUG2(printk("%s return_status=%d\n",__func__,return_status));
atomic_read(&ha->loop_state) == LOOP_DOWN) ||
test_bit(CFG_ACTIVE, &ha->cfg_flags) ||
atomic_read(&ha->loop_state) != LOOP_READY) {
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(HZ);
+ msleep(1000);
if (time_after_eq(jiffies, loop_timeout)) {
return_status = QLA_FUNCTION_FAILED;
break;
struct Scsi_Host *host;
uint8_t found = 0;
unsigned int b, t, l;
- unsigned long flags;
/* Get the SCSI request ptr */
sp = (srb_t *) CMD_SP(cmd);
qla_printk(KERN_INFO, to_qla_host(cmd->device->host),
"qla2xxx_eh_abort: cmd already done sp=%p\n", sp);
DEBUG(printk("qla2xxx_eh_abort: cmd already done sp=%p\n", sp);)
- return(SUCCESS);
+ return SUCCESS;
}
if (sp) {
DEBUG(printk("qla2xxx_eh_abort: refcount %i \n",
"qla2x00: (%x:%x:%x) No LUN queue.\n", b, t, l);
/* no action - we don't have command */
- return(FAILED);
+ return FAILED;
}
DEBUG2(printk("scsi(%ld): ABORTing cmd=%p sp=%p jiffies = 0x%lx, "
DEBUG2(qla2x00_print_scsi_cmd(cmd));
spin_unlock_irq(ha->host->host_lock);
- /* Blocking call-Does context switching if abort isp is active etc */
if (qla2x00_wait_for_hba_online(ha) != QLA_SUCCESS) {
DEBUG2(printk("%s failed:board disabled\n", __func__);)
spin_lock_irq(ha->host->host_lock);
- return (FAILED);
+ return FAILED;
}
spin_lock_irq(ha->host->host_lock);
/* Search done queue */
- spin_lock_irqsave(&ha->list_lock,flags);
+ spin_lock(&ha->list_lock);
list_for_each_safe(list, temp, &ha->done_queue) {
rp = list_entry(list, srb_t, list);
break;
} /* list_for_each_safe() */
- spin_unlock_irqrestore(&ha->list_lock, flags);
+ spin_unlock(&ha->list_lock);
/*
* Return immediately if the aborted command was already in the done
DEBUG3(printk("qla2xxx_eh_abort: searching sp %p in retry "
"queue.\n", sp);)
- spin_lock_irqsave(&ha->list_lock, flags);
+ spin_lock(&ha->list_lock);
list_for_each_safe(list, temp, &ha->retry_queue) {
rp = list_entry(list, srb_t, list);
break;
}
- spin_unlock_irqrestore(&ha->list_lock, flags);
+ spin_unlock(&ha->list_lock);
/*
DEBUG3(printk("qla2xxx_eh_abort: searching sp %p "
"in pending queue.\n", sp);)
- spin_lock_irqsave(&vis_ha->list_lock, flags);
+ spin_lock(&vis_ha->list_lock);
list_for_each_safe(list, temp, &vis_ha->pending_queue) {
rp = list_entry(list, srb_t, list);
found++;
break;
} /* list_for_each_safe() */
- spin_unlock_irqrestore(&vis_ha->list_lock, flags);
+ spin_unlock(&vis_ha->list_lock);
} /*End of if !found */
if (!found) { /* find the command in our active list */
DEBUG3(printk("qla2xxx_eh_abort: searching sp %p "
"in outstanding queue.\n", sp);)
- spin_lock_irqsave(&ha->hardware_lock, flags);
+ spin_lock(&ha->hardware_lock);
for (i = 1; i < MAX_OUTSTANDING_COMMANDS; i++) {
sp = ha->outstanding_cmds[i];
/* Get a reference to the sp and drop the lock.*/
sp_get(ha, sp);
- spin_unlock_irqrestore(&ha->hardware_lock, flags);
- spin_unlock(ha->host->host_lock);
+ spin_unlock(&ha->hardware_lock);
+ spin_unlock_irq(ha->host->host_lock);
if (qla2x00_abort_command(ha, sp)) {
DEBUG2(printk("qla2xxx_eh_abort: abort_command "
sp_put(ha,sp);
spin_lock_irq(ha->host->host_lock);
- spin_lock_irqsave(&ha->hardware_lock, flags);
+ spin_lock(&ha->hardware_lock);
/*
* Regardless of mailbox command status, go check on
break;
}/*End of for loop */
- spin_unlock_irqrestore(&ha->hardware_lock, flags);
+ spin_unlock(&ha->hardware_lock);
} /*End of if !found */
- /*Waiting for our command in done_queue to be returned to OS.*/
+ /* Waiting for our command in done_queue to be returned to OS.*/
if (qla2x00_eh_wait_on_command(ha, cmd) != 0) {
DEBUG2(printk("qla2xxx_eh_abort: cmd returned back to OS.\n");)
return_status = SUCCESS;
DEBUG2(printk("qla2xxx_eh_abort: Exiting. return_status=0x%x.\n",
return_status));
- return(return_status);
+ return return_status;
}
/**************************************************************************
*
* Note:
**************************************************************************/
-int
+static int
qla2x00_eh_wait_for_pending_target_commands(scsi_qla_host_t *ha, unsigned int t)
{
int cnt;
int status;
- unsigned long flags;
srb_t *sp;
struct scsi_cmnd *cmd;
* array
*/
for (cnt = 1; cnt < MAX_OUTSTANDING_COMMANDS; cnt++) {
- spin_lock_irqsave(&ha->hardware_lock, flags);
+ spin_lock(&ha->hardware_lock);
sp = ha->outstanding_cmds[cnt];
if (sp) {
cmd = sp->cmd;
- spin_unlock_irqrestore(&ha->hardware_lock, flags);
+ spin_unlock(&ha->hardware_lock);
if (cmd->device->id == t) {
if (!qla2x00_eh_wait_on_command(ha, cmd)) {
status = 1;
}
}
else {
- spin_unlock_irqrestore(&ha->hardware_lock, flags);
+ spin_unlock(&ha->hardware_lock);
}
}
return (status);
os_tgt_t *tq;
os_lun_t *lq;
fc_port_t *fcport_to_reset;
- unsigned long flags;
srb_t *rp;
struct list_head *list, *temp;
ha->dpc_flags, cmd->result, cmd->allowed, cmd->state));
/* Clear commands from the retry queue. */
- spin_lock_irqsave(&ha->list_lock, flags);
+ spin_lock(&ha->list_lock);
list_for_each_safe(list, temp, &ha->retry_queue) {
rp = list_entry(list, srb_t, list);
rp->cmd->result = DID_RESET << 16;
__add_to_done_queue(ha, rp);
}
- spin_unlock_irqrestore(&ha->list_lock, flags);
+ spin_unlock(&ha->list_lock);
spin_unlock_irq(ha->host->host_lock);
- /* Blocking call-Does context switching if abort isp is active etc */
if (qla2x00_wait_for_hba_online(ha) != QLA_SUCCESS) {
DEBUG2(printk(KERN_INFO
"%s failed:board disabled\n",__func__));
goto eh_dev_reset_done;
}
- /* Blocking call-Does context switching if loop is Not Ready */
if (qla2x00_wait_for_loop_ready(ha) == QLA_SUCCESS) {
if (qla2x00_device_reset(ha, fcport_to_reset) == 0) {
return_status = SUCCESS;
if (return_status == FAILED) {
DEBUG3(printk("%s(%ld): device reset failed\n",
- __func__,ha->host_no));
+ __func__, ha->host_no));
qla_printk(KERN_INFO, ha, "%s: device reset failed\n",
__func__);
*
* Note:
**************************************************************************/
-int
+static int
qla2x00_eh_wait_for_pending_commands(scsi_qla_host_t *ha)
{
int cnt;
int status;
- unsigned long flags;
srb_t *sp;
struct scsi_cmnd *cmd;
* array
*/
for (cnt = 1; cnt < MAX_OUTSTANDING_COMMANDS; cnt++) {
- spin_lock_irqsave(&ha->hardware_lock, flags);
+ spin_lock(&ha->hardware_lock);
sp = ha->outstanding_cmds[cnt];
if (sp) {
cmd = sp->cmd;
- spin_unlock_irqrestore(&ha->hardware_lock, flags);
+ spin_unlock(&ha->hardware_lock);
status = qla2x00_eh_wait_on_command(ha, cmd);
if (status == 0)
break;
}
else {
- spin_unlock_irqrestore(&ha->hardware_lock, flags);
+ spin_unlock(&ha->hardware_lock);
}
}
return (status);
spin_unlock_irq(ha->host->host_lock);
- /* Blocking call-Does context switching if abort isp is active etc*/
if (qla2x00_wait_for_hba_online(ha) != QLA_SUCCESS) {
DEBUG2(printk("%s failed:board disabled\n",__func__));
spin_lock_irq(ha->host->host_lock);
return FAILED;
}
- /* Blocking call-Does context switching if loop is Not Ready */
if (qla2x00_wait_for_loop_ready(ha) == QLA_SUCCESS) {
- if (qla2x00_loop_reset(ha))
+ if (qla2x00_loop_reset(ha) == QLA_SUCCESS)
rval = SUCCESS;
}
if (rval == FAILED)
goto out;
- /*
- * Blocking Call. It goes to sleep waiting for cmd to get to done q
- *
- * XXX(hch): really? We're under host_lock here..
- */
/* Waiting for our command in done_queue to be returned to OS.*/
- if (!qla2x00_eh_wait_for_pending_commands(ha))
- rval = FAILED;
+ if (cmd->device->host->eh_active)
+ if (!qla2x00_eh_wait_for_pending_commands(ha))
+ rval = FAILED;
out:
qla_printk(KERN_INFO, ha, "%s: reset %s\n", __func__,
spin_unlock_irq(ha->host->host_lock);
- /* Blocking call-Does context switching if abort isp is active etc*/
if (qla2x00_wait_for_hba_online(ha) != QLA_SUCCESS)
goto board_disabled;
goto out;
/* Waiting for our command in done_queue to be returned to OS.*/
- if (qla2x00_eh_wait_for_pending_commands(ha))
+ if (!qla2x00_eh_wait_for_pending_commands(ha))
rval = FAILED;
out:
* Returns:
* 0 = success
*/
-static uint8_t
+static int
qla2x00_loop_reset(scsi_qla_host_t *ha)
{
- uint8_t status = QLA_SUCCESS;
+ int status = QLA_SUCCESS;
uint16_t t;
os_tgt_t *tq;
ql2xmaxqdepth = queue_depth;
- scsi_adjust_queue_depth(sdev, MSG_ORDERED_TAG, queue_depth);
+ scsi_activate_tcq(sdev, queue_depth);
qla_printk(KERN_INFO, ha,
"scsi(%d:%d:%d:%d): Enabled tagged queuing, queue "
* assist in setting the proper dma mask.
*/
if (sizeof(dma_addr_t) > 4) {
- /* Update our PCI device dma_mask for full 64 bits */
- if (pci_set_dma_mask(ha->pdev, 0xffffffffffffffffULL) == 0) {
+ if (pci_set_dma_mask(ha->pdev, DMA_64BIT_MASK) == 0) {
ha->flags.enable_64bit_addressing = 1;
ha->calc_request_entries = qla2x00_calc_iocbs_64;
ha->build_scsi_iocbs = qla2x00_build_scsi_iocbs_64;
if (pci_set_consistent_dma_mask(ha->pdev,
- 0xffffffffffffffffULL)) {
+ DMA_64BIT_MASK)) {
qla_printk(KERN_DEBUG, ha,
"Failed to set 64 bit PCI consistent mask; "
"using 32 bit.\n");
pci_set_consistent_dma_mask(ha->pdev,
- 0xffffffffULL);
+ DMA_32BIT_MASK);
}
} else {
qla_printk(KERN_DEBUG, ha,
"Failed to set 64 bit PCI DMA mask, falling back "
"to 32 bit MASK.\n");
- pci_set_dma_mask(ha->pdev, 0xffffffff);
+ pci_set_dma_mask(ha->pdev, DMA_32BIT_MASK);
}
} else {
- pci_set_dma_mask(ha->pdev, 0xffffffff);
+ pci_set_dma_mask(ha->pdev, DMA_32BIT_MASK);
}
}
ha->pio_address = pio;
ha->pio_length = pio_len;
- ha->mmio_address = ioremap(mmio, MIN_IOBASE_LEN);
- if (!ha->mmio_address) {
+ ha->iobase = ioremap(mmio, MIN_IOBASE_LEN);
+ if (!ha->iobase) {
qla_printk(KERN_ERR, ha,
"cannot remap MMIO (%s), aborting\n", ha->pdev->slot_name);
goto iospace_error_exit;
}
- ha->mmio_length = mmio_len;
- ha->iobase = (device_reg_t *) ha->mmio_address;
return (0);
int qla2x00_probe_one(struct pci_dev *pdev, struct qla_board_info *brd_info)
{
int ret;
- device_reg_t *reg;
+ device_reg_t __iomem *reg;
struct Scsi_Host *host;
scsi_qla_host_t *ha;
unsigned long flags = 0;
if (host == NULL) {
printk(KERN_WARNING
"qla2xxx: Couldn't allocate host from scsi layer!\n");
- return -1;
+ goto probe_disable_device;
}
/* Clear our data area */
host->unique_id = ha->instance;
host->max_id = ha->max_targets;
- if (request_irq(host->irq, qla2x00_intr_handler, SA_INTERRUPT|SA_SHIRQ,
- ha->brd_info->drv_name, ha)) {
+ if (IS_QLA2100(ha) || IS_QLA2200(ha))
+ ret = request_irq(host->irq, qla2100_intr_handler,
+ SA_INTERRUPT|SA_SHIRQ, ha->brd_info->drv_name, ha);
+ else
+ ret = request_irq(host->irq, qla2300_intr_handler,
+ SA_INTERRUPT|SA_SHIRQ, ha->brd_info->drv_name, ha);
+ if (ret != 0) {
qla_printk(KERN_WARNING, ha,
"Failed to reserve interrupt %d already in use.\n",
host->irq);
}
spin_unlock_irqrestore(&ha->hardware_lock, flags);
-
/* Enable chip interrupts. */
qla2x00_enable_intrs(ha);
- /* Insert new entry into the list of adapters */
- write_lock(&qla_hostlist_lock);
- list_add_tail(&ha->list, &qla_hostlist);
- write_unlock(&qla_hostlist_lock);
-
/* v2.19.5b6 */
/*
* Wait around max loop_reset_delay secs for the devices to come
qla2x00_check_fabric_devices(ha);
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(HZ/100);
+ msleep(10);
}
pci_set_drvdata(pdev, ha);
scsi_host_put(host);
+probe_disable_device:
+ pci_disable_device(pdev);
+
return -1;
}
EXPORT_SYMBOL_GPL(qla2x00_probe_one);
ha = pci_get_drvdata(pdev);
- write_lock(&qla_hostlist_lock);
- list_del(&ha->list);
- write_unlock(&qla_hostlist_lock);
-
sysfs_remove_bin_file(&ha->host->shost_gendev.kobj,
&sysfs_fw_dump_attr);
sysfs_remove_bin_file(&ha->host->shost_gendev.kobj, &sysfs_nvram_attr);
qla2x00_mem_free(ha);
- ha->flags.online = FALSE;
+ ha->flags.online = 0;
/* Detach interrupts */
if (ha->pdev->irq)
free_irq(ha->pdev->irq, ha);
/* release io space registers */
+ if (ha->iobase)
+ iounmap(ha->iobase);
pci_release_regions(ha->pdev);
-#if MEMORY_MAPPED_IO
- if (ha->mmio_address)
- iounmap(ha->mmio_address);
-#endif
+ pci_disable_device(ha->pdev);
}
*
* inout : decides the direction of the dataflow and the meaning of the
* variables
-* buffer: If inout==FALSE data is being written to it else read from it
+* buffer: If inout==0 data is being written to it else read from it
* (ptr to a page buffer)
-* *start: If inout==FALSE start of the valid data in the buffer
-* offset: If inout==FALSE starting offset from the beginning of all
+* *start: If inout==0 start of the valid data in the buffer
+* offset: If inout==0 starting offset from the beginning of all
* possible data to return.
-* length: If inout==FALSE max number of bytes to be written into the buffer
+* length: If inout==0 max number of bytes to be written into the buffer
* else number of bytes in "buffer"
* Returns:
* < 0: error. errno value.
uint32_t tmp_sn;
uint32_t *flags;
uint8_t *loop_state;
- int found;
scsi_qla_host_t *ha;
char fw_info[30];
"Entering proc_info buff_in=%p, offset=0x%lx, length=0x%x\n",
buffer, offset, length);)
- ha = NULL;
-
- /* Find the host that was specified */
- found = 0;
- read_lock(&qla_hostlist_lock);
- list_for_each_entry(ha, &qla_hostlist, list) {
- if (ha->host == shost) {
- found++;
- break;
- }
- }
- read_unlock(&qla_hostlist_lock);
-
- /* if host wasn't found then exit */
- if (!found) {
- DEBUG2_3(printk(KERN_WARNING
- "%s: Can't find adapter for host %p\n",
- __func__, shost);)
+ ha = (scsi_qla_host_t *) shost->hostdata;
- return (retval);
- }
-
- if (inout == TRUE) {
+ if (inout) {
/* Has data been written to the file? */
DEBUG3(printk(
"%s: has data been written to the file. \n",
__func__);)
- return (qla2x00_set_info(buffer, length, shost));
+ return -ENOSYS;
}
if (start) {
copy_info(&info, "Driver version %s\n", qla2x00_version_str);
- copy_info(&info, "Entry address = %p\n", qla2x00_set_info);
-
tmp_sn = ((ha->serial0 & 0x1f) << 16) | (ha->serial2 << 8) |
ha->serial1;
copy_info(&info, "ISP: %s, Serial# %c%05d\n",
tq->port_name[4], tq->port_name[5],
tq->port_name[6], tq->port_name[7]);
}
+
copy_info(&info, "\nSCSI LUN Information:\n");
copy_info(&info,
"(Id:Lun) * - indicates lun is not registered with the OS.\n");
static uint8_t
qla2x00_mem_alloc(scsi_qla_host_t *ha)
{
+ char name[16];
uint8_t status = 1;
int retry= 10;
* bug where available mem is not allocated until after a
* little delay and a retry.
*/
- ha->request_ring = pci_alloc_consistent(ha->pdev,
- ((ha->request_q_length + 1) * (sizeof(request_t))),
- &ha->request_dma);
+ ha->request_ring = dma_alloc_coherent(&ha->pdev->dev,
+ (ha->request_q_length + 1) * sizeof(request_t),
+ &ha->request_dma, GFP_KERNEL);
if (ha->request_ring == NULL) {
qla_printk(KERN_WARNING, ha,
"Memory Allocation failed - request_ring\n");
qla2x00_mem_free(ha);
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(HZ/10);
+ msleep(100);
continue;
}
- ha->response_ring = pci_alloc_consistent(ha->pdev,
- ((ha->response_q_length + 1) * (sizeof(response_t))),
- &ha->response_dma);
+ ha->response_ring = dma_alloc_coherent(&ha->pdev->dev,
+ (ha->response_q_length + 1) * sizeof(response_t),
+ &ha->response_dma, GFP_KERNEL);
if (ha->response_ring == NULL) {
qla_printk(KERN_WARNING, ha,
"Memory Allocation failed - response_ring\n");
qla2x00_mem_free(ha);
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(HZ/10);
+ msleep(100);
+
+ continue;
+ }
+
+ ha->gid_list = dma_alloc_coherent(&ha->pdev->dev, GID_LIST_SIZE,
+ &ha->gid_list_dma, GFP_KERNEL);
+ if (ha->gid_list == NULL) {
+ qla_printk(KERN_WARNING, ha,
+ "Memory Allocation failed - gid_list\n");
+
+ qla2x00_mem_free(ha);
+ msleep(100);
+
+ continue;
+ }
+
+ ha->rlc_rsp = dma_alloc_coherent(&ha->pdev->dev,
+ sizeof(rpt_lun_cmd_rsp_t), &ha->rlc_rsp_dma, GFP_KERNEL);
+ if (ha->rlc_rsp == NULL) {
+ qla_printk(KERN_WARNING, ha,
+ "Memory Allocation failed - rlc");
+
+ qla2x00_mem_free(ha);
+ msleep(100);
+
+ continue;
+ }
+
+ snprintf(name, sizeof(name), "qla2xxx_%ld", ha->host_no);
+ ha->s_dma_pool = dma_pool_create(name, &ha->pdev->dev,
+ DMA_POOL_SIZE, 8, 0);
+ if (ha->s_dma_pool == NULL) {
+ qla_printk(KERN_WARNING, ha,
+ "Memory Allocation failed - s_dma_pool\n");
+
+ qla2x00_mem_free(ha);
+ msleep(100);
continue;
}
/* get consistent memory allocated for init control block */
- ha->init_cb = pci_alloc_consistent(ha->pdev,
- sizeof(init_cb_t), &ha->init_cb_dma);
+ ha->init_cb = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL,
+ &ha->init_cb_dma);
if (ha->init_cb == NULL) {
qla_printk(KERN_WARNING, ha,
"Memory Allocation failed - init_cb\n");
qla2x00_mem_free(ha);
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(HZ/10);
+ msleep(100);
continue;
}
memset(ha->init_cb, 0, sizeof(init_cb_t));
+ /* Get consistent memory allocated for Get Port Database cmd */
+ ha->iodesc_pd = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL,
+ &ha->iodesc_pd_dma);
+ if (ha->iodesc_pd == NULL) {
+ /* error */
+ qla_printk(KERN_WARNING, ha,
+ "Memory Allocation failed - iodesc_pd\n");
+
+ qla2x00_mem_free(ha);
+ msleep(100);
+
+ continue;
+ }
+ memset(ha->iodesc_pd, 0, PORT_DATABASE_SIZE);
+
/* Allocate ioctl related memory. */
if (qla2x00_alloc_ioctl_mem(ha)) {
qla_printk(KERN_WARNING, ha,
"Memory Allocation failed - ioctl_mem\n");
qla2x00_mem_free(ha);
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(HZ/10);
+ msleep(100);
continue;
}
"qla2x00_allocate_sp_pool()\n");
qla2x00_mem_free(ha);
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(HZ/10);
+ msleep(100);
continue;
}
/* Allocate memory for SNS commands */
if (IS_QLA2100(ha) || IS_QLA2200(ha)) {
/* Get consistent memory allocated for SNS commands */
- ha->sns_cmd = pci_alloc_consistent(ha->pdev,
- sizeof(struct sns_cmd_pkt), &ha->sns_cmd_dma);
+ ha->sns_cmd = dma_alloc_coherent(&ha->pdev->dev,
+ sizeof(struct sns_cmd_pkt), &ha->sns_cmd_dma,
+ GFP_KERNEL);
if (ha->sns_cmd == NULL) {
/* error */
qla_printk(KERN_WARNING, ha,
"Memory Allocation failed - sns_cmd\n");
qla2x00_mem_free(ha);
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(HZ/10);
+ msleep(100);
continue;
}
memset(ha->sns_cmd, 0, sizeof(struct sns_cmd_pkt));
} else {
/* Get consistent memory allocated for MS IOCB */
- ha->ms_iocb = pci_alloc_consistent(ha->pdev,
- sizeof(ms_iocb_entry_t), &ha->ms_iocb_dma);
+ ha->ms_iocb = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL,
+ &ha->ms_iocb_dma);
if (ha->ms_iocb == NULL) {
/* error */
qla_printk(KERN_WARNING, ha,
"Memory Allocation failed - ms_iocb\n");
qla2x00_mem_free(ha);
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(HZ/10);
+ msleep(100);
continue;
}
* Get consistent memory allocated for CT SNS
* commands
*/
- ha->ct_sns = pci_alloc_consistent(ha->pdev,
- sizeof(struct ct_sns_pkt), &ha->ct_sns_dma);
+ ha->ct_sns = dma_alloc_coherent(&ha->pdev->dev,
+ sizeof(struct ct_sns_pkt), &ha->ct_sns_dma,
+ GFP_KERNEL);
if (ha->ct_sns == NULL) {
/* error */
qla_printk(KERN_WARNING, ha,
"Memory Allocation failed - ct_sns\n");
qla2x00_mem_free(ha);
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(HZ/10);
+ msleep(100);
continue;
}
memset(ha->ct_sns, 0, sizeof(struct ct_sns_pkt));
}
- /* Get consistent memory allocated for Get Port Database cmd */
- ha->iodesc_pd = pci_alloc_consistent(ha->pdev,
- PORT_DATABASE_SIZE, &ha->iodesc_pd_dma);
- if (ha->iodesc_pd == NULL) {
- /* error */
- qla_printk(KERN_WARNING, ha,
- "Memory Allocation failed - iodesc_pd\n");
-
- qla2x00_mem_free(ha);
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(HZ/10);
-
- continue;
- }
- memset(ha->iodesc_pd, 0, PORT_DATABASE_SIZE);
-
/* Done all allocations without any error. */
status = 0;
/* free sp pool */
qla2x00_free_sp_pool(ha);
- if (ha->iodesc_pd) {
- pci_free_consistent(ha->pdev, PORT_DATABASE_SIZE,
- ha->iodesc_pd, ha->iodesc_pd_dma);
- }
+ if (ha->sns_cmd)
+ dma_free_coherent(&ha->pdev->dev, sizeof(struct sns_cmd_pkt),
+ ha->sns_cmd, ha->sns_cmd_dma);
- if (ha->sns_cmd) {
- pci_free_consistent(ha->pdev,
- sizeof(struct sns_cmd_pkt), ha->sns_cmd, ha->sns_cmd_dma);
- }
+ if (ha->ct_sns)
+ dma_free_coherent(&ha->pdev->dev, sizeof(struct ct_sns_pkt),
+ ha->ct_sns, ha->ct_sns_dma);
- if (ha->ct_sns) {
- pci_free_consistent(ha->pdev,
- sizeof(struct ct_sns_pkt), ha->ct_sns, ha->ct_sns_dma);
- }
- if (ha->ms_iocb) {
- pci_free_consistent(ha->pdev,
- sizeof(ms_iocb_entry_t), ha->ms_iocb, ha->ms_iocb_dma);
- }
+ if (ha->ms_iocb)
+ dma_pool_free(ha->s_dma_pool, ha->ms_iocb, ha->ms_iocb_dma);
- if (ha->init_cb) {
- pci_free_consistent(ha->pdev,
- sizeof(init_cb_t), ha->init_cb, ha->init_cb_dma);
- }
+ if (ha->iodesc_pd)
+ dma_pool_free(ha->s_dma_pool, ha->iodesc_pd, ha->iodesc_pd_dma);
- if (ha->request_ring) {
- pci_free_consistent(ha->pdev,
- ((ha->request_q_length + 1) * (sizeof(request_t))),
- ha->request_ring, ha->request_dma);
- }
+ if (ha->init_cb)
+ dma_pool_free(ha->s_dma_pool, ha->init_cb, ha->init_cb_dma);
+
+ if (ha->s_dma_pool)
+ dma_pool_destroy(ha->s_dma_pool);
- if (ha->response_ring) {
- pci_free_consistent(ha->pdev,
- ((ha->response_q_length + 1) * (sizeof(response_t))),
+ if (ha->rlc_rsp)
+ dma_free_coherent(&ha->pdev->dev,
+ sizeof(rpt_lun_cmd_rsp_t), ha->rlc_rsp,
+ ha->rlc_rsp_dma);
+
+ if (ha->gid_list)
+ dma_free_coherent(&ha->pdev->dev, GID_LIST_SIZE, ha->gid_list,
+ ha->gid_list_dma);
+
+ if (ha->response_ring)
+ dma_free_coherent(&ha->pdev->dev,
+ (ha->response_q_length + 1) * sizeof(response_t),
ha->response_ring, ha->response_dma);
- }
- ha->iodesc_pd = NULL;
- ha->iodesc_pd_dma = 0;
+ if (ha->request_ring)
+ dma_free_coherent(&ha->pdev->dev,
+ (ha->request_q_length + 1) * sizeof(request_t),
+ ha->request_ring, ha->request_dma);
+
+ ha->sns_cmd = NULL;
+ ha->sns_cmd_dma = 0;
ha->ct_sns = NULL;
+ ha->ct_sns_dma = 0;
ha->ms_iocb = NULL;
-
+ ha->ms_iocb_dma = 0;
+ ha->iodesc_pd = NULL;
+ ha->iodesc_pd_dma = 0;
ha->init_cb = NULL;
- ha->request_ring = NULL;
- ha->request_dma = 0;
+ ha->init_cb_dma = 0;
+
+ ha->s_dma_pool = NULL;
+
+ ha->rlc_rsp = NULL;
+ ha->rlc_rsp_dma = 0;
+ ha->gid_list = NULL;
+ ha->gid_list_dma = 0;
+
ha->response_ring = NULL;
ha->response_dma = 0;
+ ha->request_ring = NULL;
+ ha->request_dma = 0;
list_for_each_safe(fcpl, fcptemp, &ha->fcports) {
fcport = list_entry(fcpl, fc_port_t, list);
}
INIT_LIST_HEAD(&ha->fcports);
- if (ha->fw_dump) {
+ if (ha->fw_dump)
free_pages((unsigned long)ha->fw_dump, ha->fw_dump_order);
- ha->fw_dump = NULL;
- }
- if (ha->fw_dump_buffer) {
+ if (ha->fw_dump_buffer)
vfree(ha->fw_dump_buffer);
- ha->fw_dump_reading = 0;
- ha->fw_dump_buffer = NULL;
- }
+
+ ha->fw_dump = NULL;
+ ha->fw_dump_reading = 0;
+ ha->fw_dump_buffer = NULL;
}
/*
*
* Note: Sets the ref_count for non Null sp to one.
*/
-int
+static int
qla2x00_allocate_sp_pool(scsi_qla_host_t *ha)
{
int rval;
* This routine frees all adapter allocated memory.
*
*/
-void
+static void
qla2x00_free_sp_pool( scsi_qla_host_t *ha)
{
if (ha->srb_mempool) {
if (ha->dpc_should_die)
break;
- if (!list_empty(&ha->done_queue))
- qla2x00_done(ha);
-
DEBUG3(printk("qla2x00: DPC handler waking up\n"));
/* Initialization not yet finished. Don't do anything yet. */
ha->dpc_active = 1;
+ if (!list_empty(&ha->done_queue))
+ qla2x00_done(ha);
+
/* Process commands in retry queue */
if (test_and_clear_bit(PORT_RESTART_NEEDED, &ha->dpc_flags)) {
DEBUG(printk("scsi(%ld): DPC checking retry_q. "
fcport->login_retry) {
fcport->login_retry--;
- if (fcport->flags & FCF_FABRIC_DEVICE)
+ if (fcport->flags & FCF_FABRIC_DEVICE) {
+ if (fcport->flags &
+ FCF_TAPE_PRESENT)
+ qla2x00_fabric_logout(
+ ha,
+ fcport->loop_id);
status = qla2x00_fabric_login(
ha, fcport, &next_loopid);
- else
+ } else
status =
qla2x00_local_device_login(
ha, fcport->loop_id);
DEBUG(printk("scsi(%ld): qla2x00_restart_queues()\n",
ha->host_no));
- qla2x00_restart_queues(ha,FALSE);
+ qla2x00_restart_queues(ha, 0);
DEBUG(printk("scsi(%ld): qla2x00_restart_queues - end\n",
ha->host_no));
DEBUG(printk("scsi(%ld): qla2x00_abort_queues()\n",
ha->host_no));
- qla2x00_abort_queues(ha, FALSE);
+ qla2x00_abort_queues(ha, 0);
DEBUG(printk("scsi(%ld): qla2x00_abort_queues - end\n",
ha->host_no));
if (ha->flags.online && !ha->flags.reset_active &&
!atomic_read(&ha->loop_down_timer) &&
!(test_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags))) {
-
- /* 10/15 ha->flags.reset_active = TRUE; */
do {
clear_bit(RESET_MARKER_NEEDED, &ha->dpc_flags);
ha->marker_needed = 1;
} while (!atomic_read(&ha->loop_down_timer) &&
(test_bit(RESET_MARKER_NEEDED, &ha->dpc_flags)));
-
- /* 10/15 ha->flags.reset_active = FALSE; */
}
}
* output:
* srb_t * or NULL
*/
-srb_t *
+static srb_t *
qla2x00_get_new_sp(scsi_qla_host_t *ha)
{
srb_t *sp;
- sp = mempool_alloc(ha->srb_mempool, GFP_KERNEL);
- if (sp) {
+ sp = mempool_alloc(ha->srb_mempool, GFP_ATOMIC);
+ if (sp)
atomic_set(&sp->ref_count, 1);
- sp->req_cnt = 0;
- }
return (sp);
}
-/**************************************************************************
- * qla2x00_blink_led
- *
- * Description:
- * This function sets the colour of the LED while preserving the
- * unsued GPIO pins every sec.
- *
- * Input:
- * ha - Host adapter structure
- *
- * Return:
- * None
- *
- * Context: qla2x00_timer() Interrupt
- ***************************************************************************/
-void
-qla2x00_blink_led(scsi_qla_host_t *ha)
-{
- uint16_t gpio_enable, gpio_data, led_color;
- unsigned long cpu_flags = 0;
- device_reg_t *reg = ha->iobase;
-
- /* Save the Original GPIOE */
- spin_lock_irqsave(&ha->hardware_lock, cpu_flags);
- gpio_enable = RD_REG_WORD(®->gpioe);
- gpio_data = RD_REG_WORD(®->gpiod);
- spin_unlock_irqrestore(&ha->hardware_lock, cpu_flags);
-
- DEBUG2(printk("%s Original data of gpio_enable_reg=0x%x"
- " gpio_data_reg=0x%x\n",
- __func__,gpio_enable,gpio_data));
-
- if (ha->beacon_green_on){
- led_color = GPIO_LED_GREEN_ON_AMBER_OFF;
- ha->beacon_green_on = 0;
- } else {
- led_color = GPIO_LED_GREEN_OFF_AMBER_OFF;
- ha->beacon_green_on = 1;
- }
-
- /* Set the modified gpio_enable values */
- gpio_enable |= GPIO_LED_GREEN_ON_AMBER_OFF;
-
- DEBUG2(printk("%s Before writing enable : gpio_enable_reg=0x%x"
- " gpio_data_reg=0x%x led_color=0x%x\n",
- __func__, gpio_enable, gpio_data, led_color));
-
- spin_lock_irqsave(&ha->hardware_lock, cpu_flags);
- WRT_REG_WORD(®->gpioe,gpio_enable);
- spin_unlock_irqrestore(&ha->hardware_lock, cpu_flags);
-
- /* Clear out the previously set LED colour */
- gpio_data &= ~GPIO_LED_GREEN_ON_AMBER_OFF;
-
- /* Set the new input LED colour to GPIOD */
- gpio_data |= led_color;
-
- DEBUG2(printk("%s Before writing data: gpio_enable_reg=0x%x"
- " gpio_data_reg=0x%x led_color=0x%x\n",
- __func__,gpio_enable,gpio_data,led_color));
-
- /* Set the modified gpio_data values */
- spin_lock_irqsave(&ha->hardware_lock, cpu_flags);
- WRT_REG_WORD(®->gpiod,gpio_data);
- spin_unlock_irqrestore(&ha->hardware_lock, cpu_flags);
-}
-
/**************************************************************************
* qla2x00_timer
*
os_lun_t *lq;
os_tgt_t *tq;
int start_dpc = 0;
+ int index;
+ srb_t *sp;
/*
* We try and restart any request in the retry queue every second.
start_dpc++;
}
- /* Check if beacon LED needs to be blinked */
- if (!IS_QLA2100(ha) && !IS_QLA2200(ha) && ha->beacon_blink_led)
- qla2x00_blink_led(ha);
-
-
/*
* Ports - Port down timer.
*
if (atomic_read(&ha->loop_down_timer) > 0 &&
!(test_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags)) && ha->flags.online) {
- /* dg 10/30 if (atomic_read(&ha->loop_down_timer) == LOOP_DOWN_TIME) { */
if (atomic_read(&ha->loop_down_timer) ==
ha->loop_down_abort_time) {
if (!IS_QLA2100(ha) && ha->link_down_timeout)
atomic_set(&ha->loop_state, LOOP_DEAD);
+ /* Schedule an ISP abort to return any tape commands. */
+ spin_lock_irqsave(&ha->hardware_lock, cpu_flags);
+ for (index = 1; index < MAX_OUTSTANDING_COMMANDS;
+ index++) {
+ sp = ha->outstanding_cmds[index];
+ if (!sp)
+ continue;
+ if (!(sp->fclun->fcport->flags &
+ FCF_TAPE_PRESENT))
+ continue;
+
+ set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags);
+ break;
+ }
+ spin_unlock_irqrestore(&ha->hardware_lock, cpu_flags);
+
set_bit(ABORT_QUEUES_NEEDED, &ha->dpc_flags);
start_dpc++;
}
if (sp->state == SRB_PENDING_STATE) {
__del_from_pending_queue(vis_ha, sp);
DEBUG2(printk("scsi(%ld): Found in Pending queue pid %ld, "
- "State = %x., fcport state=%d jiffies=%lx\n",
+ "State = %x., fcport state=%d sjiffs=%lx njiffs=%lx\n",
vis_ha->host_no, cmd->serial_number, sp->state,
- atomic_read(&fcport->state), jiffies));
+ atomic_read(&fcport->state), sp->r_start, jiffies));
/*
* If FC_DEVICE is marked as dead return the cmd with
if (processed) {
qla2x00_done(dest_ha);
-
- return;
+ return;
}
spin_lock_irqsave(&dest_ha->list_lock, cpu_flags);
default:
DEBUG2(printk("scsi(%ld:%d:%d) %s: did_error "
- "= %d, comp-scsi= 0x%x-0x%x.\n",
+ "= %d, comp-scsi= 0x%x-0x%x pid=%ld.\n",
vis_ha->host_no,
cmd->device->id, cmd->device->lun,
__func__,
host_byte(cmd->result),
CMD_COMPL_STATUS(cmd),
- CMD_SCSI_STATUS(cmd)));
+ CMD_SCSI_STATUS(cmd), cmd->serial_number));
break;
}
test_bit(ABORT_ISP_ACTIVE, &dest_ha->dpc_flags) ||
atomic_read(&dest_ha->loop_state) != LOOP_READY)) {
- DEBUG3(printk("scsi(%ld): port=(0x%x) retry_q(%d) "
- "loop state = %d, loop counter = 0x%x dpc flags "
- "= 0x%lx\n",
- dest_ha->host_no,
- fcport->loop_id,
+ DEBUG3(printk("scsi(%ld): pid=%ld port=0x%x state=%d "
+ "loop state=%d, loop counter=0x%x "
+ "dpc_flags=0x%lx\n", sp->cmd->serial_number,
+ dest_ha->host_no, fcport->loop_id,
atomic_read(&fcport->state),
atomic_read(&dest_ha->loop_state),
atomic_read(&dest_ha->loop_down_timer),
}
}
-
-/**************************************************************************
-* qla2x00_check_tgt_status
-*
-* Description:
-* Checks to see if the target or loop is down.
-*
-* Input:
-* cmd - pointer to Scsi cmd structure
-*
-* Returns:
-* 1 - if target is present
-* 0 - if target is not present
-*
-**************************************************************************/
-int
-qla2x00_check_tgt_status(scsi_qla_host_t *ha, struct scsi_cmnd *cmd)
-{
- os_lun_t *lq;
- unsigned int b, t, l;
- fc_port_t *fcport;
-
- /* Generate LU queue on bus, target, LUN */
- b = cmd->device->channel;
- t = cmd->device->id;
- l = cmd->device->lun;
-
- if ((lq = GET_LU_Q(ha,t,l)) == NULL) {
- return (QLA_FUNCTION_FAILED);
- }
-
- fcport = lq->fclun->fcport;
-
- if (TGT_Q(ha, t) == NULL ||
- l >= ha->max_luns ||
- atomic_read(&fcport->state) == FCS_DEVICE_DEAD ||
- atomic_read(&ha->loop_state) == LOOP_DEAD ||
- (!atomic_read(&ha->loop_down_timer) &&
- atomic_read(&ha->loop_state) == LOOP_DOWN) ||
- test_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags) ||
- test_bit(ISP_ABORT_NEEDED, &ha->dpc_flags) ||
- atomic_read(&ha->loop_state) != LOOP_READY) {
-
- DEBUG(printk(KERN_INFO
- "scsi(%ld:%2d:%2d:%2d): %s connection is down\n",
- ha->host_no,
- b, t, l,
- __func__));
-
- cmd->result = DID_NO_CONNECT << 16;
- return (QLA_FUNCTION_FAILED);
- }
- return (QLA_SUCCESS);
-}
-
-/**************************************************************************
-* qla2x00_check_port_status
-*
-* Description:
-* Checks to see if the port or loop is down.
-*
-* Input:
-* fcport - pointer to fc_port_t structure.
-*
-* Returns:
-* 1 - if port is present
-* 0 - if port is not present
-*
-**************************************************************************/
-int
-qla2x00_check_port_status(scsi_qla_host_t *ha, fc_port_t *fcport)
-{
- if (fcport == NULL) {
- return (QLA_FUNCTION_FAILED);
- }
-
- if (atomic_read(&fcport->state) == FCS_DEVICE_DEAD ||
- atomic_read(&ha->loop_state) == LOOP_DEAD) {
- return (QLA_FUNCTION_FAILED);
- }
-
- if ((atomic_read(&fcport->state) != FCS_ONLINE) ||
- (!atomic_read(&ha->loop_down_timer) &&
- atomic_read(&ha->loop_state) == LOOP_DOWN) ||
- (test_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags)) ||
- test_bit(CFG_ACTIVE, &ha->cfg_flags) ||
- test_bit(ISP_ABORT_NEEDED, &ha->dpc_flags) ||
- atomic_read(&ha->loop_state) != LOOP_READY) {
-
- DEBUG(printk(KERN_INFO
- "scsi(%ld): Connection is down. fcport=%p.\n",
- ha->host_no, fcport));
-
- return (QLA_BUSY);
- }
-
- return (QLA_SUCCESS);
-}
-
/* XXX(hch): crude hack to emulate a down_timeout() */
int
qla2x00_down_timeout(struct semaphore *sema, unsigned long timeout)
}
static void
-qla2xxx_get_port_id(struct scsi_device *sdev)
+qla2xxx_get_port_id(struct scsi_target *starget)
{
- scsi_qla_host_t *ha = to_qla_host(sdev->host);
+ struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
+ scsi_qla_host_t *ha = to_qla_host(shost);
struct fc_port *fc;
list_for_each_entry(fc, &ha->fcports, list) {
- if (fc->os_target_id == sdev->id) {
- fc_port_id(sdev) = fc->d_id.b.domain << 16 |
+ if (fc->os_target_id == starget->id) {
+ fc_starget_port_id(starget) = fc->d_id.b.domain << 16 |
fc->d_id.b.area << 8 |
fc->d_id.b.al_pa;
return;
}
}
- fc_port_id(sdev) = -1;
+ fc_starget_port_id(starget) = -1;
}
static void
-qla2xxx_get_port_name(struct scsi_device *sdev)
+qla2xxx_get_port_name(struct scsi_target *starget)
{
- scsi_qla_host_t *ha = to_qla_host(sdev->host);
+ struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
+ scsi_qla_host_t *ha = to_qla_host(shost);
struct fc_port *fc;
list_for_each_entry(fc, &ha->fcports, list) {
- if (fc->os_target_id == sdev->id) {
- fc_port_name(sdev) =
+ if (fc->os_target_id == starget->id) {
+ fc_starget_port_name(starget) =
__be64_to_cpu(*(uint64_t *)fc->port_name);
return;
}
}
- fc_port_name(sdev) = -1;
+ fc_starget_port_name(starget) = -1;
}
static void
-qla2xxx_get_node_name(struct scsi_device *sdev)
+qla2xxx_get_node_name(struct scsi_target *starget)
{
- scsi_qla_host_t *ha = to_qla_host(sdev->host);
+ struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
+ scsi_qla_host_t *ha = to_qla_host(shost);
struct fc_port *fc;
list_for_each_entry(fc, &ha->fcports, list) {
- if (fc->os_target_id == sdev->id) {
- fc_node_name(sdev) =
+ if (fc->os_target_id == starget->id) {
+ fc_starget_node_name(starget) =
__be64_to_cpu(*(uint64_t *)fc->node_name);
return;
}
}
- fc_node_name(sdev) = -1;
+ fc_starget_node_name(starget) = -1;
}
static struct fc_function_template qla2xxx_transport_functions = {
- .get_port_id = qla2xxx_get_port_id,
- .show_port_id = 1,
- .get_port_name = qla2xxx_get_port_name,
- .show_port_name = 1,
- .get_node_name = qla2xxx_get_node_name,
- .show_node_name = 1,
+ .get_starget_port_id = qla2xxx_get_port_id,
+ .show_starget_port_id = 1,
+ .get_starget_port_name = qla2xxx_get_port_name,
+ .show_starget_port_name = 1,
+ .get_starget_node_name = qla2xxx_get_node_name,
+ .show_starget_node_name = 1,
};
/**
if (!qla2xxx_transport_template)
return -ENODEV;
- printk(KERN_INFO
- "QLogic Fibre Channel HBA Driver (%p)\n", qla2x00_set_info);
-
+ printk(KERN_INFO "QLogic Fibre Channel HBA Driver\n");
return 0;
}
MODULE_AUTHOR("QLogic Corporation");
MODULE_DESCRIPTION("QLogic Fibre Channel HBA Driver");
MODULE_LICENSE("GPL");
+MODULE_VERSION(QLA2XXX_VERSION);