diff options
-rw-r--r-- | drivers/scsi/lpfc/lpfc.h | 1 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_attr.c | 7 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_crtn.h | 5 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_hw.h | 4 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_init.c | 59 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_mbox.c | 36 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_sli.c | 158 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_sli4.h | 4 |
8 files changed, 242 insertions, 32 deletions
diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h index 8917bb2c5fc2..7b63fe530041 100644 --- a/drivers/scsi/lpfc/lpfc.h +++ b/drivers/scsi/lpfc/lpfc.h | |||
@@ -525,6 +525,7 @@ struct lpfc_hba { | |||
525 | #define FCP_XRI_ABORT_EVENT 0x20 | 525 | #define FCP_XRI_ABORT_EVENT 0x20 |
526 | #define ELS_XRI_ABORT_EVENT 0x40 | 526 | #define ELS_XRI_ABORT_EVENT 0x40 |
527 | #define ASYNC_EVENT 0x80 | 527 | #define ASYNC_EVENT 0x80 |
528 | #define LINK_DISABLED 0x100 /* Link disabled by user */ | ||
528 | struct lpfc_dmabuf slim2p; | 529 | struct lpfc_dmabuf slim2p; |
529 | 530 | ||
530 | MAILBOX_t *mbox; | 531 | MAILBOX_t *mbox; |
diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c index fc07be5fbce9..7a629511338e 100644 --- a/drivers/scsi/lpfc/lpfc_attr.c +++ b/drivers/scsi/lpfc/lpfc_attr.c | |||
@@ -394,7 +394,12 @@ lpfc_link_state_show(struct device *dev, struct device_attribute *attr, | |||
394 | case LPFC_INIT_MBX_CMDS: | 394 | case LPFC_INIT_MBX_CMDS: |
395 | case LPFC_LINK_DOWN: | 395 | case LPFC_LINK_DOWN: |
396 | case LPFC_HBA_ERROR: | 396 | case LPFC_HBA_ERROR: |
397 | len += snprintf(buf + len, PAGE_SIZE-len, "Link Down\n"); | 397 | if (phba->hba_flag & LINK_DISABLED) |
398 | len += snprintf(buf + len, PAGE_SIZE-len, | ||
399 | "Link Down - User disabled\n"); | ||
400 | else | ||
401 | len += snprintf(buf + len, PAGE_SIZE-len, | ||
402 | "Link Down\n"); | ||
398 | break; | 403 | break; |
399 | case LPFC_LINK_UP: | 404 | case LPFC_LINK_UP: |
400 | case LPFC_CLEAR_LA: | 405 | case LPFC_CLEAR_LA: |
diff --git a/drivers/scsi/lpfc/lpfc_crtn.h b/drivers/scsi/lpfc/lpfc_crtn.h index d2a922997c0f..84e53bb1daa3 100644 --- a/drivers/scsi/lpfc/lpfc_crtn.h +++ b/drivers/scsi/lpfc/lpfc_crtn.h | |||
@@ -21,7 +21,9 @@ | |||
21 | typedef int (*node_filter)(struct lpfc_nodelist *, void *); | 21 | 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_down_link(struct lpfc_hba *, LPFC_MBOXQ_t *); |
25 | void lpfc_sli_read_link_ste(struct lpfc_hba *); | ||
26 | void lpfc_dump_mem(struct lpfc_hba *, LPFC_MBOXQ_t *, uint16_t, uint16_t); | ||
25 | void lpfc_dump_wakeup_param(struct lpfc_hba *, LPFC_MBOXQ_t *); | 27 | void lpfc_dump_wakeup_param(struct lpfc_hba *, LPFC_MBOXQ_t *); |
26 | void lpfc_dump_static_vport(struct lpfc_hba *, LPFC_MBOXQ_t *, uint16_t); | 28 | void lpfc_dump_static_vport(struct lpfc_hba *, LPFC_MBOXQ_t *, uint16_t); |
27 | int lpfc_dump_fcoe_param(struct lpfc_hba *, struct lpfcMboxq *); | 29 | int lpfc_dump_fcoe_param(struct lpfc_hba *, struct lpfcMboxq *); |
@@ -234,6 +236,7 @@ void lpfc_sli_def_mbox_cmpl(struct lpfc_hba *, LPFC_MBOXQ_t *); | |||
234 | int lpfc_sli_issue_iocb(struct lpfc_hba *, uint32_t, | 236 | int lpfc_sli_issue_iocb(struct lpfc_hba *, uint32_t, |
235 | struct lpfc_iocbq *, uint32_t); | 237 | struct lpfc_iocbq *, uint32_t); |
236 | void lpfc_sli_pcimem_bcopy(void *, void *, uint32_t); | 238 | void lpfc_sli_pcimem_bcopy(void *, void *, uint32_t); |
239 | void lpfc_sli_bemem_bcopy(void *, void *, uint32_t); | ||
237 | void lpfc_sli_abort_iocb_ring(struct lpfc_hba *, struct lpfc_sli_ring *); | 240 | void lpfc_sli_abort_iocb_ring(struct lpfc_hba *, struct lpfc_sli_ring *); |
238 | void lpfc_sli_flush_fcp_rings(struct lpfc_hba *); | 241 | void lpfc_sli_flush_fcp_rings(struct lpfc_hba *); |
239 | int lpfc_sli_ringpostbuf_put(struct lpfc_hba *, struct lpfc_sli_ring *, | 242 | int lpfc_sli_ringpostbuf_put(struct lpfc_hba *, struct lpfc_sli_ring *, |
diff --git a/drivers/scsi/lpfc/lpfc_hw.h b/drivers/scsi/lpfc/lpfc_hw.h index 8a3a026667e4..ccb26724dc53 100644 --- a/drivers/scsi/lpfc/lpfc_hw.h +++ b/drivers/scsi/lpfc/lpfc_hw.h | |||
@@ -2496,8 +2496,8 @@ typedef struct { | |||
2496 | #define DMP_VPORT_REGION_SIZE 0x200 | 2496 | #define DMP_VPORT_REGION_SIZE 0x200 |
2497 | #define DMP_MBOX_OFFSET_WORD 0x5 | 2497 | #define DMP_MBOX_OFFSET_WORD 0x5 |
2498 | 2498 | ||
2499 | #define DMP_REGION_FCOEPARAM 0x17 /* fcoe param region */ | 2499 | #define DMP_REGION_23 0x17 /* fcoe param and port state region */ |
2500 | #define DMP_FCOEPARAM_RGN_SIZE 0x400 | 2500 | #define DMP_RGN23_SIZE 0x400 |
2501 | 2501 | ||
2502 | #define WAKE_UP_PARMS_REGION_ID 4 | 2502 | #define WAKE_UP_PARMS_REGION_ID 4 |
2503 | #define WAKE_UP_PARMS_WORD_SIZE 15 | 2503 | #define WAKE_UP_PARMS_WORD_SIZE 15 |
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index f8271a587aab..900b5628ceb9 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c | |||
@@ -211,7 +211,7 @@ lpfc_config_port_prep(struct lpfc_hba *phba) | |||
211 | goto out_free_mbox; | 211 | goto out_free_mbox; |
212 | 212 | ||
213 | do { | 213 | do { |
214 | lpfc_dump_mem(phba, pmb, offset); | 214 | lpfc_dump_mem(phba, pmb, offset, DMP_REGION_VPD); |
215 | rc = lpfc_sli_issue_mbox(phba, pmb, MBX_POLL); | 215 | rc = lpfc_sli_issue_mbox(phba, pmb, MBX_POLL); |
216 | 216 | ||
217 | if (rc != MBX_SUCCESS) { | 217 | if (rc != MBX_SUCCESS) { |
@@ -425,6 +425,9 @@ lpfc_config_port_post(struct lpfc_hba *phba) | |||
425 | return -EIO; | 425 | return -EIO; |
426 | } | 426 | } |
427 | 427 | ||
428 | /* Check if the port is disabled */ | ||
429 | lpfc_sli_read_link_ste(phba); | ||
430 | |||
428 | /* Reset the DFT_HBA_Q_DEPTH to the max xri */ | 431 | /* Reset the DFT_HBA_Q_DEPTH to the max xri */ |
429 | if (phba->cfg_hba_queue_depth > (mb->un.varRdConfig.max_xri+1)) | 432 | if (phba->cfg_hba_queue_depth > (mb->un.varRdConfig.max_xri+1)) |
430 | phba->cfg_hba_queue_depth = | 433 | phba->cfg_hba_queue_depth = |
@@ -524,27 +527,49 @@ lpfc_config_port_post(struct lpfc_hba *phba) | |||
524 | /* Set up error attention (ERATT) polling timer */ | 527 | /* Set up error attention (ERATT) polling timer */ |
525 | mod_timer(&phba->eratt_poll, jiffies + HZ * LPFC_ERATT_POLL_INTERVAL); | 528 | mod_timer(&phba->eratt_poll, jiffies + HZ * LPFC_ERATT_POLL_INTERVAL); |
526 | 529 | ||
527 | lpfc_init_link(phba, pmb, phba->cfg_topology, phba->cfg_link_speed); | 530 | /* Check if the port is disabled */ |
528 | pmb->mbox_cmpl = lpfc_sli_def_mbox_cmpl; | 531 | lpfc_sli_read_serdes_param(phba); |
529 | lpfc_set_loopback_flag(phba); | 532 | |
530 | rc = lpfc_sli_issue_mbox(phba, pmb, MBX_NOWAIT); | 533 | if (phba->hba_flag & LINK_DISABLED) { |
531 | if (rc != MBX_SUCCESS) { | 534 | lpfc_printf_log(phba, |
532 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, | 535 | KERN_ERR, LOG_INIT, |
536 | "2598 Adapter Link is disabled.\n"); | ||
537 | lpfc_down_link(phba, pmb); | ||
538 | pmb->mbox_cmpl = lpfc_sli_def_mbox_cmpl; | ||
539 | rc = lpfc_sli_issue_mbox(phba, pmb, MBX_NOWAIT); | ||
540 | if ((rc != MBX_SUCCESS) && (rc != MBX_BUSY)) { | ||
541 | lpfc_printf_log(phba, | ||
542 | KERN_ERR, LOG_INIT, | ||
543 | "2599 Adapter failed to issue DOWN_LINK" | ||
544 | " mbox command rc 0x%x\n", rc); | ||
545 | |||
546 | mempool_free(pmb, phba->mbox_mem_pool); | ||
547 | return -EIO; | ||
548 | } | ||
549 | } else { | ||
550 | lpfc_init_link(phba, pmb, phba->cfg_topology, | ||
551 | phba->cfg_link_speed); | ||
552 | pmb->mbox_cmpl = lpfc_sli_def_mbox_cmpl; | ||
553 | lpfc_set_loopback_flag(phba); | ||
554 | rc = lpfc_sli_issue_mbox(phba, pmb, MBX_NOWAIT); | ||
555 | if (rc != MBX_SUCCESS) { | ||
556 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, | ||
533 | "0454 Adapter failed to init, mbxCmd x%x " | 557 | "0454 Adapter failed to init, mbxCmd x%x " |
534 | "INIT_LINK, mbxStatus x%x\n", | 558 | "INIT_LINK, mbxStatus x%x\n", |
535 | mb->mbxCommand, mb->mbxStatus); | 559 | mb->mbxCommand, mb->mbxStatus); |
536 | 560 | ||
537 | /* Clear all interrupt enable conditions */ | 561 | /* Clear all interrupt enable conditions */ |
538 | writel(0, phba->HCregaddr); | 562 | writel(0, phba->HCregaddr); |
539 | readl(phba->HCregaddr); /* flush */ | 563 | readl(phba->HCregaddr); /* flush */ |
540 | /* Clear all pending interrupts */ | 564 | /* Clear all pending interrupts */ |
541 | writel(0xffffffff, phba->HAregaddr); | 565 | writel(0xffffffff, phba->HAregaddr); |
542 | readl(phba->HAregaddr); /* flush */ | 566 | readl(phba->HAregaddr); /* flush */ |
543 | 567 | ||
544 | phba->link_state = LPFC_HBA_ERROR; | 568 | phba->link_state = LPFC_HBA_ERROR; |
545 | if (rc != MBX_BUSY) | 569 | if (rc != MBX_BUSY) |
546 | mempool_free(pmb, phba->mbox_mem_pool); | 570 | mempool_free(pmb, phba->mbox_mem_pool); |
547 | return -EIO; | 571 | return -EIO; |
572 | } | ||
548 | } | 573 | } |
549 | /* MBOX buffer will be freed in mbox compl */ | 574 | /* MBOX buffer will be freed in mbox compl */ |
550 | pmb = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); | 575 | pmb = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); |
diff --git a/drivers/scsi/lpfc/lpfc_mbox.c b/drivers/scsi/lpfc/lpfc_mbox.c index 42b4f3841697..245945f2f3a0 100644 --- a/drivers/scsi/lpfc/lpfc_mbox.c +++ b/drivers/scsi/lpfc/lpfc_mbox.c | |||
@@ -79,21 +79,37 @@ lpfc_dump_static_vport(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb, | |||
79 | } | 79 | } |
80 | 80 | ||
81 | /** | 81 | /** |
82 | * lpfc_dump_mem - Prepare a mailbox command for retrieving HBA's VPD memory | 82 | * lpfc_down_link - Bring down HBAs link. |
83 | * @phba: pointer to lpfc hba data structure. | 83 | * @phba: pointer to lpfc hba data structure. |
84 | * @pmb: pointer to the driver internal queue element for mailbox command. | 84 | * @pmb: pointer to the driver internal queue element for mailbox command. |
85 | * @offset: offset for dumping VPD memory mailbox command. | 85 | * |
86 | * This routine prepares a mailbox command to bring down HBA link. | ||
87 | **/ | ||
88 | void | ||
89 | lpfc_down_link(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) | ||
90 | { | ||
91 | MAILBOX_t *mb; | ||
92 | memset(pmb, 0, sizeof(LPFC_MBOXQ_t)); | ||
93 | mb = &pmb->u.mb; | ||
94 | mb->mbxCommand = MBX_DOWN_LINK; | ||
95 | mb->mbxOwner = OWN_HOST; | ||
96 | } | ||
97 | |||
98 | /** | ||
99 | * lpfc_dump_mem - Prepare a mailbox command for reading a region. | ||
100 | * @phba: pointer to lpfc hba data structure. | ||
101 | * @pmb: pointer to the driver internal queue element for mailbox command. | ||
102 | * @offset: offset into the region. | ||
103 | * @region_id: config region id. | ||
86 | * | 104 | * |
87 | * The dump mailbox command provides a method for the device driver to obtain | 105 | * The dump mailbox command provides a method for the device driver to obtain |
88 | * various types of information from the HBA device. | 106 | * various types of information from the HBA device. |
89 | * | 107 | * |
90 | * This routine prepares the mailbox command for dumping HBA Vital Product | 108 | * This routine prepares the mailbox command for dumping HBA's config region. |
91 | * Data (VPD) memory. This mailbox command is to be used for retrieving a | ||
92 | * portion (DMP_RSP_SIZE bytes) of a HBA's VPD from the HBA at an address | ||
93 | * offset specified by the offset parameter. | ||
94 | **/ | 109 | **/ |
95 | void | 110 | void |
96 | lpfc_dump_mem(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb, uint16_t offset) | 111 | lpfc_dump_mem(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb, uint16_t offset, |
112 | uint16_t region_id) | ||
97 | { | 113 | { |
98 | MAILBOX_t *mb; | 114 | MAILBOX_t *mb; |
99 | void *ctx; | 115 | void *ctx; |
@@ -107,7 +123,7 @@ lpfc_dump_mem(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb, uint16_t offset) | |||
107 | mb->un.varDmp.cv = 1; | 123 | mb->un.varDmp.cv = 1; |
108 | mb->un.varDmp.type = DMP_NV_PARAMS; | 124 | mb->un.varDmp.type = DMP_NV_PARAMS; |
109 | mb->un.varDmp.entry_index = offset; | 125 | mb->un.varDmp.entry_index = offset; |
110 | mb->un.varDmp.region_id = DMP_REGION_VPD; | 126 | mb->un.varDmp.region_id = region_id; |
111 | mb->un.varDmp.word_cnt = (DMP_RSP_SIZE / sizeof (uint32_t)); | 127 | mb->un.varDmp.word_cnt = (DMP_RSP_SIZE / sizeof (uint32_t)); |
112 | mb->un.varDmp.co = 0; | 128 | mb->un.varDmp.co = 0; |
113 | mb->un.varDmp.resp_offset = 0; | 129 | mb->un.varDmp.resp_offset = 0; |
@@ -1864,8 +1880,8 @@ lpfc_dump_fcoe_param(struct lpfc_hba *phba, | |||
1864 | 1880 | ||
1865 | mb->mbxCommand = MBX_DUMP_MEMORY; | 1881 | mb->mbxCommand = MBX_DUMP_MEMORY; |
1866 | mb->un.varDmp.type = DMP_NV_PARAMS; | 1882 | mb->un.varDmp.type = DMP_NV_PARAMS; |
1867 | mb->un.varDmp.region_id = DMP_REGION_FCOEPARAM; | 1883 | mb->un.varDmp.region_id = DMP_REGION_23; |
1868 | mb->un.varDmp.sli4_length = DMP_FCOEPARAM_RGN_SIZE; | 1884 | mb->un.varDmp.sli4_length = DMP_RGN23_SIZE; |
1869 | mb->un.varWords[3] = putPaddrLow(mp->phys); | 1885 | mb->un.varWords[3] = putPaddrLow(mp->phys); |
1870 | mb->un.varWords[4] = putPaddrHigh(mp->phys); | 1886 | mb->un.varWords[4] = putPaddrHigh(mp->phys); |
1871 | return 0; | 1887 | return 0; |
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index 04f527ca8f5f..a3f85454368d 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c | |||
@@ -4139,7 +4139,7 @@ lpfc_sli4_read_fcoe_params(struct lpfc_hba *phba, | |||
4139 | return -EIO; | 4139 | return -EIO; |
4140 | } | 4140 | } |
4141 | data_length = mqe->un.mb_words[5]; | 4141 | data_length = mqe->un.mb_words[5]; |
4142 | if (data_length > DMP_FCOEPARAM_RGN_SIZE) { | 4142 | if (data_length > DMP_RGN23_SIZE) { |
4143 | lpfc_mbuf_free(phba, mp->virt, mp->phys); | 4143 | lpfc_mbuf_free(phba, mp->virt, mp->phys); |
4144 | kfree(mp); | 4144 | kfree(mp); |
4145 | return -EIO; | 4145 | return -EIO; |
@@ -6789,6 +6789,33 @@ lpfc_sli_pcimem_bcopy(void *srcp, void *destp, uint32_t cnt) | |||
6789 | 6789 | ||
6790 | 6790 | ||
6791 | /** | 6791 | /** |
6792 | * lpfc_sli_bemem_bcopy - SLI memory copy function | ||
6793 | * @srcp: Source memory pointer. | ||
6794 | * @destp: Destination memory pointer. | ||
6795 | * @cnt: Number of words required to be copied. | ||
6796 | * | ||
6797 | * This function is used for copying data between a data structure | ||
6798 | * with big endian representation to local endianness. | ||
6799 | * This function can be called with or without lock. | ||
6800 | **/ | ||
6801 | void | ||
6802 | lpfc_sli_bemem_bcopy(void *srcp, void *destp, uint32_t cnt) | ||
6803 | { | ||
6804 | uint32_t *src = srcp; | ||
6805 | uint32_t *dest = destp; | ||
6806 | uint32_t ldata; | ||
6807 | int i; | ||
6808 | |||
6809 | for (i = 0; i < (int)cnt; i += sizeof(uint32_t)) { | ||
6810 | ldata = *src; | ||
6811 | ldata = be32_to_cpu(ldata); | ||
6812 | *dest = ldata; | ||
6813 | src++; | ||
6814 | dest++; | ||
6815 | } | ||
6816 | } | ||
6817 | |||
6818 | /** | ||
6792 | * lpfc_sli_ringpostbuf_put - Function to add a buffer to postbufq | 6819 | * lpfc_sli_ringpostbuf_put - Function to add a buffer to postbufq |
6793 | * @phba: Pointer to HBA context object. | 6820 | * @phba: Pointer to HBA context object. |
6794 | * @pring: Pointer to driver SLI ring object. | 6821 | * @pring: Pointer to driver SLI ring object. |
@@ -11564,3 +11591,132 @@ lpfc_sli4_read_fcf_record(struct lpfc_hba *phba, uint16_t fcf_index) | |||
11564 | error = 0; | 11591 | error = 0; |
11565 | return error; | 11592 | return error; |
11566 | } | 11593 | } |
11594 | |||
11595 | /** | ||
11596 | * lpfc_sli_read_link_ste - Read region 23 to decide if link is disabled. | ||
11597 | * @phba: pointer to lpfc hba data structure. | ||
11598 | * | ||
11599 | * This function read region 23 and parse TLV for port status to | ||
11600 | * decide if the user disaled the port. If the TLV indicates the | ||
11601 | * port is disabled, the hba_flag is set accordingly. | ||
11602 | **/ | ||
11603 | void | ||
11604 | lpfc_sli_read_link_ste(struct lpfc_hba *phba) | ||
11605 | { | ||
11606 | LPFC_MBOXQ_t *pmb = NULL; | ||
11607 | MAILBOX_t *mb; | ||
11608 | uint8_t *rgn23_data = NULL; | ||
11609 | uint32_t offset = 0, data_size, sub_tlv_len, tlv_offset; | ||
11610 | int rc; | ||
11611 | |||
11612 | pmb = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); | ||
11613 | if (!pmb) { | ||
11614 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, | ||
11615 | "2600 lpfc_sli_read_serdes_param failed to" | ||
11616 | " allocate mailbox memory\n"); | ||
11617 | goto out; | ||
11618 | } | ||
11619 | mb = &pmb->u.mb; | ||
11620 | |||
11621 | /* Get adapter Region 23 data */ | ||
11622 | rgn23_data = kzalloc(DMP_RGN23_SIZE, GFP_KERNEL); | ||
11623 | if (!rgn23_data) | ||
11624 | goto out; | ||
11625 | |||
11626 | do { | ||
11627 | lpfc_dump_mem(phba, pmb, offset, DMP_REGION_23); | ||
11628 | rc = lpfc_sli_issue_mbox(phba, pmb, MBX_POLL); | ||
11629 | |||
11630 | if (rc != MBX_SUCCESS) { | ||
11631 | lpfc_printf_log(phba, KERN_INFO, LOG_INIT, | ||
11632 | "2601 lpfc_sli_read_link_ste failed to" | ||
11633 | " read config region 23 rc 0x%x Status 0x%x\n", | ||
11634 | rc, mb->mbxStatus); | ||
11635 | mb->un.varDmp.word_cnt = 0; | ||
11636 | } | ||
11637 | /* | ||
11638 | * dump mem may return a zero when finished or we got a | ||
11639 | * mailbox error, either way we are done. | ||
11640 | */ | ||
11641 | if (mb->un.varDmp.word_cnt == 0) | ||
11642 | break; | ||
11643 | if (mb->un.varDmp.word_cnt > DMP_RGN23_SIZE - offset) | ||
11644 | mb->un.varDmp.word_cnt = DMP_RGN23_SIZE - offset; | ||
11645 | |||
11646 | lpfc_sli_pcimem_bcopy(((uint8_t *)mb) + DMP_RSP_OFFSET, | ||
11647 | rgn23_data + offset, | ||
11648 | mb->un.varDmp.word_cnt); | ||
11649 | offset += mb->un.varDmp.word_cnt; | ||
11650 | } while (mb->un.varDmp.word_cnt && offset < DMP_RGN23_SIZE); | ||
11651 | |||
11652 | data_size = offset; | ||
11653 | offset = 0; | ||
11654 | |||
11655 | if (!data_size) | ||
11656 | goto out; | ||
11657 | |||
11658 | /* Check the region signature first */ | ||
11659 | if (memcmp(&rgn23_data[offset], LPFC_REGION23_SIGNATURE, 4)) { | ||
11660 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, | ||
11661 | "2619 Config region 23 has bad signature\n"); | ||
11662 | goto out; | ||
11663 | } | ||
11664 | offset += 4; | ||
11665 | |||
11666 | /* Check the data structure version */ | ||
11667 | if (rgn23_data[offset] != LPFC_REGION23_VERSION) { | ||
11668 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, | ||
11669 | "2620 Config region 23 has bad version\n"); | ||
11670 | goto out; | ||
11671 | } | ||
11672 | offset += 4; | ||
11673 | |||
11674 | /* Parse TLV entries in the region */ | ||
11675 | while (offset < data_size) { | ||
11676 | if (rgn23_data[offset] == LPFC_REGION23_LAST_REC) | ||
11677 | break; | ||
11678 | /* | ||
11679 | * If the TLV is not driver specific TLV or driver id is | ||
11680 | * not linux driver id, skip the record. | ||
11681 | */ | ||
11682 | if ((rgn23_data[offset] != DRIVER_SPECIFIC_TYPE) || | ||
11683 | (rgn23_data[offset + 2] != LINUX_DRIVER_ID) || | ||
11684 | (rgn23_data[offset + 3] != 0)) { | ||
11685 | offset += rgn23_data[offset + 1] * 4 + 4; | ||
11686 | continue; | ||
11687 | } | ||
11688 | |||
11689 | /* Driver found a driver specific TLV in the config region */ | ||
11690 | sub_tlv_len = rgn23_data[offset + 1] * 4; | ||
11691 | offset += 4; | ||
11692 | tlv_offset = 0; | ||
11693 | |||
11694 | /* | ||
11695 | * Search for configured port state sub-TLV. | ||
11696 | */ | ||
11697 | while ((offset < data_size) && | ||
11698 | (tlv_offset < sub_tlv_len)) { | ||
11699 | if (rgn23_data[offset] == LPFC_REGION23_LAST_REC) { | ||
11700 | offset += 4; | ||
11701 | tlv_offset += 4; | ||
11702 | break; | ||
11703 | } | ||
11704 | if (rgn23_data[offset] != PORT_STE_TYPE) { | ||
11705 | offset += rgn23_data[offset + 1] * 4 + 4; | ||
11706 | tlv_offset += rgn23_data[offset + 1] * 4 + 4; | ||
11707 | continue; | ||
11708 | } | ||
11709 | |||
11710 | /* This HBA contains PORT_STE configured */ | ||
11711 | if (!rgn23_data[offset + 2]) | ||
11712 | phba->hba_flag |= LINK_DISABLED; | ||
11713 | |||
11714 | goto out; | ||
11715 | } | ||
11716 | } | ||
11717 | out: | ||
11718 | if (pmb) | ||
11719 | mempool_free(pmb, phba->mbox_mem_pool); | ||
11720 | kfree(rgn23_data); | ||
11721 | return; | ||
11722 | } | ||
diff --git a/drivers/scsi/lpfc/lpfc_sli4.h b/drivers/scsi/lpfc/lpfc_sli4.h index b6f3e04f3848..b5f4ba1a5c27 100644 --- a/drivers/scsi/lpfc/lpfc_sli4.h +++ b/drivers/scsi/lpfc/lpfc_sli4.h | |||
@@ -151,6 +151,10 @@ struct lpfc_fcf { | |||
151 | #define LPFC_REGION23_SIGNATURE "RG23" | 151 | #define LPFC_REGION23_SIGNATURE "RG23" |
152 | #define LPFC_REGION23_VERSION 1 | 152 | #define LPFC_REGION23_VERSION 1 |
153 | #define LPFC_REGION23_LAST_REC 0xff | 153 | #define LPFC_REGION23_LAST_REC 0xff |
154 | #define DRIVER_SPECIFIC_TYPE 0xA2 | ||
155 | #define LINUX_DRIVER_ID 0x20 | ||
156 | #define PORT_STE_TYPE 0x1 | ||
157 | |||
154 | struct lpfc_fip_param_hdr { | 158 | struct lpfc_fip_param_hdr { |
155 | uint8_t type; | 159 | uint8_t type; |
156 | #define FCOE_PARAM_TYPE 0xA0 | 160 | #define FCOE_PARAM_TYPE 0xA0 |