mirror of
https://github.com/torvalds/linux.git
synced 2024-11-11 22:51:42 +00:00
[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>
This commit is contained in:
parent
0aa094331b
commit
3cbb7a74a7
@ -488,6 +488,7 @@ static int beiscsi_open_conn(struct iscsi_endpoint *ep,
|
||||
struct be_mcc_wrb *wrb;
|
||||
struct tcp_connect_and_offload_out *ptcpcnct_out;
|
||||
unsigned short status, extd_status;
|
||||
struct be_dma_mem nonemb_cmd;
|
||||
unsigned int tag, wrb_num;
|
||||
int ret = -ENOMEM;
|
||||
|
||||
@ -504,16 +505,31 @@ static int beiscsi_open_conn(struct iscsi_endpoint *ep,
|
||||
if (beiscsi_ep->ep_cid > (phba->fw_config.iscsi_cid_start +
|
||||
phba->params.cxns_per_ctrl * 2)) {
|
||||
SE_DEBUG(DBG_LVL_1, "Failed in allocate iscsi cid\n");
|
||||
beiscsi_put_cid(phba, beiscsi_ep->ep_cid);
|
||||
goto free_ep;
|
||||
}
|
||||
|
||||
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) {
|
||||
SE_DEBUG(DBG_LVL_1,
|
||||
"mgmt_open_connection Failed for cid=%d\n",
|
||||
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;
|
||||
} else {
|
||||
wait_event_interruptible(phba->ctrl.mcc_wait[tag],
|
||||
@ -526,7 +542,10 @@ static int beiscsi_open_conn(struct iscsi_endpoint *ep,
|
||||
SE_DEBUG(DBG_LVL_1, "mgmt_open_connection Failed"
|
||||
" status = %d extd_status = %d\n",
|
||||
status, extd_status);
|
||||
beiscsi_put_cid(phba, beiscsi_ep->ep_cid);
|
||||
free_mcc_tag(&phba->ctrl, tag);
|
||||
pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size,
|
||||
nonemb_cmd.va, nonemb_cmd.dma);
|
||||
goto free_ep;
|
||||
} else {
|
||||
wrb = queue_get_wrb(mccq, wrb_num);
|
||||
@ -538,6 +557,9 @@ static int beiscsi_open_conn(struct iscsi_endpoint *ep,
|
||||
beiscsi_ep->cid_vld = 1;
|
||||
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;
|
||||
|
||||
free_ep:
|
||||
|
@ -71,6 +71,7 @@ static int beiscsi_eh_abort(struct scsi_cmnd *sc)
|
||||
struct beiscsi_hba *phba;
|
||||
struct iscsi_session *session;
|
||||
struct invalidate_command_table *inv_tbl;
|
||||
struct be_dma_mem nonemb_cmd;
|
||||
unsigned int cid, tag, num_invalidate;
|
||||
|
||||
cls_session = starget_to_session(scsi_target(sc->device));
|
||||
@ -101,18 +102,34 @@ static int beiscsi_eh_abort(struct scsi_cmnd *sc)
|
||||
inv_tbl->cid = cid;
|
||||
inv_tbl->icd = aborted_io_task->psgl_handle->sgl_index;
|
||||
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) {
|
||||
shost_printk(KERN_WARNING, phba->shost,
|
||||
"mgmt_invalidate_icds could not be"
|
||||
" submitted\n");
|
||||
pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size,
|
||||
nonemb_cmd.va, nonemb_cmd.dma);
|
||||
|
||||
return FAILED;
|
||||
} else {
|
||||
wait_event_interruptible(phba->ctrl.mcc_wait[tag],
|
||||
phba->ctrl.mcc_numtag[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);
|
||||
}
|
||||
|
||||
@ -126,6 +143,7 @@ static int beiscsi_eh_device_reset(struct scsi_cmnd *sc)
|
||||
struct iscsi_session *session;
|
||||
struct iscsi_cls_session *cls_session;
|
||||
struct invalidate_command_table *inv_tbl;
|
||||
struct be_dma_mem nonemb_cmd;
|
||||
unsigned int cid, tag, i, num_invalidate;
|
||||
int rc = FAILED;
|
||||
|
||||
@ -160,18 +178,33 @@ static int beiscsi_eh_device_reset(struct scsi_cmnd *sc)
|
||||
spin_unlock_bh(&session->lock);
|
||||
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) {
|
||||
shost_printk(KERN_WARNING, phba->shost,
|
||||
"mgmt_invalidate_icds could not be"
|
||||
" submitted\n");
|
||||
pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size,
|
||||
nonemb_cmd.va, nonemb_cmd.dma);
|
||||
return FAILED;
|
||||
} else {
|
||||
wait_event_interruptible(phba->ctrl.mcc_wait[tag],
|
||||
phba->ctrl.mcc_numtag[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);
|
||||
unlock:
|
||||
spin_unlock_bh(&session->lock);
|
||||
|
@ -50,7 +50,7 @@ int mgmt_get_fw_config(struct be_ctrl_info *ctrl,
|
||||
pfw_cfg->ulp[0].sq_count;
|
||||
if (phba->fw_config.iscsi_cid_count > (BE2_MAX_SESSIONS / 2)) {
|
||||
SE_DEBUG(DBG_LVL_8,
|
||||
"FW reported MAX CXNS as %d \t"
|
||||
"FW reported MAX CXNS as %d\t"
|
||||
"Max Supported = %d.\n",
|
||||
phba->fw_config.iscsi_cid_count,
|
||||
BE2_MAX_SESSIONS);
|
||||
@ -145,9 +145,10 @@ int mgmt_epfw_cleanup(struct beiscsi_hba *phba, unsigned short chute)
|
||||
|
||||
unsigned int mgmt_invalidate_icds(struct beiscsi_hba *phba,
|
||||
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_mcc_wrb *wrb;
|
||||
struct be_sge *sge;
|
||||
@ -161,18 +162,7 @@ unsigned int mgmt_invalidate_icds(struct beiscsi_hba *phba,
|
||||
return tag;
|
||||
}
|
||||
|
||||
nonemb_cmd.va = pci_alloc_consistent(ctrl->pdev,
|
||||
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;
|
||||
req = nonemb_cmd->va;
|
||||
memset(req, 0, sizeof(*req));
|
||||
wrb = wrb_from_mccq(phba);
|
||||
sge = nonembedded_sgl(wrb);
|
||||
@ -190,15 +180,12 @@ unsigned int mgmt_invalidate_icds(struct beiscsi_hba *phba,
|
||||
req->icd_count++;
|
||||
inv_tbl++;
|
||||
}
|
||||
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);
|
||||
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);
|
||||
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;
|
||||
}
|
||||
|
||||
@ -269,7 +256,9 @@ unsigned int mgmt_upload_connection(struct beiscsi_hba *phba,
|
||||
|
||||
int mgmt_open_connection(struct beiscsi_hba *phba,
|
||||
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_context_memory *phwi_context;
|
||||
@ -285,6 +274,7 @@ int mgmt_open_connection(struct beiscsi_hba *phba,
|
||||
unsigned int tag = 0;
|
||||
unsigned int i;
|
||||
unsigned short cid = beiscsi_ep->ep_cid;
|
||||
struct be_sge *sge;
|
||||
|
||||
phwi_ctrlr = phba->phwi_ctrlr;
|
||||
phwi_context = phwi_ctrlr->phwi_ctxt;
|
||||
@ -300,10 +290,14 @@ int mgmt_open_connection(struct beiscsi_hba *phba,
|
||||
return tag;
|
||||
}
|
||||
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;
|
||||
|
||||
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,
|
||||
OPCODE_COMMON_ISCSI_TCP_CONNECT_AND_OFFLOAD,
|
||||
sizeof(*req));
|
||||
@ -347,6 +341,9 @@ int mgmt_open_connection(struct beiscsi_hba *phba,
|
||||
req->do_offload = 1;
|
||||
req->dataout_template_pa.lo = ptemplate_address->lo;
|
||||
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);
|
||||
spin_unlock(&ctrl->mbox_lock);
|
||||
return tag;
|
||||
|
@ -87,15 +87,18 @@ struct mcc_wrb {
|
||||
};
|
||||
|
||||
int mgmt_epfw_cleanup(struct beiscsi_hba *phba, unsigned short chute);
|
||||
int mgmt_open_connection(struct beiscsi_hba *phba, struct sockaddr *dst_addr,
|
||||
struct beiscsi_endpoint *beiscsi_ep);
|
||||
int mgmt_open_connection(struct beiscsi_hba *phba,
|
||||
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 short cid,
|
||||
unsigned int upload_flag);
|
||||
unsigned int mgmt_invalidate_icds(struct beiscsi_hba *phba,
|
||||
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 be_cmd_req_hdr hdr;
|
||||
|
Loading…
Reference in New Issue
Block a user