scsi: lpfc: Add cmf_info sysfs entry
authorJames Smart <jsmart2021@gmail.com>
Mon, 16 Aug 2021 16:28:58 +0000 (09:28 -0700)
committerMartin K. Petersen <martin.petersen@oracle.com>
Wed, 25 Aug 2021 02:56:34 +0000 (22:56 -0400)
Allow abbreviated cm framework status information to be obtained via sysfs.

Link: https://lore.kernel.org/r/20210816162901.121235-14-jsmart2021@gmail.com
Co-developed-by: Justin Tee <justin.tee@broadcom.com>
Signed-off-by: Justin Tee <justin.tee@broadcom.com>
Signed-off-by: James Smart <jsmart2021@gmail.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
drivers/scsi/lpfc/lpfc.h
drivers/scsi/lpfc/lpfc_attr.c
drivers/scsi/lpfc/lpfc_crtn.h
drivers/scsi/lpfc/lpfc_els.c
drivers/scsi/lpfc/lpfc_hw4.h
drivers/scsi/lpfc/lpfc_init.c
drivers/scsi/lpfc/lpfc_nvme.h

index dd8cb11..befeb7c 100644 (file)
@@ -1600,6 +1600,7 @@ struct lpfc_hba {
 };
 
 #define LPFC_MAX_RXMONITOR_ENTRY       800
