[SCSI] lpfc 8.3.0 : Added 3 small features and improve PCI EEH support
authorJames Smart <James.Smart@Emulex.Com>
Fri, 5 Dec 2008 03:39:19 +0000 (22:39 -0500)
committerJames Bottomley <James.Bottomley@HansenPartnership.com>
Mon, 29 Dec 2008 17:24:26 +0000 (11:24 -0600)
- Added FC_REG_VPORTRSCN_EVENT to lpfc_nl.h

- Added code to provide option ROM version from HBA and via sysfs

- Added support for HPS bit in config port mailbox command to tell HBA
  that host group pointers are in host memory.

- Bugfix for Extended Error Handling (EEH) support on IBM PowerPC P6
  platform with MSI enabled

Signed-off-by: James Smart <James.Smart@emulex.com>
Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
drivers/scsi/lpfc/lpfc_crtn.h
drivers/scsi/lpfc/lpfc_hw.h
drivers/scsi/lpfc/lpfc_init.c
drivers/scsi/lpfc/lpfc_mbox.c
drivers/scsi/lpfc/lpfc_nl.h

index 044ef4057d281d7a52584f8515e4c24e371d2214..a6594857712e8f6773d637025fa701a023ec2e11 100644 (file)
@@ -22,6 +22,7 @@ typedef int (*node_filter)(struct lpfc_nodelist *, void *);
 
 struct fc_rport;
 void lpfc_dump_mem(struct lpfc_hba *, LPFC_MBOXQ_t *, uint16_t);
+void lpfc_dump_wakeup_param(struct lpfc_hba *, LPFC_MBOXQ_t *);
 void lpfc_read_nv(struct lpfc_hba *, LPFC_MBOXQ_t *);
 void lpfc_config_async(struct lpfc_hba *, LPFC_MBOXQ_t *, uint32_t);
 
