@@ -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