aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJayamohan Kallickal <jayamohank@serverengines.com>2010-07-21 18:57:47 -0400
committerJames Bottomley <James.Bottomley@suse.de>2010-07-28 10:05:37 -0400
commit3cbb7a74a76e45f5e410367259844e8266fba6ec (patch)
tree0fecd55bd62d80961a0dd7c3fba3523fe8ab5e93
parent0aa094331b19e54f928e2ac083285ff68d91c69b (diff)
[SCSI] be2iscsi: Fix for premature buffer free
This patch fixes a bug where the buffer was being freed as soon as submission to HW is done. Signed-off-by: Jayamohan Kallickal <jayamohank@serverengines.com> Reviewed-by: Mike Christie <michaelc@cs.wisc.edu> Signed-off-by: James Bottomley <James.Bottomley@suse.de>
-rw-r--r--drivers/scsi/be2iscsi/be_iscsi.c24
-rw-r--r--drivers/scsi/be2iscsi/be_main.c41
-rw-r--r--drivers/scsi/be2iscsi/be_mgmt.c45
-rw-r--r--drivers/scsi/be2iscsi/be_mgmt.h9
4 files changed, 87 insertions, 32 deletions
diff --git a/drivers/scsi/be2iscsi/be_iscsi.c b/drivers/scsi/be2iscsi/be_iscsi.c
index a131a576a102..6d63e7b312cf 100644
--- a/drivers/scsi/be2iscsi/be_iscsi.c
+++ b/drivers/scsi/be2iscsi/be_iscsi.c
@@ -488,6 +488,7 @@ static int beiscsi_open_conn(struct iscsi_endpoint *ep,
488 struct be_mcc_wrb *wrb; 488 struct be_mcc_wrb *wrb;
489 struct tcp_connect_and_offload_out *ptcpcnct_out; 489 struct tcp_connect_and_offload_out *ptcpcnct_out;
490 unsigned short status, extd_status; 490 unsigned short status, extd_status;
491 struct be_dma_mem nonemb_cmd;
491 unsigned int tag, wrb_num; 492 unsigned int tag, wrb_num;
492 int ret = -ENOMEM; 493 int ret = -ENOMEM;
493 494
@@ -504,16 +505,31 @@ static int beiscsi_open_conn(struct iscsi_endpoint *ep,
504 if (beiscsi_ep->ep_cid > (phba->fw_config.iscsi_cid_start + 505 if (beiscsi_ep->ep_cid > (phba->fw_config.iscsi_cid_start +
505 phba->params.cxns_per_ctrl * 2)) { 506 phba->params.cxns_per_ctrl * 2)) {
506 SE_DEBUG(DBG_LVL_1, "Failed in allocate iscsi cid\n"); 507 SE_DEBUG(DBG_LVL_1, "Failed in allocate iscsi cid\n");
508 beiscsi_put_cid(phba, beiscsi_ep->ep_cid);
507 goto free_ep; 509 goto free_ep;
508 } 510 }
509 511
510 beiscsi_ep->cid_vld = 0; 512 beiscsi_ep->cid_vld = 0;
511 tag = mgmt_open_connection(phba, dst_addr, beiscsi_ep); 513 nonemb_cmd.va = pci_alloc_consistent(phba->ctrl.pdev,
514 sizeof(struct tcp_connect_and_offload_in),
515 &nonemb_cmd.dma);
516 if (nonemb_cmd.va == NULL) {
517 SE_DEBUG(DBG_LVL_1,
518 "Failed to allocate memory for mgmt_open_connection"
519 "\n");
520 beiscsi_put_cid(phba, beiscsi_ep->ep_cid);
521 return -ENOMEM;
522 }
523 nonemb_cmd.size = sizeof(struct tcp_connect_and_offload_in);
524 memset(nonemb_cmd.va, 0, nonemb_cmd.size);
525 tag = mgmt_open_connection(phba, dst_addr, beiscsi_ep, &nonemb_cmd);
512 if (!tag) { 526 if (!tag) {
513 SE_DEBUG(DBG_LVL_1, 527 SE_DEBUG(DBG_LVL_1,
514 "mgmt_open_connection Failed for cid=%d\n", 528 "mgmt_open_connection Failed for cid=%d\n",
515 beiscsi_ep->ep_cid); 529 beiscsi_ep->ep_cid);
516 beiscsi_put_cid(phba, beiscsi_ep->ep_cid); 530 beiscsi_put_cid(phba, beiscsi_ep->ep_cid);
531 pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size,
532 nonemb_cmd.va, nonemb_cmd.dma);
517 return -EAGAIN; 533 return -EAGAIN;
518 } else { 534 } else {
519 wait_event_interruptible(phba->ctrl.mcc_wait[tag], 535 wait_event_interruptible(phba->ctrl.mcc_wait[tag],
@@ -526,7 +542,10 @@ static int beiscsi_open_conn(struct iscsi_endpoint *ep,
526 SE_DEBUG(DBG_LVL_1, "mgmt_open_connection Failed" 542 SE_DEBUG(DBG_LVL_1, "mgmt_open_connection Failed"
527 " status = %d extd_status = %d\n", 543 " status = %d extd_status = %d\n",
528 status, extd_status); 544 status, extd_status);
545 beiscsi_put_cid(phba, beiscsi_ep->ep_cid);
529 free_mcc_tag(&phba->ctrl, tag); 546 free_mcc_tag(&phba->ctrl, tag);
547 pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size,
548 nonemb_cmd.va, nonemb_cmd.dma);
530 goto free_ep; 549 goto free_ep;
531 } else { 550 } else {
532 wrb = queue_get_wrb(mccq, wrb_num); 551 wrb = queue_get_wrb(mccq, wrb_num);
@@ -538,6 +557,9 @@ static int beiscsi_open_conn(struct iscsi_endpoint *ep,
538 beiscsi_ep->cid_vld = 1; 557 beiscsi_ep->cid_vld = 1;
539 SE_DEBUG(DBG_LVL_8, "mgmt_open_connection Success\n"); 558 SE_DEBUG(DBG_LVL_8, "mgmt_open_connection Success\n");
540 } 559 }
560 beiscsi_put_cid(phba, beiscsi_ep->ep_cid);
561 pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size,
562 nonemb_cmd.va, nonemb_cmd.dma);
541 return 0; 563 return 0;
542 564
543free_ep: 565free_ep:
diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c
index b70b4ba72076..7436c5ad5697 100644
--- a/drivers/scsi/be2iscsi/be_main.c
+++ b/drivers/scsi/be2iscsi/be_main.c
@@ -71,6 +71,7 @@ static int beiscsi_eh_abort(struct scsi_cmnd *sc)
71 struct beiscsi_hba *phba; 71 struct beiscsi_hba *phba;
72 struct iscsi_session *session; 72 struct iscsi_session *session;
73 struct invalidate_command_table *inv_tbl; 73 struct invalidate_command_table *inv_tbl;
74 struct be_dma_mem nonemb_cmd;
74 unsigned int cid, tag, num_invalidate; 75 unsigned int cid, tag, num_invalidate;
75 76
76 cls_session = starget_to_session(scsi_target(sc->device)); 77 cls_session = starget_to_session(scsi_target(sc->device));
@@ -101,18 +102,34 @@ static int beiscsi_eh_abort(struct scsi_cmnd *sc)
101 inv_tbl->cid = cid; 102 inv_tbl->cid = cid;
102 inv_tbl->icd = aborted_io_task->psgl_handle->sgl_index; 103 inv_tbl->icd = aborted_io_task->psgl_handle->sgl_index;
103 num_invalidate = 1; 104 num_invalidate = 1;
104 tag = mgmt_invalidate_icds(phba, inv_tbl, num_invalidate, cid); 105 nonemb_cmd.va = pci_alloc_consistent(phba->ctrl.pdev,
106 sizeof(struct invalidate_commands_params_in),
107 &nonemb_cmd.dma);
108 if (nonemb_cmd.va == NULL) {
109 SE_DEBUG(DBG_LVL_1,
110 "Failed to allocate memory for"
111 "mgmt_invalidate_icds\n");
112 return FAILED;
113 }
114 nonemb_cmd.size = sizeof(struct invalidate_commands_params_in);
115
116 tag = mgmt_invalidate_icds(phba, inv_tbl, num_invalidate,
117 cid, &nonemb_cmd);
105 if (!tag) { 118 if (!tag) {
106 shost_printk(KERN_WARNING, phba->shost, 119 shost_printk(KERN_WARNING, phba->shost,
107 "mgmt_invalidate_icds could not be" 120 "mgmt_invalidate_icds could not be"
108 " submitted\n"); 121 " submitted\n");
122 pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size,
123 nonemb_cmd.va, nonemb_cmd.dma);
124
109 return FAILED; 125 return FAILED;
110 } else { 126 } else {
111 wait_event_interruptible(phba->ctrl.mcc_wait[tag], 127 wait_event_interruptible(phba->ctrl.mcc_wait[tag],
112 phba->ctrl.mcc_numtag[tag]); 128 phba->ctrl.mcc_numtag[tag]);
113 free_mcc_tag(&phba->ctrl, tag); 129 free_mcc_tag(&phba->ctrl, tag);
114 } 130 }
115 131 pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size,
132 nonemb_cmd.va, nonemb_cmd.dma);
116 return iscsi_eh_abort(sc); 133 return iscsi_eh_abort(sc);
117} 134}
118 135
@@ -126,6 +143,7 @@ static int beiscsi_eh_device_reset(struct scsi_cmnd *sc)
126 struct iscsi_session *session; 143 struct iscsi_session *session;
127 struct iscsi_cls_session *cls_session; 144 struct iscsi_cls_session *cls_session;
128 struct invalidate_command_table *inv_tbl; 145 struct invalidate_command_table *inv_tbl;
146 struct be_dma_mem nonemb_cmd;
129 unsigned int cid, tag, i, num_invalidate; 147 unsigned int cid, tag, i, num_invalidate;
130 int rc = FAILED; 148 int rc = FAILED;
131 149
@@ -160,18 +178,33 @@ static int beiscsi_eh_device_reset(struct scsi_cmnd *sc)
160 spin_unlock_bh(&session->lock); 178 spin_unlock_bh(&session->lock);
161 inv_tbl = phba->inv_tbl; 179 inv_tbl = phba->inv_tbl;
162 180
163 tag = mgmt_invalidate_icds(phba, inv_tbl, num_invalidate, cid); 181 nonemb_cmd.va = pci_alloc_consistent(phba->ctrl.pdev,
182 sizeof(struct invalidate_commands_params_in),
183 &nonemb_cmd.dma);
184 if (nonemb_cmd.va == NULL) {
185 SE_DEBUG(DBG_LVL_1,
186 "Failed to allocate memory for"
187 "mgmt_invalidate_icds\n");
188 return FAILED;
189 }
190 nonemb_cmd.size = sizeof(struct invalidate_commands_params_in);
191 memset(nonemb_cmd.va, 0, nonemb_cmd.size);
192 tag = mgmt_invalidate_icds(phba, inv_tbl, num_invalidate,
193 cid, &nonemb_cmd);
164 if (!tag) { 194 if (!tag) {
165 shost_printk(KERN_WARNING, phba->shost, 195 shost_printk(KERN_WARNING, phba->shost,
166 "mgmt_invalidate_icds could not be" 196 "mgmt_invalidate_icds could not be"
167 " submitted\n"); 197 " submitted\n");
198 pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size,
199 nonemb_cmd.va, nonemb_cmd.dma);
168 return FAILED; 200 return FAILED;
169 } else { 201 } else {
170 wait_event_interruptible(phba->ctrl.mcc_wait[tag], 202 wait_event_interruptible(phba->ctrl.mcc_wait[tag],
171 phba->ctrl.mcc_numtag[tag]); 203 phba->ctrl.mcc_numtag[tag]);
172 free_mcc_tag(&phba->ctrl, tag); 204 free_mcc_tag(&phba->ctrl, tag);
173 } 205 }
174 206 pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size,
207 nonemb_cmd.va, nonemb_cmd.dma);
175 return iscsi_eh_device_reset(sc); 208 return iscsi_eh_device_reset(sc);
176unlock: 209unlock:
177 spin_unlock_bh(&session->lock); 210 spin_unlock_bh(&session->lock);
diff --git a/drivers/scsi/be2iscsi/be_mgmt.c b/drivers/scsi/be2iscsi/be_mgmt.c
index 3036d9ee7902..3f3fab91a7d1 100644
--- a/drivers/scsi/be2iscsi/be_mgmt.c
+++ b/drivers/scsi/be2iscsi/be_mgmt.c
@@ -50,7 +50,7 @@ int mgmt_get_fw_config(struct be_ctrl_info *ctrl,
50 pfw_cfg->ulp[0].sq_count; 50 pfw_cfg->ulp[0].sq_count;
51 if (phba->fw_config.iscsi_cid_count > (BE2_MAX_SESSIONS / 2)) { 51 if (phba->fw_config.iscsi_cid_count > (BE2_MAX_SESSIONS / 2)) {
52 SE_DEBUG(DBG_LVL_8, 52 SE_DEBUG(DBG_LVL_8,
53 "FW reported MAX CXNS as %d \t" 53 "FW reported MAX CXNS as %d\t"
54 "Max Supported = %d.\n", 54 "Max Supported = %d.\n",
55 phba->fw_config.iscsi_cid_count, 55 phba->fw_config.iscsi_cid_count,
56 BE2_MAX_SESSIONS); 56 BE2_MAX_SESSIONS);
@@ -145,9 +145,10 @@ int mgmt_epfw_cleanup(struct beiscsi_hba *phba, unsigned short chute)
145 145
146unsigned int mgmt_invalidate_icds(struct beiscsi_hba *phba, 146unsigned int mgmt_invalidate_icds(struct beiscsi_hba *phba,
147 struct invalidate_command_table *inv_tbl, 147 struct invalidate_command_table *inv_tbl,
148 unsigned int num_invalidate, unsigned int cid) 148 unsigned int num_invalidate, unsigned int cid,
149 struct be_dma_mem *nonemb_cmd)
150
149{ 151{
150 struct be_dma_mem nonemb_cmd;
151 struct be_ctrl_info *ctrl = &phba->ctrl; 152 struct be_ctrl_info *ctrl = &phba->ctrl;
152 struct be_mcc_wrb *wrb; 153 struct be_mcc_wrb *wrb;
153 struct be_sge *sge; 154 struct be_sge *sge;
@@ -161,18 +162,7 @@ unsigned int mgmt_invalidate_icds(struct beiscsi_hba *phba,
161 return tag; 162 return tag;
162 } 163 }
163 164
164 nonemb_cmd.va = pci_alloc_consistent(ctrl->pdev, 165 req = nonemb_cmd->va;
165 sizeof(struct invalidate_commands_params_in),
166 &nonemb_cmd.dma);
167 if (nonemb_cmd.va == NULL) {
168 SE_DEBUG(DBG_LVL_1,
169 "Failed to alloc memory for mgmt_invalidate_icds\n");
170 spin_unlock(&ctrl->mbox_lock);
171 free_mcc_tag(&phba->ctrl, tag);
172 return 0;
173 }
174 nonemb_cmd.size = sizeof(struct invalidate_commands_params_in);
175 req = nonemb_cmd.va;
176 memset(req, 0, sizeof(*req)); 166 memset(req, 0, sizeof(*req));
177 wrb = wrb_from_mccq(phba); 167 wrb = wrb_from_mccq(phba);
178 sge = nonembedded_sgl(wrb); 168 sge = nonembedded_sgl(wrb);
@@ -190,15 +180,12 @@ unsigned int mgmt_invalidate_icds(struct beiscsi_hba *phba,
190 req->icd_count++; 180 req->icd_count++;
191 inv_tbl++; 181 inv_tbl++;
192 } 182 }
193 sge->pa_hi = cpu_to_le32(upper_32_bits(nonemb_cmd.dma)); 183 sge->pa_hi = cpu_to_le32(upper_32_bits(nonemb_cmd->dma));
194 sge->pa_lo = cpu_to_le32(nonemb_cmd.dma & 0xFFFFFFFF); 184 sge->pa_lo = cpu_to_le32(nonemb_cmd->dma & 0xFFFFFFFF);
195 sge->len = cpu_to_le32(nonemb_cmd.size); 185 sge->len = cpu_to_le32(nonemb_cmd->size);
196 186
197 be_mcc_notify(phba); 187 be_mcc_notify(phba);
198 spin_unlock(&ctrl->mbox_lock); 188 spin_unlock(&ctrl->mbox_lock);
199 if (nonemb_cmd.va)
200 pci_free_consistent(ctrl->pdev, nonemb_cmd.size,
201 nonemb_cmd.va, nonemb_cmd.dma);
202 return tag; 189 return tag;
203} 190}
204 191
@@ -269,7 +256,9 @@ unsigned int mgmt_upload_connection(struct beiscsi_hba *phba,
269 256
270int mgmt_open_connection(struct beiscsi_hba *phba, 257int mgmt_open_connection(struct beiscsi_hba *phba,
271 struct sockaddr *dst_addr, 258 struct sockaddr *dst_addr,
272 struct beiscsi_endpoint *beiscsi_ep) 259 struct beiscsi_endpoint *beiscsi_ep,
260 struct be_dma_mem *nonemb_cmd)
261
273{ 262{
274 struct hwi_controller *phwi_ctrlr; 263 struct hwi_controller *phwi_ctrlr;
275 struct hwi_context_memory *phwi_context; 264 struct hwi_context_memory *phwi_context;
@@ -285,6 +274,7 @@ int mgmt_open_connection(struct beiscsi_hba *phba,
285 unsigned int tag = 0; 274 unsigned int tag = 0;
286 unsigned int i; 275 unsigned int i;
287 unsigned short cid = beiscsi_ep->ep_cid; 276 unsigned short cid = beiscsi_ep->ep_cid;
277 struct be_sge *sge;
288 278
289 phwi_ctrlr = phba->phwi_ctrlr; 279 phwi_ctrlr = phba->phwi_ctrlr;
290 phwi_context = phwi_ctrlr->phwi_ctxt; 280 phwi_context = phwi_ctrlr->phwi_ctxt;
@@ -300,10 +290,14 @@ int mgmt_open_connection(struct beiscsi_hba *phba,
300 return tag; 290 return tag;
301 } 291 }
302 wrb = wrb_from_mccq(phba); 292 wrb = wrb_from_mccq(phba);
303 req = embedded_payload(wrb); 293 memset(wrb, 0, sizeof(*wrb));
294 sge = nonembedded_sgl(wrb);
295
296 req = nonemb_cmd->va;
297 memset(req, 0, sizeof(*req));
304 wrb->tag0 |= tag; 298 wrb->tag0 |= tag;
305 299
306 be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); 300 be_wrb_hdr_prepare(wrb, sizeof(*req), true, 1);
307 be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI, 301 be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI,
308 OPCODE_COMMON_ISCSI_TCP_CONNECT_AND_OFFLOAD, 302 OPCODE_COMMON_ISCSI_TCP_CONNECT_AND_OFFLOAD,
309 sizeof(*req)); 303 sizeof(*req));
@@ -347,6 +341,9 @@ int mgmt_open_connection(struct beiscsi_hba *phba,
347 req->do_offload = 1; 341 req->do_offload = 1;
348 req->dataout_template_pa.lo = ptemplate_address->lo; 342 req->dataout_template_pa.lo = ptemplate_address->lo;
349 req->dataout_template_pa.hi = ptemplate_address->hi; 343 req->dataout_template_pa.hi = ptemplate_address->hi;
344 sge->pa_hi = cpu_to_le32(upper_32_bits(nonemb_cmd->dma));
345 sge->pa_lo = cpu_to_le32(nonemb_cmd->dma & 0xFFFFFFFF);
346 sge->len = cpu_to_le32(nonemb_cmd->size);
350 be_mcc_notify(phba); 347 be_mcc_notify(phba);
351 spin_unlock(&ctrl->mbox_lock); 348 spin_unlock(&ctrl->mbox_lock);
352 return tag; 349 return tag;
diff --git a/drivers/scsi/be2iscsi/be_mgmt.h b/drivers/scsi/be2iscsi/be_mgmt.h
index 74b885a4b836..b9acedf78653 100644
--- a/drivers/scsi/be2iscsi/be_mgmt.h
+++ b/drivers/scsi/be2iscsi/be_mgmt.h
@@ -87,15 +87,18 @@ struct mcc_wrb {
87}; 87};
88 88
89int mgmt_epfw_cleanup(struct beiscsi_hba *phba, unsigned short chute); 89int mgmt_epfw_cleanup(struct beiscsi_hba *phba, unsigned short chute);
90int mgmt_open_connection(struct beiscsi_hba *phba, struct sockaddr *dst_addr, 90int mgmt_open_connection(struct beiscsi_hba *phba,
91 struct beiscsi_endpoint *beiscsi_ep); 91 struct sockaddr *dst_addr,
92 struct beiscsi_endpoint *beiscsi_ep,
93 struct be_dma_mem *nonemb_cmd);
92 94
93unsigned int mgmt_upload_connection(struct beiscsi_hba *phba, 95unsigned int mgmt_upload_connection(struct beiscsi_hba *phba,
94 unsigned short cid, 96 unsigned short cid,
95 unsigned int upload_flag); 97 unsigned int upload_flag);
96unsigned int mgmt_invalidate_icds(struct beiscsi_hba *phba, 98unsigned int mgmt_invalidate_icds(struct beiscsi_hba *phba,
97 struct invalidate_command_table *inv_tbl, 99 struct invalidate_command_table *inv_tbl,
98 unsigned int num_invalidate, unsigned int cid); 100 unsigned int num_invalidate, unsigned int cid,
101 struct be_dma_mem *nonemb_cmd);
99 102
100struct iscsi_invalidate_connection_params_in { 103struct iscsi_invalidate_connection_params_in {
101 struct be_cmd_req_hdr hdr; 104 struct be_cmd_req_hdr hdr;