]> Pileus Git - ~andy/linux/blobdiff - drivers/scsi/be2iscsi/be_main.c
Merge branch 'linux-next' of git://git.kernel.org/pub/scm/linux/kernel/git/jbarnes...
[~andy/linux] / drivers / scsi / be2iscsi / be_main.c
index 26ac049c0c8521046747199f9d834ba781fa89af..7436c5ad569706261c02fd7d7d95f793cedfcb1b 100644 (file)
@@ -41,6 +41,8 @@
 static unsigned int be_iopoll_budget = 10;
 static unsigned int be_max_phys_size = 64;
 static unsigned int enable_msix = 1;
+static unsigned int gcrashmode = 0;
+static unsigned int num_hba = 0;
 
 MODULE_DEVICE_TABLE(pci, beiscsi_pci_id_table);
 MODULE_DESCRIPTION(DRV_DESC " " BUILD_STR);
@@ -69,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));
@@ -99,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);
 }
 
@@ -124,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;
 
@@ -158,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);
@@ -616,7 +651,7 @@ static int beiscsi_init_irqs(struct beiscsi_hba *phba)
        struct pci_dev *pcidev = phba->pcidev;
        struct hwi_controller *phwi_ctrlr;
        struct hwi_context_memory *phwi_context;
-       int ret, msix_vec, i = 0;
+       int ret, msix_vec, i, j;
        char desc[32];
 
        phwi_ctrlr = phba->phwi_ctrlr;
@@ -628,10 +663,25 @@ static int beiscsi_init_irqs(struct beiscsi_hba *phba)
                        msix_vec = phba->msix_entries[i].vector;
                        ret = request_irq(msix_vec, be_isr_msix, 0, desc,
                                          &phwi_context->be_eq[i]);
+                       if (ret) {
+                               shost_printk(KERN_ERR, phba->shost,
+                                            "beiscsi_init_irqs-Failed to"
+                                            "register msix for i = %d\n", i);
+                               if (!i)
+                                       return ret;
+                               goto free_msix_irqs;
+                       }
                }
                msix_vec = phba->msix_entries[i].vector;
                ret = request_irq(msix_vec, be_isr_mcc, 0, "beiscsi_msix_mcc",
                                  &phwi_context->be_eq[i]);
+               if (ret) {
+                       shost_printk(KERN_ERR, phba->shost, "beiscsi_init_irqs-"
+                                    "Failed to register beiscsi_msix_mcc\n");
+                       i++;
+                       goto free_msix_irqs;
+               }
+
        } else {
                ret = request_irq(pcidev->irq, be_isr, IRQF_SHARED,
                                  "beiscsi", phba);
@@ -642,6 +692,10 @@ static int beiscsi_init_irqs(struct beiscsi_hba *phba)
                }
        }
        return 0;
