]> bbs.cooldavid.org Git - net-next-2.6.git/commitdiff
[SCSI] be2iscsi: Fix for premature buffer free
authorJayamohan Kallickal <jayamohank@serverengines.com>
Wed, 21 Jul 2010 22:57:47 +0000 (04:27 +0530)
committerJames Bottomley <James.Bottomley@suse.de>
Wed, 28 Jul 2010 14:05:37 +0000 (09:05 -0500)
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>
drivers/scsi/be2iscsi/be_iscsi.c
drivers/scsi/be2iscsi/be_main.c
drivers/scsi/be2iscsi/be_mgmt.c
drivers/scsi/be2iscsi/be_mgmt.h

index a131a576a1020f339a58258699fdd666c7c35029..6d63e7b312cf61d33dfb0c5c7e9d11226168ba9a 100644 (file)
@@ -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:
index b70b4ba72076d8e41e3ff5bb773e5b9168ecfbaf..7436c5ad569706261c02fd7d7d95f793cedfcb1b 100644 (file)
@@ -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);
index 3036d9ee7902a5b381a4f02309c4941c987632c4..3f3fab91a7d19d472f3f78b3b38556c721b20d86 100644 (file)
@@ -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;
index 74b885a4b836013a33e3ea884edbc26e584f3692..b9acedf78653ae3a3bfda89187fab07e9fea292a 100644 (file)
@@ -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;