index 81d1df418e479380391ebf1c649f58a7c1b58335..4b5c12440b8395d03f8fa0fd8cc79f55d162cb68 100644 (file)
@@ -2362,6 +2362,30 @@ typedef struct {
 #define  DMP_RSP_OFFSET          0x14   /* word 5 contains first word of rsp */
 #define  DMP_RSP_SIZE            0x6C   /* maximum of 27 words of rsp data */
 
+#define  WAKE_UP_PARMS_REGION_ID    4
+#define  WAKE_UP_PARMS_WORD_SIZE   15
+
+/* Option rom version structure */
+struct prog_id {
+#ifdef __BIG_ENDIAN_BITFIELD
+       uint8_t  type;
+       uint8_t  id;
+       uint32_t ver:4;  /* Major Version */
+       uint32_t rev:4;  /* Revision */
+       uint32_t lev:2;  /* Level */
+       uint32_t dist:2; /* Dist Type */
+       uint32_t num:4;  /* number after dist type */
+#else /*  __LITTLE_ENDIAN_BITFIELD */
+       uint32_t num:4;  /* number after dist type */
+       uint32_t dist:2; /* Dist Type */
+       uint32_t lev:2;  /* Level */
+       uint32_t rev:4;  /* Revision */
+       uint32_t ver:4;  /* Major Version */
+       uint8_t  id;
+       uint8_t  type;
+#endif
+};
+
 /* Structure for MB Command UPDATE_CFG (0x1B) */
 
 struct update_cfg_var {
@@ -2555,10 +2579,17 @@ typedef struct {
 
        uint32_t pcbLow;       /* bit 31:0  of memory based port config block */
        uint32_t pcbHigh;      /* bit 63:32 of memory based port config block */
-       uint32_t hbainit[6];
+       uint32_t hbainit[5];
+#ifdef __BIG_ENDIAN_BITFIELD
+       uint32_t hps       :  1; /* bit 31 word9 Host Pointer in slim */
+       uint32_t rsvd      : 31; /* least significant 31 bits of word 9 */
+#else   /*  __LITTLE_ENDIAN */
+       uint32_t rsvd      : 31; /* least significant 31 bits of word 9 */
+       uint32_t hps       :  1; /* bit 31 word9 Host Pointer in slim */
+#endif
 
 #ifdef __BIG_ENDIAN_BITFIELD
-       uint32_t rsvd      : 24;  /* Reserved                             */
+       uint32_t rsvd1     : 24;  /* Reserved                             */
        uint32_t cmv       :  1;  /* Configure Max VPIs                   */
        uint32_t ccrp      :  1;  /* Config Command Ring Polling          */
        uint32_t csah      :  1;  /* Configure Synchronous Abort Handling */
@@ -2576,7 +2607,7 @@ typedef struct {
        uint32_t csah      :  1;  /* Configure Synchronous Abort Handling */
        uint32_t ccrp      :  1;  /* Config Command Ring Polling          */
        uint32_t cmv       :  1;  /* Configure Max VPIs                   */
-       uint32_t rsvd      : 24;  /* Reserved                             */
+       uint32_t rsvd1     : 24;  /* Reserved                             */
 #endif
 #ifdef __BIG_ENDIAN_BITFIELD
        uint32_t rsvd2     : 24;  /* Reserved                             */
index 56ed5282117c92b92bf92acb668f67055e3c5549..64e3d344f4dda5047ee1918ef8944e2c51632990 100644 (file)
@@ -235,6 +235,48 @@ lpfc_config_async_cmpl(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmboxq)
        return;
 }
 
+/**
+ * lpfc_dump_wakeup_param_cmpl: Completion handler for dump memory mailbox
+ *     command used for getting wake up parameters.
+ * @phba: pointer to lpfc hba data structure.
+ * @pmboxq: pointer to the driver internal queue element for mailbox command.
+ *
+ * This is the completion handler for dump mailbox command for getting
+ * wake up parameters. When this command complete, the response contain
+ * Option rom version of the HBA. This function translate the version number
+ * into a human readable string and store it in OptionROMVersion.
+ **/
+static void
+lpfc_dump_wakeup_param_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq)
+{
+       struct prog_id *prg;
+       uint32_t prog_id_word;
+       char dist = ' ';
+       /* character array used for decoding dist type. */
+       char dist_char[] = "nabx";
+
+       if (pmboxq->mb.mbxStatus != MBX_SUCCESS)
+               return;
+
+       prg = (struct prog_id *) &prog_id_word;
+
+       /* word 7 contain option rom version */
+       prog_id_word = pmboxq->mb.un.varWords[7];
+
+       /* Decode the Option rom version word to a readable string */
+       if (prg->dist < 4)
+               dist = dist_char[prg->dist];
+
+       if ((prg->dist == 3) && (prg->num == 0))
+               sprintf(phba->OptionROMVersion, "%d.%d%d",
+                       prg->ver, prg->rev, prg->lev);
+       else
+               sprintf(phba->OptionROMVersion, "%d.%d%d%c%d",
+                       prg->ver, prg->rev, prg->lev,
+                       dist, prg->num);
+       return;
+}
+
 /**
  * lpfc_config_port_post: Perform lpfc initialization after config port.
  * @phba: pointer to lpfc hba data structure.
@@ -482,6 +524,20 @@ lpfc_config_port_post(struct lpfc_hba *phba)
                                rc);
                mempool_free(pmb, phba->mbox_mem_pool);
        }
+
+       /* Get Option rom version */
+       pmb = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
+       lpfc_dump_wakeup_param(phba, pmb);
+       pmb->mbox_cmpl = lpfc_dump_wakeup_param_cmpl;
+       pmb->vport = phba->pport;
+       rc = lpfc_sli_issue_mbox(phba, pmb, MBX_NOWAIT);
+
+       if ((rc != MBX_BUSY) && (rc != MBX_SUCCESS)) {
+               lpfc_printf_log(phba, KERN_ERR, LOG_INIT, "0435 Adapter failed "
+                               "to get Option ROM version status x%x\n.", rc);
+               mempool_free(pmb, phba->mbox_mem_pool);
+       }
+
        return 0;
 }
 
@@ -2406,6 +2462,7 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid)
        phba->eratt_poll.data = (unsigned long) phba;
 
        pci_set_master(pdev);
+       pci_save_state(pdev);
        pci_try_set_mwi(pdev);
 
        if (pci_set_dma_mask(phba->pcidev, DMA_64BIT_MASK) != 0)
@@ -2982,7 +3039,9 @@ static pci_ers_result_t lpfc_io_slot_reset(struct pci_dev *pdev)
                return PCI_ERS_RESULT_DISCONNECT;
        }
 
-       pci_set_master(pdev);
+       pci_restore_state(pdev);
+       if (pdev->is_busmaster)
+               pci_set_master(pdev);
 
        spin_lock_irq(&phba->hbalock);
        psli->sli_flag &= ~LPFC_SLI2_ACTIVE;
