aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/lpfc/lpfc_sli.c
diff options
context:
space:
mode:
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}