aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/qla2xxx/qla_os.c
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/qla_os.c
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/qla_os.c')
-rw-r--r--drivers/scsi/qla2xxx/qla_os.c78
1 files changed, 76 insertions, 2 deletions
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;