index 7465fe746fe93a92da8ad243ff54f4cd0774df03..dcdb7c939520166c6400458698cc6cf287af4d81 100644 (file)
@@ -76,6 +76,38 @@ lpfc_dump_mem(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb, uint16_t offset)
        return;
 }
 
+/**
+ * lpfc_dump_mem: Prepare a mailbox command for retrieving wakeup params.
+ * @phba: pointer to lpfc hba data structure.
+ * @pmb: pointer to the driver internal queue element for mailbox command.
+ * This function create a dump memory mailbox command to dump wake up
+ * parameters.
+ */
+void
+lpfc_dump_wakeup_param(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
+{
+       MAILBOX_t *mb;
+       void *ctx;
+
+       mb = &pmb->mb;
+       /* Save context so that we can restore after memset */
+       ctx = pmb->context2;
+
+       /* Setup to dump VPD region */
+       memset(pmb, 0, sizeof(LPFC_MBOXQ_t));
+       mb->mbxCommand = MBX_DUMP_MEMORY;
+       mb->mbxOwner = OWN_HOST;
+       mb->un.varDmp.cv = 1;
+       mb->un.varDmp.type = DMP_NV_PARAMS;
+       mb->un.varDmp.entry_index = 0;
+       mb->un.varDmp.region_id = WAKE_UP_PARMS_REGION_ID;
+       mb->un.varDmp.word_cnt = WAKE_UP_PARMS_WORD_SIZE;
+       mb->un.varDmp.co = 0;
+       mb->un.varDmp.resp_offset = 0;
+       pmb->context2 = ctx;
+       return;
+}
+
 /**
  * lpfc_read_nv: Prepare a mailbox command for reading HBA's NVRAM param.
  * @phba: pointer to lpfc hba data structure.
@@ -1061,6 +1093,9 @@ lpfc_config_port(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
        mb->un.varCfgPort.pcbLow = putPaddrLow(pdma_addr);
        mb->un.varCfgPort.pcbHigh = putPaddrHigh(pdma_addr);
 
+       /* Always Host Group Pointer is in SLIM */
+       mb->un.varCfgPort.hps = 1;
+
        /* If HBA supports SLI=3 ask for it */
 
        if (phba->sli_rev == 3 && phba->vpd.sli3Feat.cerbm) {
index 991ad53bd3ce35b093403511da1294ae7463cd77..27d1a88a98fe2fdeeb549ec7f69b045f49407de0 100644 (file)
 #define FC_REG_LINK_EVENT              0x0001  /* link up / down events */
 #define FC_REG_RSCN_EVENT              0x0002  /* RSCN events */
 #define FC_REG_CT_EVENT                        0x0004  /* CT request events */
-#define FC_REG_DUMP_EVENT              0x0008  /* Dump events */
-#define FC_REG_TEMPERATURE_EVENT       0x0010  /* temperature events */
-#define FC_REG_ELS_EVENT               0x0020  /* lpfc els events */
-#define FC_REG_FABRIC_EVENT            0x0040  /* lpfc fabric events */
-#define FC_REG_SCSI_EVENT              0x0080  /* lpfc scsi events */
-#define FC_REG_BOARD_EVENT             0x0100  /* lpfc board events */
-#define FC_REG_ADAPTER_EVENT           0x0200  /* lpfc adapter events */
+#define FC_REG_DUMP_EVENT              0x0010  /* Dump events */
+#define FC_REG_TEMPERATURE_EVENT       0x0020  /* temperature events */
+#define FC_REG_VPORTRSCN_EVENT         0x0040  /* Vport RSCN events */
+#define FC_REG_ELS_EVENT               0x0080  /* lpfc els events */
+#define FC_REG_FABRIC_EVENT            0x0100  /* lpfc fabric events */
+#define FC_REG_SCSI_EVENT              0x0200  /* lpfc scsi events */
+#define FC_REG_BOARD_EVENT             0x0400  /* lpfc board events */
+#define FC_REG_ADAPTER_EVENT           0x0800  /* lpfc adapter events */
 #define FC_REG_EVENT_MASK              (FC_REG_LINK_EVENT | \
                                                FC_REG_RSCN_EVENT | \
                                                FC_REG_CT_EVENT | \
                                                FC_REG_DUMP_EVENT | \
                                                FC_REG_TEMPERATURE_EVENT | \
+                                               FC_REG_VPORTRSCN_EVENT | \
                                                FC_REG_ELS_EVENT | \
                                                FC_REG_FABRIC_EVENT | \
                                                FC_REG_SCSI_EVENT | \