summaryrefslogtreecommitdiffstats
path: root/drivers/scsi/qla2xxx
diff options
context:
space:
mode:
authorAnirban Chakraborty <anirban.chakraborty@qlogic.com>2009-08-05 18:18:40 +0200
committerJames Bottomley <James.Bottomley@suse.de>2009-08-23 00:52:20 +0200
commit7163ea815170f8c5d56ead27d7e6fa3fa1f9844b (patch)
treef85fafb74828242c1be343caa020a45753ec1dfa /drivers/scsi/qla2xxx
parent[SCSI] qla2xxx: Correct display of vp_count in debug printk. (diff)
downloadlinux-7163ea815170f8c5d56ead27d7e6fa3fa1f9844b.tar.xz
linux-7163ea815170f8c5d56ead27d7e6fa3fa1f9844b.zip
[SCSI] qla2xxx: Fix to ensure driver works in sinlge queue mode if multiqueue fails
When the multiqueue mode fails to work, the driver falls back on single queue mode. This ensures that the firmware is reinitialized with single queue options and all the resources are readjusted accordingly. Signed-off-by: Anirban Chakraborty <anirban.chakraborty@qlogic.com> Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com> Signed-off-by: James Bottomley <James.Bottomley@suse.de>
Diffstat (limited to 'drivers/scsi/qla2xxx')
-rw-r--r--drivers/scsi/qla2xxx/qla_attr.c4
-rw-r--r--drivers/scsi/qla2xxx/qla_def.h1
-rw-r--r--drivers/scsi/qla2xxx/qla_init.c5
-rw-r--r--drivers/scsi/qla2xxx/qla_iocb.c2
-rw-r--r--drivers/scsi/qla2xxx/qla_mbx.c4
-rw-r--r--drivers/scsi/qla2xxx/qla_os.c23
6 files changed, 27 insertions, 12 deletions
diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c
index 0f8796201504..5b0a222241bb 100644
--- a/drivers/scsi/qla2xxx/qla_attr.c
+++ b/drivers/scsi/qla2xxx/qla_attr.c
@@ -1670,7 +1670,7 @@ qla24xx_vport_create(struct fc_vport *fc_vport, bool disable)
qla24xx_vport_disable(fc_vport, disable);
- if (ql2xmultique_tag) {
+ if (ha->flags.cpu_affinity_enabled) {
req = ha->req_q_map[1];
goto vport_queue;
} else if (ql2xmaxqueues == 1 || !ha->npiv_info)
@@ -1743,7 +1743,7 @@ qla24xx_vport_delete(struct fc_vport *fc_vport)
vha->host_no, vha->vp_idx, vha));
}
- if (vha->req->id && !ql2xmultique_tag) {
+ if (vha->req->id && !ha->flags.cpu_affinity_enabled) {
if (qla25xx_delete_req_que(vha, vha->req) != QLA_SUCCESS)
qla_printk(KERN_WARNING, ha,
"Queue delete failed.\n");
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index 9fde8bfe7607..68ab28c8152b 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -2224,6 +2224,7 @@ struct qla_hw_data {
uint32_t chip_reset_done :1;
uint32_t port0 :1;
uint32_t running_gold_fw :1;
+ uint32_t cpu_affinity_enabled :1;
} flags;
/* This spinlock is used to protect "io transactions", you must
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index f2ce8e3cc91b..0cbe39e92506 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -987,7 +987,6 @@ qla2x00_setup_chip(scsi_qla_host_t *vha)
ha->phy_version);
if (rval != QLA_SUCCESS)
goto failed;
-
ha->flags.npiv_supported = 0;
if (IS_QLA2XXX_MIDTYPE(ha) &&
(ha->fw_attributes & BIT_2)) {
@@ -3244,7 +3243,7 @@ qla2x00_loop_resync(scsi_qla_host_t *vha)
struct req_que *req;
struct rsp_que *rsp;
- if (ql2xmultique_tag)
+ if (vha->hw->flags.cpu_affinity_enabled)
req = vha->hw->req_q_map[0];
else
req = vha->req;
@@ -4264,7 +4263,7 @@ qla24xx_configure_vhba(scsi_qla_host_t *vha)
return -EINVAL;
rval = qla2x00_fw_ready(base_vha);
- if (ql2xmultique_tag)
+ if (ha->flags.cpu_affinity_enabled)
req = ha->req_q_map[0];
else
req = vha->req;
diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c
index 13396beae2ce..c0ba370b23cf 100644
--- a/drivers/scsi/qla2xxx/qla_iocb.c
+++ b/drivers/scsi/qla2xxx/qla_iocb.c
@@ -852,7 +852,7 @@ static void qla25xx_set_que(srb_t *sp, struct rsp_que **rsp)
struct qla_hw_data *ha = sp->fcport->vha->hw;
int affinity = cmd->request->cpu;
- if (ql2xmultique_tag && affinity >= 0 &&
+ if (ha->flags.cpu_affinity_enabled && affinity >= 0 &&
affinity < ha->max_rsp_queues - 1)
*rsp = ha->rsp_q_map[affinity + 1];
else
diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c
index 8fcd99eeec00..b6202fe118ac 100644
--- a/drivers/scsi/qla2xxx/qla_mbx.c
+++ b/drivers/scsi/qla2xxx/qla_mbx.c
@@ -1507,7 +1507,7 @@ qla24xx_login_fabric(scsi_qla_host_t *vha, uint16_t loop_id, uint8_t domain,
DEBUG11(printk("%s(%ld): entered.\n", __func__, vha->host_no));
- if (ql2xmultique_tag)
+ if (ha->flags.cpu_affinity_enabled)
req = ha->req_q_map[0];
else
req = vha->req;
@@ -2324,7 +2324,7 @@ __qla24xx_issue_tmf(char *name, uint32_t type, struct fc_port *fcport,
vha = fcport->vha;
ha = vha->hw;
req = vha->req;
- if (ql2xmultique_tag)
+ if (ha->flags.cpu_affinity_enabled)
rsp = ha->rsp_q_map[tag + 1];
else
rsp = req->rsp;
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index f0396e79b6fa..d7b271339a5c 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -287,9 +287,12 @@ static int qla25xx_setup_mode(struct scsi_qla_host *vha)
int ques, req, ret;
struct qla_hw_data *ha = vha->hw;
+ if (!(ha->fw_attributes & BIT_6)) {
+ qla_printk(KERN_INFO, ha,
+ "Firmware is not multi-queue capable\n");
+ goto fail;
+ }
if (ql2xmultique_tag) {
- /* CPU affinity mode */
- ha->wq = create_workqueue("qla2xxx_wq");
/* create a request queue for IO */
options |= BIT_7;
req = qla25xx_create_req_que(ha, options, 0, 0, -1,
@@ -299,6 +302,7 @@ static int qla25xx_setup_mode(struct scsi_qla_host *vha)
"Can't create request queue\n");
goto fail;
}
+ ha->wq = create_workqueue("qla2xxx_wq");
vha->req = ha->req_q_map[req];
options |= BIT_1;
for (ques = 1; ques < ha->max_rsp_queues; ques++) {
@@ -309,6 +313,8 @@ static int qla25xx_setup_mode(struct scsi_qla_host *vha)
goto fail2;
}
}
+ ha->flags.cpu_affinity_enabled = 1;
+
DEBUG2(qla_printk(KERN_INFO, ha,
"CPU affinity mode enabled, no. of response"
" queues:%d, no. of request queues:%d\n",
@@ -317,8 +323,13 @@ static int qla25xx_setup_mode(struct scsi_qla_host *vha)
return 0;
fail2:
qla25xx_delete_queues(vha);
+ destroy_workqueue(ha->wq);
+ ha->wq = NULL;
fail:
ha->mqenable = 0;
+ kfree(ha->req_q_map);
+ kfree(ha->rsp_q_map);
+ ha->max_req_queues = ha->max_rsp_queues = 1;
return 1;
}
@@ -1923,6 +1934,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
if (ret)
goto probe_init_failed;
/* Alloc arrays of request and response ring ptrs */
+que_init:
if (!qla2x00_alloc_queues(ha)) {
qla_printk(KERN_WARNING, ha,
"[ERROR] Failed to allocate memory for queue"
@@ -1959,11 +1971,14 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
goto probe_failed;
}
- if (ha->mqenable)
- if (qla25xx_setup_mode(base_vha))
+ if (ha->mqenable) {
+ if (qla25xx_setup_mode(base_vha)) {
qla_printk(KERN_WARNING, ha,
"Can't create queues, falling back to single"
" queue mode\n");
+ goto que_init;
+ }
+ }
if (ha->flags.running_gold_fw)
goto skip_dpc;