Skip to content

Commit 72df8a4

Browse files
jsmart-ghmartinkpetersen
authored andcommitted
scsi: lpfc: Add support for cm enablement buffer
As part of the cmf framework, the firmware maintains a table with congestion related state information, specifically whether enabled and if enabled, whether monitoring or actively managing congestion. Add definition of the table and add support to read the table from the adapter and determine if it is enabled. In support of this, the READ_OBJECT mailbox command definition is added to the driver. 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 8c42a65 commit 72df8a4

File tree

6 files changed

+363
-5
lines changed

6 files changed

+363
-5
lines changed

drivers/scsi/lpfc/lpfc.h

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,12 @@ struct lpfc_sli2_slim;
114114
#define LPFC_MBX_NO_WAIT 0
115115
#define LPFC_MBX_WAIT 1
116116

117+
#define LPFC_CFG_PARAM_MAGIC_NUM 0xFEAA0005
118+
#define LPFC_PORT_CFG_NAME "/cfg/port.cfg"
119+
120+
#define lpfc_rangecheck(val, min, max) \
121+
((uint)(val) >= (uint)(min) && (val) <= (max))
122+
117123
enum lpfc_polling_flags {
118124
ENABLE_FCP_RING_POLLING = 0x1,
119125
DISABLE_FCP_RING_INT = 0x2
@@ -403,6 +409,26 @@ struct lpfc_trunk_link {
403409
link3;
404410
};
405411

412+
/* Format of congestion module parameters */
413+
struct lpfc_cgn_param {
414+
uint32_t cgn_param_magic;
415+
uint8_t cgn_param_version; /* version 1 */
416+
uint8_t cgn_param_mode; /* 0=off 1=managed 2=monitor only */
417+
#define LPFC_CFG_OFF 0
418+
#define LPFC_CFG_MANAGED 1
419+
#define LPFC_CFG_MONITOR 2
420+
uint8_t cgn_rsvd1;
421+
uint8_t cgn_rsvd2;
422+
uint8_t cgn_param_level0;
423+
uint8_t cgn_param_level1;
424+
uint8_t cgn_param_level2;
425+
uint8_t byte11;
426+
uint8_t byte12;
427+
uint8_t byte13;
428+
uint8_t byte14;
429+
uint8_t byte15;
430+
};
431+
406432
/* Max number of days of congestion data */
407433
#define LPFC_MAX_CGN_DAYS 10
408434

@@ -1491,6 +1517,9 @@ struct lpfc_hba {
14911517
u32 cgn_sig_freq;
14921518
u32 cgn_acqe_cnt;
14931519

1520+
/* Congestion parameters from flash */
1521+
struct lpfc_cgn_param cgn_p;
1522+
14941523
/* Statistics counter for ACQE cgn alarms and warnings */
14951524
struct lpfc_cgn_acqe_stat cgn_acqe_stat;
14961525

drivers/scsi/lpfc/lpfc_attr.c

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2248,11 +2248,6 @@ lpfc_sriov_hw_max_virtfn_show(struct device *dev,
22482248
return scnprintf(buf, PAGE_SIZE, "%d\n", max_nr_virtfn);
22492249
}
22502250

2251-
static inline bool lpfc_rangecheck(uint val, uint min, uint max)
2252-
{
2253-
return val >= min && val <= max;
2254-
}
2255-
22562251
/**
22572252
* lpfc_enable_bbcr_set: Sets an attribute value.
22582253
* @phba: pointer the the adapter structure.

drivers/scsi/lpfc/lpfc_crtn.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ int lpfc_post_rq_buffer(struct lpfc_hba *phba, struct lpfc_queue *hrq,
7777
struct lpfc_queue *drq, int count, int idx);
7878
void lpfc_init_congestion_stat(struct lpfc_hba *phba);
7979
void lpfc_init_congestion_buf(struct lpfc_hba *phba);
80+
int lpfc_sli4_cgn_params_read(struct lpfc_hba *phba);
8081
int lpfc_config_cgn_signal(struct lpfc_hba *phba);
8182

8283
void lpfc_mbx_cmpl_local_config_link(struct lpfc_hba *, LPFC_MBOXQ_t *);
@@ -220,6 +221,9 @@ irqreturn_t lpfc_sli_fp_intr_handler(int, void *);
220221
irqreturn_t lpfc_sli4_intr_handler(int, void *);
221222
irqreturn_t lpfc_sli4_hba_intr_handler(int, void *);
222223

224+
int lpfc_read_object(struct lpfc_hba *phba, char *s, uint32_t *datap,
225+
uint32_t len);
226+
223227
void lpfc_sli4_cleanup_poll_list(struct lpfc_hba *phba);
224228
int lpfc_sli4_poll_eq(struct lpfc_queue *q, uint8_t path);
225229
void lpfc_sli4_poll_hbtimer(struct timer_list *t);

drivers/scsi/lpfc/lpfc_hw4.h

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1134,6 +1134,12 @@ struct lpfc_mbx_sge {
11341134
uint32_t length;
11351135
};
11361136

1137+
struct lpfc_mbx_host_buf {
1138+
uint32_t length;
1139+
uint32_t pa_lo;
1140+
uint32_t pa_hi;
1141+
};
1142+
11371143
struct lpfc_mbx_nembed_cmd {
11381144
struct lpfc_sli4_cfg_mhdr cfg_mhdr;
11391145
#define LPFC_SLI4_MBX_SGE_MAX_PAGES 19
@@ -1144,6 +1150,30 @@ struct lpfc_mbx_nembed_sge_virt {
11441150
void *addr[LPFC_SLI4_MBX_SGE_MAX_PAGES];
11451151
};
11461152

1153+
struct lpfc_mbx_read_object { /* Version 0 */
1154+
struct mbox_header header;
1155+
union {
1156+
struct {
1157+
uint32_t word0;
1158+
#define lpfc_mbx_rd_object_rlen_SHIFT 0
1159+
#define lpfc_mbx_rd_object_rlen_MASK 0x00FFFFFF
1160+
#define lpfc_mbx_rd_object_rlen_WORD word0
1161+
uint32_t rd_object_offset;
1162+
uint32_t rd_object_name[26];
1163+
#define LPFC_OBJ_NAME_SZ 104 /* 26 x sizeof(uint32_t) is 104. */
1164+
uint32_t rd_object_cnt;
1165+
struct lpfc_mbx_host_buf rd_object_hbuf[4];
1166+
} request;
1167+
struct {
1168+
uint32_t rd_object_actual_rlen;
1169+
uint32_t word1;
1170+
#define lpfc_mbx_rd_object_eof_SHIFT 31
1171+
#define lpfc_mbx_rd_object_eof_MASK 0x1
1172+
#define lpfc_mbx_rd_object_eof_WORD word1
1173+
} response;
1174+
} u;
1175+
};
1176+
11471177
struct lpfc_mbx_eq_create {
11481178
struct mbox_header header;
11491179
union {
@@ -2339,6 +2369,7 @@ struct lpfc_mbx_redisc_fcf_tbl {
23392369
#define ADD_STATUS_OPERATION_ALREADY_ACTIVE 0x67
23402370
#define ADD_STATUS_FW_NOT_SUPPORTED 0xEB
23412371
#define ADD_STATUS_INVALID_REQUEST 0x4B
2372+
#define ADD_STATUS_INVALID_OBJECT_NAME 0xA0
23422373
#define ADD_STATUS_FW_DOWNLOAD_HW_DISABLED 0x58
23432374

23442375
struct lpfc_mbx_sli4_config {
@@ -3893,6 +3924,7 @@ struct lpfc_mqe {
38933924
struct lpfc_mbx_unreg_fcfi unreg_fcfi;
38943925
struct lpfc_mbx_mq_create mq_create;
38953926
struct lpfc_mbx_mq_create_ext mq_create_ext;
3927+
struct lpfc_mbx_read_object read_object;
38963928
struct lpfc_mbx_eq_create eq_create;
38973929
struct lpfc_mbx_modify_eq_delay eq_delay;
38983930
struct lpfc_mbx_cq_create cq_create;

drivers/scsi/lpfc/lpfc_init.c

Lines changed: 188 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6113,6 +6113,194 @@ lpfc_sli4_async_grp5_evt(struct lpfc_hba *phba,
61136113
phba->sli4_hba.link_state.logical_speed);
61146114
}
61156115

6116+
/**
6117+
* lpfc_cgn_params_val - Validate FW congestion parameters.
6118+
* @phba: pointer to lpfc hba data structure.
6119+
* @p_cfg_param: pointer to FW provided congestion parameters.
6120+
*
6121+
* This routine validates the congestion parameters passed
6122+
* by the FW to the driver via an ACQE event.
6123+
**/
6124+
static void
6125+
lpfc_cgn_params_val(struct lpfc_hba *phba, struct lpfc_cgn_param *p_cfg_param)
6126+
{
6127+
spin_lock_irq(&phba->hbalock);
6128+
6129+
if (!lpfc_rangecheck(p_cfg_param->cgn_param_mode, LPFC_CFG_OFF,
6130+
LPFC_CFG_MONITOR)) {
6131+
lpfc_printf_log(phba, KERN_ERR, LOG_CGN_MGMT,
6132+
"6225 CMF mode param out of range: %d\n",
6133+
p_cfg_param->cgn_param_mode);
6134+
p_cfg_param->cgn_param_mode = LPFC_CFG_OFF;
6135+
}
6136+
6137+
spin_unlock_irq(&phba->hbalock);
6138+
}
6139+
6140+
/**
6141+
* lpfc_cgn_params_parse - Process a FW cong parm change event
6142+
* @phba: pointer to lpfc hba data structure.
6143+
* @p_cgn_param: pointer to a data buffer with the FW cong params.
6144+
* @len: the size of pdata in bytes.
6145+
*
6146+
* This routine validates the congestion management buffer signature
6147+
* from the FW, validates the contents and makes corrections for
6148+
* valid, in-range values. If the signature magic is correct and
6149+
* after parameter validation, the contents are copied to the driver's
6150+
* @phba structure. If the magic is incorrect, an error message is
6151+
* logged.
6152+
**/
6153+
static void
6154+
lpfc_cgn_params_parse(struct lpfc_hba *phba,
6155+
struct lpfc_cgn_param *p_cgn_param, uint32_t len)
6156+
{
6157+
uint32_t oldmode;
6158+
6159+
/* Make sure the FW has encoded the correct magic number to
6160+
* validate the congestion parameter in FW memory.
6161+
*/
6162+
if (p_cgn_param->cgn_param_magic == LPFC_CFG_PARAM_MAGIC_NUM) {
6163+
lpfc_printf_log(phba, KERN_INFO, LOG_CGN_MGMT | LOG_INIT,
6164+
"4668 FW cgn parm buffer data: "
6165+
"magic 0x%x version %d mode %d "
6166+
"level0 %d level1 %d "
6167+
"level2 %d byte13 %d "
6168+
"byte14 %d byte15 %d "
6169+
"byte11 %d byte12 %d activeMode %d\n",
6170+
p_cgn_param->cgn_param_magic,
6171+
p_cgn_param->cgn_param_version,
6172+
p_cgn_param->cgn_param_mode,
6173+
p_cgn_param->cgn_param_level0,
6174+
p_cgn_param->cgn_param_level1,
6175+
p_cgn_param->cgn_param_level2,
6176+
p_cgn_param->byte13,
6177+
p_cgn_param->byte14,
6178+
p_cgn_param->byte15,
6179+
p_cgn_param->byte11,
6180+
p_cgn_param->byte12,
6181+
phba->cmf_active_mode);
6182+
6183+
oldmode = phba->cmf_active_mode;
6184+
6185+
/* Any parameters out of range are corrected to defaults
6186+
* by this routine. No need to fail.
6187+
*/
6188+
lpfc_cgn_params_val(phba, p_cgn_param);
6189+
6190+
/* Parameters are verified, move them into driver storage */
6191+
spin_lock_irq(&phba->hbalock);
6192+
memcpy(&phba->cgn_p, p_cgn_param,
6193+
sizeof(struct lpfc_cgn_param));
6194+
6195+
spin_unlock_irq(&phba->hbalock);
6196+
6197+
phba->cmf_active_mode = phba->cgn_p.cgn_param_mode;
6198+
6199+
switch (oldmode) {
6200+
case LPFC_CFG_OFF:
6201+
if (phba->cgn_p.cgn_param_mode != LPFC_CFG_OFF) {
6202+
/* Turning CMF on */
6203+
6204+
if (phba->link_state >= LPFC_LINK_UP) {
6205+
phba->cgn_reg_fpin =
6206+
phba->cgn_init_reg_fpin;
6207+
phba->cgn_reg_signal =
6208+
phba->cgn_init_reg_signal;
6209+
lpfc_issue_els_edc(phba->pport, 0);
6210+
}
6211+
}
6212+
break;
6213+
case LPFC_CFG_MANAGED:
6214+
switch (phba->cgn_p.cgn_param_mode) {
6215+
case LPFC_CFG_OFF:
6216+
/* Turning CMF off */
6217+
if (phba->link_state >= LPFC_LINK_UP)
6218+
lpfc_issue_els_edc(phba->pport, 0);
6219+
break;
6220+
case LPFC_CFG_MONITOR:
6221+
lpfc_printf_log(phba, KERN_INFO, LOG_CGN_MGMT,
6222+
"4661 Switch from MANAGED to "
6223+
"`MONITOR mode\n");
6224+
break;
6225+
}
6226+
break;
6227+
case LPFC_CFG_MONITOR:
6228+
switch (phba->cgn_p.cgn_param_mode) {
6229+
case LPFC_CFG_OFF:
6230+
/* Turning CMF off */
6231+
if (phba->link_state >= LPFC_LINK_UP)
6232+
lpfc_issue_els_edc(phba->pport, 0);
6233+
break;
6234+
case LPFC_CFG_MANAGED:
6235+
lpfc_printf_log(phba, KERN_INFO, LOG_CGN_MGMT,
6236+
"4662 Switch from MONITOR to "
6237+
"MANAGED mode\n");
6238+
break;
6239+
}
6240+
break;
6241+
}
6242+
} else {
6243+
lpfc_printf_log(phba, KERN_ERR, LOG_CGN_MGMT | LOG_INIT,
6244+
"4669 FW cgn parm buf wrong magic 0x%x "
6245+
"version %d\n", p_cgn_param->cgn_param_magic,
6246+
p_cgn_param->cgn_param_version);
6247+
}
6248+
}
6249+
6250+
/**
6251+
* lpfc_sli4_cgn_params_read - Read and Validate FW congestion parameters.
6252+
* @phba: pointer to lpfc hba data structure.
6253+
*
6254+
* This routine issues a read_object mailbox command to
6255+
* get the congestion management parameters from the FW
6256+
* parses it and updates the driver maintained values.
6257+
*
6258+
* Returns
6259+
* 0 if the object was empty
6260+
* -Eval if an error was encountered
6261+
* Count if bytes were read from object
6262+
**/
6263+
int
6264+
lpfc_sli4_cgn_params_read(struct lpfc_hba *phba)
6265+
{
6266+
int ret = 0;
6267+
struct lpfc_cgn_param *p_cgn_param = NULL;
6268+
u32 *pdata = NULL;
6269+
u32 len = 0;
6270+
6271+
/* Find out if the FW has a new set of congestion parameters. */
6272+
len = sizeof(struct lpfc_cgn_param);
6273+
pdata = kzalloc(len, GFP_KERNEL);
6274+
ret = lpfc_read_object(phba, (char *)LPFC_PORT_CFG_NAME,
6275+
pdata, len);
6276+
6277+
/* 0 means no data. A negative means error. A positive means
6278+
* bytes were copied.
6279+
*/
6280+
if (!ret) {
6281+
lpfc_printf_log(phba, KERN_ERR, LOG_CGN_MGMT | LOG_INIT,
6282+
"4670 CGN RD OBJ returns no data\n");
6283+
goto rd_obj_err;
6284+
} else if (ret < 0) {
6285+
/* Some error. Just exit and return it to the caller.*/
6286+
goto rd_obj_err;
6287+
}
6288+
6289+
lpfc_printf_log(phba, KERN_INFO, LOG_CGN_MGMT | LOG_INIT,
6290+
"6234 READ CGN PARAMS Successful %d\n", len);
6291+
6292+
/* Parse data pointer over len and update the phba congestion
6293+
* parameters with values passed back. The receive rate values
6294+
* may have been altered in FW, but take no action here.
6295+
*/
6296+
p_cgn_param = (struct lpfc_cgn_param *)pdata;
6297+
lpfc_cgn_params_parse(phba, p_cgn_param, len);
6298+
6299+
rd_obj_err:
6300+
kfree(pdata);
6301+
return ret;
6302+
}
6303+
61166304
/**
61176305
* lpfc_sli4_async_event_proc - Process all the pending asynchronous event
61186306
* @phba: pointer to lpfc hba data structure.

0 commit comments

Comments
 (0)