aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/lpfc
diff options
context:
space:
mode:
authorJames Smart <James.Smart@Emulex.Com>2009-07-19 10:01:10 -0400
committerJames Bottomley <James.Bottomley@suse.de>2009-08-22 18:51:57 -0400
commita0c87cbdb52467a16343b31251f2722643db603c (patch)
tree0242b3b51f1984ca3f8d59390487f39a865812aa /drivers/scsi/lpfc
parent8fa38513ddc1076f3e26c651f3567b084c273ba2 (diff)
[SCSI] lpfc 8.3.4: Consistently Implement persistent port disable
Consistently implement persistent port disable. Ability was to be managed in the adapter via firmware via flash settings. However, not all firmware images supported it. Uniformly support it everywhere. Signed-off-by: James Smart <James.Smart@emulex.com> Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com> Signed-off-by: James Bottomley <James.Bottomley@suse.de>
Diffstat (limited to 'drivers/scsi/lpfc')
-rw-r--r--drivers/scsi/lpfc/lpfc.h1
-rw-r--r--drivers/scsi/lpfc/lpfc_attr.c7
-rw-r--r--drivers/scsi/lpfc/lpfc_crtn.h5
-rw-r--r--drivers/scsi/lpfc/lpfc_hw.h4
-rw-r--r--drivers/scsi/lpfc/lpfc_init.c59
-rw-r--r--drivers/scsi/lpfc/lpfc_mbox.c36
-rw-r--r--drivers/scsi/lpfc/lpfc_sli.c158
-rw-r--r--drivers/scsi/lpfc/lpfc_sli4.h4
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 @@
21typedef int (*node_filter)(struct lpfc_nodelist *, void *); 21typedef int (*node_filter)(struct lpfc_nodelist *, void *);
22 22
23struct fc_rport; 23struct fc_rport;
24void lpfc_dump_mem(struct lpfc_hba *, LPFC_MBOXQ_t *, uint16_t); 24void lpfc_down_link(struct lpfc_hba *, LPFC_MBOXQ_t *);
25void lpfc_sli_read_link_ste(struct lpfc_hba *);
26void lpfc_dump_mem(struct lpfc_hba *, LPFC_MBOXQ_t *, uint16_t, uint16_t);
25void lpfc_dump_wakeup_param(struct lpfc_hba *, LPFC_MBOXQ_t *); 27void lpfc_dump_wakeup_param(struct lpfc_hba *, LPFC_MBOXQ_t *);
26void lpfc_dump_static_vport(struct lpfc_hba *, LPFC_MBOXQ_t *, uint16_t); 28void lpfc_dump_static_vport(struct lpfc_hba *, LPFC_MBOXQ_t *, uint16_t);
27int lpfc_dump_fcoe_param(struct lpfc_hba *, struct lpfcMboxq *); 29int 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 *);
234int lpfc_sli_issue_iocb(struct lpfc_hba *, uint32_t, 236int lpfc_sli_issue_iocb(struct lpfc_hba *, uint32_t,
235 struct lpfc_iocbq *, uint32_t); 237 struct lpfc_iocbq *, uint32_t);
236void lpfc_sli_pcimem_bcopy(void *, void *, uint32_t); 238void lpfc_sli_pcimem_bcopy(void *, void *, uint32_t);
239void lpfc_sli_bemem_bcopy(void *, void *, uint32_t);
237void lpfc_sli_abort_iocb_ring(struct lpfc_hba *, struct lpfc_sli_ring *); 240void lpfc_sli_abort_iocb_ring(struct lpfc_hba *, struct lpfc_sli_ring *);
238void lpfc_sli_flush_fcp_rings(struct lpfc_hba *); 241void lpfc_sli_flush_fcp_rings(struct lpfc_hba *);
239int lpfc_sli_ringpostbuf_put(struct lpfc_hba *, struct lpfc_sli_ring *, 242int 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 **/
88void
89lpfc_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 **/
95void 110void
96lpfc_dump_mem(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb, uint16_t offset) 111lpfc_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 **/
6801void
6802lpfc_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 **/
11603void
11604lpfc_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 }
11717out:
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
154struct lpfc_fip_param_hdr { 158struct lpfc_fip_param_hdr {
155 uint8_t type; 159 uint8_t type;
156#define FCOE_PARAM_TYPE 0xA0 160#define FCOE_PARAM_TYPE 0xA0