[SCSI] be2iscsi: Adding crashdump support
authorJayamohan Kallickal <jayamohank@serverengines.com>
Wed, 21 Jul 2010 22:54:53 +0000 (04:24 +0530)
committerJames Bottomley <James.Bottomley@suse.de>
Wed, 28 Jul 2010 14:05:34 +0000 (09:05 -0500)
These changes allow the driver to support crashdump. We need to reset the
chip incase of a crashdump

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_cmds.c
drivers/scsi/be2iscsi/be_cmds.h
drivers/scsi/be2iscsi/be_main.c
drivers/scsi/be2iscsi/be_main.h

index 9cc1f557315056d6ef8d0d7feb6b12b54e24e5d4..7c7537335c88ba6b78e432eecb3f160821d28941 100644 (file)
 #include "be_mgmt.h"
 #include "be_main.h"
 
+int beiscsi_pci_soft_reset(struct beiscsi_hba *phba)
+{
+       u32 sreset;
+       u8 *pci_reset_offset = 0;
+       u8 *pci_online0_offset = 0;
+       u8 *pci_online1_offset = 0;
+       u32 pconline0 = 0;
+       u32 pconline1 = 0;
+       u32 i;
+
+       pci_reset_offset = (u8 *)phba->pci_va + BE2_SOFT_RESET;
+       pci_online0_offset = (u8 *)phba->pci_va + BE2_PCI_ONLINE0;
+       pci_online1_offset = (u8 *)phba->pci_va + BE2_PCI_ONLINE1;
+       sreset = readl((void *)pci_reset_offset);
+       sreset |= BE2_SET_RESET;
+       writel(sreset, (void *)pci_reset_offset);
+
+       i = 0;
+       while (sreset & BE2_SET_RESET) {
+               if (i > 64)
+                       break;
+               msleep(100);
+               sreset = readl((void *)pci_reset_offset);
+               i++;
+       }
+
+       if (sreset & BE2_SET_RESET) {
+               printk(KERN_ERR "Soft Reset  did not deassert\n");
+               return -EIO;
+       }
+       pconline1 = BE2_MPU_IRAM_ONLINE;
+       writel(pconline0, (void *)pci_online0_offset);
+       writel(pconline1, (void *)pci_online1_offset);
+
+       sreset = BE2_SET_RESET;
+       writel(sreset, (void *)pci_reset_offset);
+
+       i = 0;
+       while (sreset & BE2_SET_RESET) {
+               if (i > 64)
+                       break;
+               msleep(1);
+               sreset = readl((void *)pci_reset_offset);
+               i++;
+       }
+       if (sreset & BE2_SET_RESET) {
+               printk(KERN_ERR "MPU Online Soft Reset did not deassert\n");
+               return -EIO;
+       }
+       return 0;
+}
+
+int be_chk_reset_complete(struct beiscsi_hba *phba)
+{
+       unsigned int num_loop;
+       u8 *mpu_sem = 0;
+       u32 status;
+
+       num_loop = 1000;
+       mpu_sem = (u8 *)phba->csr_va + MPU_EP_SEMAPHORE;
+       msleep(5000);
+
+       while (num_loop) {
+               status = readl((void *)mpu_sem);
+
+               if ((status & 0x80000000) || (status & 0x0000FFFF) == 0xC000)
+                       break;
+               msleep(60);
+               num_loop--;
+       }
+
+       if ((status & 0x80000000) || (!num_loop)) {
+               printk(KERN_ERR "Failed in be_chk_reset_complete"
+               "status = 0x%x\n", status);
+               return -EIO;
+       }
+
+       return 0;
+}
+
 void be_mcc_notify(struct beiscsi_hba *phba)
 {
        struct be_queue_info *mccq = &phba->ctrl.mcc_obj.q;
index 30a293f52ef708a052a3e3f976c0aeb40e8d7051..0df19cb58a39c985e2c54318e3268ee7f342621f 100644 (file)
@@ -901,6 +901,9 @@ struct be_fw_cfg {
                                                 * the cxn
                                                 */
 
+int beiscsi_pci_soft_reset(struct beiscsi_hba *phba);
+int be_chk_reset_complete(struct beiscsi_hba *phba);
+
 void be_wrb_hdr_prepare(struct be_mcc_wrb *wrb, int payload_len,
                        bool embedded, u8 sge_cnt);
 
index 67a7e3f7bae6c111d704f0e358933513ac5f784f..1a22125f5202431b91c7aada801b3779845ab33d 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);
@@ -3731,6 +3733,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) {
@@ -3759,6 +3763,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,
@@ -3792,6 +3804,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) {
@@ -3837,6 +3851,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);
@@ -3907,6 +3948,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,
index e6ddddbbae7ab6714bcbcfaea42ac01fc5d4443b..05ad76e48d806e4ca5808f9ae78c29771610da21 100644 (file)
 #define BEISCSI_NUM_DEVICES_SUPPORTED  0x01
 #define BEISCSI_MAX_FRAGS_INIT 192
 #define BE_NUM_MSIX_ENTRIES    1
-#define MPU_EP_SEMAPHORE       0xac
+
+#define MPU_EP_CONTROL          0
+#define MPU_EP_SEMAPHORE        0xac
+#define BE2_SOFT_RESET          0x5c
+#define BE2_PCI_ONLINE0         0xb0
+#define BE2_PCI_ONLINE1         0xb4
+#define BE2_SET_RESET           0x80
+#define BE2_MPU_IRAM_ONLINE     0x00000080
 
 #define BE_SENSE_INFO_SIZE             258
 #define BE_ISCSI_PDU_HEADER_SIZE       64