diff options
author | Anirban Chakraborty <anirban.chakraborty@qlogic.com> | 2008-12-09 19:45:39 -0500 |
---|---|---|
committer | James Bottomley <James.Bottomley@HansenPartnership.com> | 2008-12-29 12:24:33 -0500 |
commit | 73208dfd7ab19f379d73e8a0fbf30f92c203e5e8 (patch) | |
tree | f69be5e89817d17b066ece4dbe04e395339c0754 /drivers/scsi/qla2xxx/qla_mbx.c | |
parent | 85b4aa4926a50210b683ac89326e338e7d131211 (diff) |
[SCSI] qla2xxx: add support for multi-queue adapter
Following changes have been made.
1. qla_hw_data structure holds an array for request queue pointers,
and an array for response queue pointers.
2. The base request and response queues are created by default.
3. Additional request and response queues are created at the time of vport
creation. If queue resources are exhausted during vport creation, newly
created vports use the default queue.
4. Requests are sent to the request queue that the vport was assigned
in the beginning.
5. Responses are completed on the response queue with which the request queue
is associated with.
[fixup memcpy argument reversal spotted by davej@redhat.com]
Signed-off-by: Anirban Chakraborty <anirban.chakraborty@qlogic.com>
Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
Diffstat (limited to 'drivers/scsi/qla2xxx/qla_mbx.c')
-rw-r--r-- | drivers/scsi/qla2xxx/qla_mbx.c | 147 |
1 files changed, 133 insertions, 14 deletions
diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c index bbe7181fb3d5..c54bc977c7b8 100644 --- a/drivers/scsi/qla2xxx/qla_mbx.c +++ b/drivers/scsi/qla2xxx/qla_mbx.c | |||
@@ -153,7 +153,7 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp) | |||
153 | break; | 153 | break; |
154 | 154 | ||
155 | /* Check for pending interrupts. */ | 155 | /* Check for pending interrupts. */ |
156 | qla2x00_poll(ha->rsp); | 156 | qla2x00_poll(ha->rsp_q_map[0]); |
157 | 157 | ||
158 | if (command != MBC_LOAD_RISC_RAM_EXTENDED && | 158 | if (command != MBC_LOAD_RISC_RAM_EXTENDED && |
159 | !ha->flags.mbox_int) | 159 | !ha->flags.mbox_int) |
@@ -223,7 +223,7 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp) | |||
223 | "interrupt.\n", __func__, base_vha->host_no)); | 223 | "interrupt.\n", __func__, base_vha->host_no)); |
224 | 224 | ||
225 | /* polling mode for non isp_abort commands. */ | 225 | /* polling mode for non isp_abort commands. */ |
226 | qla2x00_poll(ha->rsp); | 226 | qla2x00_poll(ha->rsp_q_map[0]); |
227 | } | 227 | } |
228 | 228 | ||
229 | if (rval == QLA_FUNCTION_TIMEOUT && | 229 | if (rval == QLA_FUNCTION_TIMEOUT && |
@@ -713,8 +713,6 @@ qla2x00_issue_iocb_timeout(scsi_qla_host_t *vha, void *buffer, | |||
713 | /*EMPTY*/ | 713 | /*EMPTY*/ |
714 | DEBUG(printk("qla2x00_issue_iocb(%ld): failed rval 0x%x\n", | 714 | DEBUG(printk("qla2x00_issue_iocb(%ld): failed rval 0x%x\n", |
715 | vha->host_no, rval)); | 715 | vha->host_no, rval)); |
716 | DEBUG2(printk("qla2x00_issue_iocb(%ld): failed rval 0x%x\n", | ||
717 | vha->host_no, rval)); | ||
718 | } else { | 716 | } else { |
719 | sts_entry_t *sts_entry = (sts_entry_t *) buffer; | 717 | sts_entry_t *sts_entry = (sts_entry_t *) buffer; |
720 | 718 | ||
@@ -749,16 +747,15 @@ qla2x00_issue_iocb(scsi_qla_host_t *vha, void *buffer, dma_addr_t phys_addr, | |||
749 | * Kernel context. | 747 | * Kernel context. |
750 | */ | 748 | */ |
751 | int | 749 | int |
752 | qla2x00_abort_command(scsi_qla_host_t *vha, srb_t *sp) | 750 | qla2x00_abort_command(scsi_qla_host_t *vha, srb_t *sp, struct req_que *req) |
753 | { | 751 | { |
754 | unsigned long flags = 0; | 752 | unsigned long flags = 0; |
755 | fc_port_t *fcport; | 753 | fc_port_t *fcport; |
756 | int rval; | 754 | int rval; |
757 | uint32_t handle; | 755 | uint32_t handle = 0; |
758 | mbx_cmd_t mc; | 756 | mbx_cmd_t mc; |
759 | mbx_cmd_t *mcp = &mc; | 757 | mbx_cmd_t *mcp = &mc; |
760 | struct qla_hw_data *ha = vha->hw; | 758 | struct qla_hw_data *ha = vha->hw; |
761 | struct req_que *req = ha->req; | ||
762 | 759 | ||
763 | DEBUG11(printk("qla2x00_abort_command(%ld): entered.\n", vha->host_no)); | 760 | DEBUG11(printk("qla2x00_abort_command(%ld): entered.\n", vha->host_no)); |
764 | 761 | ||
@@ -808,11 +805,15 @@ qla2x00_abort_target(struct fc_port *fcport, unsigned int l) | |||
808 | mbx_cmd_t mc; | 805 | mbx_cmd_t mc; |
809 | mbx_cmd_t *mcp = &mc; | 806 | mbx_cmd_t *mcp = &mc; |
810 | scsi_qla_host_t *vha; | 807 | scsi_qla_host_t *vha; |
808 | struct req_que *req; | ||
809 | struct rsp_que *rsp; | ||
811 | 810 | ||
812 | DEBUG11(printk("%s(%ld): entered.\n", __func__, fcport->vha->host_no)); | 811 | DEBUG11(printk("%s(%ld): entered.\n", __func__, fcport->vha->host_no)); |
813 | 812 | ||
814 | l = l; | 813 | l = l; |
815 | vha = fcport->vha; | 814 | vha = fcport->vha; |
815 | req = vha->hw->req_q_map[0]; | ||
816 | rsp = vha->hw->rsp_q_map[0]; | ||
816 | mcp->mb[0] = MBC_ABORT_TARGET; | 817 | mcp->mb[0] = MBC_ABORT_TARGET; |
817 | mcp->out_mb = MBX_9|MBX_2|MBX_1|MBX_0; | 818 | mcp->out_mb = MBX_9|MBX_2|MBX_1|MBX_0; |
818 | if (HAS_EXTENDED_IDS(vha->hw)) { | 819 | if (HAS_EXTENDED_IDS(vha->hw)) { |
@@ -835,7 +836,8 @@ qla2x00_abort_target(struct fc_port *fcport, unsigned int l) | |||
835 | } | 836 | } |
836 | 837 | ||
837 | /* Issue marker IOCB. */ | 838 | /* Issue marker IOCB. */ |
838 | rval2 = qla2x00_marker(vha, fcport->loop_id, 0, MK_SYNC_ID); | 839 | rval2 = qla2x00_marker(vha, req, rsp, fcport->loop_id, 0, |
840 | MK_SYNC_ID); | ||
839 | if (rval2 != QLA_SUCCESS) { | 841 | if (rval2 != QLA_SUCCESS) { |
840 | DEBUG2_3_11(printk("%s(%ld): failed to issue Marker IOCB " | 842 | DEBUG2_3_11(printk("%s(%ld): failed to issue Marker IOCB " |
841 | "(%x).\n", __func__, vha->host_no, rval2)); | 843 | "(%x).\n", __func__, vha->host_no, rval2)); |
@@ -853,10 +855,14 @@ qla2x00_lun_reset(struct fc_port *fcport, unsigned int l) | |||
853 | mbx_cmd_t mc; | 855 | mbx_cmd_t mc; |
854 | mbx_cmd_t *mcp = &mc; | 856 | mbx_cmd_t *mcp = &mc; |
855 | scsi_qla_host_t *vha; | 857 | scsi_qla_host_t *vha; |
858 | struct req_que *req; | ||
859 | struct rsp_que *rsp; | ||
856 | 860 | ||
857 | DEBUG11(printk("%s(%ld): entered.\n", __func__, fcport->vha->host_no)); | 861 | DEBUG11(printk("%s(%ld): entered.\n", __func__, fcport->vha->host_no)); |
858 | 862 | ||
859 | vha = fcport->vha; | 863 | vha = fcport->vha; |
864 | req = vha->hw->req_q_map[0]; | ||
865 | rsp = vha->hw->rsp_q_map[0]; | ||
860 | mcp->mb[0] = MBC_LUN_RESET; | 866 | mcp->mb[0] = MBC_LUN_RESET; |
861 | mcp->out_mb = MBX_9|MBX_3|MBX_2|MBX_1|MBX_0; | 867 | mcp->out_mb = MBX_9|MBX_3|MBX_2|MBX_1|MBX_0; |
862 | if (HAS_EXTENDED_IDS(vha->hw)) | 868 | if (HAS_EXTENDED_IDS(vha->hw)) |
@@ -877,7 +883,8 @@ qla2x00_lun_reset(struct fc_port *fcport, unsigned int l) | |||
877 | } | 883 | } |
878 | 884 | ||
879 | /* Issue marker IOCB. */ | 885 | /* Issue marker IOCB. */ |
880 | rval2 = qla2x00_marker(vha, fcport->loop_id, l, MK_SYNC_ID_LUN); | 886 | rval2 = qla2x00_marker(vha, req, rsp, fcport->loop_id, l, |
887 | MK_SYNC_ID_LUN); | ||
881 | if (rval2 != QLA_SUCCESS) { | 888 | if (rval2 != QLA_SUCCESS) { |
882 | DEBUG2_3_11(printk("%s(%ld): failed to issue Marker IOCB " | 889 | DEBUG2_3_11(printk("%s(%ld): failed to issue Marker IOCB " |
883 | "(%x).\n", __func__, vha->host_no, rval2)); | 890 | "(%x).\n", __func__, vha->host_no, rval2)); |
@@ -1743,6 +1750,7 @@ qla24xx_fabric_logout(scsi_qla_host_t *vha, uint16_t loop_id, uint8_t domain, | |||
1743 | lg->port_id[1] = area; | 1750 | lg->port_id[1] = area; |
1744 | lg->port_id[2] = domain; | 1751 | lg->port_id[2] = domain; |
1745 | lg->vp_index = vha->vp_idx; | 1752 | lg->vp_index = vha->vp_idx; |
1753 | |||
1746 | rval = qla2x00_issue_iocb(vha, lg, lg_dma, 0); | 1754 | rval = qla2x00_issue_iocb(vha, lg, lg_dma, 0); |
1747 | if (rval != QLA_SUCCESS) { | 1755 | if (rval != QLA_SUCCESS) { |
1748 | DEBUG2_3_11(printk("%s(%ld): failed to issue Logout IOCB " | 1756 | DEBUG2_3_11(printk("%s(%ld): failed to issue Logout IOCB " |
@@ -1753,9 +1761,9 @@ qla24xx_fabric_logout(scsi_qla_host_t *vha, uint16_t loop_id, uint8_t domain, | |||
1753 | lg->entry_status)); | 1761 | lg->entry_status)); |
1754 | rval = QLA_FUNCTION_FAILED; | 1762 | rval = QLA_FUNCTION_FAILED; |
1755 | } else if (lg->comp_status != __constant_cpu_to_le16(CS_COMPLETE)) { | 1763 | } else if (lg->comp_status != __constant_cpu_to_le16(CS_COMPLETE)) { |
1756 | DEBUG2_3_11(printk("%s(%ld): failed to complete IOCB " | 1764 | DEBUG2_3_11(printk("%s(%ld %d): failed to complete IOCB " |
1757 | "-- completion status (%x) ioparam=%x/%x.\n", __func__, | 1765 | "-- completion status (%x) ioparam=%x/%x.\n", __func__, |
1758 | vha->host_no, le16_to_cpu(lg->comp_status), | 1766 | vha->host_no, vha->vp_idx, le16_to_cpu(lg->comp_status), |
1759 | le32_to_cpu(lg->io_parameter[0]), | 1767 | le32_to_cpu(lg->io_parameter[0]), |
1760 | le32_to_cpu(lg->io_parameter[1]))); | 1768 | le32_to_cpu(lg->io_parameter[1]))); |
1761 | } else { | 1769 | } else { |
@@ -2173,7 +2181,7 @@ qla24xx_get_isp_stats(scsi_qla_host_t *vha, struct link_statistics *stats, | |||
2173 | } | 2181 | } |
2174 | 2182 | ||
2175 | int | 2183 | int |
2176 | qla24xx_abort_command(scsi_qla_host_t *vha, srb_t *sp) | 2184 | qla24xx_abort_command(scsi_qla_host_t *vha, srb_t *sp, struct req_que *req) |
2177 | { | 2185 | { |
2178 | int rval; | 2186 | int rval; |
2179 | fc_port_t *fcport; | 2187 | fc_port_t *fcport; |
@@ -2183,7 +2191,6 @@ qla24xx_abort_command(scsi_qla_host_t *vha, srb_t *sp) | |||
2183 | dma_addr_t abt_dma; | 2191 | dma_addr_t abt_dma; |
2184 | uint32_t handle; | 2192 | uint32_t handle; |
2185 | struct qla_hw_data *ha = vha->hw; | 2193 | struct qla_hw_data *ha = vha->hw; |
2186 | struct req_que *req = ha->req; | ||
2187 | 2194 | ||
2188 | DEBUG11(printk("%s(%ld): entered.\n", __func__, vha->host_no)); | 2195 | DEBUG11(printk("%s(%ld): entered.\n", __func__, vha->host_no)); |
2189 | 2196 | ||
@@ -2216,6 +2223,9 @@ qla24xx_abort_command(scsi_qla_host_t *vha, srb_t *sp) | |||
2216 | abt->port_id[1] = fcport->d_id.b.area; | 2223 | abt->port_id[1] = fcport->d_id.b.area; |
2217 | abt->port_id[2] = fcport->d_id.b.domain; | 2224 | abt->port_id[2] = fcport->d_id.b.domain; |
2218 | abt->vp_index = fcport->vp_idx; | 2225 | abt->vp_index = fcport->vp_idx; |
2226 | |||
2227 | abt->req_que_no = cpu_to_le16(req->id); | ||
2228 | |||
2219 | rval = qla2x00_issue_iocb(vha, abt, abt_dma, 0); | 2229 | rval = qla2x00_issue_iocb(vha, abt, abt_dma, 0); |
2220 | if (rval != QLA_SUCCESS) { | 2230 | if (rval != QLA_SUCCESS) { |
2221 | DEBUG2_3_11(printk("%s(%ld): failed to issue IOCB (%x).\n", | 2231 | DEBUG2_3_11(printk("%s(%ld): failed to issue IOCB (%x).\n", |
@@ -2255,11 +2265,15 @@ __qla24xx_issue_tmf(char *name, uint32_t type, struct fc_port *fcport, | |||
2255 | dma_addr_t tsk_dma; | 2265 | dma_addr_t tsk_dma; |
2256 | scsi_qla_host_t *vha; | 2266 | scsi_qla_host_t *vha; |
2257 | struct qla_hw_data *ha; | 2267 | struct qla_hw_data *ha; |
2268 | struct req_que *req; | ||
2269 | struct rsp_que *rsp; | ||
2258 | 2270 | ||
2259 | DEBUG11(printk("%s(%ld): entered.\n", __func__, fcport->vha->host_no)); | 2271 | DEBUG11(printk("%s(%ld): entered.\n", __func__, fcport->vha->host_no)); |
2260 | 2272 | ||
2261 | vha = fcport->vha; | 2273 | vha = fcport->vha; |
2262 | ha = vha->hw; | 2274 | ha = vha->hw; |
2275 | req = ha->req_q_map[0]; | ||
2276 | rsp = ha->rsp_q_map[0]; | ||
2263 | tsk = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &tsk_dma); | 2277 | tsk = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &tsk_dma); |
2264 | if (tsk == NULL) { | 2278 | if (tsk == NULL) { |
2265 | DEBUG2_3(printk("%s(%ld): failed to allocate Task Management " | 2279 | DEBUG2_3(printk("%s(%ld): failed to allocate Task Management " |
@@ -2301,7 +2315,7 @@ __qla24xx_issue_tmf(char *name, uint32_t type, struct fc_port *fcport, | |||
2301 | } | 2315 | } |
2302 | 2316 | ||
2303 | /* Issue marker IOCB. */ | 2317 | /* Issue marker IOCB. */ |
2304 | rval2 = qla2x00_marker(vha, fcport->loop_id, l, | 2318 | rval2 = qla2x00_marker(vha, req, rsp, fcport->loop_id, l, |
2305 | type == TCF_LUN_RESET ? MK_SYNC_ID_LUN: MK_SYNC_ID); | 2319 | type == TCF_LUN_RESET ? MK_SYNC_ID_LUN: MK_SYNC_ID); |
2306 | if (rval2 != QLA_SUCCESS) { | 2320 | if (rval2 != QLA_SUCCESS) { |
2307 | DEBUG2_3_11(printk("%s(%ld): failed to issue Marker IOCB " | 2321 | DEBUG2_3_11(printk("%s(%ld): failed to issue Marker IOCB " |
@@ -3069,3 +3083,108 @@ verify_done: | |||
3069 | 3083 | ||
3070 | return rval; | 3084 | return rval; |
3071 | } | 3085 | } |
3086 | |||
3087 | int | ||
3088 | qla25xx_init_req_que(struct scsi_qla_host *vha, struct req_que *req, | ||
3089 | uint8_t options) | ||
3090 | { | ||
3091 | int rval; | ||
3092 | unsigned long flags; | ||
3093 | mbx_cmd_t mc; | ||
3094 | mbx_cmd_t *mcp = &mc; | ||
3095 | struct device_reg_25xxmq __iomem *reg; | ||
3096 | struct qla_hw_data *ha = vha->hw; | ||
3097 | |||
3098 | mcp->mb[0] = MBC_INITIALIZE_MULTIQ; | ||
3099 | mcp->mb[1] = options; | ||
3100 | mcp->mb[2] = MSW(LSD(req->dma)); | ||
3101 | mcp->mb[3] = LSW(LSD(req->dma)); | ||
3102 | mcp->mb[6] = MSW(MSD(req->dma)); | ||
3103 | mcp->mb[7] = LSW(MSD(req->dma)); | ||
3104 | mcp->mb[5] = req->length; | ||
3105 | if (req->rsp) | ||
3106 | mcp->mb[10] = req->rsp->id; | ||
3107 | mcp->mb[12] = req->qos; | ||
3108 | mcp->mb[11] = req->vp_idx; | ||
3109 | mcp->mb[13] = req->rid; | ||
3110 | |||
3111 | reg = (struct device_reg_25xxmq *)((void *)(ha->mqiobase) + | ||
3112 | QLA_QUE_PAGE * req->id); | ||
3113 | |||
3114 | mcp->mb[4] = req->id; | ||
3115 | /* que in ptr index */ | ||
3116 | mcp->mb[8] = 0; | ||
3117 | /* que out ptr index */ | ||
3118 | mcp->mb[9] = 0; | ||
3119 | mcp->out_mb = MBX_14|MBX_13|MBX_12|MBX_11|MBX_10|MBX_9|MBX_8|MBX_7| | ||
3120 | MBX_6|MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0; | ||
3121 | mcp->in_mb = MBX_0; | ||
3122 | mcp->flags = MBX_DMA_OUT; | ||
3123 | mcp->tov = 60; | ||
3124 | |||
3125 | spin_lock_irqsave(&ha->hardware_lock, flags); | ||
3126 | if (!(options & BIT_0)) { | ||
3127 | WRT_REG_DWORD(®->req_q_in, 0); | ||
3128 | WRT_REG_DWORD(®->req_q_out, 0); | ||
3129 | } | ||
3130 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | ||
3131 | |||
3132 | rval = (int)qla2x00_mailbox_command(vha, mcp); | ||
3133 | if (rval != QLA_SUCCESS) | ||
3134 | DEBUG2_3_11(printk(KERN_WARNING "%s(%ld): failed=%x mb0=%x.\n", | ||
3135 | __func__, vha->host_no, rval, mcp->mb[0])); | ||
3136 | return rval; | ||
3137 | } | ||
3138 | |||
3139 | int | ||
3140 | qla25xx_init_rsp_que(struct scsi_qla_host *vha, struct rsp_que *rsp, | ||
3141 | uint8_t options) | ||
3142 | { | ||
3143 | int rval; | ||
3144 | unsigned long flags; | ||
3145 | mbx_cmd_t mc; | ||
3146 | mbx_cmd_t *mcp = &mc; | ||
3147 | struct device_reg_25xxmq __iomem *reg; | ||
3148 | struct qla_hw_data *ha = vha->hw; | ||
3149 | |||
3150 | mcp->mb[0] = MBC_INITIALIZE_MULTIQ; | ||
3151 | mcp->mb[1] = options; | ||
3152 | mcp->mb[2] = MSW(LSD(rsp->dma)); | ||
3153 | mcp->mb[3] = LSW(LSD(rsp->dma)); | ||
3154 | mcp->mb[6] = MSW(MSD(rsp->dma)); | ||
3155 | mcp->mb[7] = LSW(MSD(rsp->dma)); | ||
3156 | mcp->mb[5] = rsp->length; | ||
3157 | mcp->mb[11] = rsp->vp_idx; | ||
3158 | mcp->mb[14] = rsp->msix->vector; | ||
3159 | mcp->mb[13] = rsp->rid; | ||
3160 | |||
3161 | reg = (struct device_reg_25xxmq *)((void *)(ha->mqiobase) + | ||
3162 | QLA_QUE_PAGE * rsp->id); | ||
3163 | |||
3164 | mcp->mb[4] = rsp->id; | ||
3165 | /* que in ptr index */ | ||
3166 | mcp->mb[8] = 0; | ||
3167 | /* que out ptr index */ | ||
3168 | mcp->mb[9] = 0; | ||
3169 | mcp->out_mb = MBX_14|MBX_13|MBX_12|MBX_11|MBX_10|MBX_9|MBX_8|MBX_7 | ||
3170 | |MBX_6|MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0; | ||
3171 | mcp->in_mb = MBX_0; | ||
3172 | mcp->flags = MBX_DMA_OUT; | ||
3173 | mcp->tov = 60; | ||
3174 | |||
3175 | spin_lock_irqsave(&ha->hardware_lock, flags); | ||
3176 | if (!(options & BIT_0)) { | ||
3177 | WRT_REG_DWORD(®->rsp_q_out, 0); | ||
3178 | WRT_REG_DWORD(®->rsp_q_in, 0); | ||
3179 | } | ||
3180 | |||
3181 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | ||
3182 | |||
3183 | rval = (int)qla2x00_mailbox_command(vha, mcp); | ||
3184 | if (rval != QLA_SUCCESS) | ||
3185 | DEBUG2_3_11(printk(KERN_WARNING "%s(%ld): failed=%x " | ||
3186 | "mb0=%x.\n", __func__, | ||
3187 | vha->host_no, rval, mcp->mb[0])); | ||
3188 | return rval; | ||
3189 | } | ||
3190 | |||