summaryrefslogtreecommitdiff
path: root/drivers/scsi/qla2xxx
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/qla2xxx')
-rw-r--r--drivers/scsi/qla2xxx/qla_attr.c130
-rw-r--r--drivers/scsi/qla2xxx/qla_dbg.c2
-rw-r--r--drivers/scsi/qla2xxx/qla_def.h13
-rw-r--r--drivers/scsi/qla2xxx/qla_gbl.h5
-rw-r--r--drivers/scsi/qla2xxx/qla_gs.c6
-rw-r--r--drivers/scsi/qla2xxx/qla_init.c141
-rw-r--r--drivers/scsi/qla2xxx/qla_iocb.c14
-rw-r--r--drivers/scsi/qla2xxx/qla_isr.c18
-rw-r--r--drivers/scsi/qla2xxx/qla_mbx.c11
-rw-r--r--drivers/scsi/qla2xxx/qla_mid.c17
-rw-r--r--drivers/scsi/qla2xxx/qla_os.c112
-rw-r--r--drivers/scsi/qla2xxx/qla_sup.c48
-rw-r--r--drivers/scsi/qla2xxx/qla_version.h2
13 files changed, 317 insertions, 202 deletions
diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c
index 8dd88fc1244a..45e7dcb4b34d 100644
--- a/drivers/scsi/qla2xxx/qla_attr.c
+++ b/drivers/scsi/qla2xxx/qla_attr.c
@@ -8,6 +8,7 @@
#include <linux/kthread.h>
#include <linux/vmalloc.h>
+#include <linux/delay.h>
static int qla24xx_vport_disable(struct fc_vport *, bool);
@@ -20,18 +21,12 @@ qla2x00_sysfs_read_fw_dump(struct kobject *kobj,
{
struct scsi_qla_host *ha = shost_priv(dev_to_shost(container_of(kobj,
struct device, kobj)));
- char *rbuf = (char *)ha->fw_dump;
if (ha->fw_dump_reading == 0)
return 0;
- if (off > ha->fw_dump_len)
- return 0;
- if (off + count > ha->fw_dump_len)
- count = ha->fw_dump_len - off;
- memcpy(buf, &rbuf[off], count);
-
- return (count);
+ return memory_read_from_buffer(buf, count, &off, ha->fw_dump,
+ ha->fw_dump_len);
}
static ssize_t
@@ -94,20 +89,13 @@ qla2x00_sysfs_read_nvram(struct kobject *kobj,
{
struct scsi_qla_host *ha = shost_priv(dev_to_shost(container_of(kobj,
struct device, kobj)));
- int size = ha->nvram_size;
- char *nvram_cache = ha->nvram;
- if (!capable(CAP_SYS_ADMIN) || off > size || count == 0)
+ if (!capable(CAP_SYS_ADMIN))
return 0;
- if (off + count > size) {
- size -= off;
- count = size;
- }
/* Read NVRAM data from cache. */
- memcpy(buf, &nvram_cache[off], count);
-
- return count;
+ return memory_read_from_buffer(buf, count, &off, ha->nvram,
+ ha->nvram_size);
}
static ssize_t
@@ -175,14 +163,9 @@ qla2x00_sysfs_read_optrom(struct kobject *kobj,
if (ha->optrom_state != QLA_SREADING)
return 0;
- if (off > ha->optrom_region_size)
- return 0;
- if (off + count > ha->optrom_region_size)
- count = ha->optrom_region_size - off;
-
- memcpy(buf, &ha->optrom_buffer[off], count);
- return count;
+ return memory_read_from_buffer(buf, count, &off, ha->optrom_buffer,
+ ha->optrom_region_size);
}
static ssize_t
@@ -374,20 +357,12 @@ qla2x00_sysfs_read_vpd(struct kobject *kobj,
{
struct scsi_qla_host *ha = shost_priv(dev_to_shost(container_of(kobj,
struct device, kobj)));
- int size = ha->vpd_size;
- char *vpd_cache = ha->vpd;
- if (!capable(CAP_SYS_ADMIN) || off > size || count == 0)
+ if (!capable(CAP_SYS_ADMIN))
return 0;
- if (off + count > size) {
- size -= off;
- count = size;
- }
/* Read NVRAM data from cache. */
- memcpy(buf, &vpd_cache[off], count);
-
- return count;
+ return memory_read_from_buffer(buf, count, &off, ha->vpd, ha->vpd_size);
}
static ssize_t
@@ -557,8 +532,10 @@ qla2x00_serial_num_show(struct device *dev, struct device_attribute *attr,
scsi_qla_host_t *ha = shost_priv(class_to_shost(dev));
uint32_t sn;
- if (IS_FWI2_CAPABLE(ha))
- return snprintf(buf, PAGE_SIZE, "\n");
+ if (IS_FWI2_CAPABLE(ha)) {
+ qla2xxx_get_vpd_field(ha, "SN", buf, PAGE_SIZE);
+ return snprintf(buf, PAGE_SIZE, "%s\n", buf);
+ }
sn = ((ha->serial0 & 0x1f) << 16) | (ha->serial2 << 8) | ha->serial1;
return snprintf(buf, PAGE_SIZE, "%c%05d\n", 'A' + sn / 100000,
@@ -809,6 +786,16 @@ qla2x00_optrom_fw_version_show(struct device *dev,
ha->fw_revision[3]);
}
+static ssize_t
+qla2x00_total_isp_aborts_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ scsi_qla_host_t *ha = shost_priv(class_to_shost(dev));
+
+ return snprintf(buf, PAGE_SIZE, "%d\n",
+ ha->qla_stats.total_isp_aborts);
+}
+
static DEVICE_ATTR(driver_version, S_IRUGO, qla2x00_drvr_version_show, NULL);
static DEVICE_ATTR(fw_version, S_IRUGO, qla2x00_fw_version_show, NULL);
static DEVICE_ATTR(serial_num, S_IRUGO, qla2x00_serial_num_show, NULL);
@@ -831,6 +818,8 @@ static DEVICE_ATTR(optrom_fcode_version, S_IRUGO,
qla2x00_optrom_fcode_version_show, NULL);
static DEVICE_ATTR(optrom_fw_version, S_IRUGO, qla2x00_optrom_fw_version_show,
NULL);
+static DEVICE_ATTR(total_isp_aborts, S_IRUGO, qla2x00_total_isp_aborts_show,
+ NULL);
struct device_attribute *qla2x00_host_attrs[] = {
&dev_attr_driver_version,
@@ -849,6 +838,7 @@ struct device_attribute *qla2x00_host_attrs[] = {
&dev_attr_optrom_efi_version,
&dev_attr_optrom_fcode_version,
&dev_attr_optrom_fw_version,
+ &dev_attr_total_isp_aborts,
NULL,
};
@@ -972,26 +962,50 @@ qla2x00_get_starget_port_id(struct scsi_target *starget)
}
static void
-qla2x00_get_rport_loss_tmo(struct fc_rport *rport)
+qla2x00_set_rport_loss_tmo(struct fc_rport *rport, uint32_t timeout)
{
- struct Scsi_Host *host = rport_to_shost(rport);
- scsi_qla_host_t *ha = shost_priv(host);
-
- rport->dev_loss_tmo = ha->port_down_retry_count + 5;
+ if (timeout)
+ rport->dev_loss_tmo = timeout;
+ else
+ rport->dev_loss_tmo = 1;
}
static void
-qla2x00_set_rport_loss_tmo(struct fc_rport *rport, uint32_t timeout)
+qla2x00_dev_loss_tmo_callbk(struct fc_rport *rport)
{
struct Scsi_Host *host = rport_to_shost(rport);
- scsi_qla_host_t *ha = shost_priv(host);
+ fc_port_t *fcport = *(fc_port_t **)rport->dd_data;
+
+ qla2x00_abort_fcport_cmds(fcport);
+
+ /*
+ * Transport has effectively 'deleted' the rport, clear
+ * all local references.
+ */
+ spin_lock_irq(host->host_lock);
+ fcport->rport = NULL;
+ *((fc_port_t **)rport->dd_data) = NULL;
+ spin_unlock_irq(host->host_lock);
+}
- if (timeout)
- ha->port_down_retry_count = timeout;
- else
- ha->port_down_retry_count = 1;
+static void
+qla2x00_terminate_rport_io(struct fc_rport *rport)
+{
+ fc_port_t *fcport = *(fc_port_t **)rport->dd_data;
+
+ /*
+ * At this point all fcport's software-states are cleared. Perform any
+ * final cleanup of firmware resources (PCBs and XCBs).
+ */
+ if (fcport->loop_id != FC_NO_LOOP_ID) {
+ fcport->ha->isp_ops->fabric_logout(fcport->ha, fcport->loop_id,
+ fcport->d_id.b.domain, fcport->d_id.b.area,
+ fcport->d_id.b.al_pa);
+ fcport->loop_id = FC_NO_LOOP_ID;
+ }
- rport->dev_loss_tmo = ha->port_down_retry_count + 5;
+ qla2x00_abort_fcport_cmds(fcport);
+ scsi_target_unblock(&rport->dev);
}
static int
@@ -1045,6 +1059,7 @@ qla2x00_get_fc_host_stats(struct Scsi_Host *shost)
pfc_host_stat->invalid_tx_word_count = stats->inval_xmit_word_cnt;
pfc_host_stat->invalid_crc_count = stats->inval_crc_cnt;
if (IS_FWI2_CAPABLE(ha)) {
+ pfc_host_stat->lip_count = stats->lip_cnt;
pfc_host_stat->tx_frames = stats->tx_frames;
pfc_host_stat->rx_frames = stats->rx_frames;
pfc_host_stat->dumped_frames = stats->dumped_frames;
@@ -1173,17 +1188,16 @@ vport_create_failed_2:
static int
qla24xx_vport_delete(struct fc_vport *fc_vport)
{
- scsi_qla_host_t *ha = shost_priv(fc_vport->shost);
scsi_qla_host_t *vha = fc_vport->dd_data;
+ scsi_qla_host_t *pha = to_qla_parent(vha);
+
+ while (test_bit(LOOP_RESYNC_ACTIVE, &vha->dpc_flags) ||
+ test_bit(FCPORT_UPDATE_NEEDED, &pha->dpc_flags))
+ msleep(1000);
qla24xx_disable_vp(vha);
qla24xx_deallocate_vp_id(vha);
- mutex_lock(&ha->vport_lock);
- ha->cur_vport_count--;
- clear_bit(vha->vp_idx, ha->vp_idx_map);
- mutex_unlock(&ha->vport_lock);
-
kfree(vha->node_name);
kfree(vha->port_name);
@@ -1248,11 +1262,12 @@ struct fc_function_template qla2xxx_transport_functions = {
.get_starget_port_id = qla2x00_get_starget_port_id,
.show_starget_port_id = 1,
- .get_rport_dev_loss_tmo = qla2x00_get_rport_loss_tmo,
.set_rport_dev_loss_tmo = qla2x00_set_rport_loss_tmo,
.show_rport_dev_loss_tmo = 1,
.issue_fc_host_lip = qla2x00_issue_lip,
+ .dev_loss_tmo_callbk = qla2x00_dev_loss_tmo_callbk,
+ .terminate_rport_io = qla2x00_terminate_rport_io,
.get_fc_host_stats = qla2x00_get_fc_host_stats,
.vport_create = qla24xx_vport_create,
@@ -1291,11 +1306,12 @@ struct fc_function_template qla2xxx_transport_vport_functions = {
.get_starget_port_id = qla2x00_get_starget_port_id,
.show_starget_port_id = 1,
- .get_rport_dev_loss_tmo = qla2x00_get_rport_loss_tmo,
.set_rport_dev_loss_tmo = qla2x00_set_rport_loss_tmo,
.show_rport_dev_loss_tmo = 1,
.issue_fc_host_lip = qla2x00_issue_lip,
+ .dev_loss_tmo_callbk = qla2x00_dev_loss_tmo_callbk,
+ .terminate_rport_io = qla2x00_terminate_rport_io,
.get_fc_host_stats = qla2x00_get_fc_host_stats,
};
diff --git a/drivers/scsi/qla2xxx/qla_dbg.c b/drivers/scsi/qla2xxx/qla_dbg.c
index cbef785765cf..510ba64bc286 100644
--- a/drivers/scsi/qla2xxx/qla_dbg.c
+++ b/drivers/scsi/qla2xxx/qla_dbg.c
@@ -216,7 +216,7 @@ qla24xx_soft_reset(scsi_qla_host_t *ha)
static int
qla2xxx_dump_ram(scsi_qla_host_t *ha, uint32_t addr, uint16_t *ram,
- uint16_t ram_words, void **nxt)
+ uint32_t ram_words, void **nxt)
{
int rval;
uint32_t cnt, stat, timer, words, idx;
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index 8dd600013bd1..94a720eabfd8 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -864,7 +864,8 @@ struct link_statistics {
uint32_t prim_seq_err_cnt;
uint32_t inval_xmit_word_cnt;
uint32_t inval_crc_cnt;
- uint32_t unused1[0x1b];
+ uint32_t lip_cnt;
+ uint32_t unused1[0x1a];
uint32_t tx_frames;
uint32_t rx_frames;
uint32_t dumped_frames;
@@ -1544,7 +1545,6 @@ typedef struct fc_port {
int login_retry;
atomic_t port_down_timer;
- spinlock_t rport_lock;
struct fc_rport *rport, *drport;
u32 supported_classes;
@@ -2155,6 +2155,10 @@ struct qla_chip_state_84xx {
uint32_t gold_fw_version;
};
+struct qla_statistics {
+ uint32_t total_isp_aborts;
+};
+
/*
* Linux Host Adapter structure
*/
@@ -2166,7 +2170,6 @@ typedef struct scsi_qla_host {
struct pci_dev *pdev;
unsigned long host_no;
- unsigned long instance;
volatile struct {
uint32_t init_done :1;
@@ -2234,6 +2237,7 @@ typedef struct scsi_qla_host {
#define REGISTER_FDMI_NEEDED 26
#define FCPORT_UPDATE_NEEDED 27
#define VP_DPC_NEEDED 28 /* wake up for VP dpc handling */
+#define UNLOADING 29
uint32_t device_flags;
#define DFLG_LOCAL_DEVICES BIT_0
@@ -2515,7 +2519,7 @@ typedef struct scsi_qla_host {
uint8_t model_number[16+1];
#define BINZERO "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
- char *model_desc;
+ char model_desc[80];
uint8_t adapter_id[16+1];
uint8_t *node_name;
@@ -2596,6 +2600,7 @@ typedef struct scsi_qla_host {
int cur_vport_count;
struct qla_chip_state_84xx *cs84xx;
+ struct qla_statistics qla_stats;
} scsi_qla_host_t;
diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
index 9b4bebee6879..0b156735e9a6 100644
--- a/drivers/scsi/qla2xxx/qla_gbl.h
+++ b/drivers/scsi/qla2xxx/qla_gbl.h
@@ -62,7 +62,7 @@ extern int ql2xfdmienable;
extern int ql2xallocfwdump;
extern int ql2xextended_error_logging;
extern int ql2xqfullrampup;
-extern int num_hosts;
+extern int ql2xiidmaenable;
extern int qla2x00_loop_reset(scsi_qla_host_t *);
extern void qla2x00_abort_all_cmds(scsi_qla_host_t *, int);
@@ -71,6 +71,8 @@ extern int qla2x00_post_aen_work(struct scsi_qla_host *, enum
extern int qla2x00_post_hwe_work(struct scsi_qla_host *, uint16_t , uint16_t,
uint16_t, uint16_t);
+extern void qla2x00_abort_fcport_cmds(fc_port_t *);
+
/*
* Global Functions in qla_mid.c source file.
*/
@@ -312,6 +314,7 @@ extern int qla2xxx_hw_event_log(scsi_qla_host_t *, uint16_t , uint16_t,
uint16_t, uint16_t);
extern void qla2xxx_get_flash_info(scsi_qla_host_t *);
+extern int qla2xxx_get_vpd_field(scsi_qla_host_t *, char *, char *, size_t);
/*
* Global Function Prototypes in qla_dbg.c source file.
diff --git a/drivers/scsi/qla2xxx/qla_gs.c b/drivers/scsi/qla2xxx/qla_gs.c
index 4cb80b476c85..c2a4bfbcb05b 100644
--- a/drivers/scsi/qla2xxx/qla_gs.c
+++ b/drivers/scsi/qla2xxx/qla_gs.c
@@ -1661,6 +1661,12 @@ qla2x00_fdmi_register(scsi_qla_host_t *ha)
{
int rval;
+ if (IS_QLA2100(ha) || IS_QLA2200(ha)) {
+ DEBUG2(printk("scsi(%ld): FDMI unsupported on "
+ "ISP2100/ISP2200.\n", ha->host_no));
+ return QLA_SUCCESS;
+ }
+
rval = qla2x00_mgmt_svr_login(ha);
if (rval)
return rval;
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index bbbc5a632a1d..ee89ddd64aae 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -334,6 +334,8 @@ static int
qla2x00_isp_firmware(scsi_qla_host_t *ha)
{
int rval;
+ uint16_t loop_id, topo, sw_cap;
+ uint8_t domain, area, al_pa;
/* Assume loading risc code */
rval = QLA_FUNCTION_FAILED;
@@ -345,6 +347,11 @@ qla2x00_isp_firmware(scsi_qla_host_t *ha)
/* Verify checksum of loaded RISC code. */
rval = qla2x00_verify_checksum(ha, ha->fw_srisc_address);
+ if (rval == QLA_SUCCESS) {
+ /* And, verify we are not in ROM code. */
+ rval = qla2x00_get_adapter_id(ha, &loop_id, &al_pa,
+ &area, &domain, &topo, &sw_cap);
+ }
}
if (rval) {
@@ -722,7 +729,7 @@ qla24xx_chip_diag(scsi_qla_host_t *ha)
/* Perform RISC reset. */
qla24xx_reset_risc(ha);
- ha->fw_transfer_size = REQUEST_ENTRY_SIZE * 1024;
+ ha->fw_transfer_size = REQUEST_ENTRY_SIZE * ha->request_q_length;
rval = qla2x00_mbx_reg_test(ha);
if (rval) {
@@ -768,42 +775,16 @@ qla2x00_alloc_fw_dump(scsi_qla_host_t *ha)
mem_size = (ha->fw_memory_size - 0x100000 + 1) *
sizeof(uint32_t);
- /* Allocate memory for Extended Trace Buffer. */
- tc = dma_alloc_coherent(&ha->pdev->dev, EFT_SIZE, &tc_dma,
- GFP_KERNEL);
- if (!tc) {
- qla_printk(KERN_WARNING, ha, "Unable to allocate "
- "(%d KB) for EFT.\n", EFT_SIZE / 1024);
- goto cont_alloc;
- }
-
- memset(tc, 0, EFT_SIZE);
- rval = qla2x00_enable_eft_trace(ha, tc_dma, EFT_NUM_BUFFERS);
- if (rval) {
- qla_printk(KERN_WARNING, ha, "Unable to initialize "
- "EFT (%d).\n", rval);
- dma_free_coherent(&ha->pdev->dev, EFT_SIZE, tc,
- tc_dma);
- goto cont_alloc;
- }
-
- qla_printk(KERN_INFO, ha, "Allocated (%d KB) for EFT...\n",
- EFT_SIZE / 1024);
-
- eft_size = EFT_SIZE;
- ha->eft_dma = tc_dma;
- ha->eft = tc;
-
/* Allocate memory for Fibre Channel Event Buffer. */
if (!IS_QLA25XX(ha))
- goto cont_alloc;
+ goto try_eft;
tc = dma_alloc_coherent(&ha->pdev->dev, FCE_SIZE, &tc_dma,
GFP_KERNEL);
if (!tc) {
qla_printk(KERN_WARNING, ha, "Unable to allocate "
"(%d KB) for FCE.\n", FCE_SIZE / 1024);
- goto cont_alloc;
+ goto try_eft;
}
memset(tc, 0, FCE_SIZE);
@@ -815,7 +796,7 @@ qla2x00_alloc_fw_dump(scsi_qla_host_t *ha)
dma_free_coherent(&ha->pdev->dev, FCE_SIZE, tc,
tc_dma);
ha->flags.fce_enabled = 0;
- goto cont_alloc;
+ goto try_eft;
}
qla_printk(KERN_INFO, ha, "Allocated (%d KB) for FCE...\n",
@@ -825,6 +806,32 @@ qla2x00_alloc_fw_dump(scsi_qla_host_t *ha)
ha->flags.fce_enabled = 1;
ha->fce_dma = tc_dma;
ha->fce = tc;
+try_eft:
+ /* Allocate memory for Extended Trace Buffer. */
+ tc = dma_alloc_coherent(&ha->pdev->dev, EFT_SIZE, &tc_dma,
+ GFP_KERNEL);
+ if (!tc) {
+ qla_printk(KERN_WARNING, ha, "Unable to allocate "
+ "(%d KB) for EFT.\n", EFT_SIZE / 1024);
+ goto cont_alloc;
+ }
+
+ memset(tc, 0, EFT_SIZE);
+ rval = qla2x00_enable_eft_trace(ha, tc_dma, EFT_NUM_BUFFERS);
+ if (rval) {
+ qla_printk(KERN_WARNING, ha, "Unable to initialize "
+ "EFT (%d).\n", rval);
+ dma_free_coherent(&ha->pdev->dev, EFT_SIZE, tc,
+ tc_dma);
+ goto cont_alloc;
+ }
+
+ qla_printk(KERN_INFO, ha, "Allocated (%d KB) for EFT...\n",
+ EFT_SIZE / 1024);
+
+ eft_size = EFT_SIZE;
+ ha->eft_dma = tc_dma;
+ ha->eft = tc;
}
cont_alloc:
req_q_size = ha->request_q_length * sizeof(request_t);
@@ -969,8 +976,9 @@ qla2x00_setup_chip(scsi_qla_host_t *ha)
&ha->fw_attributes, &ha->fw_memory_size);
qla2x00_resize_request_q(ha);
ha->flags.npiv_supported = 0;
- if ((IS_QLA24XX(ha) || IS_QLA25XX(ha)) &&
- (ha->fw_attributes & BIT_2)) {
+ if ((IS_QLA24XX(ha) || IS_QLA25XX(ha) ||
+ IS_QLA84XX(ha)) &&
+ (ha->fw_attributes & BIT_2)) {
ha->flags.npiv_supported = 1;
if ((!ha->max_npiv_vports) ||
((ha->max_npiv_vports + 1) %
@@ -1501,18 +1509,25 @@ qla2x00_set_model_info(scsi_qla_host_t *ha, uint8_t *model, size_t len, char *de
index = (ha->pdev->subsystem_device & 0xff);
if (ha->pdev->subsystem_vendor == PCI_VENDOR_ID_QLOGIC &&
index < QLA_MODEL_NAMES)
- ha->model_desc = qla2x00_model_name[index * 2 + 1];
+ strncpy(ha->model_desc,
+ qla2x00_model_name[index * 2 + 1],
+ sizeof(ha->model_desc) - 1);
} else {
index = (ha->pdev->subsystem_device & 0xff);
if (ha->pdev->subsystem_vendor == PCI_VENDOR_ID_QLOGIC &&
index < QLA_MODEL_NAMES) {
strcpy(ha->model_number,
qla2x00_model_name[index * 2]);
- ha->model_desc = qla2x00_model_name[index * 2 + 1];
+ strncpy(ha->model_desc,
+ qla2x00_model_name[index * 2 + 1],
+ sizeof(ha->model_desc) - 1);
} else {
strcpy(ha->model_number, def);
}
}
+ if (IS_FWI2_CAPABLE(ha))
+ qla2xxx_get_vpd_field(ha, "\x82", ha->model_desc,
+ sizeof(ha->model_desc));
}
/* On sparc systems, obtain port and node WWN from firmware
@@ -1864,12 +1879,11 @@ qla2x00_rport_del(void *data)
{
fc_port_t *fcport = data;
struct fc_rport *rport;
- unsigned long flags;
- spin_lock_irqsave(&fcport->rport_lock, flags);
+ spin_lock_irq(fcport->ha->host->host_lock);
rport = fcport->drport;
fcport->drport = NULL;
- spin_unlock_irqrestore(&fcport->rport_lock, flags);
+ spin_unlock_irq(fcport->ha->host->host_lock);
if (rport)
fc_remote_port_delete(rport);
}
@@ -1898,7 +1912,6 @@ qla2x00_alloc_fcport(scsi_qla_host_t *ha, gfp_t flags)
atomic_set(&fcport->state, FCS_UNCONFIGURED);
fcport->flags = FCF_RLC_SUPPORT;
fcport->supported_classes = FC_COS_UNSPECIFIED;
- spin_lock_init(&fcport->rport_lock);
return fcport;
}
@@ -2007,8 +2020,10 @@ qla2x00_configure_loop(scsi_qla_host_t *ha)
if (test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags)) {
if (test_bit(LOCAL_LOOP_UPDATE, &save_flags))
set_bit(LOCAL_LOOP_UPDATE, &ha->dpc_flags);
- if (test_bit(RSCN_UPDATE, &save_flags))
+ if (test_bit(RSCN_UPDATE, &save_flags)) {
+ ha->flags.rscn_queue_overflow = 1;
set_bit(RSCN_UPDATE, &ha->dpc_flags);
+ }
}
return (rval);
@@ -2243,28 +2258,24 @@ qla2x00_reg_remote_port(scsi_qla_host_t *ha, fc_port_t *fcport)
{
struct fc_rport_identifiers rport_ids;
struct fc_rport *rport;
- unsigned long flags;
if (fcport->drport)
qla2x00_rport_del(fcport);
- if (fcport->rport)
- return;
rport_ids.node_name = wwn_to_u64(fcport->node_name);
rport_ids.port_name = wwn_to_u64(fcport->port_name);
rport_ids.port_id = fcport->d_id.b.domain << 16 |
fcport->d_id.b.area << 8 | fcport->d_id.b.al_pa;
rport_ids.roles = FC_RPORT_ROLE_UNKNOWN;
- rport = fc_remote_port_add(ha->host, 0, &rport_ids);
+ fcport->rport = rport = fc_remote_port_add(ha->host, 0, &rport_ids);
if (!rport) {
qla_printk(KERN_WARNING, ha,
"Unable to allocate fc remote port!\n");
return;
}
- spin_lock_irqsave(&fcport->rport_lock, flags);
- fcport->rport = rport;
+ spin_lock_irq(fcport->ha->host->host_lock);
*((fc_port_t **)rport->dd_data) = fcport;
- spin_unlock_irqrestore(&fcport->rport_lock, flags);
+ spin_unlock_irq(fcport->ha->host->host_lock);
rport->supported_classes = fcport->supported_classes;
@@ -2565,7 +2576,8 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *ha, struct list_head *new_fcports)
} else if (qla2x00_gnn_id(ha, swl) != QLA_SUCCESS) {
kfree(swl);
swl = NULL;
- } else if (qla2x00_gfpn_id(ha, swl) == QLA_SUCCESS) {
+ } else if (ql2xiidmaenable &&
+ qla2x00_gfpn_id(ha, swl) == QLA_SUCCESS) {
qla2x00_gpsc(ha, swl);
}
}
@@ -3220,7 +3232,8 @@ qla2x00_update_fcports(scsi_qla_host_t *ha)
/* Go with deferred removal of rport references. */
list_for_each_entry(fcport, &ha->fcports, list)
- if (fcport->drport)
+ if (fcport->drport &&
+ atomic_read(&fcport->state) != FCS_UNCONFIGURED)
qla2x00_rport_del(fcport);
}
@@ -3239,10 +3252,12 @@ qla2x00_abort_isp(scsi_qla_host_t *ha)
{
int rval;
uint8_t status = 0;
+ scsi_qla_host_t *vha;
if (ha->flags.online) {
ha->flags.online = 0;
clear_bit(ISP_ABORT_NEEDED, &ha->dpc_flags);
+ ha->qla_stats.total_isp_aborts++;
qla_printk(KERN_INFO, ha,
"Performing ISP error recovery - ha= %p.\n", ha);
@@ -3252,6 +3267,8 @@ qla2x00_abort_isp(scsi_qla_host_t *ha)
if (atomic_read(&ha->loop_state) != LOOP_DOWN) {
atomic_set(&ha->loop_state, LOOP_DOWN);
qla2x00_mark_all_devices_lost(ha, 0);
+ list_for_each_entry(vha, &ha->vp_list, vp_list)
+ qla2x00_mark_all_devices_lost(vha, 0);
} else {
if (!atomic_read(&ha->loop_down_timer))
atomic_set(&ha->loop_down_timer,
@@ -3283,17 +3300,6 @@ qla2x00_abort_isp(scsi_qla_host_t *ha)
ha->isp_abort_cnt = 0;
clear_bit(ISP_ABORT_RETRY, &ha->dpc_flags);
- if (ha->eft) {
- memset(ha->eft, 0, EFT_SIZE);
- rval = qla2x00_enable_eft_trace(ha,
- ha->eft_dma, EFT_NUM_BUFFERS);
- if (rval) {
- qla_printk(KERN_WARNING, ha,
- "Unable to reinitialize EFT "
- "(%d).\n", rval);
- }
- }
-
if (ha->fce) {
ha->flags.fce_enabled = 1;
memset(ha->fce, 0,
@@ -3308,6 +3314,17 @@ qla2x00_abort_isp(scsi_qla_host_t *ha)
ha->flags.fce_enabled = 0;
}
}
+
+ if (ha->eft) {
+ memset(ha->eft, 0, EFT_SIZE);
+ rval = qla2x00_enable_eft_trace(ha,
+ ha->eft_dma, EFT_NUM_BUFFERS);
+ if (rval) {
+ qla_printk(KERN_WARNING, ha,
+ "Unable to reinitialize EFT "
+ "(%d).\n", rval);
+ }
+ }
} else { /* failed the ISP abort */
ha->flags.online = 1;
if (test_bit(ISP_ABORT_RETRY, &ha->dpc_flags)) {
@@ -4026,8 +4043,8 @@ qla2x00_try_to_stop_firmware(scsi_qla_host_t *ha)
ret = qla2x00_stop_firmware(ha);
for (retries = 5; ret != QLA_SUCCESS && ret != QLA_FUNCTION_TIMEOUT &&
retries ; retries--) {
- qla2x00_reset_chip(ha);
- if (qla2x00_chip_diag(ha) != QLA_SUCCESS)
+ ha->isp_ops->reset_chip(ha);
+ if (ha->isp_ops->chip_diag(ha) != QLA_SUCCESS)
continue;
if (qla2x00_setup_chip(ha) != QLA_SUCCESS)
continue;
@@ -4049,7 +4066,7 @@ qla24xx_configure_vhba(scsi_qla_host_t *ha)
rval = qla2x00_fw_ready(ha->parent);
if (rval == QLA_SUCCESS) {
clear_bit(RESET_MARKER_NEEDED, &ha->dpc_flags);
- qla2x00_marker(ha->parent, 0, 0, MK_SYNC_ALL);
+ qla2x00_marker(ha, 0, 0, MK_SYNC_ALL);
}
ha->flags.management_server_logged_in = 0;
diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c
index 5489d5024673..d57669aa4615 100644
--- a/drivers/scsi/qla2xxx/qla_iocb.c
+++ b/drivers/scsi/qla2xxx/qla_iocb.c
@@ -454,10 +454,11 @@ qla2x00_marker(scsi_qla_host_t *ha, uint16_t loop_id, uint16_t lun,
{
int ret;
unsigned long flags = 0;
+ scsi_qla_host_t *pha = to_qla_parent(ha);
- spin_lock_irqsave(&ha->hardware_lock, flags);
+ spin_lock_irqsave(&pha->hardware_lock, flags);
ret = __qla2x00_marker(ha, loop_id, lun, type);
- spin_unlock_irqrestore(&ha->hardware_lock, flags);
+ spin_unlock_irqrestore(&pha->hardware_lock, flags);
return (ret);
}
@@ -672,7 +673,7 @@ qla24xx_start_scsi(srb_t *sp)
{
int ret, nseg;
unsigned long flags;
- scsi_qla_host_t *ha;
+ scsi_qla_host_t *ha, *pha;
struct scsi_cmnd *cmd;
uint32_t *clr_ptr;
uint32_t index;
@@ -686,6 +687,7 @@ qla24xx_start_scsi(srb_t *sp)
/* Setup device pointers. */
ret = 0;
ha = sp->ha;
+ pha = to_qla_parent(ha);
reg = &ha->iobase->isp24;
cmd = sp->cmd;
/* So we know we haven't pci_map'ed anything yet */
@@ -700,7 +702,7 @@ qla24xx_start_scsi(srb_t *sp)
}
/* Acquire ring specific lock */
- spin_lock_irqsave(&ha->hardware_lock, flags);
+ spin_lock_irqsave(&pha->hardware_lock, flags);
/* Check for room in outstanding command list. */
handle = ha->current_outstanding_cmd;
@@ -795,14 +797,14 @@ qla24xx_start_scsi(srb_t *sp)
ha->response_ring_ptr->signature != RESPONSE_PROCESSED)
qla24xx_process_response_queue(ha);
- spin_unlock_irqrestore(&ha->hardware_lock, flags);
+ spin_unlock_irqrestore(&pha->hardware_lock, flags);
return QLA_SUCCESS;
queuing_error:
if (tot_dsds)
scsi_dma_unmap(cmd);
- spin_unlock_irqrestore(&ha->hardware_lock, flags);
+ spin_unlock_irqrestore(&pha->hardware_lock, flags);
return QLA_FUNCTION_FAILED;
}
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
index ec63b79f900a..45a3b93eed57 100644
--- a/drivers/scsi/qla2xxx/qla_isr.c
+++ b/drivers/scsi/qla2xxx/qla_isr.c
@@ -542,10 +542,6 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb)
break;
case MBA_PORT_UPDATE: /* Port database update */
- /* Only handle SCNs for our Vport index. */
- if (ha->parent && ha->vp_idx != (mb[3] & 0xff))
- break;
-
/*
* If PORT UPDATE is global (recieved LIP_OCCURED/LIP_RESET
* event etc. earlier indicating loop is down) then process
@@ -883,11 +879,12 @@ qla2x00_handle_sense(srb_t *sp, uint8_t *sense_data, uint32_t sense_len)
sp->request_sense_ptr += sense_len;
sp->request_sense_length -= sense_len;
if (sp->request_sense_length != 0)
- sp->ha->status_srb = sp;
+ sp->fcport->ha->status_srb = sp;
DEBUG5(printk("%s(): Check condition Sense data, scsi(%ld:%d:%d:%d) "
- "cmd=%p pid=%ld\n", __func__, sp->ha->host_no, cp->device->channel,
- cp->device->id, cp->device->lun, cp, cp->serial_number));
+ "cmd=%p pid=%ld\n", __func__, sp->fcport->ha->host_no,
+ cp->device->channel, cp->device->id, cp->device->lun, cp,
+ cp->serial_number));
if (sense_len)
DEBUG5(qla2x00_dump_buffer(cp->sense_buffer,
CMD_ACTUAL_SNSLEN(cp)));
@@ -1188,9 +1185,8 @@ qla2x00_status_entry(scsi_qla_host_t *ha, void *pkt)
atomic_read(&fcport->state)));
cp->result = DID_BUS_BUSY << 16;
- if (atomic_read(&fcport->state) == FCS_ONLINE) {
- qla2x00_mark_device_lost(ha, fcport, 1, 1);
- }
+ if (atomic_read(&fcport->state) == FCS_ONLINE)
+ qla2x00_mark_device_lost(fcport->ha, fcport, 1, 1);
break;
case CS_RESET:
@@ -1233,7 +1229,7 @@ qla2x00_status_entry(scsi_qla_host_t *ha, void *pkt)
/* Check to see if logout occurred. */
if ((le16_to_cpu(sts->status_flags) & SF_LOGOUT_SENT))
- qla2x00_mark_device_lost(ha, fcport, 1, 1);
+ qla2x00_mark_device_lost(fcport->ha, fcport, 1, 1);
break;
default:
diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c
index 250d2f604397..813bc7784c0a 100644
--- a/drivers/scsi/qla2xxx/qla_mbx.c
+++ b/drivers/scsi/qla2xxx/qla_mbx.c
@@ -918,6 +918,8 @@ qla2x00_get_adapter_id(scsi_qla_host_t *ha, uint16_t *id, uint8_t *al_pa,
rval = qla2x00_mailbox_command(ha, mcp);
if (mcp->mb[0] == MBS_COMMAND_ERROR)
rval = QLA_COMMAND_ERROR;
+ else if (mcp->mb[0] == MBS_INVALID_COMMAND)
+ rval = QLA_INVALID_COMMAND;
/* Return data. */
*id = mcp->mb[1];
@@ -2161,17 +2163,18 @@ qla24xx_abort_command(scsi_qla_host_t *ha, srb_t *sp)
struct abort_entry_24xx *abt;
dma_addr_t abt_dma;
uint32_t handle;
+ scsi_qla_host_t *pha = to_qla_parent(ha);
DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no));
fcport = sp->fcport;
- spin_lock_irqsave(&ha->hardware_lock, flags);
+ spin_lock_irqsave(&pha->hardware_lock, flags);
for (handle = 1; handle < MAX_OUTSTANDING_COMMANDS; handle++) {
- if (ha->outstanding_cmds[handle] == sp)
+ if (pha->outstanding_cmds[handle] == sp)
break;
}
- spin_unlock_irqrestore(&ha->hardware_lock, flags);
+ spin_unlock_irqrestore(&pha->hardware_lock, flags);
if (handle == MAX_OUTSTANDING_COMMANDS) {
/* Command not found. */
return QLA_FUNCTION_FAILED;
@@ -2683,7 +2686,7 @@ qla24xx_report_id_acquisition(scsi_qla_host_t *ha,
set_bit(VP_IDX_ACQUIRED, &vha->vp_flags);
set_bit(VP_DPC_NEEDED, &ha->dpc_flags);
- wake_up_process(ha->dpc_thread);
+ qla2xxx_wake_dpc(ha);
}
}
diff --git a/drivers/scsi/qla2xxx/qla_mid.c b/drivers/scsi/qla2xxx/qla_mid.c
index 62a3ad6e8ecb..93560cd72784 100644
--- a/drivers/scsi/qla2xxx/qla_mid.c
+++ b/drivers/scsi/qla2xxx/qla_mid.c
@@ -6,7 +6,6 @@
*/
#include "qla_def.h"
-#include <linux/version.h>
#include <linux/moduleparam.h>
#include <linux/vmalloc.h>
#include <linux/smp_lock.h>
@@ -43,6 +42,7 @@ qla24xx_allocate_vp_id(scsi_qla_host_t *vha)
set_bit(vp_id, ha->vp_idx_map);
ha->num_vhosts++;
+ ha->cur_vport_count++;
vha->vp_idx = vp_id;
list_add_tail(&vha->vp_list, &ha->vp_list);
mutex_unlock(&ha->vport_lock);
@@ -58,6 +58,7 @@ qla24xx_deallocate_vp_id(scsi_qla_host_t *vha)
mutex_lock(&ha->vport_lock);
vp_id = vha->vp_idx;
ha->num_vhosts--;
+ ha->cur_vport_count--;
clear_bit(vp_id, ha->vp_idx_map);
list_del(&vha->vp_list);
mutex_unlock(&ha->vport_lock);
@@ -103,8 +104,8 @@ qla2x00_mark_vp_devices_dead(scsi_qla_host_t *vha)
"loop_id=0x%04x :%x\n",
vha->host_no, fcport->loop_id, fcport->vp_idx));
- atomic_set(&fcport->state, FCS_DEVICE_DEAD);
qla2x00_mark_device_lost(vha, fcport, 0, 0);
+ atomic_set(&fcport->state, FCS_UNCONFIGURED);
}
}
@@ -276,7 +277,8 @@ qla2x00_do_dpc_vp(scsi_qla_host_t *vha)
clear_bit(RESET_ACTIVE, &vha->dpc_flags);
}
- if (test_and_clear_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags)) {
+ if (atomic_read(&vha->vp_state) == VP_ACTIVE &&
+ test_and_clear_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags)) {
if (!(test_and_set_bit(LOOP_RESYNC_ACTIVE, &vha->dpc_flags))) {
qla2x00_loop_resync(vha);
clear_bit(LOOP_RESYNC_ACTIVE, &vha->dpc_flags);
@@ -390,7 +392,6 @@ qla24xx_create_vhost(struct fc_vport *fc_vport)
vha->parent = ha;
vha->fc_vport = fc_vport;
vha->device_flags = 0;
- vha->instance = num_hosts;
vha->vp_idx = qla24xx_allocate_vp_id(vha);
if (vha->vp_idx > ha->max_npiv_vports) {
DEBUG15(printk("scsi(%ld): Couldn't allocate vp_id.\n",
@@ -428,7 +429,7 @@ qla24xx_create_vhost(struct fc_vport *fc_vport)
host->max_cmd_len = MAX_CMDSZ;
host->max_channel = MAX_BUSES - 1;
host->max_lun = MAX_LUNS;
- host->unique_id = vha->instance;
+ host->unique_id = host->host_no;
host->max_id = MAX_TARGETS_2200;
host->transportt = qla2xxx_transport_vport_template;
@@ -436,12 +437,6 @@ qla24xx_create_vhost(struct fc_vport *fc_vport)
vha->host_no, vha));
vha->flags.init_done = 1;
- num_hosts++;
-
- mutex_lock(&ha->vport_lock);
- set_bit(vha->vp_idx, ha->vp_idx_map);
- ha->cur_vport_count++;
- mutex_unlock(&ha->vport_lock);
return vha;
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index 48eaa3bb5433..26afe44265c7 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -27,7 +27,6 @@ char qla2x00_version_str[40];
*/
static struct kmem_cache *srb_cachep;
-int num_hosts;
int ql2xlogintimeout = 20;
module_param(ql2xlogintimeout, int, S_IRUGO|S_IRUSR);
MODULE_PARM_DESC(ql2xlogintimeout,
@@ -87,6 +86,13 @@ MODULE_PARM_DESC(ql2xqfullrampup,
"depth for a device after a queue-full condition has been "
"detected. Default is 120 seconds.");
+int ql2xiidmaenable=1;
+module_param(ql2xiidmaenable, int, S_IRUGO|S_IRUSR);
+MODULE_PARM_DESC(ql2xiidmaenable,
+ "Enables iIDMA settings "
+ "Default is 1 - perform iIDMA. 0 - no iIDMA.");
+
+
/*
* SCSI host template entry points
*/
@@ -388,7 +394,7 @@ qla2x00_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
}
/* Close window on fcport/rport state-transitioning. */
- if (!*(fc_port_t **)rport->dd_data) {
+ if (fcport->drport) {
cmd->result = DID_IMM_RETRY << 16;
goto qc_fail_command;
}
@@ -443,7 +449,7 @@ qla24xx_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
int rval;
scsi_qla_host_t *pha = to_qla_parent(ha);
- if (unlikely(pci_channel_offline(ha->pdev))) {
+ if (unlikely(pci_channel_offline(pha->pdev))) {
cmd->result = DID_REQUEUE << 16;
goto qc24_fail_command;
}
@@ -455,7 +461,7 @@ qla24xx_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
}
/* Close window on fcport/rport state-transitioning. */
- if (!*(fc_port_t **)rport->dd_data) {
+ if (fcport->drport) {
cmd->result = DID_IMM_RETRY << 16;
goto qc24_fail_command;
}
@@ -617,6 +623,40 @@ qla2x00_wait_for_loop_ready(scsi_qla_host_t *ha)
return (return_status);
}
+void
+qla2x00_abort_fcport_cmds(fc_port_t *fcport)
+{
+ int cnt;
+ unsigned long flags;
+ srb_t *sp;
+ scsi_qla_host_t *ha = fcport->ha;
+ scsi_qla_host_t *pha = to_qla_parent(ha);
+
+ spin_lock_irqsave(&pha->hardware_lock, flags);
+ for (cnt = 1; cnt < MAX_OUTSTANDING_COMMANDS; cnt++) {
+ sp = pha->outstanding_cmds[cnt];
+ if (!sp)
+ continue;
+ if (sp->fcport != fcport)
+ continue;
+
+ spin_unlock_irqrestore(&pha->hardware_lock, flags);
+ if (ha->isp_ops->abort_command(ha, sp)) {
+ DEBUG2(qla_printk(KERN_WARNING, ha,
+ "Abort failed -- %lx\n", sp->cmd->serial_number));
+ } else {
+ if (qla2x00_eh_wait_on_command(ha, sp->cmd) !=
+ QLA_SUCCESS)
+ DEBUG2(qla_printk(KERN_WARNING, ha,
+ "Abort failed while waiting -- %lx\n",
+ sp->cmd->serial_number));
+
+ }
+ spin_lock_irqsave(&pha->hardware_lock, flags);
+ }
+ spin_unlock_irqrestore(&pha->hardware_lock, flags);
+}
+
static void
qla2x00_block_error_handler(struct scsi_cmnd *cmnd)
{
@@ -740,7 +780,8 @@ qla2x00_eh_wait_for_pending_commands(scsi_qla_host_t *ha, unsigned int t,
sp = pha->outstanding_cmds[cnt];
if (!sp)
continue;
- if (ha->vp_idx != sp->ha->vp_idx)
+
+ if (ha->vp_idx != sp->fcport->ha->vp_idx)
continue;
match = 0;
switch (type) {
@@ -1040,9 +1081,7 @@ qla2x00_abort_all_cmds(scsi_qla_host_t *ha, int res)
sp = ha->outstanding_cmds[cnt];
if (sp) {
ha->outstanding_cmds[cnt] = NULL;
- sp->flags = 0;
sp->cmd->result = res;
- sp->cmd->host_scribble = (unsigned char *)NULL;
qla2x00_sp_compl(ha, sp);
}
}
@@ -1073,7 +1112,7 @@ qla2xxx_slave_configure(struct scsi_device *sdev)
else
scsi_deactivate_tcq(sdev, ha->max_q_depth);
- rport->dev_loss_tmo = ha->port_down_retry_count + 5;
+ rport->dev_loss_tmo = ha->port_down_retry_count;
return 0;
}
@@ -1629,9 +1668,6 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
}
host->can_queue = ha->request_q_length + 128;
- /* load the F/W, read paramaters, and init the H/W */
- ha->instance = num_hosts;
-
mutex_init(&ha->vport_lock);
init_completion(&ha->mbx_cmd_comp);
complete(&ha->mbx_cmd_comp);
@@ -1679,7 +1715,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
host->this_id = 255;
host->cmd_per_lun = 3;
- host->unique_id = ha->instance;
+ host->unique_id = host->host_no;
host->max_cmd_len = MAX_CMDSZ;
host->max_channel = MAX_BUSES - 1;
host->max_lun = MAX_LUNS;
@@ -1700,8 +1736,6 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
ha->flags.init_done = 1;
ha->flags.online = 1;
- num_hosts++;
-
ret = scsi_add_host(host, &pdev->dev);
if (ret)
goto probe_failed;
@@ -1741,10 +1775,15 @@ probe_out:
static void
qla2x00_remove_one(struct pci_dev *pdev)
{
- scsi_qla_host_t *ha;
+ scsi_qla_host_t *ha, *vha, *temp;
ha = pci_get_drvdata(pdev);
+ list_for_each_entry_safe(vha, temp, &ha->vp_list, vp_list)
+ fc_vport_terminate(vha->fc_vport);
+
+ set_bit(UNLOADING, &ha->dpc_flags);
+
qla2x00_dfs_remove(ha);
qla84xx_put_chip(ha);
@@ -1813,27 +1852,21 @@ static inline void
qla2x00_schedule_rport_del(struct scsi_qla_host *ha, fc_port_t *fcport,
int defer)
{
- unsigned long flags;
struct fc_rport *rport;
+ scsi_qla_host_t *pha = to_qla_parent(ha);
if (!fcport->rport)
return;
rport = fcport->rport;
if (defer) {
- spin_lock_irqsave(&fcport->rport_lock, flags);
+ spin_lock_irq(ha->host->host_lock);
fcport->drport = rport;
- fcport->rport = NULL;
- *(fc_port_t **)rport->dd_data = NULL;
- spin_unlock_irqrestore(&fcport->rport_lock, flags);
- set_bit(FCPORT_UPDATE_NEEDED, &ha->dpc_flags);
- } else {
- spin_lock_irqsave(&fcport->rport_lock, flags);
- fcport->rport = NULL;
- *(fc_port_t **)rport->dd_data = NULL;
- spin_unlock_irqrestore(&fcport->rport_lock, flags);
+ spin_unlock_irq(ha->host->host_lock);
+ set_bit(FCPORT_UPDATE_NEEDED, &pha->dpc_flags);
+ qla2xxx_wake_dpc(pha);
+ } else
fc_remote_port_delete(rport);
- }
}
/*
@@ -1903,7 +1936,7 @@ qla2x00_mark_all_devices_lost(scsi_qla_host_t *ha, int defer)
scsi_qla_host_t *pha = to_qla_parent(ha);
list_for_each_entry(fcport, &pha->fcports, list) {
- if (ha->vp_idx != 0 && ha->vp_idx != fcport->vp_idx)
+ if (ha->vp_idx != fcport->vp_idx)
continue;
/*
* No point in marking the device as lost, if the device is
@@ -1911,17 +1944,10 @@ qla2x00_mark_all_devices_lost(scsi_qla_host_t *ha, int defer)
*/
if (atomic_read(&fcport->state) == FCS_DEVICE_DEAD)
continue;
- if (atomic_read(&fcport->state) == FCS_ONLINE) {
- if (defer)
- qla2x00_schedule_rport_del(ha, fcport, defer);
- else if (ha->vp_idx == fcport->vp_idx)
- qla2x00_schedule_rport_del(ha, fcport, defer);
- }
+ if (atomic_read(&fcport->state) == FCS_ONLINE)
+ qla2x00_schedule_rport_del(ha, fcport, defer);
atomic_set(&fcport->state, FCS_DEVICE_LOST);
}
-
- if (defer)
- qla2xxx_wake_dpc(ha);
}
/*
@@ -2156,7 +2182,7 @@ qla2x00_alloc_work(struct scsi_qla_host *ha, enum qla_work_type type,
static int
qla2x00_post_work(struct scsi_qla_host *ha, struct qla_work_evt *e, int locked)
{
- unsigned long flags;
+ unsigned long uninitialized_var(flags);
scsi_qla_host_t *pha = to_qla_parent(ha);
if (!locked)
@@ -2313,8 +2339,10 @@ qla2x00_do_dpc(void *data)
ha->host_no));
}
- if (test_and_clear_bit(FCPORT_UPDATE_NEEDED, &ha->dpc_flags))
+ if (test_bit(FCPORT_UPDATE_NEEDED, &ha->dpc_flags)) {
qla2x00_update_fcports(ha);
+ clear_bit(FCPORT_UPDATE_NEEDED, &ha->dpc_flags);
+ }
if (test_and_clear_bit(RESET_MARKER_NEEDED, &ha->dpc_flags) &&
(!(test_and_set_bit(RESET_ACTIVE, &ha->dpc_flags)))) {
@@ -2427,8 +2455,10 @@ qla2x00_do_dpc(void *data)
void
qla2xxx_wake_dpc(scsi_qla_host_t *ha)
{
- if (ha->dpc_thread)
- wake_up_process(ha->dpc_thread);
+ struct task_struct *t = ha->dpc_thread;
+
+ if (!test_bit(UNLOADING, &ha->dpc_flags) && t)
+ wake_up_process(t);
}
/*
diff --git a/drivers/scsi/qla2xxx/qla_sup.c b/drivers/scsi/qla2xxx/qla_sup.c
index 1728ab3ccb20..1bca74474935 100644
--- a/drivers/scsi/qla2xxx/qla_sup.c
+++ b/drivers/scsi/qla2xxx/qla_sup.c
@@ -869,11 +869,9 @@ qla24xx_write_nvram_data(scsi_qla_host_t *ha, uint8_t *buf, uint32_t naddr,
uint32_t i;
uint32_t *dwptr;
struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
- unsigned long flags;
ret = QLA_SUCCESS;
- spin_lock_irqsave(&ha->hardware_lock, flags);
/* Enable flash write. */
WRT_REG_DWORD(&reg->ctrl_status,
RD_REG_DWORD(&reg->ctrl_status) | CSRX_FLASH_ENABLE);
@@ -907,7 +905,6 @@ qla24xx_write_nvram_data(scsi_qla_host_t *ha, uint8_t *buf, uint32_t naddr,
WRT_REG_DWORD(&reg->ctrl_status,
RD_REG_DWORD(&reg->ctrl_status) & ~CSRX_FLASH_ENABLE);
RD_REG_DWORD(&reg->ctrl_status); /* PCI Posting. */
- spin_unlock_irqrestore(&ha->hardware_lock, flags);
return ret;
}
@@ -2306,6 +2303,51 @@ qla24xx_get_flash_version(scsi_qla_host_t *ha, void *mbuf)
}
static int
+qla2xxx_is_vpd_valid(uint8_t *pos, uint8_t *end)
+{
+ if (pos >= end || *pos != 0x82)
+ return 0;
+
+ pos += 3 + pos[1];
+ if (pos >= end || *pos != 0x90)
+ return 0;
+
+ pos += 3 + pos[1];
+ if (pos >= end || *pos != 0x78)
+ return 0;
+
+ return 1;
+}
+
+int
+qla2xxx_get_vpd_field(scsi_qla_host_t *ha, char *key, char *str, size_t size)
+{
+ uint8_t *pos = ha->vpd;
+ uint8_t *end = pos + ha->vpd_size;
+ int len = 0;
+
+ if (!IS_FWI2_CAPABLE(ha) || !qla2xxx_is_vpd_valid(pos, end))
+ return 0;
+
+ while (pos < end && *pos != 0x78) {
+ len = (*pos == 0x82) ? pos[1] : pos[2];
+
+ if (!strncmp(pos, key, strlen(key)))
+ break;
+
+ if (*pos != 0x90 && *pos != 0x91)
+ pos += len;
+
+ pos += 3;
+ }
+
+ if (pos < end - len && *pos != 0x78)
+ return snprintf(str, size, "%.*s", len, pos + 3);
+
+ return 0;
+}
+
+static int
qla2xxx_hw_event_store(scsi_qla_host_t *ha, uint32_t *fdata)
{
uint32_t d[2], faddr;
diff --git a/drivers/scsi/qla2xxx/qla_version.h b/drivers/scsi/qla2xxx/qla_version.h
index d058c8862b35..4160e4caa7b9 100644
--- a/drivers/scsi/qla2xxx/qla_version.h
+++ b/drivers/scsi/qla2xxx/qla_version.h
@@ -7,7 +7,7 @@
/*
* Driver version
*/
-#define QLA2XXX_VERSION "8.02.01-k4"
+#define QLA2XXX_VERSION "8.02.01-k7"
#define QLA_DRIVER_MAJOR_VER 8
#define QLA_DRIVER_MINOR_VER 2