+free_msix_irqs:
+       for (j = i - 1; j == 0; j++)
+               free_irq(msix_vec, &phwi_context->be_eq[j]);
+       return ret;
 }
 
 static void hwi_ring_cq_db(struct beiscsi_hba *phba,
@@ -3431,14 +3485,12 @@ static int beiscsi_alloc_pdu(struct iscsi_task *task, uint8_t opcode)
                return -ENOMEM;
        io_task->bhs_pa.u.a64.address = paddr;
        io_task->libiscsi_itt = (itt_t)task->itt;
-       io_task->pwrb_handle = alloc_wrb_handle(phba,
-                                               beiscsi_conn->beiscsi_conn_cid -
-                                               phba->fw_config.iscsi_cid_start
-                                               );
        io_task->conn = beiscsi_conn;
 
        task->hdr = (struct iscsi_hdr *)&io_task->cmd_bhs->iscsi_hdr;
        task->hdr_max = sizeof(struct be_cmd_bhs);
+       io_task->psgl_handle = NULL;
+       io_task->psgl_handle = NULL;
 
        if (task->sc) {
                spin_lock(&phba->io_sgl_lock);
@@ -3446,6 +3498,11 @@ static int beiscsi_alloc_pdu(struct iscsi_task *task, uint8_t opcode)
                spin_unlock(&phba->io_sgl_lock);
                if (!io_task->psgl_handle)
                        goto free_hndls;
+               io_task->pwrb_handle = alloc_wrb_handle(phba,
+                                       beiscsi_conn->beiscsi_conn_cid -
+                                       phba->fw_config.iscsi_cid_start);
+               if (!io_task->pwrb_handle)
+                       goto free_io_hndls;
        } else {
                io_task->scsi_cmnd = NULL;
                if ((opcode & ISCSI_OPCODE_MASK) == ISCSI_OP_LOGIN) {
@@ -3460,9 +3517,20 @@ static int beiscsi_alloc_pdu(struct iscsi_task *task, uint8_t opcode)
                                beiscsi_conn->login_in_progress = 1;
                                beiscsi_conn->plogin_sgl_handle =
                                                        io_task->psgl_handle;
+                               io_task->pwrb_handle =
+                                       alloc_wrb_handle(phba,
+                                       beiscsi_conn->beiscsi_conn_cid -
+                                       phba->fw_config.iscsi_cid_start);
+                               if (!io_task->pwrb_handle)
+                                       goto free_io_hndls;
+                               beiscsi_conn->plogin_wrb_handle =
+                                                       io_task->pwrb_handle;
+
                        } else {
                                io_task->psgl_handle =
                                                beiscsi_conn->plogin_sgl_handle;
+                               io_task->pwrb_handle =
+                                               beiscsi_conn->plogin_wrb_handle;
                        }
                } else {
                        spin_lock(&phba->mgmt_sgl_lock);
@@ -3470,6 +3538,13 @@ static int beiscsi_alloc_pdu(struct iscsi_task *task, uint8_t opcode)
                        spin_unlock(&phba->mgmt_sgl_lock);
                        if (!io_task->psgl_handle)
                                goto free_hndls;
+                       io_task->pwrb_handle =
+                                       alloc_wrb_handle(phba,
+                                       beiscsi_conn->beiscsi_conn_cid -
+                                       phba->fw_config.iscsi_cid_start);
+                       if (!io_task->pwrb_handle)
+                               goto free_mgmt_hndls;
+
                }
        }
        itt = (itt_t) cpu_to_be32(((unsigned int)io_task->pwrb_handle->
@@ -3480,12 +3555,22 @@ static int beiscsi_alloc_pdu(struct iscsi_task *task, uint8_t opcode)
        io_task->cmd_bhs->iscsi_hdr.itt = itt;
        return 0;
 
+free_io_hndls:
+       spin_lock(&phba->io_sgl_lock);
+       free_io_sgl_handle(phba, io_task->psgl_handle);
+       spin_unlock(&phba->io_sgl_lock);
+       goto free_hndls;
+free_mgmt_hndls:
+       spin_lock(&phba->mgmt_sgl_lock);
+       free_mgmt_sgl_handle(phba, io_task->psgl_handle);
+       spin_unlock(&phba->mgmt_sgl_lock);
 free_hndls:
        phwi_ctrlr = phba->phwi_ctrlr;
        pwrb_context = &phwi_ctrlr->wrb_context[
                        beiscsi_conn->beiscsi_conn_cid -
                        phba->fw_config.iscsi_cid_start];
-       free_wrb_handle(phba, pwrb_context, io_task->pwrb_handle);
+       if (io_task->pwrb_handle)
+               free_wrb_handle(phba, pwrb_context, io_task->pwrb_handle);
        io_task->pwrb_handle = NULL;
        pci_pool_free(beiscsi_sess->bhs_pool, io_task->cmd_bhs,
                      io_task->bhs_pa.u.a64.address);
@@ -3692,8 +3777,6 @@ static int beiscsi_task_xmit(struct iscsi_task *task)
                SE_DEBUG(DBG_LVL_1, " scsi_dma_map Failed\n")
                return num_sg;
        }
-       SE_DEBUG(DBG_LVL_4, "xferlen=0x%08x scmd=%p num_sg=%d sernum=%lu\n",
-                 (scsi_bufflen(sc)), sc, num_sg, sc->serial_number);
        xferlen = scsi_bufflen(sc);
        sg = scsi_sglist(sc);
        if (sc->sc_data_direction == DMA_TO_DEVICE) {
@@ -3712,6 +3795,8 @@ static void beiscsi_remove(struct pci_dev *pcidev)
        struct hwi_context_memory *phwi_context;
        struct be_eq_obj *pbe_eq;
        unsigned int i, msix_vec;
+       u8 *real_offset = 0;
+       u32 value = 0;
 
        phba = (struct beiscsi_hba *)pci_get_drvdata(pcidev);
        if (!phba) {
@@ -3740,6 +3825,14 @@ static void beiscsi_remove(struct pci_dev *pcidev)
 
        beiscsi_clean_port(phba);
        beiscsi_free_mem(phba);
+       real_offset = (u8 *)phba->csr_va + MPU_EP_SEMAPHORE;
+
+       value = readl((void *)real_offset);
+
+       if (value & 0x00010000) {
+               value &= 0xfffeffff;
+               writel(value, (void *)real_offset);
+       }
        beiscsi_unmap_pci_function(phba);
        pci_free_consistent(phba->pcidev,
                            phba->ctrl.mbox_mem_alloced.size,
@@ -3773,6 +3866,8 @@ static int __devinit beiscsi_dev_probe(struct pci_dev *pcidev,
        struct hwi_context_memory *phwi_context;
        struct be_eq_obj *pbe_eq;
        int ret, num_cpus, i;
+       u8 *real_offset = 0;
+       u32 value = 0;
 
        ret = beiscsi_enable_pci(pcidev);
        if (ret < 0) {
@@ -3818,6 +3913,33 @@ static int __devinit beiscsi_dev_probe(struct pci_dev *pcidev,
                goto hba_free;
        }
 
+       if (!num_hba) {
+               real_offset = (u8 *)phba->csr_va + MPU_EP_SEMAPHORE;
+               value = readl((void *)real_offset);
+               if (value & 0x00010000) {
+                       gcrashmode++;
+                       shost_printk(KERN_ERR, phba->shost,
+                               "Loading Driver in crashdump mode\n");
+                       ret = beiscsi_pci_soft_reset(phba);
+                       if (ret) {
+                               shost_printk(KERN_ERR, phba->shost,
+                                       "Reset Failed. Aborting Crashdump\n");
+                               goto hba_free;
+                       }
+                       ret = be_chk_reset_complete(phba);
+                       if (ret) {
+                               shost_printk(KERN_ERR, phba->shost,
+                                       "Failed to get out of reset."
+                                       "Aborting Crashdump\n");
+                               goto hba_free;
+                       }
+               } else {
+                       value |= 0x00010000;
+                       writel(value, (void *)real_offset);
+                       num_hba++;
+               }
+       }
+
        spin_lock_init(&phba->io_sgl_lock);
        spin_lock_init(&phba->mgmt_sgl_lock);
        spin_lock_init(&phba->isr_lock);
@@ -3888,6 +4010,15 @@ free_twq:
        beiscsi_clean_port(phba);
        beiscsi_free_mem(phba);
 free_port:
+       real_offset = (u8 *)phba->csr_va + MPU_EP_SEMAPHORE;
+
+       value = readl((void *)real_offset);
+
+       if (value & 0x00010000) {
+               value &= 0xfffeffff;
+               writel(value, (void *)real_offset);
+       }
+
        pci_free_consistent(phba->pcidev,
                            phba->ctrl.mbox_mem_alloced.size,
                            phba->ctrl.mbox_mem_alloced.va,