[SCSI] qla4xxx: Throttle active IOCBs to firmware limits
authorKaren Higgins <karen.higgins@qlogic.com>
Mon, 21 Jan 2013 04:51:00 +0000 (23:51 -0500)
committerJames Bottomley <JBottomley@Parallels.com>
Wed, 30 Jan 2013 02:47:16 +0000 (13:47 +1100)
Problem:
QLA4xxx firmware may assert if given more IOCBs than it can handle.

Solution:
The driver was updated to throttle the number of active IOCBs based
on the total number of IOCB buffers received from get_firmware_status
mbx_sts[2].

Signed-off-by: Karen Higgins <karen.higgins@qlogic.com>
Signed-off-by: Vikas Chaudhary <vikas.chaudhary@qlogic.com>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
drivers/scsi/qla4xxx/ql4_def.h
drivers/scsi/qla4xxx/ql4_iocb.c
drivers/scsi/qla4xxx/ql4_mbx.c

index 8f41937666636c3198d03527f585a58faab955da..ad580625a47772b578437cd0cfe2a915aa835527 100644 (file)
 #define RESPONSE_QUEUE_DEPTH           64
 #define QUEUE_SIZE                     64
 #define DMA_BUFFER_SIZE                        512
+#define IOCB_HIWAT_CUSHION             4
 
 /*
  * Misc
@@ -540,6 +541,7 @@ struct scsi_qla_host {
        uint32_t tot_ddbs;
 
        uint16_t iocb_cnt;
+       uint16_t iocb_hiwat;
 
        /* SRB cache. */
 #define SRB_MIN_REQ    128
index f48f37a281d185c32dcc23790413109ffc158289..14fec976f634e1c4804855617c65aae7fcd4a566 100644 (file)
@@ -316,7 +316,7 @@ int qla4xxx_send_command_to_isp(struct scsi_qla_host *ha, struct srb * srb)
                goto queuing_error;
 
        /* total iocbs active */
-       if ((ha->iocb_cnt + req_cnt) >= REQUEST_QUEUE_DEPTH)
+       if ((ha->iocb_cnt + req_cnt) >= ha->iocb_hiwat)
                goto queuing_error;
 
        /* Build command packet */
index 1c57c227c808e26255ab159911535e64726d12d0..81e738d61ec02073580981ef85d12e2c016402ac 100644 (file)
@@ -697,8 +697,24 @@ int qla4xxx_get_firmware_status(struct scsi_qla_host * ha)
                return QLA_ERROR;
        }
 
-       ql4_printk(KERN_INFO, ha, "%ld firmware IOCBs available (%d).\n",
-           ha->host_no, mbox_sts[2]);
+       /* High-water mark of IOCBs */
+       ha->iocb_hiwat = mbox_sts[2];
+       DEBUG2(ql4_printk(KERN_INFO, ha,
+                         "%s: firmware IOCBs available = %d\n", __func__,
+                         ha->iocb_hiwat));
+
+       if (ha->iocb_hiwat > IOCB_HIWAT_CUSHION)
+               ha->iocb_hiwat -= IOCB_HIWAT_CUSHION;
+
+       /* Ideally, we should not enter this code, as the # of firmware
+        * IOCBs is hard-coded in the firmware. We set a default
+        * iocb_hiwat here just in case */
+       if (ha->iocb_hiwat == 0) {
+               ha->iocb_hiwat = REQUEST_QUEUE_DEPTH / 4;
+               DEBUG2(ql4_printk(KERN_WARNING, ha,
+                                 "%s: Setting IOCB's to = %d\n", __func__,
+                                 ha->iocb_hiwat));
+       }
 
        return QLA_SUCCESS;
 }