aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/qla2xxx
diff options
context:
space:
mode:
authorAnirban Chakraborty <anirban.chakraborty@qlogic.com>2009-04-07 01:33:41 -0400
committerJames Bottomley <James.Bottomley@HansenPartnership.com>2009-05-20 18:21:08 -0400
commit68ca949cdb04b4dc71451a999148fbc5f187a220 (patch)
treed1d06940e8f128804529386ccea9c0757e61db0f /drivers/scsi/qla2xxx
parent2afa19a9377ca61b9489e44bf50029574fbe63be (diff)
[SCSI] qla2xxx: Add CPU affinity support.
Set the module parameter ql2xmultique_tag to 1 to enable this feature. In this mode, the total number of response queues created is equal to the number of online cpus. Turning the block layer's rq_affinity mode on enables requests to be routed to the proper cpu and at the same time it enables completion of the IO in a response queue that is affined to the cpu in the request path. Signed-off-by: Anirban Chakraborty <anirban.chakraborty@qlogic.com> Signed-off-by: Andrew Vasquez <andrew.vasquez@qlogic.com> Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
Diffstat (limited to 'drivers/scsi/qla2xxx')
-rw-r--r--drivers/scsi/qla2xxx/qla_attr.c4
-rw-r--r--drivers/scsi/qla2xxx/qla_def.h2
-rw-r--r--drivers/scsi/qla2xxx/qla_iocb.c22
-rw-r--r--drivers/scsi/qla2xxx/qla_isr.c22
-rw-r--r--drivers/scsi/qla2xxx/qla_mbx.c10
-rw-r--r--drivers/scsi/qla2xxx/qla_mid.c11
-rw-r--r--drivers/scsi/qla2xxx/qla_os.c78
7 files changed, 140 insertions, 9 deletions
diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c
index bda6658d4fbf..f3536e56dce4 100644
--- a/drivers/scsi/qla2xxx/qla_attr.c
+++ b/drivers/scsi/qla2xxx/qla_attr.c
@@ -1531,7 +1531,7 @@ qla24xx_vport_create(struct fc_vport *fc_vport, bool disable)
1531 qla24xx_vport_disable(fc_vport, disable); 1531 qla24xx_vport_disable(fc_vport, disable);
1532 1532
1533 ret = 0; 1533 ret = 0;
1534 if (ha->cur_vport_count <= ha->flex_port_count 1534 if (ha->cur_vport_count <= ha->flex_port_count || ql2xmultique_tag
1535 || ha->max_req_queues == 1 || !ha->npiv_info) 1535 || ha->max_req_queues == 1 || !ha->npiv_info)
1536 goto vport_queue; 1536 goto vport_queue;
1537 /* Create a request queue in QoS mode for the vport */ 1537 /* Create a request queue in QoS mode for the vport */
@@ -1599,7 +1599,7 @@ qla24xx_vport_delete(struct fc_vport *fc_vport)
1599 vha->host_no, vha->vp_idx, vha)); 1599 vha->host_no, vha->vp_idx, vha));
1600 } 1600 }
1601 1601
1602 if (vha->req->id) { 1602 if (vha->req->id && !ql2xmultique_tag) {
1603 if (qla25xx_delete_req_que(vha, vha->req) != QLA_SUCCESS) 1603 if (qla25xx_delete_req_que(vha, vha->req) != QLA_SUCCESS)
1604 qla_printk(KERN_WARNING, ha, 1604 qla_printk(KERN_WARNING, ha,
1605 "Queue delete failed.\n"); 1605 "Queue delete failed.\n");
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index 57d659cf99ee..09190ba411fd 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -2171,6 +2171,7 @@ struct rsp_que {
2171 struct qla_msix_entry *msix; 2171 struct qla_msix_entry *msix;
2172 struct req_que *req; 2172 struct req_que *req;
2173 srb_t *status_srb; /* status continuation entry */ 2173 srb_t *status_srb; /* status continuation entry */
2174 struct work_struct q_work;
2174}; 2175};
2175 2176
2176/* Request queue data structure */ 2177/* Request queue data structure */
@@ -2539,6 +2540,7 @@ struct qla_hw_data {
2539 struct qla_chip_state_84xx *cs84xx; 2540 struct qla_chip_state_84xx *cs84xx;
2540 struct qla_statistics qla_stats; 2541 struct qla_statistics qla_stats;
2541 struct isp_operations *isp_ops; 2542 struct isp_operations *isp_ops;
2543 struct workqueue_struct *wq;
2542}; 2544};
2543 2545
2544/* 2546/*
diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c
index 94b69d86482d..7b15ded991cb 100644
--- a/drivers/scsi/qla2xxx/qla_iocb.c
+++ b/drivers/scsi/qla2xxx/qla_iocb.c
@@ -15,6 +15,7 @@ static request_t *qla2x00_req_pkt(struct scsi_qla_host *, struct req_que *,
15 struct rsp_que *rsp); 15 struct rsp_que *rsp);
16static void qla2x00_isp_cmd(struct scsi_qla_host *, struct req_que *); 16static void qla2x00_isp_cmd(struct scsi_qla_host *, struct req_que *);
17 17
18static void qla25xx_set_que(srb_t *, struct req_que **, struct rsp_que **);
18/** 19/**
19 * qla2x00_get_cmd_direction() - Determine control_flag data direction. 20 * qla2x00_get_cmd_direction() - Determine control_flag data direction.
20 * @cmd: SCSI command 21 * @cmd: SCSI command
@@ -726,8 +727,7 @@ qla24xx_start_scsi(srb_t *sp)
726 /* Setup device pointers. */ 727 /* Setup device pointers. */
727 ret = 0; 728 ret = 0;
728 729
729 req = vha->req; 730 qla25xx_set_que(sp, &req, &rsp);
730 rsp = ha->rsp_q_map[0];
731 sp->que = req; 731 sp->que = req;
732 732
733 /* So we know we haven't pci_map'ed anything yet */ 733 /* So we know we haven't pci_map'ed anything yet */
@@ -850,3 +850,21 @@ queuing_error:
850 850
851 return QLA_FUNCTION_FAILED; 851 return QLA_FUNCTION_FAILED;
852} 852}
853
854static void qla25xx_set_que(srb_t *sp, struct req_que **req,
855 struct rsp_que **rsp)
856{
857 struct scsi_cmnd *cmd = sp->cmd;
858 struct scsi_qla_host *vha = sp->fcport->vha;
859 struct qla_hw_data *ha = sp->fcport->vha->hw;
860 int affinity = cmd->request->cpu;
861
862 if (ql2xmultique_tag && affinity >= 0 &&
863 affinity < ha->max_rsp_queues - 1) {
864 *rsp = ha->rsp_q_map[affinity + 1];
865 *req = ha->req_q_map[1];
866 } else {
867 *req = vha->req;
868 *rsp = ha->rsp_q_map[0];
869 }
870}
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
index c8e906c702a1..41e50c2bec0f 100644
--- a/drivers/scsi/qla2xxx/qla_isr.c
+++ b/drivers/scsi/qla2xxx/qla_isr.c
@@ -1718,6 +1718,25 @@ qla24xx_msix_rsp_q(int irq, void *dev_id)
1718} 1718}
1719 1719
1720static irqreturn_t 1720static irqreturn_t
1721qla25xx_msix_rsp_q(int irq, void *dev_id)
1722{
1723 struct qla_hw_data *ha;
1724 struct rsp_que *rsp;
1725
1726 rsp = (struct rsp_que *) dev_id;
1727 if (!rsp) {
1728 printk(KERN_INFO
1729 "%s(): NULL response queue pointer\n", __func__);
1730 return IRQ_NONE;
1731 }
1732 ha = rsp->hw;
1733
1734 queue_work_on((int) (rsp->id - 1), ha->wq, &rsp->q_work);
1735
1736 return IRQ_HANDLED;
1737}
1738
1739static irqreturn_t
1721qla24xx_msix_default(int irq, void *dev_id) 1740qla24xx_msix_default(int irq, void *dev_id)
1722{ 1741{
1723 scsi_qla_host_t *vha; 1742 scsi_qla_host_t *vha;
@@ -1806,9 +1825,10 @@ struct qla_init_msix_entry {
1806 irq_handler_t handler; 1825 irq_handler_t handler;
1807}; 1826};
1808 1827
1809static struct qla_init_msix_entry msix_entries[2] = { 1828static struct qla_init_msix_entry msix_entries[3] = {
1810 { "qla2xxx (default)", qla24xx_msix_default }, 1829 { "qla2xxx (default)", qla24xx_msix_default },
1811 { "qla2xxx (rsp_q)", qla24xx_msix_rsp_q }, 1830 { "qla2xxx (rsp_q)", qla24xx_msix_rsp_q },
1831 { "qla2xxx (multiq)", qla25xx_msix_rsp_q },
1812}; 1832};
1813 1833
1814static void 1834static void
diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c
index bfdc89f8569b..366522e8a766 100644
--- a/drivers/scsi/qla2xxx/qla_mbx.c
+++ b/drivers/scsi/qla2xxx/qla_mbx.c
@@ -1497,7 +1497,10 @@ qla24xx_login_fabric(scsi_qla_host_t *vha, uint16_t loop_id, uint8_t domain,
1497 1497
1498 DEBUG11(printk("%s(%ld): entered.\n", __func__, vha->host_no)); 1498 DEBUG11(printk("%s(%ld): entered.\n", __func__, vha->host_no));
1499 1499
1500 req = vha->req; 1500 if (ql2xmultique_tag)
1501 req = ha->req_q_map[0];
1502 else
1503 req = vha->req;
1501 rsp = req->rsp; 1504 rsp = req->rsp;
1502 1505
1503 lg = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &lg_dma); 1506 lg = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &lg_dma);
@@ -2311,7 +2314,10 @@ __qla24xx_issue_tmf(char *name, uint32_t type, struct fc_port *fcport,
2311 vha = fcport->vha; 2314 vha = fcport->vha;
2312 ha = vha->hw; 2315 ha = vha->hw;
2313 req = vha->req; 2316 req = vha->req;
2314 rsp = req->rsp; 2317 if (ql2xmultique_tag)
2318 rsp = ha->rsp_q_map[tag + 1];
2319 else
2320 rsp = req->rsp;
2315 tsk = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &tsk_dma); 2321 tsk = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &tsk_dma);
2316 if (tsk == NULL) { 2322 if (tsk == NULL) {
2317 DEBUG2_3(printk("%s(%ld): failed to allocate Task Management " 2323 DEBUG2_3(printk("%s(%ld): failed to allocate Task Management "
diff --git a/drivers/scsi/qla2xxx/qla_mid.c b/drivers/scsi/qla2xxx/qla_mid.c
index 9c08479c3e1b..650bcef08f2a 100644
--- a/drivers/scsi/qla2xxx/qla_mid.c
+++ b/drivers/scsi/qla2xxx/qla_mid.c
@@ -633,6 +633,15 @@ que_failed:
633 return 0; 633 return 0;
634} 634}
635 635
636static void qla_do_work(struct work_struct *work)
637{
638 struct rsp_que *rsp = container_of(work, struct rsp_que, q_work);
639 struct scsi_qla_host *vha;
640
641 vha = qla25xx_get_host(rsp);
642 qla24xx_process_response_queue(vha, rsp);
643}
644
636/* create response queue */ 645/* create response queue */
637int 646int
638qla25xx_create_rsp_que(struct qla_hw_data *ha, uint16_t options, 647qla25xx_create_rsp_que(struct qla_hw_data *ha, uint16_t options,
@@ -711,6 +720,8 @@ qla25xx_create_rsp_que(struct qla_hw_data *ha, uint16_t options,
711 rsp->req = NULL; 720 rsp->req = NULL;
712 721
713 qla2x00_init_response_q_entries(rsp); 722 qla2x00_init_response_q_entries(rsp);
723 if (rsp->hw->wq)
724 INIT_WORK(&rsp->q_work, qla_do_work);
714 return rsp->id; 725 return rsp->id;
715 726
716que_failed: 727que_failed:
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index e2647e02dac9..d6817df95e30 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -96,6 +96,13 @@ MODULE_PARM_DESC(ql2xmaxqueues,
96 "Enables MQ settings " 96 "Enables MQ settings "
97 "Default is 1 for single queue. Set it to number \ 97 "Default is 1 for single queue. Set it to number \
98 of queues in MQ mode."); 98 of queues in MQ mode.");
99
100int ql2xmultique_tag;
101module_param(ql2xmultique_tag, int, S_IRUGO|S_IRUSR);
102MODULE_PARM_DESC(ql2xmultique_tag,
103 "Enables CPU affinity settings for the driver "
104 "Default is 0 for no affinity of request and response IO. "
105 "Set it to 1 to turn on the cpu affinity.");
99/* 106/*
100 * SCSI host template entry points 107 * SCSI host template entry points
101 */ 108 */
@@ -256,6 +263,47 @@ static void qla2x00_free_queues(struct qla_hw_data *ha)
256 ha->rsp_q_map = NULL; 263 ha->rsp_q_map = NULL;
257} 264}
258 265
266static int qla25xx_setup_mode(struct scsi_qla_host *vha)
267{
268 uint16_t options = 0;
269 int ques, req, ret;
270 struct qla_hw_data *ha = vha->hw;
271
272 if (ql2xmultique_tag) {
273 /* CPU affinity mode */
274 ha->wq = create_workqueue("qla2xxx_wq");
275 /* create a request queue for IO */
276 options |= BIT_7;
277 req = qla25xx_create_req_que(ha, options, 0, 0, -1,
278 QLA_DEFAULT_QUE_QOS);
279 if (!req) {
280 qla_printk(KERN_WARNING, ha,
281 "Can't create request queue\n");
282 goto fail;
283 }
284 vha->req = ha->req_q_map[req];
285 options |= BIT_1;
286 for (ques = 1; ques < ha->max_rsp_queues; ques++) {
287 ret = qla25xx_create_rsp_que(ha, options, 0, 0, req);
288 if (!ret) {
289 qla_printk(KERN_WARNING, ha,
290 "Response Queue create failed\n");
291 goto fail2;
292 }
293 }
294 DEBUG2(qla_printk(KERN_INFO, ha,
295 "CPU affinity mode enabled, no. of response"
296 " queues:%d, no. of request queues:%d\n",
297 ha->max_rsp_queues, ha->max_req_queues));
298 }
299 return 0;
300fail2:
301 qla25xx_delete_queues(vha);
302fail:
303 ha->mqenable = 0;
304 return 1;
305}
306
259static char * 307static char *
260qla2x00_pci_info_str(struct scsi_qla_host *vha, char *str) 308qla2x00_pci_info_str(struct scsi_qla_host *vha, char *str)
261{ 309{
@@ -998,6 +1046,9 @@ qla2xxx_eh_host_reset(struct scsi_cmnd *cmd)
998 if (qla2x00_vp_abort_isp(vha)) 1046 if (qla2x00_vp_abort_isp(vha))
999 goto eh_host_reset_lock; 1047 goto eh_host_reset_lock;
1000 } else { 1048 } else {
1049 if (ha->wq)
1050 flush_workqueue(ha->wq);
1051
1001 set_bit(ABORT_ISP_ACTIVE, &base_vha->dpc_flags); 1052 set_bit(ABORT_ISP_ACTIVE, &base_vha->dpc_flags);
1002 if (qla2x00_abort_isp(base_vha)) { 1053 if (qla2x00_abort_isp(base_vha)) {
1003 clear_bit(ABORT_ISP_ACTIVE, &base_vha->dpc_flags); 1054 clear_bit(ABORT_ISP_ACTIVE, &base_vha->dpc_flags);
@@ -1521,6 +1572,7 @@ qla2x00_iospace_config(struct qla_hw_data *ha)
1521{ 1572{
1522 resource_size_t pio; 1573 resource_size_t pio;
1523 uint16_t msix; 1574 uint16_t msix;
1575 int cpus;
1524 1576
1525 if (pci_request_selected_regions(ha->pdev, ha->bars, 1577 if (pci_request_selected_regions(ha->pdev, ha->bars,
1526 QLA2XXX_DRIVER_NAME)) { 1578 QLA2XXX_DRIVER_NAME)) {
@@ -1575,7 +1627,7 @@ skip_pio:
1575 1627
1576 /* Determine queue resources */ 1628 /* Determine queue resources */
1577 ha->max_req_queues = ha->max_rsp_queues = 1; 1629 ha->max_req_queues = ha->max_rsp_queues = 1;
1578 if (ql2xmaxqueues <= 1 && 1630 if ((ql2xmaxqueues <= 1 || ql2xmultique_tag < 1) &&
1579 (!IS_QLA25XX(ha) && !IS_QLA81XX(ha))) 1631 (!IS_QLA25XX(ha) && !IS_QLA81XX(ha)))
1580 goto mqiobase_exit; 1632 goto mqiobase_exit;
1581 ha->mqiobase = ioremap(pci_resource_start(ha->pdev, 3), 1633 ha->mqiobase = ioremap(pci_resource_start(ha->pdev, 3),
@@ -1584,12 +1636,21 @@ skip_pio:
1584 /* Read MSIX vector size of the board */ 1636 /* Read MSIX vector size of the board */
1585 pci_read_config_word(ha->pdev, QLA_PCI_MSIX_CONTROL, &msix); 1637 pci_read_config_word(ha->pdev, QLA_PCI_MSIX_CONTROL, &msix);
1586 ha->msix_count = msix; 1638 ha->msix_count = msix;
1587 if (ql2xmaxqueues > 1) { 1639 /* Max queues are bounded by available msix vectors */
1640 /* queue 0 uses two msix vectors */
1641 if (ql2xmultique_tag) {
1642 cpus = num_online_cpus();
1643 ha->max_rsp_queues = (ha->msix_count - 1 - cpus) ?
1644 (cpus + 1) : (ha->msix_count - 1);
1645 ha->max_req_queues = 2;
1646 } else if (ql2xmaxqueues > 1) {
1588 ha->max_req_queues = ql2xmaxqueues > QLA_MQ_SIZE ? 1647 ha->max_req_queues = ql2xmaxqueues > QLA_MQ_SIZE ?
1589 QLA_MQ_SIZE : ql2xmaxqueues; 1648 QLA_MQ_SIZE : ql2xmaxqueues;
1590 DEBUG2(qla_printk(KERN_INFO, ha, "QoS mode set, max no" 1649 DEBUG2(qla_printk(KERN_INFO, ha, "QoS mode set, max no"
1591 " of request queues:%d\n", ha->max_req_queues)); 1650 " of request queues:%d\n", ha->max_req_queues));
1592 } 1651 }
1652 qla_printk(KERN_INFO, ha,
1653 "MSI-X vector count: %d\n", msix);
1593 } else 1654 } else
1594 qla_printk(KERN_INFO, ha, "BAR 3 not enabled\n"); 1655 qla_printk(KERN_INFO, ha, "BAR 3 not enabled\n");
1595 1656
@@ -1871,6 +1932,12 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
1871 goto probe_failed; 1932 goto probe_failed;
1872 } 1933 }
1873 1934
1935 if (ha->mqenable)
1936 if (qla25xx_setup_mode(base_vha))
1937 qla_printk(KERN_WARNING, ha,
1938 "Can't create queues, falling back to single"
1939 " queue mode\n");
1940
1874 /* 1941 /*
1875 * Startup the kernel thread for this host adapter 1942 * Startup the kernel thread for this host adapter
1876 */ 1943 */
@@ -1982,6 +2049,13 @@ qla2x00_remove_one(struct pci_dev *pdev)
1982 2049
1983 base_vha->flags.online = 0; 2050 base_vha->flags.online = 0;
1984 2051
2052 /* Flush the work queue and remove it */
2053 if (ha->wq) {
2054 flush_workqueue(ha->wq);
2055 destroy_workqueue(ha->wq);
2056 ha->wq = NULL;
2057 }
2058
1985 /* Kill the kernel thread for this host */ 2059 /* Kill the kernel thread for this host */
1986 if (ha->dpc_thread) { 2060 if (ha->dpc_thread) {
1987 struct task_struct *t = ha->dpc_thread; 2061 struct task_struct *t = ha->dpc_thread;