提交 3cbb7a74 编写于 作者: J Jayamohan Kallickal 提交者: James Bottomley

[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: NJayamohan Kallickal <jayamohank@serverengines.com>
Reviewed-by: NMike Christie <michaelc@cs.wisc.edu>
Signed-off-by: NJames Bottomley <James.Bottomley@suse.de>
上级 0aa09433
...@@ -488,6 +488,7 @@ static int beiscsi_open_conn(struct iscsi_endpoint *ep, ...@@ -488,6 +488,7 @@ static int beiscsi_open_conn(struct iscsi_endpoint *ep,
struct be_mcc_wrb *wrb; struct be_mcc_wrb *wrb;
struct tcp_connect_and_offload_out *ptcpcnct_out; struct tcp_connect_and_offload_out *ptcpcnct_out;
unsigned short status, extd_status; unsigned short status, extd_status;
struct be_dma_mem nonemb_cmd;
unsigned int tag, wrb_num; unsigned int tag, wrb_num;
int ret = -ENOMEM; int ret = -ENOMEM;
...@@ -504,16 +505,31 @@ static int beiscsi_open_conn(struct iscsi_endpoint *ep, ...@@ -504,16 +505,31 @@ static int beiscsi_open_conn(struct iscsi_endpoint *ep,
if (beiscsi_ep->ep_cid > (phba->fw_config.iscsi_cid_start + if (beiscsi_ep->ep_cid > (phba->fw_config.iscsi_cid_start +
phba->params.cxns_per_ctrl * 2)) { phba->params.cxns_per_ctrl * 2)) {
SE_DEBUG(DBG_LVL_1, "Failed in allocate iscsi cid\n"); SE_DEBUG(DBG_LVL_1, "Failed in allocate iscsi cid\n");
beiscsi_put_cid(phba, beiscsi_ep->ep_cid);
goto free_ep; goto free_ep;
} }
beiscsi_ep->cid_vld = 0; beiscsi_ep->cid_vld = 0;
tag = mgmt_open_connection(phba, dst_addr, beiscsi_ep); nonemb_cmd.va = pci_alloc_consistent(phba->ctrl.pdev,
sizeof(struct tcp_connect_and_offload_in),
&nonemb_cmd.dma);
if (nonemb_cmd.va == NULL) {
SE_DEBUG(DBG_LVL_1,
"Failed to allocate memory for mgmt_open_connection"
"\n");
beiscsi_put_cid(phba, beiscsi_ep->ep_cid);
return -ENOMEM;
}
nonemb_cmd.size = sizeof(struct tcp_connect_and_offload_in);
memset(nonemb_cmd.va, 0, nonemb_cmd.size);
tag = mgmt_open_connection(phba, dst_addr, beiscsi_ep, &nonemb_cmd);
if (!tag) { if (!tag) {
SE_DEBUG(DBG_LVL_1, SE_DEBUG(DBG_LVL_1,
"mgmt_open_connection Failed for cid=%d\n", "mgmt_open_connection Failed for cid=%d\n",
beiscsi_ep->ep_cid); beiscsi_ep->ep_cid);
beiscsi_put_cid(phba, beiscsi_ep->ep_cid); beiscsi_put_cid(phba, beiscsi_ep->ep_cid);
pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size,
nonemb_cmd.va, nonemb_cmd.dma);
return -EAGAIN; return -EAGAIN;
} else { } else {
wait_event_interruptible(phba->ctrl.mcc_wait[tag], wait_event_interruptible(phba->ctrl.mcc_wait[tag],
...@@ -526,7 +542,10 @@ static int beiscsi_open_conn(struct iscsi_endpoint *ep, ...@@ -526,7 +542,10 @@ static int beiscsi_open_conn(struct iscsi_endpoint *ep,
SE_DEBUG(DBG_LVL_1, "mgmt_open_connection Failed" SE_DEBUG(DBG_LVL_1, "mgmt_open_connection Failed"
" status = %d extd_status = %d\n", " status = %d extd_status = %d\n",
status, extd_status); status, extd_status);
beiscsi_put_cid(phba, beiscsi_ep->ep_cid);
free_mcc_tag(&phba->ctrl, tag); free_mcc_tag(&phba->ctrl, tag);
pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size,
nonemb_cmd.va, nonemb_cmd.dma);
goto free_ep; goto free_ep;
} else { } else {
wrb = queue_get_wrb(mccq, wrb_num); wrb = queue_get_wrb(mccq, wrb_num);
...@@ -538,6 +557,9 @@ static int beiscsi_open_conn(struct iscsi_endpoint *ep, ...@@ -538,6 +557,9 @@ static int beiscsi_open_conn(struct iscsi_endpoint *ep,
beiscsi_ep->cid_vld = 1; beiscsi_ep->cid_vld = 1;
SE_DEBUG(DBG_LVL_8, "mgmt_open_connection Success\n"); SE_DEBUG(DBG_LVL_8, "mgmt_open_connection Success\n");
} }
beiscsi_put_cid(phba, beiscsi_ep->ep_cid);
pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size,
nonemb_cmd.va, nonemb_cmd.dma);
return 0; return 0;
free_ep: free_ep:
......
...@@ -71,6 +71,7 @@ static int beiscsi_eh_abort(struct scsi_cmnd *sc) ...@@ -71,6 +71,7 @@ static int beiscsi_eh_abort(struct scsi_cmnd *sc)
struct beiscsi_hba *phba; struct beiscsi_hba *phba;
struct iscsi_session *session; struct iscsi_session *session;
struct invalidate_command_table *inv_tbl; struct invalidate_command_table *inv_tbl;
struct be_dma_mem nonemb_cmd;
unsigned int cid, tag, num_invalidate; unsigned int cid, tag, num_invalidate;
cls_session = starget_to_session(scsi_target(sc->device)); cls_session = starget_to_session(scsi_target(sc->device));
...@@ -101,18 +102,34 @@ static int beiscsi_eh_abort(struct scsi_cmnd *sc) ...@@ -101,18 +102,34 @@ static int beiscsi_eh_abort(struct scsi_cmnd *sc)
inv_tbl->cid = cid; inv_tbl->cid = cid;
inv_tbl->icd = aborted_io_task->psgl_handle->sgl_index; inv_tbl->icd = aborted_io_task->psgl_handle->sgl_index;
num_invalidate = 1; num_invalidate = 1;
tag = mgmt_invalidate_icds(phba, inv_tbl, num_invalidate, cid); nonemb_cmd.va = pci_alloc_consistent(phba->ctrl.pdev,
sizeof(struct invalidate_commands_params_in),
&nonemb_cmd.dma);
if (nonemb_cmd.va == NULL) {
SE_DEBUG(DBG_LVL_1,
"Failed to allocate memory for"
"mgmt_invalidate_icds\n");
return FAILED;
}
nonemb_cmd.size = sizeof(struct invalidate_commands_params_in);
tag = mgmt_invalidate_icds(phba, inv_tbl, num_invalidate,
cid, &nonemb_cmd);
if (!tag) { if (!tag) {
shost_printk(KERN_WARNING, phba->shost, shost_printk(KERN_WARNING, phba->shost,
"mgmt_invalidate_icds could not be" "mgmt_invalidate_icds could not be"
" submitted\n"); " submitted\n");
pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size,
nonemb_cmd.va, nonemb_cmd.dma);
return FAILED; return FAILED;
} else { } else {
wait_event_interruptible(phba->ctrl.mcc_wait[tag], wait_event_interruptible(phba->ctrl.mcc_wait[tag],
phba->ctrl.mcc_numtag[tag]); phba->ctrl.mcc_numtag[tag]);
free_mcc_tag(&phba->ctrl, tag); free_mcc_tag(&phba->ctrl, tag);
} }
pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size,
nonemb_cmd.va, nonemb_cmd.dma);
return iscsi_eh_abort(sc); return iscsi_eh_abort(sc);
} }
...@@ -126,6 +143,7 @@ static int beiscsi_eh_device_reset(struct scsi_cmnd *sc) ...@@ -126,6 +143,7 @@ static int beiscsi_eh_device_reset(struct scsi_cmnd *sc)
struct iscsi_session *session; struct iscsi_session *session;
struct iscsi_cls_session *cls_session; struct iscsi_cls_session *cls_session;
struct invalidate_command_table *inv_tbl; struct invalidate_command_table *inv_tbl;
struct be_dma_mem nonemb_cmd;
unsigned int cid, tag, i, num_invalidate; unsigned int cid, tag, i, num_invalidate;
int rc = FAILED; int rc = FAILED;
...@@ -160,18 +178,33 @@ static int beiscsi_eh_device_reset(struct scsi_cmnd *sc) ...@@ -160,18 +178,33 @@ static int beiscsi_eh_device_reset(struct scsi_cmnd *sc)
spin_unlock_bh(&session->lock); spin_unlock_bh(&session->lock);
inv_tbl = phba->inv_tbl; inv_tbl = phba->inv_tbl;
tag = mgmt_invalidate_icds(phba, inv_tbl, num_invalidate, cid); nonemb_cmd.va = pci_alloc_consistent(phba->ctrl.pdev,
sizeof(struct invalidate_commands_params_in),
&nonemb_cmd.dma);
if (nonemb_cmd.va == NULL) {
SE_DEBUG(DBG_LVL_1,
"Failed to allocate memory for"
"mgmt_invalidate_icds\n");
return FAILED;
}
nonemb_cmd.size = sizeof(struct invalidate_commands_params_in);
memset(nonemb_cmd.va, 0, nonemb_cmd.size);
tag = mgmt_invalidate_icds(phba, inv_tbl, num_invalidate,
cid, &nonemb_cmd);
if (!tag) { if (!tag) {
shost_printk(KERN_WARNING, phba->shost, shost_printk(KERN_WARNING, phba->shost,
"mgmt_invalidate_icds could not be" "mgmt_invalidate_icds could not be"
" submitted\n"); " submitted\n");
pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size,
nonemb_cmd.va, nonemb_cmd.dma);
return FAILED; return FAILED;
} else { } else {
wait_event_interruptible(phba->ctrl.mcc_wait[tag], wait_event_interruptible(phba->ctrl.mcc_wait[tag],
phba->ctrl.mcc_numtag[tag]); phba->ctrl.mcc_numtag[tag]);
free_mcc_tag(&phba->ctrl, tag); free_mcc_tag(&phba->ctrl, tag);
} }
pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size,
nonemb_cmd.va, nonemb_cmd.dma);
return iscsi_eh_device_reset(sc); return iscsi_eh_device_reset(sc);
unlock: unlock:
spin_unlock_bh(&session->lock); spin_unlock_bh(&session->lock);
......
...@@ -50,7 +50,7 @@ int mgmt_get_fw_config(struct be_ctrl_info *ctrl, ...@@ -50,7 +50,7 @@ int mgmt_get_fw_config(struct be_ctrl_info *ctrl,
pfw_cfg->ulp[0].sq_count; pfw_cfg->ulp[0].sq_count;
if (phba->fw_config.iscsi_cid_count > (BE2_MAX_SESSIONS / 2)) { if (phba->fw_config.iscsi_cid_count > (BE2_MAX_SESSIONS / 2)) {
SE_DEBUG(DBG_LVL_8, SE_DEBUG(DBG_LVL_8,
"FW reported MAX CXNS as %d \t" "FW reported MAX CXNS as %d\t"
"Max Supported = %d.\n", "Max Supported = %d.\n",
phba->fw_config.iscsi_cid_count, phba->fw_config.iscsi_cid_count,
BE2_MAX_SESSIONS); BE2_MAX_SESSIONS);
...@@ -145,9 +145,10 @@ int mgmt_epfw_cleanup(struct beiscsi_hba *phba, unsigned short chute) ...@@ -145,9 +145,10 @@ int mgmt_epfw_cleanup(struct beiscsi_hba *phba, unsigned short chute)
unsigned int mgmt_invalidate_icds(struct beiscsi_hba *phba, unsigned int mgmt_invalidate_icds(struct beiscsi_hba *phba,
struct invalidate_command_table *inv_tbl, struct invalidate_command_table *inv_tbl,
unsigned int num_invalidate, unsigned int cid) unsigned int num_invalidate, unsigned int cid,
struct be_dma_mem *nonemb_cmd)
{ {
struct be_dma_mem nonemb_cmd;
struct be_ctrl_info *ctrl = &phba->ctrl; struct be_ctrl_info *ctrl = &phba->ctrl;
struct be_mcc_wrb *wrb; struct be_mcc_wrb *wrb;
struct be_sge *sge; struct be_sge *sge;
...@@ -161,18 +162,7 @@ unsigned int mgmt_invalidate_icds(struct beiscsi_hba *phba, ...@@ -161,18 +162,7 @@ unsigned int mgmt_invalidate_icds(struct beiscsi_hba *phba,
return tag; return tag;
} }
nonemb_cmd.va = pci_alloc_consistent(ctrl->pdev, req = nonemb_cmd->va;
sizeof(struct invalidate_commands_params_in),
&nonemb_cmd.dma);
if (nonemb_cmd.va == NULL) {
SE_DEBUG(DBG_LVL_1,
"Failed to alloc memory for mgmt_invalidate_icds\n");
spin_unlock(&ctrl->mbox_lock);
free_mcc_tag(&phba->ctrl, tag);
return 0;
}
nonemb_cmd.size = sizeof(struct invalidate_commands_params_in);
req = nonemb_cmd.va;
memset(req, 0, sizeof(*req)); memset(req, 0, sizeof(*req));
wrb = wrb_from_mccq(phba); wrb = wrb_from_mccq(phba);
sge = nonembedded_sgl(wrb); sge = nonembedded_sgl(wrb);
...@@ -190,15 +180,12 @@ unsigned int mgmt_invalidate_icds(struct beiscsi_hba *phba, ...@@ -190,15 +180,12 @@ unsigned int mgmt_invalidate_icds(struct beiscsi_hba *phba,
req->icd_count++; req->icd_count++;
inv_tbl++; inv_tbl++;
} }
sge->pa_hi = cpu_to_le32(upper_32_bits(nonemb_cmd.dma)); sge->pa_hi = cpu_to_le32(upper_32_bits(nonemb_cmd->dma));
sge->pa_lo = cpu_to_le32(nonemb_cmd.dma & 0xFFFFFFFF); sge->pa_lo = cpu_to_le32(nonemb_cmd->dma & 0xFFFFFFFF);
sge->len = cpu_to_le32(nonemb_cmd.size); sge->len = cpu_to_le32(nonemb_cmd->size);
be_mcc_notify(phba); be_mcc_notify(phba);
spin_unlock(&ctrl->mbox_lock); spin_unlock(&ctrl->mbox_lock);
if (nonemb_cmd.va)
pci_free_consistent(ctrl->pdev, nonemb_cmd.size,
nonemb_cmd.va, nonemb_cmd.dma);
return tag; return tag;
} }
...@@ -269,7 +256,9 @@ unsigned int mgmt_upload_connection(struct beiscsi_hba *phba, ...@@ -269,7 +256,9 @@ unsigned int mgmt_upload_connection(struct beiscsi_hba *phba,
int mgmt_open_connection(struct beiscsi_hba *phba, int mgmt_open_connection(struct beiscsi_hba *phba,
struct sockaddr *dst_addr, struct sockaddr *dst_addr,
struct beiscsi_endpoint *beiscsi_ep) struct beiscsi_endpoint *beiscsi_ep,
struct be_dma_mem *nonemb_cmd)
{ {
struct hwi_controller *phwi_ctrlr; struct hwi_controller *phwi_ctrlr;
struct hwi_context_memory *phwi_context; struct hwi_context_memory *phwi_context;
...@@ -285,6 +274,7 @@ int mgmt_open_connection(struct beiscsi_hba *phba, ...@@ -285,6 +274,7 @@ int mgmt_open_connection(struct beiscsi_hba *phba,
unsigned int tag = 0; unsigned int tag = 0;
unsigned int i; unsigned int i;
unsigned short cid = beiscsi_ep->ep_cid; unsigned short cid = beiscsi_ep->ep_cid;
struct be_sge *sge;
phwi_ctrlr = phba->phwi_ctrlr; phwi_ctrlr = phba->phwi_ctrlr;
phwi_context = phwi_ctrlr->phwi_ctxt; phwi_context = phwi_ctrlr->phwi_ctxt;
...@@ -300,10 +290,14 @@ int mgmt_open_connection(struct beiscsi_hba *phba, ...@@ -300,10 +290,14 @@ int mgmt_open_connection(struct beiscsi_hba *phba,
return tag; return tag;
} }
wrb = wrb_from_mccq(phba); wrb = wrb_from_mccq(phba);
req = embedded_payload(wrb); memset(wrb, 0, sizeof(*wrb));
sge = nonembedded_sgl(wrb);
req = nonemb_cmd->va;
memset(req, 0, sizeof(*req));
wrb->tag0 |= tag; wrb->tag0 |= tag;
be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); be_wrb_hdr_prepare(wrb, sizeof(*req), true, 1);
be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI, be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI,
OPCODE_COMMON_ISCSI_TCP_CONNECT_AND_OFFLOAD, OPCODE_COMMON_ISCSI_TCP_CONNECT_AND_OFFLOAD,
sizeof(*req)); sizeof(*req));
...@@ -347,6 +341,9 @@ int mgmt_open_connection(struct beiscsi_hba *phba, ...@@ -347,6 +341,9 @@ int mgmt_open_connection(struct beiscsi_hba *phba,
req->do_offload = 1; req->do_offload = 1;
req->dataout_template_pa.lo = ptemplate_address->lo; req->dataout_template_pa.lo = ptemplate_address->lo;
req->dataout_template_pa.hi = ptemplate_address->hi; req->dataout_template_pa.hi = ptemplate_address->hi;
sge->pa_hi = cpu_to_le32(upper_32_bits(nonemb_cmd->dma));
sge->pa_lo = cpu_to_le32(nonemb_cmd->dma & 0xFFFFFFFF);
sge->len = cpu_to_le32(nonemb_cmd->size);
be_mcc_notify(phba); be_mcc_notify(phba);
spin_unlock(&ctrl->mbox_lock); spin_unlock(&ctrl->mbox_lock);
return tag; return tag;
......
...@@ -87,15 +87,18 @@ struct mcc_wrb { ...@@ -87,15 +87,18 @@ struct mcc_wrb {
}; };
int mgmt_epfw_cleanup(struct beiscsi_hba *phba, unsigned short chute); int mgmt_epfw_cleanup(struct beiscsi_hba *phba, unsigned short chute);
int mgmt_open_connection(struct beiscsi_hba *phba, struct sockaddr *dst_addr, int mgmt_open_connection(struct beiscsi_hba *phba,
struct beiscsi_endpoint *beiscsi_ep); struct sockaddr *dst_addr,
struct beiscsi_endpoint *beiscsi_ep,
struct be_dma_mem *nonemb_cmd);
unsigned int mgmt_upload_connection(struct beiscsi_hba *phba, unsigned int mgmt_upload_connection(struct beiscsi_hba *phba,
unsigned short cid, unsigned short cid,
unsigned int upload_flag); unsigned int upload_flag);
unsigned int mgmt_invalidate_icds(struct beiscsi_hba *phba, unsigned int mgmt_invalidate_icds(struct beiscsi_hba *phba,
struct invalidate_command_table *inv_tbl, struct invalidate_command_table *inv_tbl,
unsigned int num_invalidate, unsigned int cid); unsigned int num_invalidate, unsigned int cid,
struct be_dma_mem *nonemb_cmd);
struct iscsi_invalidate_connection_params_in { struct iscsi_invalidate_connection_params_in {
struct be_cmd_req_hdr hdr; struct be_cmd_req_hdr hdr;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册