+#define LPFC_MAX_RXMONITOR_DUMP                32
 struct rxtable_entry {
        uint64_t total_bytes;   /* Total no of read bytes requested */
        uint64_t rcv_bytes;     /* Total no of read bytes completed */
index b41891a..b35bf70 100644 (file)
@@ -57,6 +57,8 @@
 #define LPFC_MIN_DEVLOSS_TMO   1
 #define LPFC_MAX_DEVLOSS_TMO   255
 
+#define LPFC_MAX_INFO_TMP_LEN  100
+#define LPFC_INFO_MORE_STR     "\nCould be more info...\n"
 /*
  * Write key size should be multiple of 4. If write key is changed
  * make sure that library write key is also changed.
@@ -112,6 +114,186 @@ lpfc_jedec_to_ascii(int incr, char hdw[])
        return;
 }
 
+static ssize_t
+lpfc_cmf_info_show(struct device *dev, struct device_attribute *attr,
+                  char *buf)
+{
+       struct Scsi_Host  *shost = class_to_shost(dev);
+       struct lpfc_vport *vport = (struct lpfc_vport *)shost->hostdata;
+       struct lpfc_hba   *phba = vport->phba;
+       struct lpfc_cgn_info *cp = NULL;
+       struct lpfc_cgn_stat *cgs;
+       int  len = 0;
+       int cpu;
+       u64 rcv, total;
+       char tmp[LPFC_MAX_INFO_TMP_LEN] = {0};
+
+       if (phba->cgn_i)
+               cp = (struct lpfc_cgn_info *)phba->cgn_i->virt;
+
+       scnprintf(tmp, sizeof(tmp),
+                 "Congestion Mgmt Info: E2Eattr %d Ver %d "
+                 "CMF %d cnt %d\n",
+                 phba->sli4_hba.pc_sli4_params.mi_ver,
+                 cp ? cp->cgn_info_version : 0,
+                 phba->sli4_hba.pc_sli4_params.cmf, phba->cmf_timer_cnt);
+
+       if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE)
+               goto buffer_done;
+
+       if (!phba->sli4_hba.pc_sli4_params.cmf)
+               goto buffer_done;
+
+       switch (phba->cgn_init_reg_signal) {
+       case EDC_CG_SIG_WARN_ONLY:
+               scnprintf(tmp, sizeof(tmp),
+                         "Register: Init:  Signal:WARN  ");
+               break;
+       case EDC_CG_SIG_WARN_ALARM:
+               scnprintf(tmp, sizeof(tmp),
+                         "Register: Init:  Signal:WARN|ALARM  ");
+               break;
+       default:
+               scnprintf(tmp, sizeof(tmp),
+                         "Register: Init:  Signal:NONE  ");
+               break;
+       }
+       if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE)
+               goto buffer_done;
+
+       switch (phba->cgn_init_reg_fpin) {
+       case LPFC_CGN_FPIN_WARN:
+               scnprintf(tmp, sizeof(tmp),
+                         "FPIN:WARN\n");
+               break;
+       case LPFC_CGN_FPIN_ALARM:
+               scnprintf(tmp, sizeof(tmp),
+                         "FPIN:ALARM\n");
+               break;
+       case LPFC_CGN_FPIN_BOTH:
+               scnprintf(tmp, sizeof(tmp),
+                         "FPIN:WARN|ALARM\n");
+               break;
+       default:
+               scnprintf(tmp, sizeof(tmp),
+                         "FPIN:NONE\n");
+               break;
+       }
+       if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE)
+               goto buffer_done;
+
+       switch (phba->cgn_reg_signal) {
+       case EDC_CG_SIG_WARN_ONLY:
+               scnprintf(tmp, sizeof(tmp),
+                         "       Current:  Signal:WARN  ");
+               break;
+       case EDC_CG_SIG_WARN_ALARM:
+               scnprintf(tmp, sizeof(tmp),
+                         "       Current:  Signal:WARN|ALARM  ");
+               break;
+       default:
+               scnprintf(tmp, sizeof(tmp),
+                         "       Current:  Signal:NONE  ");
+               break;
+       }
+       if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE)
+               goto buffer_done;
+
+       switch (phba->cgn_reg_fpin) {
+       case LPFC_CGN_FPIN_WARN:
+               scnprintf(tmp, sizeof(tmp),
+                         "FPIN:WARN  ACQEcnt:%d\n", phba->cgn_acqe_cnt);
+               break;
+       case LPFC_CGN_FPIN_ALARM:
+               scnprintf(tmp, sizeof(tmp),
+                         "FPIN:ALARM  ACQEcnt:%d\n", phba->cgn_acqe_cnt);
+               break;
+       case LPFC_CGN_FPIN_BOTH:
+               scnprintf(tmp, sizeof(tmp),
+                         "FPIN:WARN|ALARM  ACQEcnt:%d\n", phba->cgn_acqe_cnt);
+               break;
+       default:
+               scnprintf(tmp, sizeof(tmp),
+                         "FPIN:NONE  ACQEcnt:%d\n", phba->cgn_acqe_cnt);
+               break;
+       }
+       if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE)
+               goto buffer_done;
+
+       if (phba->cmf_active_mode != phba->cgn_p.cgn_param_mode) {
+               switch (phba->cmf_active_mode) {
+               case LPFC_CFG_OFF:
+                       scnprintf(tmp, sizeof(tmp), "Active: Mode:Off\n");
+                       break;
+               case LPFC_CFG_MANAGED:
+                       scnprintf(tmp, sizeof(tmp), "Active: Mode:Managed\n");
+                       break;
+               case LPFC_CFG_MONITOR:
+                       scnprintf(tmp, sizeof(tmp), "Active: Mode:Monitor\n");
+                       break;
+               default:
+                       scnprintf(tmp, sizeof(tmp), "Active: Mode:Unknown\n");
+               }
+               if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE)
+                       goto buffer_done;
+       }
+
+       switch (phba->cgn_p.cgn_param_mode) {
+       case LPFC_CFG_OFF:
+               scnprintf(tmp, sizeof(tmp), "Config: Mode:Off  ");
+               break;
+       case LPFC_CFG_MANAGED:
+               scnprintf(tmp, sizeof(tmp), "Config: Mode:Managed ");
+               break;
+       case LPFC_CFG_MONITOR:
+               scnprintf(tmp, sizeof(tmp), "Config: Mode:Monitor ");
+               break;
+       default:
+               scnprintf(tmp, sizeof(tmp), "Config: Mode:Unknown ");
+       }
+       if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE)
+               goto buffer_done;
+
+       total = 0;
+       rcv = 0;
+       for_each_present_cpu(cpu) {
+               cgs = per_cpu_ptr(phba->cmf_stat, cpu);
+               total += atomic64_read(&cgs->total_bytes);
+               rcv += atomic64_read(&cgs->rcv_bytes);
+       }
+
+       scnprintf(tmp, sizeof(tmp),
+                 "IObusy:%d Info:%d Bytes: Rcv:x%llx Total:x%llx\n",
+                 atomic_read(&phba->cmf_busy),
+                 phba->cmf_active_info, rcv, total);
+       if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE)
+               goto buffer_done;
+
+       scnprintf(tmp, sizeof(tmp),
+                 "Port_speed:%d  Link_byte_cnt:%ld  "
+                 "Max_byte_per_interval:%ld\n",
+                 lpfc_sli_port_speed_get(phba),
+                 (unsigned long)phba->cmf_link_byte_count,
+                 (unsigned long)phba->cmf_max_bytes_per_interval);
+       strlcat(buf, tmp, PAGE_SIZE);
+
+buffer_done:
+       len = strnlen(buf, PAGE_SIZE);
+
+       if (unlikely(len >= (PAGE_SIZE - 1))) {
+               lpfc_printf_log(phba, KERN_INFO, LOG_CGN_MGMT,
+                               "6312 Catching potential buffer "
+                               "overflow > PAGE_SIZE = %lu bytes\n",
+                               PAGE_SIZE);
+               strscpy(buf + PAGE_SIZE - 1 -
+                       strnlen(LPFC_INFO_MORE_STR, PAGE_SIZE - 1),
+                       LPFC_INFO_MORE_STR,
+                       strnlen(LPFC_INFO_MORE_STR, PAGE_SIZE - 1)
+                       + 1);
+       }
+       return len;
+}
+
 /**
  * lpfc_drvr_version_show - Return the Emulex driver string with version number
  * @dev: class unused variable.
@@ -168,7 +350,7 @@ lpfc_nvme_info_show(struct device *dev, struct device_attribute *attr,
        char *statep;
        int i;
        int len = 0;
-       char tmp[LPFC_MAX_NVME_INFO_TMP_LEN] = {0};
+       char tmp[LPFC_MAX_INFO_TMP_LEN] = {0};
 
        if (!(vport->cfg_enable_fc4_type & LPFC_ENABLE_NVME)) {
                len = scnprintf(buf, PAGE_SIZE, "NVME Disabled\n");
@@ -512,9 +694,9 @@ lpfc_nvme_info_show(struct device *dev, struct device_attribute *attr,
                                "6314 Catching potential buffer "
                                "overflow > PAGE_SIZE = %lu bytes\n",
                                PAGE_SIZE);
-               strlcpy(buf + PAGE_SIZE - 1 - sizeof(LPFC_NVME_INFO_MORE_STR),
-                       LPFC_NVME_INFO_MORE_STR,
-                       sizeof(LPFC_NVME_INFO_MORE_STR) + 1);
+               strscpy(buf + PAGE_SIZE - 1 - sizeof(LPFC_INFO_MORE_STR),
+                       LPFC_INFO_MORE_STR,
+                       sizeof(LPFC_INFO_MORE_STR) + 1);
        }
 
        return len;
@@ -2636,6 +2818,7 @@ static DEVICE_ATTR_RO(lpfc_sriov_hw_max_virtfn);
 static DEVICE_ATTR(protocol, S_IRUGO, lpfc_sli4_protocol_show, NULL);
 static DEVICE_ATTR(lpfc_xlane_supported, S_IRUGO, lpfc_oas_supported_show,
                   NULL);
+static DEVICE_ATTR(cmf_info, 0444, lpfc_cmf_info_show, NULL);
 
 static char *lpfc_soft_wwn_key = "C99G71SL8032A";
 #define WWN_SZ 8
@@ -6332,6 +6515,7 @@ struct device_attribute *lpfc_hba_attrs[] = {
        &dev_attr_lpfc_enable_bbcr,
        &dev_attr_lpfc_enable_dpp,
        &dev_attr_lpfc_enable_mi,
+       &dev_attr_cmf_info,
        &dev_attr_lpfc_max_vmid,
        &dev_attr_lpfc_vmid_inactivity_timeout,
        &dev_attr_lpfc_vmid_app_header,
@@ -6362,6 +6546,7 @@ struct device_attribute *lpfc_vport_attrs[] = {
        &dev_attr_lpfc_max_scsicmpl_time,
        &dev_attr_lpfc_stat_data_ctrl,
        &dev_attr_lpfc_static_vport,
+       &dev_attr_cmf_info,
        NULL,
 };
 
index 252670a..c512f41 100644 (file)
@@ -86,6 +86,7 @@ int lpfc_sli4_cgn_params_read(struct lpfc_hba *phba);
 uint32_t lpfc_cgn_calc_crc32(void *bufp, uint32_t sz, uint32_t seed);
 int lpfc_config_cgn_signal(struct lpfc_hba *phba);
 int lpfc_issue_cmf_sync_wqe(struct lpfc_hba *phba, u32 ms, u64 total);
+void lpfc_cgn_dump_rxmonitor(struct lpfc_hba *phba);
 void lpfc_cgn_update_stat(struct lpfc_hba *phba, uint32_t dtag);
 void lpfc_unblock_requests(struct lpfc_hba *phba);
 void lpfc_block_requests(struct lpfc_hba *phba);
@@ -159,6 +160,7 @@ int lpfc_issue_els_rscn(struct lpfc_vport *vport, uint8_t retry);
 int lpfc_issue_fabric_reglogin(struct lpfc_vport *);
 int lpfc_issue_els_rdf(struct lpfc_vport *vport, uint8_t retry);
 int lpfc_issue_els_edc(struct lpfc_vport *vport, uint8_t retry);
+void lpfc_els_rcv_fpin(struct lpfc_vport *vport, void *p, u32 fpin_length);
 int lpfc_els_free_iocb(struct lpfc_hba *, struct lpfc_iocbq *);
 int lpfc_ct_free_iocb(struct lpfc_hba *, struct lpfc_iocbq *);
 int lpfc_els_rsp_acc(struct lpfc_vport *, uint32_t, struct lpfc_iocbq *,
index 0ebe5d7..1254a57 100644 (file)
@@ -9632,7 +9632,7 @@ cleanup:
        return rc;
 }
 
-static void
+void
 lpfc_els_rcv_fpin(struct lpfc_vport *vport, void *p, u32 fpin_length)
 {
        struct lpfc_hba *phba = vport->phba;
index 73b249d..79a4872 100644 (file)
@@ -1157,6 +1157,7 @@ struct lpfc_mbx_nembed_sge_virt {
        void *addr[LPFC_SLI4_MBX_SGE_MAX_PAGES];
 };
 
+#define LPFC_MBX_OBJECT_NAME_LEN_DW    26
 struct lpfc_mbx_read_object {  /* Version 0 */
        struct mbox_header header;
        union {
@@ -1166,7 +1167,7 @@ struct lpfc_mbx_read_object {  /* Version 0 */
 #define lpfc_mbx_rd_object_rlen_MASK   0x00FFFFFF
 #define lpfc_mbx_rd_object_rlen_WORD   word0
                        uint32_t rd_object_offset;
-                       uint32_t rd_object_name[26];
+                       uint32_t rd_object_name[LPFC_MBX_OBJECT_NAME_LEN_DW];
 #define LPFC_OBJ_NAME_SZ 104   /* 26 x sizeof(uint32_t) is 104. */
                        uint32_t rd_object_cnt;
                        struct lpfc_mbx_host_buf rd_object_hbuf[4];
@@ -3871,6 +3872,7 @@ struct lpfc_mbx_get_port_name {
 #define MB_CEQ_STATUS_QUEUE_FLUSHING           0x4
 #define MB_CQE_STATUS_DMA_FAILED               0x5
 
+
 #define LPFC_MBX_WR_CONFIG_MAX_BDE             1
 struct lpfc_mbx_wr_object {
        struct mbox_header header;
@@ -3887,7 +3889,7 @@ struct lpfc_mbx_wr_object {
 #define lpfc_wr_object_write_length_MASK       0x00FFFFFF
 #define lpfc_wr_object_write_length_WORD       word4
                        uint32_t write_offset;
-                       uint32_t object_name[26];
+                       uint32_t object_name[LPFC_MBX_OBJECT_NAME_LEN_DW];
                        uint32_t bde_count;
                        struct ulp_bde64 bde[LPFC_MBX_WR_CONFIG_MAX_BDE];
                } request;
index 3711707..6e742d3 100644 (file)
@@ -5404,6 +5404,44 @@ lpfc_async_link_speed_to_read_top(struct lpfc_hba *phba, uint8_t speed_code)
        return port_speed;
 }
 
+void
+lpfc_cgn_dump_rxmonitor(struct lpfc_hba *phba)
+{
+       struct rxtable_entry *entry;
+       int cnt = 0, head, tail, last, start;
+
+       head = atomic_read(&phba->rxtable_idx_head);
+       tail = atomic_read(&phba->rxtable_idx_tail);
+       if (!phba->rxtable || head == tail) {
+               lpfc_printf_log(phba, KERN_ERR, LOG_CGN_MGMT,
+                               "4411 Rxtable is empty\n");
+               return;
+       }
+       last = tail;
+       start = head;
+
+       /* Display the last LPFC_MAX_RXMONITOR_DUMP entries from the rxtable */
+       while (start != last) {
+               if (start)
+                       start--;
+               else
+                       start = LPFC_MAX_RXMONITOR_ENTRY - 1;
+               entry = &phba->rxtable[start];
+               lpfc_printf_log(phba, KERN_INFO, LOG_CGN_MGMT,
+                               "4410 %02d: MBPI %lld Xmit %lld Cmpl %lld "
+                               "Lat %lld ASz %lld Info %02d BWUtil %d "
+                               "Int %d slot %d\n",
+                               cnt, entry->max_bytes_per_interval,
+                               entry->total_bytes, entry->rcv_bytes,
+                               entry->avg_io_latency, entry->avg_io_size,
+                               entry->cmf_info, entry->timer_utilization,
+                               entry->timer_interval, start);
+               cnt++;
+               if (cnt >= LPFC_MAX_RXMONITOR_DUMP)
+                       return;
+       }
+}
+
 /**
  * lpfc_cgn_update_stat - Save data into congestion stats buffer
  * @phba: pointer to lpfc hba data structure.
index f61223f..cc54ffb 100644 (file)
@@ -34,9 +34,6 @@
 #define LPFC_NVME_FB_SHIFT             9
 #define LPFC_NVME_MAX_FB               (1 << 20)       /* 1M */
 
-#define LPFC_MAX_NVME_INFO_TMP_LEN     100
-#define LPFC_NVME_INFO_MORE_STR                "\nCould be more info...\n"
-
 #define lpfc_ndlp_get_nrport(ndlp)                             \
        ((!ndlp->nrport || (ndlp->fc4_xpt_flags & NVME_XPT_UNREG_WAIT))\
        ? NULL : ndlp->nrport)