diff options
author | James Smart <James.Smart@Emulex.Com> | 2008-12-04 22:39:19 -0500 |
---|---|---|
committer | James Bottomley <James.Bottomley@HansenPartnership.com> | 2008-12-29 12:24:26 -0500 |
commit | 97207482fcdd120a60a44e9eb6bbad8da6f81c9d (patch) | |
tree | 505eaae602772597da496232efe787e485dda718 /drivers | |
parent | eada272dfc32ba3dcd33e7ca5875337defb13c54 (diff) |
[SCSI] lpfc 8.3.0 : Added 3 small features and improve PCI EEH support
- 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>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/scsi/lpfc/lpfc_crtn.h | 1 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_hw.h | 37 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_init.c | 61 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_mbox.c | 35 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_nl.h | 16 |
5 files changed, 139 insertions, 11 deletions
diff --git a/drivers/scsi/lpfc/lpfc_crtn.h b/drivers/scsi/lpfc/lpfc_crtn.h index 044ef4057d28..a6594857712e 100644 --- a/drivers/scsi/lpfc/lpfc_crtn.h +++ b/drivers/scsi/lpfc/lpfc_crtn.h | |||
@@ -22,6 +22,7 @@ typedef int (*node_filter)(struct lpfc_nodelist *, void *); | |||
22 | 22 | ||
23 | struct fc_rport; | 23 | struct fc_rport; |
24 | void lpfc_dump_mem(struct lpfc_hba *, LPFC_MBOXQ_t *, uint16_t); | 24 | void lpfc_dump_mem(struct lpfc_hba *, LPFC_MBOXQ_t *, uint16_t); |
25 | void lpfc_dump_wakeup_param(struct lpfc_hba *, LPFC_MBOXQ_t *); | ||
25 | void lpfc_read_nv(struct lpfc_hba *, LPFC_MBOXQ_t *); | 26 | void lpfc_read_nv(struct lpfc_hba *, LPFC_MBOXQ_t *); |
26 | void lpfc_config_async(struct lpfc_hba *, LPFC_MBOXQ_t *, uint32_t); | 27 | void lpfc_config_async(struct lpfc_hba *, LPFC_MBOXQ_t *, uint32_t); |
27 | 28 | ||
diff --git a/drivers/scsi/lpfc/lpfc_hw.h b/drivers/scsi/lpfc/lpfc_hw.h index 81d1df418e47..4b5c12440b83 100644 --- a/drivers/scsi/lpfc/lpfc_hw.h +++ b/drivers/scsi/lpfc/lpfc_hw.h | |||
@@ -2362,6 +2362,30 @@ typedef struct { | |||
2362 | #define DMP_RSP_OFFSET 0x14 /* word 5 contains first word of rsp */ | 2362 | #define DMP_RSP_OFFSET 0x14 /* word 5 contains first word of rsp */ |
2363 | #define DMP_RSP_SIZE 0x6C /* maximum of 27 words of rsp data */ | 2363 | #define DMP_RSP_SIZE 0x6C /* maximum of 27 words of rsp data */ |
2364 | 2364 | ||
2365 | #define WAKE_UP_PARMS_REGION_ID 4 | ||
2366 | #define WAKE_UP_PARMS_WORD_SIZE 15 | ||
2367 | |||
2368 | /* Option rom version structure */ | ||
2369 | struct prog_id { | ||
2370 | #ifdef __BIG_ENDIAN_BITFIELD | ||
2371 | uint8_t type; | ||
2372 | uint8_t id; | ||
2373 | uint32_t ver:4; /* Major Version */ | ||
2374 | uint32_t rev:4; /* Revision */ | ||
2375 | uint32_t lev:2; /* Level */ | ||
2376 | uint32_t dist:2; /* Dist Type */ | ||
2377 | uint32_t num:4; /* number after dist type */ | ||
2378 | #else /* __LITTLE_ENDIAN_BITFIELD */ | ||
2379 | uint32_t num:4; /* number after dist type */ | ||
2380 | uint32_t dist:2; /* Dist Type */ | ||
2381 | uint32_t lev:2; /* Level */ | ||
2382 | uint32_t rev:4; /* Revision */ | ||
2383 | uint32_t ver:4; /* Major Version */ | ||
2384 | uint8_t id; | ||
2385 | uint8_t type; | ||
2386 | #endif | ||
2387 | }; | ||
2388 | |||
2365 | /* Structure for MB Command UPDATE_CFG (0x1B) */ | 2389 | /* Structure for MB Command UPDATE_CFG (0x1B) */ |
2366 | 2390 | ||
2367 | struct update_cfg_var { | 2391 | struct update_cfg_var { |
@@ -2555,10 +2579,17 @@ typedef struct { | |||
2555 | 2579 | ||
2556 | uint32_t pcbLow; /* bit 31:0 of memory based port config block */ | 2580 | uint32_t pcbLow; /* bit 31:0 of memory based port config block */ |
2557 | uint32_t pcbHigh; /* bit 63:32 of memory based port config block */ | 2581 | uint32_t pcbHigh; /* bit 63:32 of memory based port config block */ |
2558 | uint32_t hbainit[6]; | 2582 | uint32_t hbainit[5]; |
2583 | #ifdef __BIG_ENDIAN_BITFIELD | ||
2584 | uint32_t hps : 1; /* bit 31 word9 Host Pointer in slim */ | ||
2585 | uint32_t rsvd : 31; /* least significant 31 bits of word 9 */ | ||
2586 | #else /* __LITTLE_ENDIAN */ | ||
2587 | uint32_t rsvd : 31; /* least significant 31 bits of word 9 */ | ||
2588 | uint32_t hps : 1; /* bit 31 word9 Host Pointer in slim */ | ||
2589 | #endif | ||
2559 | 2590 | ||
2560 | #ifdef __BIG_ENDIAN_BITFIELD | 2591 | #ifdef __BIG_ENDIAN_BITFIELD |
2561 | uint32_t rsvd : 24; /* Reserved */ | 2592 | uint32_t rsvd1 : 24; /* Reserved */ |
2562 | uint32_t cmv : 1; /* Configure Max VPIs */ | 2593 | uint32_t cmv : 1; /* Configure Max VPIs */ |
2563 | uint32_t ccrp : 1; /* Config Command Ring Polling */ | 2594 | uint32_t ccrp : 1; /* Config Command Ring Polling */ |
2564 | uint32_t csah : 1; /* Configure Synchronous Abort Handling */ | 2595 | uint32_t csah : 1; /* Configure Synchronous Abort Handling */ |
@@ -2576,7 +2607,7 @@ typedef struct { | |||
2576 | uint32_t csah : 1; /* Configure Synchronous Abort Handling */ | 2607 | uint32_t csah : 1; /* Configure Synchronous Abort Handling */ |
2577 | uint32_t ccrp : 1; /* Config Command Ring Polling */ | 2608 | uint32_t ccrp : 1; /* Config Command Ring Polling */ |
2578 | uint32_t cmv : 1; /* Configure Max VPIs */ | 2609 | uint32_t cmv : 1; /* Configure Max VPIs */ |
2579 | uint32_t rsvd : 24; /* Reserved */ | 2610 | uint32_t rsvd1 : 24; /* Reserved */ |
2580 | #endif | 2611 | #endif |
2581 | #ifdef __BIG_ENDIAN_BITFIELD | 2612 | #ifdef __BIG_ENDIAN_BITFIELD |
2582 | uint32_t rsvd2 : 24; /* Reserved */ | 2613 | uint32_t rsvd2 : 24; /* Reserved */ |
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index 56ed5282117c..64e3d344f4dd 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c | |||
@@ -236,6 +236,48 @@ lpfc_config_async_cmpl(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmboxq) | |||
236 | } | 236 | } |
237 | 237 | ||
238 | /** | 238 | /** |
239 | * lpfc_dump_wakeup_param_cmpl: Completion handler for dump memory mailbox | ||
240 | * command used for getting wake up parameters. | ||
241 | * @phba: pointer to lpfc hba data structure. | ||
242 | * @pmboxq: pointer to the driver internal queue element for mailbox command. | ||
243 | * | ||
244 | * This is the completion handler for dump mailbox command for getting | ||
245 | * wake up parameters. When this command complete, the response contain | ||
246 | * Option rom version of the HBA. This function translate the version number | ||
247 | * into a human readable string and store it in OptionROMVersion. | ||
248 | **/ | ||
249 | static void | ||
250 | lpfc_dump_wakeup_param_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq) | ||
251 | { | ||
252 | struct prog_id *prg; | ||
253 | uint32_t prog_id_word; | ||
254 | char dist = ' '; | ||
255 | /* character array used for decoding dist type. */ | ||
256 | char dist_char[] = "nabx"; | ||
257 | |||
258 | if (pmboxq->mb.mbxStatus != MBX_SUCCESS) | ||
259 | return; | ||
260 | |||
261 | prg = (struct prog_id *) &prog_id_word; | ||
262 | |||
263 | /* word 7 contain option rom version */ | ||
264 | prog_id_word = pmboxq->mb.un.varWords[7]; | ||
265 | |||
266 | /* Decode the Option rom version word to a readable string */ | ||
267 | if (prg->dist < 4) | ||
268 | dist = dist_char[prg->dist]; | ||
269 | |||
270 | if ((prg->dist == 3) && (prg->num == 0)) | ||
271 | sprintf(phba->OptionROMVersion, "%d.%d%d", | ||
272 | prg->ver, prg->rev, prg->lev); | ||
273 | else | ||
274 | sprintf(phba->OptionROMVersion, "%d.%d%d%c%d", | ||
275 | prg->ver, prg->rev, prg->lev, | ||
276 | dist, prg->num); | ||
277 | return; | ||
278 | } | ||
279 | |||
280 | /** | ||
239 | * lpfc_config_port_post: Perform lpfc initialization after config port. | 281 | * lpfc_config_port_post: Perform lpfc initialization after config port. |
240 | * @phba: pointer to lpfc hba data structure. | 282 | * @phba: pointer to lpfc hba data structure. |
241 | * | 283 | * |
@@ -482,6 +524,20 @@ lpfc_config_port_post(struct lpfc_hba *phba) | |||
482 | rc); | 524 | rc); |
483 | mempool_free(pmb, phba->mbox_mem_pool); | 525 | mempool_free(pmb, phba->mbox_mem_pool); |
484 | } | 526 | } |
527 | |||
528 | /* Get Option rom version */ | ||
529 | pmb = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); | ||
530 | lpfc_dump_wakeup_param(phba, pmb); | ||
531 | pmb->mbox_cmpl = lpfc_dump_wakeup_param_cmpl; | ||
532 | pmb->vport = phba->pport; | ||
533 | rc = lpfc_sli_issue_mbox(phba, pmb, MBX_NOWAIT); | ||
534 | |||
535 | if ((rc != MBX_BUSY) && (rc != MBX_SUCCESS)) { | ||
536 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, "0435 Adapter failed " | ||
537 | "to get Option ROM version status x%x\n.", rc); | ||
538 | mempool_free(pmb, phba->mbox_mem_pool); | ||
539 | } | ||
540 | |||
485 | return 0; | 541 | return 0; |
486 | } | 542 | } |
487 | 543 | ||
@@ -2406,6 +2462,7 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid) | |||
2406 | phba->eratt_poll.data = (unsigned long) phba; | 2462 | phba->eratt_poll.data = (unsigned long) phba; |
2407 | 2463 | ||
2408 | pci_set_master(pdev); | 2464 | pci_set_master(pdev); |
2465 | pci_save_state(pdev); | ||
2409 | pci_try_set_mwi(pdev); | 2466 | pci_try_set_mwi(pdev); |
2410 | 2467 | ||
2411 | if (pci_set_dma_mask(phba->pcidev, DMA_64BIT_MASK) != 0) | 2468 | 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) | |||
2982 | return PCI_ERS_RESULT_DISCONNECT; | 3039 | return PCI_ERS_RESULT_DISCONNECT; |
2983 | } | 3040 | } |
2984 | 3041 | ||
2985 | pci_set_master(pdev); | 3042 | pci_restore_state(pdev); |
3043 | if (pdev->is_busmaster) | ||
3044 | pci_set_master(pdev); | ||
2986 | 3045 | ||
2987 | spin_lock_irq(&phba->hbalock); | 3046 | spin_lock_irq(&phba->hbalock); |
2988 | psli->sli_flag &= ~LPFC_SLI2_ACTIVE; | 3047 | psli->sli_flag &= ~LPFC_SLI2_ACTIVE; |
diff --git a/drivers/scsi/lpfc/lpfc_mbox.c b/drivers/scsi/lpfc/lpfc_mbox.c index 7465fe746fe9..dcdb7c939520 100644 --- a/drivers/scsi/lpfc/lpfc_mbox.c +++ b/drivers/scsi/lpfc/lpfc_mbox.c | |||
@@ -77,6 +77,38 @@ lpfc_dump_mem(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb, uint16_t offset) | |||
77 | } | 77 | } |
78 | 78 | ||
79 | /** | 79 | /** |
80 | * lpfc_dump_mem: Prepare a mailbox command for retrieving wakeup params. | ||
81 | * @phba: pointer to lpfc hba data structure. | ||
82 | * @pmb: pointer to the driver internal queue element for mailbox command. | ||
83 | * This function create a dump memory mailbox command to dump wake up | ||
84 | * parameters. | ||
85 | */ | ||
86 | void | ||
87 | lpfc_dump_wakeup_param(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) | ||
88 | { | ||
89 | MAILBOX_t *mb; | ||
90 | void *ctx; | ||
91 | |||
92 | mb = &pmb->mb; | ||
93 | /* Save context so that we can restore after memset */ | ||
94 | ctx = pmb->context2; | ||
95 | |||
96 | /* Setup to dump VPD region */ | ||
97 | memset(pmb, 0, sizeof(LPFC_MBOXQ_t)); | ||
98 | mb->mbxCommand = MBX_DUMP_MEMORY; | ||
99 | mb->mbxOwner = OWN_HOST; | ||
100 | mb->un.varDmp.cv = 1; | ||
101 | mb->un.varDmp.type = DMP_NV_PARAMS; | ||
102 | mb->un.varDmp.entry_index = 0; | ||
103 | mb->un.varDmp.region_id = WAKE_UP_PARMS_REGION_ID; | ||
104 | mb->un.varDmp.word_cnt = WAKE_UP_PARMS_WORD_SIZE; | ||
105 | mb->un.varDmp.co = 0; | ||
106 | mb->un.varDmp.resp_offset = 0; | ||
107 | pmb->context2 = ctx; | ||
108 | return; | ||
109 | } | ||
110 | |||
111 | /** | ||
80 | * lpfc_read_nv: Prepare a mailbox command for reading HBA's NVRAM param. | 112 | * lpfc_read_nv: Prepare a mailbox command for reading HBA's NVRAM param. |
81 | * @phba: pointer to lpfc hba data structure. | 113 | * @phba: pointer to lpfc hba data structure. |
82 | * @pmb: pointer to the driver internal queue element for mailbox command. | 114 | * @pmb: pointer to the driver internal queue element for mailbox command. |
@@ -1061,6 +1093,9 @@ lpfc_config_port(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) | |||
1061 | mb->un.varCfgPort.pcbLow = putPaddrLow(pdma_addr); | 1093 | mb->un.varCfgPort.pcbLow = putPaddrLow(pdma_addr); |
1062 | mb->un.varCfgPort.pcbHigh = putPaddrHigh(pdma_addr); | 1094 | mb->un.varCfgPort.pcbHigh = putPaddrHigh(pdma_addr); |
1063 | 1095 | ||
1096 | /* Always Host Group Pointer is in SLIM */ | ||
1097 | mb->un.varCfgPort.hps = 1; | ||
1098 | |||
1064 | /* If HBA supports SLI=3 ask for it */ | 1099 | /* If HBA supports SLI=3 ask for it */ |
1065 | 1100 | ||
1066 | if (phba->sli_rev == 3 && phba->vpd.sli3Feat.cerbm) { | 1101 | if (phba->sli_rev == 3 && phba->vpd.sli3Feat.cerbm) { |
diff --git a/drivers/scsi/lpfc/lpfc_nl.h b/drivers/scsi/lpfc/lpfc_nl.h index 991ad53bd3ce..27d1a88a98fe 100644 --- a/drivers/scsi/lpfc/lpfc_nl.h +++ b/drivers/scsi/lpfc/lpfc_nl.h | |||
@@ -22,18 +22,20 @@ | |||
22 | #define FC_REG_LINK_EVENT 0x0001 /* link up / down events */ | 22 | #define FC_REG_LINK_EVENT 0x0001 /* link up / down events */ |
23 | #define FC_REG_RSCN_EVENT 0x0002 /* RSCN events */ | 23 | #define FC_REG_RSCN_EVENT 0x0002 /* RSCN events */ |
24 | #define FC_REG_CT_EVENT 0x0004 /* CT request events */ | 24 | #define FC_REG_CT_EVENT 0x0004 /* CT request events */ |
25 | #define FC_REG_DUMP_EVENT 0x0008 /* Dump events */ | 25 | #define FC_REG_DUMP_EVENT 0x0010 /* Dump events */ |
26 | #define FC_REG_TEMPERATURE_EVENT 0x0010 /* temperature events */ | 26 | #define FC_REG_TEMPERATURE_EVENT 0x0020 /* temperature events */ |
27 | #define FC_REG_ELS_EVENT 0x0020 /* lpfc els events */ | 27 | #define FC_REG_VPORTRSCN_EVENT 0x0040 /* Vport RSCN events */ |
28 | #define FC_REG_FABRIC_EVENT 0x0040 /* lpfc fabric events */ | 28 | #define FC_REG_ELS_EVENT 0x0080 /* lpfc els events */ |
29 | #define FC_REG_SCSI_EVENT 0x0080 /* lpfc scsi events */ | 29 | #define FC_REG_FABRIC_EVENT 0x0100 /* lpfc fabric events */ |
30 | #define FC_REG_BOARD_EVENT 0x0100 /* lpfc board events */ | 30 | #define FC_REG_SCSI_EVENT 0x0200 /* lpfc scsi events */ |
31 | #define FC_REG_ADAPTER_EVENT 0x0200 /* lpfc adapter events */ | 31 | #define FC_REG_BOARD_EVENT 0x0400 /* lpfc board events */ |
32 | #define FC_REG_ADAPTER_EVENT 0x0800 /* lpfc adapter events */ | ||
32 | #define FC_REG_EVENT_MASK (FC_REG_LINK_EVENT | \ | 33 | #define FC_REG_EVENT_MASK (FC_REG_LINK_EVENT | \ |
33 | FC_REG_RSCN_EVENT | \ | 34 | FC_REG_RSCN_EVENT | \ |
34 | FC_REG_CT_EVENT | \ | 35 | FC_REG_CT_EVENT | \ |
35 | FC_REG_DUMP_EVENT | \ | 36 | FC_REG_DUMP_EVENT | \ |
36 | FC_REG_TEMPERATURE_EVENT | \ | 37 | FC_REG_TEMPERATURE_EVENT | \ |
38 | FC_REG_VPORTRSCN_EVENT | \ | ||
37 | FC_REG_ELS_EVENT | \ | 39 | FC_REG_ELS_EVENT | \ |
38 | FC_REG_FABRIC_EVENT | \ | 40 | FC_REG_FABRIC_EVENT | \ |
39 | FC_REG_SCSI_EVENT | \ | 41 | FC_REG_SCSI_EVENT | \ |