aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/lpfc/lpfc_sli.c
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/lpfc_sli.c
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/lpfc_sli.c')
-rw-r--r--drivers/scsi/lpfc/lpfc_sli.c158
1 files changed, 157 insertions, 1 deletions
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}