[SCSI] qla2xxx: Ensure there's enough request-queue space for passthru IOCBs.
authorAndrew Vasquez <andrew.vasquez@qlogic.com>
Fri, 18 Nov 2011 17:03:20 +0000 (09:03 -0800)
committerJames Bottomley <JBottomley@Parallels.com>
Thu, 15 Dec 2011 06:55:11 +0000 (10:55 +0400)
The driver should ensure there's a sufficient number of IOCBs
to satisfy the number of scatter-gather entries specified in the
command.  Add a 'count' to the control structure, srb_ctx, to use
in qla2x00_alloc_iocbs().

Signed-off-by: Andrew Vasquez <andrew.vasquez@qlogic.com>
Signed-off-by: Chad Dupuis <chad.dupuis@qlogic.com>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
drivers/scsi/qla2xxx/qla_bsg.c
drivers/scsi/qla2xxx/qla_def.h
drivers/scsi/qla2xxx/qla_init.c
drivers/scsi/qla2xxx/qla_iocb.c

index c0bc0c6f084d69f6474d2c75e19bd046aa92639a..b1d0f936bf2d9530391ec532594a52aee3a154d2 100644 (file)
@@ -31,6 +31,7 @@ qla2x00_get_ctx_bsg_sp(scsi_qla_host_t *vha, fc_port_t *fcport, size_t size)
        memset(sp, 0, sizeof(*sp));
        sp->fcport = fcport;
        sp->ctx = ctx;
+       ctx->iocbs = 1;
 done:
        return sp;
 }
@@ -389,6 +390,20 @@ done:
        return rval;
 }
 
+inline uint16_t
+qla24xx_calc_ct_iocbs(uint16_t dsds)
+{
+       uint16_t iocbs;
+
+       iocbs = 1;
+       if (dsds > 2) {
+               iocbs += (dsds - 2) / 5;
+               if ((dsds - 2) % 5)
+                       iocbs++;
+       }
+       return iocbs;
+}
+
 static int
 qla2x00_process_ct(struct fc_bsg_job *bsg_job)
 {
@@ -489,6 +504,7 @@ qla2x00_process_ct(struct fc_bsg_job *bsg_job)
        ct = sp->ctx;
        ct->type = SRB_CT_CMD;
        ct->name = "bsg_ct";
+       ct->iocbs = qla24xx_calc_ct_iocbs(req_sg_cnt + rsp_sg_cnt);
        ct->u.bsg_job = bsg_job;
 
        ql_dbg(ql_dbg_user, vha, 0x7016,
index d046db1a2dedeb740edeee3b353bb16770052eb9..a6a4eebce4a889c5bfc02c6e5420a469b2517f6f 100644 (file)
@@ -271,6 +271,7 @@ struct srb_iocb {
 struct srb_ctx {
        uint16_t type;
        char *name;
+       int iocbs;
        union {
                struct srb_iocb *iocb_cmd;
                struct fc_bsg_job *bsg_job;
index 05931e6469aaac1d89da6a24fb2bc4944e1f4f03..1fa067e053d2877fad3a175099d1b9a38da06d4f 100644 (file)
@@ -111,6 +111,7 @@ qla2x00_get_ctx_sp(scsi_qla_host_t *vha, fc_port_t *fcport, size_t size,
        memset(sp, 0, sizeof(*sp));
        sp->fcport = fcport;
        sp->ctx = ctx;
+       ctx->iocbs = 1;
        ctx->u.iocb_cmd = iocb;
        iocb->free = qla2x00_ctx_sp_free;
 
index 841ffb34d416bab94df364d0bc9c16d061f1f800..55a96761b5a4bc8210b781c8060d5b4803cee0a4 100644 (file)
@@ -1818,6 +1818,7 @@ qla2x00_alloc_iocbs(scsi_qla_host_t *vha, srb_t *sp)
        uint32_t index, handle;
        request_t *pkt;
        uint16_t cnt, req_cnt;
+       struct srb_ctx *ctx;
 
        pkt = NULL;
        req_cnt = 1;
@@ -1846,6 +1847,12 @@ qla2x00_alloc_iocbs(scsi_qla_host_t *vha, srb_t *sp)
        req->outstanding_cmds[handle] = sp;
        sp->handle = handle;
 
+       /* Adjust entry-counts as needed. */
+       if (sp->ctx) {
+               ctx = sp->ctx;
+               req_cnt = ctx->iocbs;
+       }
+
 skip_cmd_array:
        /* Check for room on request queue. */
        if (req->cnt < req_cnt) {
@@ -2622,8 +2629,8 @@ qla2x00_start_sp(srb_t *sp)
                break;
        case SRB_CT_CMD:
                IS_FWI2_CAPABLE(ha) ?
-               qla24xx_ct_iocb(sp, pkt) :
-               qla2x00_ct_iocb(sp, pkt);
+                   qla24xx_ct_iocb(sp, pkt) :
+                   qla2x00_ct_iocb(sp, pkt);
                break;
        case SRB_ADISC_CMD:
                IS_FWI2_CAPABLE(ha) ?