aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrew Vasquez <andrew.vasquez@qlogic.com>2005-10-27 14:09:48 -0400
committerJames Bottomley <jejb@mulgrave.(none)>2005-10-28 12:52:11 -0400
commit4fdfefe52944f5c4132a372ed5c208962a73c3f2 (patch)
tree23e4c9cb3f899d82e07fcfc55d75744b919415e5
parent0eedfcf0cdac30b14d1e6c99abc6604347ef0af8 (diff)
[SCSI] qla2xxx: Add support to dynamically enable/disable ZIO.
ISP23xx and ISP24xx chips have support for an adaptive method of posting SCSI command completions for multiple SCSI commands during a single system interrupt. SCSI commands are placed on the system response queue without interrupting the host until 1) a delay timer expires; or 2) a SCSI command completes with an error. As long as the host software (qla2xxx) services the response queue for completions (this polling is done during queuecommand()) within the 'delay timer' period, the firmware will not generate system interrupt. Signed-off-by: Andrew Vasquez <andrew.vasquez@qlogic.com> Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
-rw-r--r--drivers/scsi/qla2xxx/qla_attr.c83
-rw-r--r--drivers/scsi/qla2xxx/qla_def.h8
-rw-r--r--drivers/scsi/qla2xxx/qla_gbl.h3
-rw-r--r--drivers/scsi/qla2xxx/qla_init.c53
-rw-r--r--drivers/scsi/qla2xxx/qla_iocb.c10
-rw-r--r--drivers/scsi/qla2xxx/qla_isr.c7
-rw-r--r--drivers/scsi/qla2xxx/qla_os.c23
7 files changed, 146 insertions, 41 deletions
diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c
index fc25cd834668..47c9ecfc1d8f 100644
--- a/drivers/scsi/qla2xxx/qla_attr.c
+++ b/drivers/scsi/qla2xxx/qla_attr.c
@@ -319,6 +319,83 @@ qla2x00_state_show(struct class_device *cdev, char *buf)
319 return len; 319 return len;
320} 320}
321 321
322static ssize_t
323qla2x00_zio_show(struct class_device *cdev, char *buf)
324{
325 scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev));
326 int len = 0;
327
328 switch (ha->zio_mode) {
329 case QLA_ZIO_MODE_5:
330 len += snprintf(buf + len, PAGE_SIZE-len, "Mode 5\n");
331 break;
332 case QLA_ZIO_MODE_6:
333 len += snprintf(buf + len, PAGE_SIZE-len, "Mode 6\n");
334 break;
335 case QLA_ZIO_DISABLED:
336 len += snprintf(buf + len, PAGE_SIZE-len, "Disabled\n");
337 break;
338 }
339 return len;
340}
341
342static ssize_t
343qla2x00_zio_store(struct class_device *cdev, const char *buf, size_t count)
344{
345 scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev));
346 int val = 0;
347 uint16_t zio_mode;
348
349 if (sscanf(buf, "%d", &val) != 1)
350 return -EINVAL;
351
352 switch (val) {
353 case 1:
354 zio_mode = QLA_ZIO_MODE_5;
355 break;
356 case 2:
357 zio_mode = QLA_ZIO_MODE_6;
358 break;
359 default:
360 zio_mode = QLA_ZIO_DISABLED;
361 break;
362 }
363
364 /* Update per-hba values and queue a reset. */
365 if (zio_mode != QLA_ZIO_DISABLED || ha->zio_mode != QLA_ZIO_DISABLED) {
366 ha->zio_mode = zio_mode;
367 set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags);
368 }
369 return strlen(buf);
370}
371
372static ssize_t
373qla2x00_zio_timer_show(struct class_device *cdev, char *buf)
374{
375 scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev));
376
377 return snprintf(buf, PAGE_SIZE, "%d us\n", ha->zio_timer * 100);
378}
379
380static ssize_t
381qla2x00_zio_timer_store(struct class_device *cdev, const char *buf,
382 size_t count)
383{
384 scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev));
385 int val = 0;
386 uint16_t zio_timer;
387
388 if (sscanf(buf, "%d", &val) != 1)
389 return -EINVAL;
390 if (val > 25500 || val < 100)
391 return -ERANGE;
392
393 zio_timer = (uint16_t)(val / 100);
394 ha->zio_timer = zio_timer;
395
396 return strlen(buf);
397}
398
322static CLASS_DEVICE_ATTR(driver_version, S_IRUGO, qla2x00_drvr_version_show, 399static CLASS_DEVICE_ATTR(driver_version, S_IRUGO, qla2x00_drvr_version_show,
323 NULL); 400 NULL);
324static CLASS_DEVICE_ATTR(fw_version, S_IRUGO, qla2x00_fw_version_show, NULL); 401static CLASS_DEVICE_ATTR(fw_version, S_IRUGO, qla2x00_fw_version_show, NULL);
@@ -329,6 +406,10 @@ static CLASS_DEVICE_ATTR(model_name, S_IRUGO, qla2x00_model_name_show, NULL);
329static CLASS_DEVICE_ATTR(model_desc, S_IRUGO, qla2x00_model_desc_show, NULL); 406static CLASS_DEVICE_ATTR(model_desc, S_IRUGO, qla2x00_model_desc_show, NULL);
330static CLASS_DEVICE_ATTR(pci_info, S_IRUGO, qla2x00_pci_info_show, NULL); 407static CLASS_DEVICE_ATTR(pci_info, S_IRUGO, qla2x00_pci_info_show, NULL);
331static CLASS_DEVICE_ATTR(state, S_IRUGO, qla2x00_state_show, NULL); 408static CLASS_DEVICE_ATTR(state, S_IRUGO, qla2x00_state_show, NULL);
409static CLASS_DEVICE_ATTR(zio, S_IRUGO | S_IWUSR, qla2x00_zio_show,
410 qla2x00_zio_store);
411static CLASS_DEVICE_ATTR(zio_timer, S_IRUGO | S_IWUSR, qla2x00_zio_timer_show,
412 qla2x00_zio_timer_store);
332 413
333struct class_device_attribute *qla2x00_host_attrs[] = { 414struct class_device_attribute *qla2x00_host_attrs[] = {
334 &class_device_attr_driver_version, 415 &class_device_attr_driver_version,
@@ -340,6 +421,8 @@ struct class_device_attribute *qla2x00_host_attrs[] = {
340 &class_device_attr_model_desc, 421 &class_device_attr_model_desc,
341 &class_device_attr_pci_info, 422 &class_device_attr_pci_info,
342 &class_device_attr_state, 423 &class_device_attr_state,
424 &class_device_attr_zio,
425 &class_device_attr_zio_timer,
343 NULL, 426 NULL,
344}; 427};
345 428
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index b455c31405e4..522bb2d3f084 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -823,6 +823,11 @@ typedef struct {
823#define PD_STATE_WAIT_PORT_LOGOUT_ACK 11 823#define PD_STATE_WAIT_PORT_LOGOUT_ACK 11
824 824
825 825
826#define QLA_ZIO_MODE_5 (BIT_2 | BIT_0)
827#define QLA_ZIO_MODE_6 (BIT_2 | BIT_1)
828#define QLA_ZIO_DISABLED 0
829#define QLA_ZIO_DEFAULT_TIMER 2
830
826/* 831/*
827 * ISP Initialization Control Block. 832 * ISP Initialization Control Block.
828 * Little endian except where noted. 833 * Little endian except where noted.
@@ -2470,6 +2475,9 @@ typedef struct scsi_qla_host {
2470 /* Needed for BEACON */ 2475 /* Needed for BEACON */
2471 uint16_t beacon_blink_led; 2476 uint16_t beacon_blink_led;
2472 uint16_t beacon_green_on; 2477 uint16_t beacon_green_on;
2478
2479 uint16_t zio_mode;
2480 uint16_t zio_timer;
2473} scsi_qla_host_t; 2481} scsi_qla_host_t;
2474 2482
2475 2483
diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
index e451941ad81d..c26b74da4054 100644
--- a/drivers/scsi/qla2xxx/qla_gbl.h
+++ b/drivers/scsi/qla2xxx/qla_gbl.h
@@ -76,8 +76,6 @@ extern char qla2x00_version_str[];
76extern int ql2xlogintimeout; 76extern int ql2xlogintimeout;
77extern int qlport_down_retry; 77extern int qlport_down_retry;
78extern int ql2xplogiabsentdevice; 78extern int ql2xplogiabsentdevice;
79extern int ql2xenablezio;
80extern int ql2xintrdelaytimer;
81extern int ql2xloginretrycount; 79extern int ql2xloginretrycount;
82extern int ql2xfdmienable; 80extern int ql2xfdmienable;
83 81
@@ -223,6 +221,7 @@ extern irqreturn_t qla2100_intr_handler(int, void *, struct pt_regs *);
223extern irqreturn_t qla2300_intr_handler(int, void *, struct pt_regs *); 221extern irqreturn_t qla2300_intr_handler(int, void *, struct pt_regs *);
224extern irqreturn_t qla24xx_intr_handler(int, void *, struct pt_regs *); 222extern irqreturn_t qla24xx_intr_handler(int, void *, struct pt_regs *);
225extern void qla2x00_process_response_queue(struct scsi_qla_host *); 223extern void qla2x00_process_response_queue(struct scsi_qla_host *);
224extern void qla24xx_process_response_queue(struct scsi_qla_host *);
226 225
227/* 226/*
228 * Global Function Prototypes in qla_sup.c source file. 227 * Global Function Prototypes in qla_sup.c source file.
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index 6fc8bbae9398..9e36fbd9245a 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -1372,7 +1372,6 @@ qla2x00_nvram_config(scsi_qla_host_t *ha)
1372 nvram_t *nv = (nvram_t *)ha->request_ring; 1372 nvram_t *nv = (nvram_t *)ha->request_ring;
1373 uint8_t *ptr = (uint8_t *)ha->request_ring; 1373 uint8_t *ptr = (uint8_t *)ha->request_ring;
1374 struct device_reg_2xxx __iomem *reg = &ha->iobase->isp; 1374 struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
1375 uint8_t timer_mode;
1376 1375
1377 rval = QLA_SUCCESS; 1376 rval = QLA_SUCCESS;
1378 1377
@@ -1650,22 +1649,26 @@ qla2x00_nvram_config(scsi_qla_host_t *ha)
1650 1649
1651 ha->flags.process_response_queue = 1; 1650 ha->flags.process_response_queue = 1;
1652 } else { 1651 } else {
1653 /* Enable ZIO -- Support mode 5 only. */ 1652 /* Enable ZIO. */
1654 timer_mode = icb->add_firmware_options[0] & 1653 if (!ha->flags.init_done) {
1655 (BIT_3 | BIT_2 | BIT_1 | BIT_0); 1654 ha->zio_mode = icb->add_firmware_options[0] &
1655 (BIT_3 | BIT_2 | BIT_1 | BIT_0);
1656 ha->zio_timer = icb->interrupt_delay_timer ?
1657 icb->interrupt_delay_timer: 2;
1658 }
1656 icb->add_firmware_options[0] &= 1659 icb->add_firmware_options[0] &=
1657 ~(BIT_3 | BIT_2 | BIT_1 | BIT_0); 1660 ~(BIT_3 | BIT_2 | BIT_1 | BIT_0);
1658 if (ql2xenablezio) 1661 ha->flags.process_response_queue = 0;
1659 timer_mode = BIT_2 | BIT_0; 1662 if (ha->zio_mode != QLA_ZIO_DISABLED) {
1660 if (timer_mode == (BIT_2 | BIT_0)) { 1663 DEBUG2(printk("scsi(%ld): ZIO mode %d enabled; timer "
1661 DEBUG2(printk("scsi(%ld): ZIO enabled; timer delay " 1664 "delay (%d us).\n", ha->host_no, ha->zio_mode,
1662 "(%d).\n", ha->host_no, ql2xintrdelaytimer)); 1665 ha->zio_timer * 100));
1663 qla_printk(KERN_INFO, ha, 1666 qla_printk(KERN_INFO, ha,
1664 "ZIO enabled; timer delay (%d).\n", 1667 "ZIO mode %d enabled; timer delay (%d us).\n",
1665 ql2xintrdelaytimer); 1668 ha->zio_mode, ha->zio_timer * 100);
1666 1669
1667 icb->add_firmware_options[0] |= timer_mode; 1670 icb->add_firmware_options[0] |= (uint8_t)ha->zio_mode;
1668 icb->interrupt_delay_timer = ql2xintrdelaytimer; 1671 icb->interrupt_delay_timer = (uint8_t)ha->zio_timer;
1669 ha->flags.process_response_queue = 1; 1672 ha->flags.process_response_queue = 1;
1670 } 1673 }
1671 } 1674 }
@@ -3442,6 +3445,30 @@ qla24xx_nvram_config(scsi_qla_host_t *ha)
3442 if (ql2xloginretrycount) 3445 if (ql2xloginretrycount)
3443 ha->login_retry_count = ql2xloginretrycount; 3446 ha->login_retry_count = ql2xloginretrycount;
3444 3447
3448 /* Enable ZIO. */
3449 if (!ha->flags.init_done) {
3450 ha->zio_mode = le32_to_cpu(icb->firmware_options_2) &
3451 (BIT_3 | BIT_2 | BIT_1 | BIT_0);
3452 ha->zio_timer = le16_to_cpu(icb->interrupt_delay_timer) ?
3453 le16_to_cpu(icb->interrupt_delay_timer): 2;
3454 }
3455 icb->firmware_options_2 &= __constant_cpu_to_le32(
3456 ~(BIT_3 | BIT_2 | BIT_1 | BIT_0));
3457 ha->flags.process_response_queue = 0;
3458 if (ha->zio_mode != QLA_ZIO_DISABLED) {
3459 DEBUG2(printk("scsi(%ld): ZIO mode %d enabled; timer delay "
3460 "(%d us).\n", ha->host_no, ha->zio_mode,
3461 ha->zio_timer * 100));
3462 qla_printk(KERN_INFO, ha,
3463 "ZIO mode %d enabled; timer delay (%d us).\n",
3464 ha->zio_mode, ha->zio_timer * 100);
3465
3466 icb->firmware_options_2 |= cpu_to_le32(
3467 (uint32_t)ha->zio_mode);
3468 icb->interrupt_delay_timer = cpu_to_le16(ha->zio_timer);
3469 ha->flags.process_response_queue = 1;
3470 }
3471
3445 if (rval) { 3472 if (rval) {
3446 DEBUG2_3(printk(KERN_WARNING 3473 DEBUG2_3(printk(KERN_WARNING
3447 "scsi(%ld): NVRAM configuration failed!\n", ha->host_no)); 3474 "scsi(%ld): NVRAM configuration failed!\n", ha->host_no));
diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c
index 37f82e2cd7fb..d7355627f110 100644
--- a/drivers/scsi/qla2xxx/qla_iocb.c
+++ b/drivers/scsi/qla2xxx/qla_iocb.c
@@ -440,6 +440,11 @@ qla2x00_start_scsi(srb_t *sp)
440 WRT_REG_WORD(ISP_REQ_Q_IN(ha, reg), ha->req_ring_index); 440 WRT_REG_WORD(ISP_REQ_Q_IN(ha, reg), ha->req_ring_index);
441 RD_REG_WORD_RELAXED(ISP_REQ_Q_IN(ha, reg)); /* PCI Posting. */ 441 RD_REG_WORD_RELAXED(ISP_REQ_Q_IN(ha, reg)); /* PCI Posting. */
442 442
443 /* Manage unprocessed RIO/ZIO commands in response queue. */
444 if (ha->flags.process_response_queue &&
445 ha->response_ring_ptr->signature != RESPONSE_PROCESSED)
446 qla2x00_process_response_queue(ha);
447
443 spin_unlock_irqrestore(&ha->hardware_lock, flags); 448 spin_unlock_irqrestore(&ha->hardware_lock, flags);
444 return (QLA_SUCCESS); 449 return (QLA_SUCCESS);
445 450
@@ -877,6 +882,11 @@ qla24xx_start_scsi(srb_t *sp)
877 WRT_REG_DWORD(&reg->req_q_in, ha->req_ring_index); 882 WRT_REG_DWORD(&reg->req_q_in, ha->req_ring_index);
878 RD_REG_DWORD_RELAXED(&reg->req_q_in); /* PCI Posting. */ 883 RD_REG_DWORD_RELAXED(&reg->req_q_in); /* PCI Posting. */
879 884
885 /* Manage unprocessed RIO/ZIO commands in response queue. */
886 if (ha->flags.process_response_queue &&
887 ha->response_ring_ptr->signature != RESPONSE_PROCESSED)
888 qla24xx_process_response_queue(ha);
889
880 spin_unlock_irqrestore(&ha->hardware_lock, flags); 890 spin_unlock_irqrestore(&ha->hardware_lock, flags);
881 return QLA_SUCCESS; 891 return QLA_SUCCESS;
882 892
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
index c255bb0268a9..cf6c6ce0b42b 100644
--- a/drivers/scsi/qla2xxx/qla_isr.c
+++ b/drivers/scsi/qla2xxx/qla_isr.c
@@ -21,13 +21,11 @@
21static void qla2x00_mbx_completion(scsi_qla_host_t *, uint16_t); 21static void qla2x00_mbx_completion(scsi_qla_host_t *, uint16_t);
22static void qla2x00_async_event(scsi_qla_host_t *, uint16_t *); 22static void qla2x00_async_event(scsi_qla_host_t *, uint16_t *);
23static void qla2x00_process_completed_request(struct scsi_qla_host *, uint32_t); 23static void qla2x00_process_completed_request(struct scsi_qla_host *, uint32_t);
24void qla2x00_process_response_queue(struct scsi_qla_host *);
25static void qla2x00_status_entry(scsi_qla_host_t *, void *); 24static void qla2x00_status_entry(scsi_qla_host_t *, void *);
26static void qla2x00_status_cont_entry(scsi_qla_host_t *, sts_cont_entry_t *); 25static void qla2x00_status_cont_entry(scsi_qla_host_t *, sts_cont_entry_t *);
27static void qla2x00_error_entry(scsi_qla_host_t *, sts_entry_t *); 26static void qla2x00_error_entry(scsi_qla_host_t *, sts_entry_t *);
28static void qla2x00_ms_entry(scsi_qla_host_t *, ms_iocb_entry_t *); 27static void qla2x00_ms_entry(scsi_qla_host_t *, ms_iocb_entry_t *);
29 28
30void qla24xx_process_response_queue(scsi_qla_host_t *);
31static void qla24xx_ms_entry(scsi_qla_host_t *, struct ct_entry_24xx *); 29static void qla24xx_ms_entry(scsi_qla_host_t *, struct ct_entry_24xx *);
32 30
33/** 31/**
@@ -651,7 +649,10 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb)
651 "scsi(%ld): [R|Z]IO update completion.\n", 649 "scsi(%ld): [R|Z]IO update completion.\n",
652 ha->host_no)); 650 ha->host_no));
653 651
654 qla2x00_process_response_queue(ha); 652 if (IS_QLA24XX(ha) || IS_QLA25XX(ha))
653 qla24xx_process_response_queue(ha);
654 else
655 qla2x00_process_response_queue(ha);
655 break; 656 break;
656 657
657 case MBA_DISCARD_RND_FRAME: 658 case MBA_DISCARD_RND_FRAME:
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index 7aec93f9d423..77054d7692c4 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -61,19 +61,6 @@ MODULE_PARM_DESC(ql2xplogiabsentdevice,
61 "a Fabric scan. This is needed for several broken switches." 61 "a Fabric scan. This is needed for several broken switches."
62 "Default is 0 - no PLOGI. 1 - perfom PLOGI."); 62 "Default is 0 - no PLOGI. 1 - perfom PLOGI.");
63 63
64int ql2xenablezio = 0;
65module_param(ql2xenablezio, int, S_IRUGO|S_IRUSR);
66MODULE_PARM_DESC(ql2xenablezio,
67 "Option to enable ZIO:If 1 then enable it otherwise"
68 " use the default set in the NVRAM."
69 " Default is 0 : disabled");
70
71int ql2xintrdelaytimer = 10;
72module_param(ql2xintrdelaytimer, int, S_IRUGO|S_IRUSR);
73MODULE_PARM_DESC(ql2xintrdelaytimer,
74 "ZIO: Waiting time for Firmware before it generates an "
75 "interrupt to the host to notify completion of request.");
76
77int ql2xloginretrycount = 0; 64int ql2xloginretrycount = 0;
78module_param(ql2xloginretrycount, int, S_IRUGO|S_IRUSR); 65module_param(ql2xloginretrycount, int, S_IRUGO|S_IRUSR);
79MODULE_PARM_DESC(ql2xloginretrycount, 66MODULE_PARM_DESC(ql2xloginretrycount,
@@ -400,16 +387,6 @@ qla2x00_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
400 if (rval != QLA_SUCCESS) 387 if (rval != QLA_SUCCESS)
401 goto qc_host_busy_free_sp; 388 goto qc_host_busy_free_sp;
402 389
403 /* Manage unprocessed RIO/ZIO commands in response queue. */
404 if (ha->flags.online && ha->flags.process_response_queue &&
405 ha->response_ring_ptr->signature != RESPONSE_PROCESSED) {
406 unsigned long flags;
407
408 spin_lock_irqsave(&ha->hardware_lock, flags);
409 qla2x00_process_response_queue(ha);
410 spin_unlock_irqrestore(&ha->hardware_lock, flags);
411 }
412
413 spin_lock_irq(ha->host->host_lock); 390 spin_lock_irq(ha->host->host_lock);
414 391
415 return 0; 392 return 0;