Skip to content

Commit daebf93

Browse files
jsmart-ghmartinkpetersen
authored andcommitted
scsi: lpfc: Add cmfsync WQE support
When congestion mgmt is enabled, cmf has the driver regularly issue a command to synchronize reporting of congestion mgmt events such as fpin and signal delivery. This patch adds the definition of the CMF_SYNC WQE and its CQE fields as well as support for issuing the command. The patch also adds the few remaining cmf-related SLI additions, such as feature definition for enablement of CMF and notifications to the driver if the cm enablement mode changes. Link: https://lore.kernel.org/r/[email protected] Co-developed-by: Justin Tee <[email protected]> Signed-off-by: Justin Tee <[email protected]> Signed-off-by: James Smart <[email protected]> Signed-off-by: Martin K. Petersen <[email protected]>
1 parent 72df8a4 commit daebf93

File tree

5 files changed

+268
-3
lines changed

5 files changed

+268
-3
lines changed

drivers/scsi/lpfc/lpfc.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1499,6 +1499,10 @@ struct lpfc_hba {
14991499
u32 cmf_active_mode;
15001500
#define LPFC_CFG_OFF 0
15011501

1502+
#define LPFC_CMF_INTERVAL 90
1503+
#define LPFC_CMF_BLK_SIZE 512
1504+
#define LPFC_MAX_CMF_INFO 32
1505+
15021506
/* Signal / FPIN handling for Congestion Mgmt */
15031507
u8 cgn_reg_fpin; /* Negotiated value from RDF */
15041508
u8 cgn_init_reg_fpin; /* Initial value from READ_CONFIG */

drivers/scsi/lpfc/lpfc_crtn.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ void lpfc_init_congestion_stat(struct lpfc_hba *phba);
7979
void lpfc_init_congestion_buf(struct lpfc_hba *phba);
8080
int lpfc_sli4_cgn_params_read(struct lpfc_hba *phba);
8181
int lpfc_config_cgn_signal(struct lpfc_hba *phba);
82+
int lpfc_issue_cmf_sync_wqe(struct lpfc_hba *phba, u32 ms, u64 total);
8283

8384
void lpfc_mbx_cmpl_local_config_link(struct lpfc_hba *, LPFC_MBOXQ_t *);
8485
void lpfc_mbx_cmpl_reg_login(struct lpfc_hba *, LPFC_MBOXQ_t *);

drivers/scsi/lpfc/lpfc_hw4.h

Lines changed: 84 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -397,6 +397,12 @@ struct lpfc_wcqe_complete {
397397
#define lpfc_wcqe_c_ersp0_MASK 0x0000FFFF
398398
#define lpfc_wcqe_c_ersp0_WORD word0
399399
uint32_t total_data_placed;
400+
#define lpfc_wcqe_c_cmf_cg_SHIFT 31
401+
#define lpfc_wcqe_c_cmf_cg_MASK 0x00000001
402+
#define lpfc_wcqe_c_cmf_cg_WORD total_data_placed
403+
#define lpfc_wcqe_c_cmf_bw_SHIFT 0
404+
#define lpfc_wcqe_c_cmf_bw_MASK 0x0FFFFFFF
405+
#define lpfc_wcqe_c_cmf_bw_WORD total_data_placed
400406
uint32_t parameter;
401407
#define lpfc_wcqe_c_bg_edir_SHIFT 5
402408
#define lpfc_wcqe_c_bg_edir_MASK 0x00000001
@@ -691,6 +697,7 @@ struct lpfc_register {
691697
#define lpfc_sliport_eqdelay_id_MASK 0xfff
692698
#define lpfc_sliport_eqdelay_id_WORD word0
693699
#define LPFC_SEC_TO_USEC 1000000
700+
#define LPFC_SEC_TO_MSEC 1000
694701

695702
/* The following Registers apply to SLI4 if_type 0 UCNAs. They typically
696703
* reside in BAR 2.
@@ -3397,12 +3404,13 @@ struct lpfc_sli4_parameters {
33973404
#define cfg_max_tow_xri_WORD word20
33983405

33993406
uint32_t word21;
3400-
#define cfg_mib_bde_cnt_SHIFT 16
3401-
#define cfg_mib_bde_cnt_MASK 0x000000ff
3402-
#define cfg_mib_bde_cnt_WORD word21
34033407
#define cfg_mi_ver_SHIFT 0
34043408
#define cfg_mi_ver_MASK 0x0000ffff
34053409
#define cfg_mi_ver_WORD word21
3410+
#define cfg_cmf_SHIFT 24
3411+
#define cfg_cmf_MASK 0x000000ff
3412+
#define cfg_cmf_WORD word21
3413+
34063414
uint32_t mib_size;
34073415
uint32_t word23; /* RESERVED */
34083416

@@ -3434,6 +3442,7 @@ struct lpfc_sli4_parameters {
34343442
#define LPFC_SET_CGN_SIGNAL 0x1f
34353443
#define LPFC_SET_DUAL_DUMP 0x1e
34363444
#define LPFC_SET_ENABLE_MI 0x21
3445+
#define LPFC_SET_ENABLE_CMF 0x24
34373446
struct lpfc_mbx_set_feature {
34383447
struct mbox_header header;
34393448
uint32_t feature;
@@ -3460,6 +3469,9 @@ struct lpfc_mbx_set_feature {
34603469
#define LPFC_DISABLE_DUAL_DUMP 0
34613470
#define LPFC_ENABLE_DUAL_DUMP 1
34623471
#define LPFC_QUERY_OP_DUAL_DUMP 2
3472+
#define lpfc_mbx_set_feature_cmf_SHIFT 0
3473+
#define lpfc_mbx_set_feature_cmf_MASK 0x00000001
3474+
#define lpfc_mbx_set_feature_cmf_WORD word6
34633475
#define lpfc_mbx_set_feature_mi_SHIFT 0
34643476
#define lpfc_mbx_set_feature_mi_MASK 0x0000ffff
34653477
#define lpfc_mbx_set_feature_mi_WORD word6
@@ -4005,6 +4017,7 @@ struct lpfc_mcqe {
40054017
#define LPFC_TRAILER_CODE_GRP5 0x5
40064018
#define LPFC_TRAILER_CODE_FC 0x10
40074019
#define LPFC_TRAILER_CODE_SLI 0x11
4020+
#define LPFC_TRAILER_CODE_CMSTAT 0x13
40084021
};
40094022

40104023
struct lpfc_acqe_link {
@@ -4264,6 +4277,7 @@ struct lpfc_acqe_sli {
42644277
#define LPFC_SLI_EVENT_TYPE_DIAG_DUMP 0x5
42654278
#define LPFC_SLI_EVENT_TYPE_MISCONFIGURED 0x9
42664279
#define LPFC_SLI_EVENT_TYPE_REMOTE_DPORT 0xA
4280+
#define LPFC_SLI_EVENT_TYPE_PORT_PARAMS_CHG 0xE
42674281
#define LPFC_SLI_EVENT_TYPE_MISCONF_FAWWN 0xF
42684282
#define LPFC_SLI_EVENT_TYPE_EEPROM_FAILURE 0x10
42694283
#define LPFC_SLI_EVENT_TYPE_CGN_SIGNAL 0x11
@@ -4674,6 +4688,69 @@ struct create_xri_wqe {
46744688
#define T_REQUEST_TAG 3
46754689
#define T_XRI_TAG 1
46764690

4691+
struct cmf_sync_wqe {
4692+
uint32_t rsrvd[3];
4693+
uint32_t word3;
4694+
#define cmf_sync_interval_SHIFT 0
4695+
#define cmf_sync_interval_MASK 0x00000ffff
4696+
#define cmf_sync_interval_WORD word3
4697+
#define cmf_sync_afpin_SHIFT 16
4698+
#define cmf_sync_afpin_MASK 0x000000001
4699+
#define cmf_sync_afpin_WORD word3
4700+
#define cmf_sync_asig_SHIFT 17
4701+
#define cmf_sync_asig_MASK 0x000000001
4702+
#define cmf_sync_asig_WORD word3
4703+
#define cmf_sync_op_SHIFT 20
4704+
#define cmf_sync_op_MASK 0x00000000f
4705+
#define cmf_sync_op_WORD word3
4706+
#define cmf_sync_ver_SHIFT 24
4707+
#define cmf_sync_ver_MASK 0x0000000ff
4708+
#define cmf_sync_ver_WORD word3
4709+
#define LPFC_CMF_SYNC_VER 1
4710+
uint32_t event_tag;
4711+
uint32_t word5;
4712+
#define cmf_sync_wsigmax_SHIFT 0
4713+
#define cmf_sync_wsigmax_MASK 0x00000ffff
4714+
#define cmf_sync_wsigmax_WORD word5
4715+
#define cmf_sync_wsigcnt_SHIFT 16
4716+
#define cmf_sync_wsigcnt_MASK 0x00000ffff
4717+
#define cmf_sync_wsigcnt_WORD word5
4718+
uint32_t word6;
4719+
uint32_t word7;
4720+
#define cmf_sync_cmnd_SHIFT 8
4721+
#define cmf_sync_cmnd_MASK 0x0000000ff
4722+
#define cmf_sync_cmnd_WORD word7
4723+
uint32_t word8;
4724+
uint32_t word9;
4725+
#define cmf_sync_reqtag_SHIFT 0
4726+
#define cmf_sync_reqtag_MASK 0x00000ffff
4727+
#define cmf_sync_reqtag_WORD word9
4728+
#define cmf_sync_wfpinmax_SHIFT 16
4729+
#define cmf_sync_wfpinmax_MASK 0x0000000ff
4730+
#define cmf_sync_wfpinmax_WORD word9
4731+
#define cmf_sync_wfpincnt_SHIFT 24
4732+
#define cmf_sync_wfpincnt_MASK 0x0000000ff
4733+
#define cmf_sync_wfpincnt_WORD word9
4734+
uint32_t word10;
4735+
#define cmf_sync_qosd_SHIFT 9
4736+
#define cmf_sync_qosd_MASK 0x00000001
4737+
#define cmf_sync_qosd_WORD word10
4738+
uint32_t word11;
4739+
#define cmf_sync_cmd_type_SHIFT 0
4740+
#define cmf_sync_cmd_type_MASK 0x0000000f
4741+
#define cmf_sync_cmd_type_WORD word11
4742+
#define cmf_sync_wqec_SHIFT 7
4743+
#define cmf_sync_wqec_MASK 0x00000001
4744+
#define cmf_sync_wqec_WORD word11
4745+
#define cmf_sync_cqid_SHIFT 16
4746+
#define cmf_sync_cqid_MASK 0x0000ffff
4747+
#define cmf_sync_cqid_WORD word11
4748+
uint32_t read_bytes;
4749+
uint32_t word13;
4750+
uint32_t word14;
4751+
uint32_t word15;
4752+
};
4753+
46774754
struct abort_cmd_wqe {
46784755
uint32_t rsrvd[3];
46794756
uint32_t word3;
@@ -4803,6 +4880,7 @@ union lpfc_wqe {
48034880
struct fcp_iread64_wqe fcp_iread;
48044881
struct fcp_iwrite64_wqe fcp_iwrite;
48054882
struct abort_cmd_wqe abort_cmd;
4883+
struct cmf_sync_wqe cmf_sync;
48064884
struct create_xri_wqe create_xri;
48074885
struct xmit_bcast64_wqe xmit_bcast64;
48084886
struct xmit_seq64_wqe xmit_sequence;
@@ -4823,6 +4901,7 @@ union lpfc_wqe128 {
48234901
struct fcp_iread64_wqe fcp_iread;
48244902
struct fcp_iwrite64_wqe fcp_iwrite;
48254903
struct abort_cmd_wqe abort_cmd;
4904+
struct cmf_sync_wqe cmf_sync;
48264905
struct create_xri_wqe create_xri;
48274906
struct xmit_bcast64_wqe xmit_bcast64;
48284907
struct xmit_seq64_wqe xmit_sequence;
@@ -4866,6 +4945,7 @@ struct lpfc_grp_hdr {
48664945
#define FCP_COMMAND_TRSP 0x3
48674946
#define FCP_COMMAND_TSEND 0x7
48684947
#define OTHER_COMMAND 0x8
4948+
#define CMF_SYNC_COMMAND 0xA
48694949
#define ELS_COMMAND_NON_FIP 0xC
48704950
#define ELS_COMMAND_FIP 0xD
48714951

@@ -4887,6 +4967,7 @@ struct lpfc_grp_hdr {
48874967
#define CMD_FCP_TRECEIVE64_WQE 0xA1
48884968
#define CMD_FCP_TRSP64_WQE 0xA3
48894969
#define CMD_GEN_REQUEST64_WQE 0xC2
4970+
#define CMD_CMF_SYNC_WQE 0xE8
48904971

48914972
#define CMD_WQE_MASK 0xff
48924973

drivers/scsi/lpfc/lpfc_sli.c

Lines changed: 178 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1768,6 +1768,184 @@ lpfc_sli_ringtx_get(struct lpfc_hba *phba, struct lpfc_sli_ring *pring)
17681768
return cmd_iocb;
17691769
}
17701770

1771+
/**
1772+
* lpfc_cmf_sync_cmpl - Process a CMF_SYNC_WQE cmpl
1773+
* @phba: Pointer to HBA context object.
1774+
* @cmdiocb: Pointer to driver command iocb object.
1775+
* @cmf_cmpl: Pointer to completed WCQE.
1776+
*
1777+
* This routine will inform the driver of any BW adjustments we need
1778+
* to make. These changes will be picked up during the next CMF
1779+
* timer interrupt. In addition, any BW changes will be logged
1780+
* with LOG_CGN_MGMT.
1781+
**/
1782+
static void
1783+
lpfc_cmf_sync_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
1784+
struct lpfc_wcqe_complete *cmf_cmpl)
1785+
{
1786+
union lpfc_wqe128 *wqe;
1787+
uint32_t status, info;
1788+
uint64_t bw;
1789+
int asig, afpin, sigcnt, fpincnt;
1790+
int cg, tdp;
1791+
1792+
/* First check for error */
1793+
status = bf_get(lpfc_wcqe_c_status, cmf_cmpl);
1794+
if (status) {
1795+
lpfc_printf_log(phba, KERN_INFO, LOG_CGN_MGMT,
1796+
"6211 CMF_SYNC_WQE Error "
1797+
"req_tag x%x status x%x hwstatus x%x "
1798+
"tdatap x%x parm x%x\n",
1799+
bf_get(lpfc_wcqe_c_request_tag, cmf_cmpl),
1800+
bf_get(lpfc_wcqe_c_status, cmf_cmpl),
1801+
bf_get(lpfc_wcqe_c_hw_status, cmf_cmpl),
1802+
cmf_cmpl->total_data_placed,
1803+
cmf_cmpl->parameter);
1804+
goto out;
1805+
}
1806+
1807+
/* Gather congestion information on a successful cmpl */
1808+
info = cmf_cmpl->parameter;
1809+
tdp = bf_get(lpfc_wcqe_c_cmf_bw, cmf_cmpl);
1810+
cg = bf_get(lpfc_wcqe_c_cmf_cg, cmf_cmpl);
1811+
1812+
/* Get BW requirement from firmware */
1813+
bw = (uint64_t)tdp * LPFC_CMF_BLK_SIZE;
1814+
if (!bw) {
1815+
lpfc_printf_log(phba, KERN_INFO, LOG_CGN_MGMT,
1816+
"6212 CMF_SYNC_WQE x%x: NULL bw\n",
1817+
bf_get(lpfc_wcqe_c_request_tag, cmf_cmpl));
1818+
goto out;
1819+
}
1820+
1821+
/* Gather information needed for logging if a BW change is required */
1822+
wqe = &cmdiocb->wqe;
1823+
asig = bf_get(cmf_sync_asig, &wqe->cmf_sync);
1824+
afpin = bf_get(cmf_sync_afpin, &wqe->cmf_sync);
1825+
fpincnt = bf_get(cmf_sync_wfpincnt, &wqe->cmf_sync);
1826+
sigcnt = bf_get(cmf_sync_wsigcnt, &wqe->cmf_sync);
1827+
1828+
out:
1829+
lpfc_sli_release_iocbq(phba, cmdiocb);
1830+
}
1831+
1832+
/**
1833+
* lpfc_issue_cmf_sync_wqe - Issue a CMF_SYNC_WQE
1834+
* @phba: Pointer to HBA context object.
1835+
* @ms: ms to set in WQE interval, 0 means use init op
1836+
* @total: Total rcv bytes for this interval
1837+
*
1838+
* This routine is called every CMF timer interrupt. Its purpose is
1839+
* to issue a CMF_SYNC_WQE to the firmware to inform it of any events
1840+
* that may indicate we have congestion (FPINs or Signals). Upon
1841+
* completion, the firmware will indicate any BW restrictions the
1842+
* driver may need to take.
1843+
**/
1844+
int
1845+
lpfc_issue_cmf_sync_wqe(struct lpfc_hba *phba, u32 ms, u64 total)
1846+
{
1847+
union lpfc_wqe128 *wqe;
1848+
struct lpfc_iocbq *sync_buf;
1849+
unsigned long iflags;
1850+
u32 ret_val;
1851+
u32 atot, wtot, max;
1852+
1853+
/* First address any alarm / warning activity */
1854+
atot = atomic_xchg(&phba->cgn_sync_alarm_cnt, 0);
1855+
wtot = atomic_xchg(&phba->cgn_sync_warn_cnt, 0);
1856+
1857+
/* ONLY Managed mode will send the CMF_SYNC_WQE to the HBA */
1858+
if (phba->cmf_active_mode != LPFC_CFG_MANAGED ||
1859+
phba->link_state == LPFC_LINK_DOWN)
1860+
return 0;
1861+
1862+
spin_lock_irqsave(&phba->hbalock, iflags);
1863+
sync_buf = __lpfc_sli_get_iocbq(phba);
1864+
if (!sync_buf) {
1865+
lpfc_printf_log(phba, KERN_ERR, LOG_CGN_MGMT,
1866+
"6213 No available WQEs for CMF_SYNC_WQE\n");
1867+
ret_val = ENOMEM;
1868+
goto out_unlock;
1869+
}
1870+
1871+
wqe = &sync_buf->wqe;
1872+
1873+
/* WQEs are reused. Clear stale data and set key fields to zero */
1874+
memset(wqe, 0, sizeof(*wqe));
1875+
1876+
/* If this is the very first CMF_SYNC_WQE, issue an init operation */
1877+
if (!ms) {
1878+
lpfc_printf_log(phba, KERN_INFO, LOG_CGN_MGMT,
1879+
"6441 CMF Init %d - CMF_SYNC_WQE\n",
1880+
phba->fc_eventTag);
1881+
bf_set(cmf_sync_op, &wqe->cmf_sync, 1); /* 1=init */
1882+
bf_set(cmf_sync_interval, &wqe->cmf_sync, LPFC_CMF_INTERVAL);
1883+
goto initpath;
1884+
}
1885+
1886+
bf_set(cmf_sync_op, &wqe->cmf_sync, 0); /* 0=recalc */
1887+
bf_set(cmf_sync_interval, &wqe->cmf_sync, ms);
1888+
1889+
/* Check for alarms / warnings */
1890+
if (atot) {
1891+
if (phba->cgn_reg_signal == EDC_CG_SIG_WARN_ALARM) {
1892+
/* We hit an Signal alarm condition */
1893+
bf_set(cmf_sync_asig, &wqe->cmf_sync, 1);
1894+
} else {
1895+
/* We hit a FPIN alarm condition */
1896+
bf_set(cmf_sync_afpin, &wqe->cmf_sync, 1);
1897+
}
1898+
} else if (wtot) {
1899+
if (phba->cgn_reg_signal == EDC_CG_SIG_WARN_ONLY ||
1900+
phba->cgn_reg_signal == EDC_CG_SIG_WARN_ALARM) {
1901+
/* We hit an Signal warning condition */
1902+
max = LPFC_SEC_TO_MSEC / lpfc_fabric_cgn_frequency *
1903+
lpfc_acqe_cgn_frequency;
1904+
bf_set(cmf_sync_wsigmax, &wqe->cmf_sync, max);
1905+
bf_set(cmf_sync_wsigcnt, &wqe->cmf_sync, wtot);
1906+
} else {
1907+
/* We hit a FPIN warning condition */
1908+
bf_set(cmf_sync_wfpinmax, &wqe->cmf_sync, 1);
1909+
bf_set(cmf_sync_wfpincnt, &wqe->cmf_sync, 1);
1910+
}
1911+
}
1912+
1913+
/* Update total read blocks during previous timer interval */
1914+
wqe->cmf_sync.read_bytes = (u32)(total / LPFC_CMF_BLK_SIZE);
1915+
1916+
initpath:
1917+
bf_set(cmf_sync_ver, &wqe->cmf_sync, LPFC_CMF_SYNC_VER);
1918+
wqe->cmf_sync.event_tag = phba->fc_eventTag;
1919+
bf_set(cmf_sync_cmnd, &wqe->cmf_sync, CMD_CMF_SYNC_WQE);
1920+
1921+
/* Setup reqtag to match the wqe completion. */
1922+
bf_set(cmf_sync_reqtag, &wqe->cmf_sync, sync_buf->iotag);
1923+
1924+
bf_set(cmf_sync_qosd, &wqe->cmf_sync, 1);
1925+
1926+
bf_set(cmf_sync_cmd_type, &wqe->cmf_sync, CMF_SYNC_COMMAND);
1927+
bf_set(cmf_sync_wqec, &wqe->cmf_sync, 1);
1928+
bf_set(cmf_sync_cqid, &wqe->cmf_sync, LPFC_WQE_CQ_ID_DEFAULT);
1929+
1930+
sync_buf->vport = phba->pport;
1931+
sync_buf->wqe_cmpl = lpfc_cmf_sync_cmpl;
1932+
sync_buf->iocb_cmpl = NULL;
1933+
sync_buf->context1 = NULL;
1934+
sync_buf->context2 = NULL;
1935+
sync_buf->context3 = NULL;
1936+
sync_buf->sli4_xritag = NO_XRI;
1937+
1938+
sync_buf->iocb_flag |= LPFC_IO_CMF;
1939+
ret_val = lpfc_sli4_issue_wqe(phba, &phba->sli4_hba.hdwq[0], sync_buf);
1940+
if (ret_val)
1941+
lpfc_printf_log(phba, KERN_INFO, LOG_CGN_MGMT,
1942+
"6214 Cannot issue CMF_SYNC_WQE: x%x\n",
1943+
ret_val);
1944+
out_unlock:
1945+
spin_unlock_irqrestore(&phba->hbalock, iflags);
1946+
return ret_val;
1947+
}
1948+
17711949
/**
17721950
* lpfc_sli_next_iocb_slot - Get next iocb slot in the ring
17731951
* @phba: Pointer to HBA context object.

drivers/scsi/lpfc/lpfc_sli.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@ struct lpfc_iocbq {
107107
#define LPFC_IO_NVME_LS 0x400000 /* NVME LS command */
108108
#define LPFC_IO_NVMET 0x800000 /* NVMET command */
109109
#define LPFC_IO_VMID 0x1000000 /* VMID tagged IO */
110+
#define LPFC_IO_CMF 0x4000000 /* CMF command */
110111

111112
uint32_t drvrTimeout; /* driver timeout in seconds */
112113
struct lpfc_vport *vport;/* virtual port pointer */

0 commit comments

Comments
 (0)