@@ -6113,6 +6113,194 @@ lpfc_sli4_async_grp5_evt(struct lpfc_hba *phba,
6113
6113
phba -> sli4_hba .link_state .logical_speed );
6114
6114
}
6115
6115
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
+
6116
6304
/**
6117
6305
* lpfc_sli4_async_event_proc - Process all the pending asynchronous event
6118
6306
* @phba: pointer to lpfc hba data structure.
0 commit comments