diff options
author | Giridhar Malavali <giridhar.malavali@qlogic.com> | 2010-02-18 13:07:24 -0500 |
---|---|---|
committer | James Bottomley <James.Bottomley@suse.de> | 2010-02-19 11:44:52 -0500 |
commit | db3ad7f8852cfdfa03f72b27472e5a8bc9c1e1cf (patch) | |
tree | cf71e747b4844cf20e73fd582ee63d38ec7e0080 /drivers | |
parent | 236b0249c2274cd24bc98a1fbbb5e78d861d4bd9 (diff) |
[SCSI] qla2xxx: Proper clean-up of BSG requests when request times out.
Fix for BSG request cleanup when the request timesout.
Proper release of driver resources used for BSG request during timeout cleanup.
Cc: stable@kernel.org
Signed-off-by: Giridhar Malavali <giridhar.malavali@qlogic.com>
Signed-off-by: James Bottomley <James.Bottomley@suse.de>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/scsi/qla2xxx/qla_attr.c | 125 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_os.c | 15 |
2 files changed, 67 insertions, 73 deletions
diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c index cbce52eb9b94..25596feea162 100644 --- a/drivers/scsi/qla2xxx/qla_attr.c +++ b/drivers/scsi/qla2xxx/qla_attr.c | |||
@@ -1882,12 +1882,6 @@ qla2x00_process_els(struct fc_bsg_job *bsg_job) | |||
1882 | ha = vha->hw; | 1882 | ha = vha->hw; |
1883 | type = "FC_BSG_RPT_ELS"; | 1883 | type = "FC_BSG_RPT_ELS"; |
1884 | 1884 | ||
1885 | DEBUG2(printk(KERN_INFO | ||
1886 | "scsi(%ld): loop-id=%x portid=%02x%02x%02x.\n", | ||
1887 | fcport->vha->host_no, fcport->loop_id, | ||
1888 | fcport->d_id.b.domain, fcport->d_id.b.area, | ||
1889 | fcport->d_id.b.al_pa)); | ||
1890 | |||
1891 | /* make sure the rport is logged in, | 1885 | /* make sure the rport is logged in, |
1892 | * if not perform fabric login | 1886 | * if not perform fabric login |
1893 | */ | 1887 | */ |
@@ -1904,11 +1898,6 @@ qla2x00_process_els(struct fc_bsg_job *bsg_job) | |||
1904 | ha = vha->hw; | 1898 | ha = vha->hw; |
1905 | type = "FC_BSG_HST_ELS_NOLOGIN"; | 1899 | type = "FC_BSG_HST_ELS_NOLOGIN"; |
1906 | 1900 | ||
1907 | DEBUG2(printk(KERN_INFO | ||
1908 | "scsi(%ld): loop-id=%x portid=%02x%02x%02x.\n", | ||
1909 | vha->host_no, vha->loop_id, | ||
1910 | vha->d_id.b.domain, vha->d_id.b.area, vha->d_id.b.al_pa)); | ||
1911 | |||
1912 | /* Allocate a dummy fcport structure, since functions | 1901 | /* Allocate a dummy fcport structure, since functions |
1913 | * preparing the IOCB and mailbox command retrieves port | 1902 | * preparing the IOCB and mailbox command retrieves port |
1914 | * specific information from fcport structure. For Host based | 1903 | * specific information from fcport structure. For Host based |
@@ -1934,9 +1923,12 @@ qla2x00_process_els(struct fc_bsg_job *bsg_job) | |||
1934 | NPH_FABRIC_CONTROLLER : NPH_F_PORT; | 1923 | NPH_FABRIC_CONTROLLER : NPH_F_PORT; |
1935 | } | 1924 | } |
1936 | 1925 | ||
1937 | DEBUG2(printk(KERN_INFO | 1926 | if (!vha->flags.online) { |
1938 | "scsi(%ld): vendor-id = %llu\n", | 1927 | DEBUG2(qla_printk(KERN_WARNING, ha, |
1939 | vha->host_no, host->hostt->vendor_id)); | 1928 | "host not online\n")); |
1929 | rval = -EIO; | ||
1930 | goto done; | ||
1931 | } | ||
1940 | 1932 | ||
1941 | req_sg_cnt = | 1933 | req_sg_cnt = |
1942 | dma_map_sg(&ha->pdev->dev, bsg_job->request_payload.sg_list, | 1934 | dma_map_sg(&ha->pdev->dev, bsg_job->request_payload.sg_list, |
@@ -2059,6 +2051,13 @@ qla2x00_process_ct(struct fc_bsg_job *bsg_job) | |||
2059 | goto done_unmap_sg; | 2051 | goto done_unmap_sg; |
2060 | } | 2052 | } |
2061 | 2053 | ||
2054 | if (!vha->flags.online) { | ||
2055 | DEBUG2(qla_printk(KERN_WARNING, ha, | ||
2056 | "host not online\n")); | ||
2057 | rval = -EIO; | ||
2058 | goto done_unmap_sg; | ||
2059 | } | ||
2060 | |||
2062 | loop_id = | 2061 | loop_id = |
2063 | (bsg_job->request->rqst_data.h_ct.preamble_word1 & 0xFF000000) | 2062 | (bsg_job->request->rqst_data.h_ct.preamble_word1 & 0xFF000000) |
2064 | >> 24; | 2063 | >> 24; |
@@ -2161,6 +2160,13 @@ qla2x00_process_vendor_specific(struct fc_bsg_job *bsg_job) | |||
2161 | goto done; | 2160 | goto done; |
2162 | } | 2161 | } |
2163 | 2162 | ||
2163 | if (!vha->flags.online) { | ||
2164 | DEBUG2(qla_printk(KERN_WARNING, ha, | ||
2165 | "host not online\n")); | ||
2166 | rval = -EIO; | ||
2167 | goto done; | ||
2168 | } | ||
2169 | |||
2164 | elreq.req_sg_cnt = | 2170 | elreq.req_sg_cnt = |
2165 | dma_map_sg(&ha->pdev->dev, bsg_job->request_payload.sg_list, | 2171 | dma_map_sg(&ha->pdev->dev, bsg_job->request_payload.sg_list, |
2166 | bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE); | 2172 | bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE); |
@@ -2219,20 +2225,10 @@ qla2x00_process_vendor_specific(struct fc_bsg_job *bsg_job) | |||
2219 | if (ha->current_topology != ISP_CFG_F) { | 2225 | if (ha->current_topology != ISP_CFG_F) { |
2220 | type = "FC_BSG_HST_VENDOR_LOOPBACK"; | 2226 | type = "FC_BSG_HST_VENDOR_LOOPBACK"; |
2221 | 2227 | ||
2222 | if ((IS_QLA81XX(ha)) && | ||
2223 | ((elreq.options == 0) || (elreq.options == 2))) { | ||
2224 | DEBUG2(qla_printk(KERN_INFO, ha, "scsi(%ld)" | ||
2225 | "loopback option:0x%x not supported\n", vha->host_no, elreq.options)); | ||
2226 | rval = -EINVAL; | ||
2227 | goto done_unmap_sg; | ||
2228 | } | ||
2229 | |||
2230 | DEBUG2(qla_printk(KERN_INFO, ha, | 2228 | DEBUG2(qla_printk(KERN_INFO, ha, |
2231 | "scsi(%ld) bsg rqst type: %s vendor rqst type: %x options: %x.\n", | 2229 | "scsi(%ld) bsg rqst type: %s vendor rqst type: %x options: %x.\n", |
2232 | vha->host_no, type, vendor_cmd, elreq.options)); | 2230 | vha->host_no, type, vendor_cmd, elreq.options)); |
2233 | DEBUG2(qla_printk(KERN_INFO, ha, | 2231 | |
2234 | "scsi(%ld) tx_addr: 0x%llx rx_addr: 0x%llx tx_sg_cnt: %x rx_sg_cnt: %x\n", | ||
2235 | vha->host_no, (unsigned long long)elreq.send_dma, (unsigned long long)elreq.rcv_dma, elreq.req_sg_cnt, elreq.rsp_sg_cnt)); | ||
2236 | command_sent = INT_DEF_LB_LOOPBACK_CMD; | 2232 | command_sent = INT_DEF_LB_LOOPBACK_CMD; |
2237 | rval = qla2x00_loopback_test(vha, &elreq, response); | 2233 | rval = qla2x00_loopback_test(vha, &elreq, response); |
2238 | if (IS_QLA81XX(ha)) { | 2234 | if (IS_QLA81XX(ha)) { |
@@ -2248,9 +2244,7 @@ qla2x00_process_vendor_specific(struct fc_bsg_job *bsg_job) | |||
2248 | DEBUG2(qla_printk(KERN_INFO, ha, | 2244 | DEBUG2(qla_printk(KERN_INFO, ha, |
2249 | "scsi(%ld) bsg rqst type: %s vendor rqst type: %x options: %x.\n", | 2245 | "scsi(%ld) bsg rqst type: %s vendor rqst type: %x options: %x.\n", |
2250 | vha->host_no, type, vendor_cmd, elreq.options)); | 2246 | vha->host_no, type, vendor_cmd, elreq.options)); |
2251 | DEBUG2(qla_printk(KERN_INFO, ha, | 2247 | |
2252 | "scsi(%ld) tx_addr: 0x%llx rx_addr: 0x%llx tx_sg_cnt: %x rx_sg_cnt: %x\n", | ||
2253 | vha->host_no, (unsigned long long)elreq.send_dma, (unsigned long long)elreq.rcv_dma, elreq.req_sg_cnt, elreq.rsp_sg_cnt)); | ||
2254 | command_sent = INT_DEF_LB_ECHO_CMD; | 2248 | command_sent = INT_DEF_LB_ECHO_CMD; |
2255 | rval = qla2x00_echo_test(vha, &elreq, response); | 2249 | rval = qla2x00_echo_test(vha, &elreq, response); |
2256 | } | 2250 | } |
@@ -2353,60 +2347,49 @@ qla24xx_bsg_timeout(struct fc_bsg_job *bsg_job) | |||
2353 | scsi_qla_host_t *vha = shost_priv(bsg_job->shost); | 2347 | scsi_qla_host_t *vha = shost_priv(bsg_job->shost); |
2354 | struct qla_hw_data *ha = vha->hw; | 2348 | struct qla_hw_data *ha = vha->hw; |
2355 | srb_t *sp; | 2349 | srb_t *sp; |
2356 | int i; | 2350 | int cnt, que; |
2357 | unsigned long flags; | 2351 | unsigned long flags; |
2358 | uint16_t que_id; | ||
2359 | struct req_que *req; | 2352 | struct req_que *req; |
2360 | struct rsp_que *rsp; | ||
2361 | int found = 0; | ||
2362 | struct srb_bsg *sp_bsg; | 2353 | struct srb_bsg *sp_bsg; |
2363 | 2354 | ||
2364 | /* find the bsg job from the active list of commands */ | 2355 | /* find the bsg job from the active list of commands */ |
2365 | spin_lock_irqsave(&ha->hardware_lock, flags); | 2356 | spin_lock_irqsave(&ha->hardware_lock, flags); |
2366 | req = ha->req_q_map[0]; | 2357 | for (que = 0; que < ha->max_req_queues; que++) { |
2367 | que_id = req->id; | 2358 | req = ha->req_q_map[que]; |
2368 | if (req->rsp) | 2359 | if (!req) |
2369 | rsp = req->rsp; | 2360 | continue; |
2370 | else | ||
2371 | rsp = ha->rsp_q_map[que_id]; | ||
2372 | |||
2373 | for (i = 1; i < MAX_OUTSTANDING_COMMANDS; i++ ) { | ||
2374 | sp = req->outstanding_cmds[i]; | ||
2375 | |||
2376 | if (sp == NULL) | ||
2377 | continue; | ||
2378 | |||
2379 | sp_bsg = (struct srb_bsg*)sp->ctx; | ||
2380 | 2361 | ||
2381 | if (((sp_bsg->ctx.type == SRB_CT_CMD) || | 2362 | for (cnt = 1; cnt < MAX_OUTSTANDING_COMMANDS; cnt++ ) { |
2382 | (sp_bsg->ctx.type == SRB_ELS_CMD_RPT) | 2363 | sp = req->outstanding_cmds[cnt]; |
2383 | || ( sp_bsg->ctx.type == SRB_ELS_CMD_HST)) && | 2364 | |
2384 | (sp_bsg->bsg_job == bsg_job)) { | 2365 | if (sp) { |
2385 | DEBUG2(qla_printk(KERN_INFO, ha, | 2366 | sp_bsg = (struct srb_bsg*)sp->ctx; |
2386 | "scsi(%ld) req_q: %p rsp_q: %p que_id: %x sp: %p\n", | 2367 | |
2387 | vha->host_no, req, rsp, que_id, sp)); | 2368 | if (((sp_bsg->ctx.type == SRB_CT_CMD) || |
2388 | found = 1; | 2369 | (sp_bsg->ctx.type == SRB_ELS_CMD_RPT) |
2389 | break; | 2370 | || ( sp_bsg->ctx.type == SRB_ELS_CMD_HST)) && |
2371 | (sp_bsg->bsg_job == bsg_job)) { | ||
2372 | if (ha->isp_ops->abort_command(sp)) { | ||
2373 | DEBUG2(qla_printk(KERN_INFO, ha, | ||
2374 | "scsi(%ld): mbx abort_command failed\n", vha->host_no)); | ||
2375 | bsg_job->req->errors = bsg_job->reply->result = -EIO; | ||
2376 | } else { | ||
2377 | DEBUG2(qla_printk(KERN_INFO, ha, | ||
2378 | "scsi(%ld): mbx abort_command success\n", vha->host_no)); | ||
2379 | bsg_job->req->errors = bsg_job->reply->result = 0; | ||
2380 | } | ||
2381 | goto done; | ||
2382 | } | ||
2383 | } | ||
2390 | } | 2384 | } |
2391 | } | 2385 | } |
2392 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | 2386 | spin_unlock_irqrestore(&ha->hardware_lock, flags); |
2393 | if (!found) { | 2387 | DEBUG2(qla_printk(KERN_INFO, ha, |
2394 | DEBUG2(qla_printk(KERN_INFO, ha, | 2388 | "scsi(%ld) SRB not found to abort\n", vha->host_no)); |
2395 | "scsi(%ld) SRB not found to abort\n", vha->host_no)); | 2389 | bsg_job->req->errors = bsg_job->reply->result = -ENXIO; |
2396 | bsg_job->req->errors = bsg_job->reply->result = -ENXIO; | 2390 | return 0; |
2397 | return 0; | ||
2398 | } | ||
2399 | |||
2400 | if (ha->isp_ops->abort_command(sp)) { | ||
2401 | DEBUG2(qla_printk(KERN_INFO, ha, | ||
2402 | "scsi(%ld): mbx abort_command failed\n", vha->host_no)); | ||
2403 | bsg_job->req->errors = bsg_job->reply->result = -EIO; | ||
2404 | } else { | ||
2405 | DEBUG2(qla_printk(KERN_INFO, ha, | ||
2406 | "scsi(%ld): mbx abort_command success\n", vha->host_no)); | ||
2407 | bsg_job->req->errors = bsg_job->reply->result = 0; | ||
2408 | } | ||
2409 | 2391 | ||
2392 | done: | ||
2410 | if (bsg_job->request->msgcode == FC_BSG_HST_CT) | 2393 | if (bsg_job->request->msgcode == FC_BSG_HST_CT) |
2411 | kfree(sp->fcport); | 2394 | kfree(sp->fcport); |
2412 | kfree(sp->ctx); | 2395 | kfree(sp->ctx); |
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 82e57d778428..83615e71fa0d 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c | |||
@@ -1160,8 +1160,19 @@ qla2x00_abort_all_cmds(scsi_qla_host_t *vha, int res) | |||
1160 | qla2x00_sp_compl(ha, sp); | 1160 | qla2x00_sp_compl(ha, sp); |
1161 | } else { | 1161 | } else { |
1162 | ctx = sp->ctx; | 1162 | ctx = sp->ctx; |
1163 | del_timer_sync(&ctx->timer); | 1163 | if (ctx->type == SRB_LOGIN_CMD || ctx->type == SRB_LOGOUT_CMD) { |
1164 | ctx->free(sp); | 1164 | del_timer_sync(&ctx->timer); |
1165 | ctx->free(sp); | ||
1166 | } else { | ||
1167 | struct srb_bsg* sp_bsg = (struct srb_bsg*)sp->ctx; | ||
1168 | if (sp_bsg->bsg_job->request->msgcode == FC_BSG_HST_CT) | ||
1169 | kfree(sp->fcport); | ||
1170 | sp_bsg->bsg_job->req->errors = 0; | ||
1171 | sp_bsg->bsg_job->reply->result = res; | ||
1172 | sp_bsg->bsg_job->job_done(sp_bsg->bsg_job); | ||
1173 | kfree(sp->ctx); | ||
1174 | mempool_free(sp, ha->srb_mempool); | ||
1175 | } | ||
1165 | } | 1176 | } |
1166 | } | 1177 | } |
1167 | } | 1178 | } |