2014-06-19 21:37:12 -07:00
/*
* Copyright ( C ) 2013 - 2014 Chelsio Communications . All rights reserved .
*
* Written by Anish Bhatt ( anish @ chelsio . com )
* Casey Leedom ( leedom @ chelsio . com )
*
* This program is free software ; you can redistribute it and / or modify it
* under the terms and conditions of the GNU General Public License ,
* version 2 , as published by the Free Software Foundation .
*
* This program is distributed in the hope it will be useful , but WITHOUT
* ANY WARRANTY ; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE . See the GNU General Public License for
* more details .
*
* The full GNU General Public License is included in this distribution in
* the file called " COPYING " .
*
*/
# include "cxgb4.h"
2014-08-07 16:14:03 -07:00
/* DCBx version control
*/
2015-02-05 15:20:09 +00:00
static const char * const dcb_ver_array [ ] = {
2014-08-07 16:14:03 -07:00
" Unknown " ,
" DCBx-CIN " ,
" DCBx-CEE 1.01 " ,
" DCBx-IEEE " ,
" " , " " , " " ,
" Auto Negotiated "
} ;
2015-07-17 13:12:31 -07:00
static inline bool cxgb4_dcb_state_synced ( enum cxgb4_dcb_state state )
{
if ( state = = CXGB4_DCB_STATE_FW_ALLSYNCED | |
state = = CXGB4_DCB_STATE_HOST )
return true ;
else
return false ;
}
2014-06-19 21:37:12 -07:00
/* Initialize a port's Data Center Bridging state. Typically used after a
* Link Down event .
*/
void cxgb4_dcb_state_init ( struct net_device * dev )
{
struct port_info * pi = netdev2pinfo ( dev ) ;
struct port_dcb_info * dcb = & pi - > dcb ;
2014-08-07 16:14:03 -07:00
int version_temp = dcb - > dcb_version ;
2014-06-19 21:37:12 -07:00
memset ( dcb , 0 , sizeof ( struct port_dcb_info ) ) ;
dcb - > state = CXGB4_DCB_STATE_START ;
2014-08-07 16:14:03 -07:00
if ( version_temp )
dcb - > dcb_version = version_temp ;
netdev_dbg ( dev , " %s: Initializing DCB state for port[%d] \n " ,
__func__ , pi - > port_id ) ;
}
void cxgb4_dcb_version_init ( struct net_device * dev )
{
struct port_info * pi = netdev2pinfo ( dev ) ;
struct port_dcb_info * dcb = & pi - > dcb ;
/* Any writes here are only done on kernels that exlicitly need
* a specific version , say < 2.6 .38 which only support CEE
*/
dcb - > dcb_version = FW_PORT_DCB_VER_AUTO ;
2014-06-19 21:37:12 -07:00
}
2014-10-23 14:37:30 -07:00
static void cxgb4_dcb_cleanup_apps ( struct net_device * dev )
{
struct port_info * pi = netdev2pinfo ( dev ) ;
struct adapter * adap = pi - > adapter ;
struct port_dcb_info * dcb = & pi - > dcb ;
struct dcb_app app ;
int i , err ;
/* zero priority implies remove */
app . priority = 0 ;
for ( i = 0 ; i < CXGB4_MAX_DCBX_APP_SUPPORTED ; i + + ) {
/* Check if app list is exhausted */
if ( ! dcb - > app_priority [ i ] . protocolid )
break ;
app . protocol = dcb - > app_priority [ i ] . protocolid ;
if ( dcb - > dcb_version = = FW_PORT_DCB_VER_IEEE ) {
2014-11-07 15:41:21 -08:00
app . priority = dcb - > app_priority [ i ] . user_prio_map ;
2014-10-23 14:37:30 -07:00
app . selector = dcb - > app_priority [ i ] . sel_field + 1 ;
2014-11-07 15:41:21 -08:00
err = dcb_ieee_delapp ( dev , & app ) ;
2014-10-23 14:37:30 -07:00
} else {
app . selector = ! ! ( dcb - > app_priority [ i ] . sel_field ) ;
err = dcb_setapp ( dev , & app ) ;
}
if ( err ) {
dev_err ( adap - > pdev_dev ,
" Failed DCB Clear %s Application Priority: sel=%d, prot=%d, , err=%d \n " ,
dcb_ver_array [ dcb - > dcb_version ] , app . selector ,
app . protocol , - err ) ;
break ;
}
}
}
2014-06-19 21:37:12 -07:00
/* Finite State machine for Data Center Bridging.
*/
void cxgb4_dcb_state_fsm ( struct net_device * dev ,
2014-08-07 16:14:03 -07:00
enum cxgb4_dcb_state_input transition_to )
2014-06-19 21:37:12 -07:00
{
struct port_info * pi = netdev2pinfo ( dev ) ;
struct port_dcb_info * dcb = & pi - > dcb ;
struct adapter * adap = pi - > adapter ;
2014-08-07 16:14:03 -07:00
enum cxgb4_dcb_state current_state = dcb - > state ;
netdev_dbg ( dev , " %s: State change from %d to %d for %s \n " ,
__func__ , dcb - > state , transition_to , dev - > name ) ;
2014-06-19 21:37:12 -07:00
2014-08-07 16:14:03 -07:00
switch ( current_state ) {
case CXGB4_DCB_STATE_START : {
switch ( transition_to ) {
case CXGB4_DCB_INPUT_FW_DISABLED : {
2014-06-19 21:37:12 -07:00
/* we're going to use Host DCB */
dcb - > state = CXGB4_DCB_STATE_HOST ;
dcb - > supported = CXGB4_DCBX_HOST_SUPPORT ;
break ;
}
2014-08-07 16:14:03 -07:00
case CXGB4_DCB_INPUT_FW_ENABLED : {
/* we're going to use Firmware DCB */
dcb - > state = CXGB4_DCB_STATE_FW_INCOMPLETE ;
2014-11-11 23:30:51 -08:00
dcb - > supported = DCB_CAP_DCBX_LLD_MANAGED ;
if ( dcb - > dcb_version = = FW_PORT_DCB_VER_IEEE )
dcb - > supported | = DCB_CAP_DCBX_VER_IEEE ;
else
dcb - > supported | = DCB_CAP_DCBX_VER_CEE ;
2014-08-07 16:14:03 -07:00
break ;
}
case CXGB4_DCB_INPUT_FW_INCOMPLETE : {
/* expected transition */
break ;
}
case CXGB4_DCB_INPUT_FW_ALLSYNCED : {
dcb - > state = CXGB4_DCB_STATE_FW_ALLSYNCED ;
2014-06-19 21:37:12 -07:00
break ;
}
default :
2014-08-07 16:14:03 -07:00
goto bad_state_input ;
2014-06-19 21:37:12 -07:00
}
break ;
}
2014-08-07 16:14:03 -07:00
case CXGB4_DCB_STATE_FW_INCOMPLETE : {
switch ( transition_to ) {
case CXGB4_DCB_INPUT_FW_ENABLED : {
/* we're alreaady in firmware DCB mode */
2014-06-19 21:37:12 -07:00
break ;
}
2014-08-07 16:14:03 -07:00
case CXGB4_DCB_INPUT_FW_INCOMPLETE : {
/* we're already incomplete */
break ;
}
case CXGB4_DCB_INPUT_FW_ALLSYNCED : {
dcb - > state = CXGB4_DCB_STATE_FW_ALLSYNCED ;
dcb - > enabled = 1 ;
linkwatch_fire_event ( dev ) ;
2014-06-19 21:37:12 -07:00
break ;
}
default :
2014-08-07 16:14:03 -07:00
goto bad_state_input ;
2014-06-19 21:37:12 -07:00
}
break ;
}
2014-08-07 16:14:03 -07:00
case CXGB4_DCB_STATE_FW_ALLSYNCED : {
switch ( transition_to ) {
case CXGB4_DCB_INPUT_FW_ENABLED : {
/* we're alreaady in firmware DCB mode */
2014-06-19 21:37:12 -07:00
break ;
}
2014-08-07 16:14:03 -07:00
case CXGB4_DCB_INPUT_FW_INCOMPLETE : {
2014-06-19 21:37:12 -07:00
/* We were successfully running with firmware DCB but
* now it ' s telling us that it ' s in an " incomplete
* state . We need to reset back to a ground state
* of incomplete .
*/
2014-10-23 14:37:30 -07:00
cxgb4_dcb_cleanup_apps ( dev ) ;
2014-06-19 21:37:12 -07:00
cxgb4_dcb_state_init ( dev ) ;
dcb - > state = CXGB4_DCB_STATE_FW_INCOMPLETE ;
dcb - > supported = CXGB4_DCBX_FW_SUPPORT ;
linkwatch_fire_event ( dev ) ;
break ;
}
2014-08-07 16:14:03 -07:00
case CXGB4_DCB_INPUT_FW_ALLSYNCED : {
/* we're already all sync'ed
* this is only applicable for IEEE or
* when another VI already completed negotiaton
*/
2014-06-19 21:37:12 -07:00
dcb - > enabled = 1 ;
linkwatch_fire_event ( dev ) ;
break ;
}
2014-08-07 16:14:03 -07:00
default :
goto bad_state_input ;
}
break ;
}
case CXGB4_DCB_STATE_HOST : {
switch ( transition_to ) {
case CXGB4_DCB_INPUT_FW_DISABLED : {
/* we're alreaady in Host DCB mode */
2014-06-19 21:37:12 -07:00
break ;
}
default :
2014-08-07 16:14:03 -07:00
goto bad_state_input ;
2014-06-19 21:37:12 -07:00
}
break ;
}
default :
2014-08-07 16:14:03 -07:00
goto bad_state_transition ;
2014-06-19 21:37:12 -07:00
}
return ;
bad_state_input :
dev_err ( adap - > pdev_dev , " cxgb4_dcb_state_fsm: illegal input symbol %d \n " ,
2014-08-07 16:14:03 -07:00
transition_to ) ;
2014-06-19 21:37:12 -07:00
return ;
bad_state_transition :
dev_err ( adap - > pdev_dev , " cxgb4_dcb_state_fsm: bad state transition, state = %d, input = %d \n " ,
2014-08-07 16:14:03 -07:00
current_state , transition_to ) ;
2014-06-19 21:37:12 -07:00
}
/* Handle a DCB/DCBX update message from the firmware.
*/
void cxgb4_dcb_handle_fw_update ( struct adapter * adap ,
const struct fw_port_cmd * pcmd )
{
const union fw_port_dcb * fwdcb = & pcmd - > u . dcb ;
2014-11-21 12:52:04 +05:30
int port = FW_PORT_CMD_PORTID_G ( be32_to_cpu ( pcmd - > op_to_portid ) ) ;
2014-06-19 21:37:12 -07:00
struct net_device * dev = adap - > port [ port ] ;
struct port_info * pi = netdev_priv ( dev ) ;
struct port_dcb_info * dcb = & pi - > dcb ;
int dcb_type = pcmd - > u . dcb . pgid . type ;
2014-08-07 16:14:03 -07:00
int dcb_running_version ;
2014-06-19 21:37:12 -07:00
/* Handle Firmware DCB Control messages separately since they drive
* our state machine .
*/
if ( dcb_type = = FW_PORT_DCB_TYPE_CONTROL ) {
enum cxgb4_dcb_state_input input =
( ( pcmd - > u . dcb . control . all_syncd_pkd &
2014-11-21 12:52:04 +05:30
FW_PORT_CMD_ALL_SYNCD_F )
2014-06-19 21:37:12 -07:00
? CXGB4_DCB_STATE_FW_ALLSYNCED
: CXGB4_DCB_STATE_FW_INCOMPLETE ) ;
2014-08-07 16:14:03 -07:00
if ( dcb - > dcb_version ! = FW_PORT_DCB_VER_UNKNOWN ) {
2014-11-21 12:52:04 +05:30
dcb_running_version = FW_PORT_CMD_DCB_VERSION_G (
2014-08-07 16:14:03 -07:00
be16_to_cpu (
pcmd - > u . dcb . control . dcb_version_to_app_state ) ) ;
if ( dcb_running_version = = FW_PORT_DCB_VER_CEE1D01 | |
dcb_running_version = = FW_PORT_DCB_VER_IEEE ) {
dcb - > dcb_version = dcb_running_version ;
dev_warn ( adap - > pdev_dev , " Interface %s is running %s \n " ,
dev - > name ,
dcb_ver_array [ dcb - > dcb_version ] ) ;
} else {
dev_warn ( adap - > pdev_dev ,
" Something screwed up, requested firmware for %s, but firmware returned %s instead \n " ,
dcb_ver_array [ dcb - > dcb_version ] ,
dcb_ver_array [ dcb_running_version ] ) ;
dcb - > dcb_version = FW_PORT_DCB_VER_UNKNOWN ;
}
}
2014-06-19 21:37:12 -07:00
cxgb4_dcb_state_fsm ( dev , input ) ;
return ;
}
/* It's weird, and almost certainly an error, to get Firmware DCB
* messages when we either haven ' t been told whether we ' re going to be
* doing Host or Firmware DCB ; and even worse when we ' ve been told
* that we ' re doing Host DCB !
*/
if ( dcb - > state = = CXGB4_DCB_STATE_START | |
dcb - > state = = CXGB4_DCB_STATE_HOST ) {
dev_err ( adap - > pdev_dev , " Receiving Firmware DCB messages in State %d \n " ,
dcb - > state ) ;
return ;
}
/* Now handle the general Firmware DCB update messages ...
*/
switch ( dcb_type ) {
case FW_PORT_DCB_TYPE_PGID :
dcb - > pgid = be32_to_cpu ( fwdcb - > pgid . pgid ) ;
dcb - > msgs | = CXGB4_DCB_FW_PGID ;
break ;
case FW_PORT_DCB_TYPE_PGRATE :
dcb - > pg_num_tcs_supported = fwdcb - > pgrate . num_tcs_supported ;
memcpy ( dcb - > pgrate , & fwdcb - > pgrate . pgrate ,
sizeof ( dcb - > pgrate ) ) ;
2014-08-07 16:14:03 -07:00
memcpy ( dcb - > tsa , & fwdcb - > pgrate . tsa ,
sizeof ( dcb - > tsa ) ) ;
2014-06-19 21:37:12 -07:00
dcb - > msgs | = CXGB4_DCB_FW_PGRATE ;
2014-08-07 16:14:03 -07:00
if ( dcb - > msgs & CXGB4_DCB_FW_PGID )
IEEE_FAUX_SYNC ( dev , dcb ) ;
2014-06-19 21:37:12 -07:00
break ;
case FW_PORT_DCB_TYPE_PRIORATE :
memcpy ( dcb - > priorate , & fwdcb - > priorate . strict_priorate ,
sizeof ( dcb - > priorate ) ) ;
dcb - > msgs | = CXGB4_DCB_FW_PRIORATE ;
break ;
case FW_PORT_DCB_TYPE_PFC :
dcb - > pfcen = fwdcb - > pfc . pfcen ;
dcb - > pfc_num_tcs_supported = fwdcb - > pfc . max_pfc_tcs ;
dcb - > msgs | = CXGB4_DCB_FW_PFC ;
2014-08-07 16:14:03 -07:00
IEEE_FAUX_SYNC ( dev , dcb ) ;
2014-06-19 21:37:12 -07:00
break ;
case FW_PORT_DCB_TYPE_APP_ID : {
const struct fw_port_app_priority * fwap = & fwdcb - > app_priority ;
int idx = fwap - > idx ;
struct app_priority * ap = & dcb - > app_priority [ idx ] ;
struct dcb_app app = {
. protocol = be16_to_cpu ( fwap - > protocolid ) ,
} ;
int err ;
2014-08-07 16:14:03 -07:00
/* Convert from firmware format to relevant format
* when using app selector
*/
if ( dcb - > dcb_version = = FW_PORT_DCB_VER_IEEE ) {
app . selector = ( fwap - > sel_field + 1 ) ;
app . priority = ffs ( fwap - > user_prio_map ) - 1 ;
err = dcb_ieee_setapp ( dev , & app ) ;
IEEE_FAUX_SYNC ( dev , dcb ) ;
} else {
/* Default is CEE */
app . selector = ! ! ( fwap - > sel_field ) ;
app . priority = fwap - > user_prio_map ;
err = dcb_setapp ( dev , & app ) ;
}
2014-06-19 21:37:12 -07:00
if ( err )
dev_err ( adap - > pdev_dev ,
" Failed DCB Set Application Priority: sel=%d, prot=%d, prio=%d, err=%d \n " ,
app . selector , app . protocol , app . priority , - err ) ;
ap - > user_prio_map = fwap - > user_prio_map ;
ap - > sel_field = fwap - > sel_field ;
ap - > protocolid = be16_to_cpu ( fwap - > protocolid ) ;
dcb - > msgs | = CXGB4_DCB_FW_APP_ID ;
break ;
}
default :
dev_err ( adap - > pdev_dev , " Unknown DCB update type received %x \n " ,
dcb_type ) ;
break ;
}
}
/* Data Center Bridging netlink operations.
*/
/* Get current DCB enabled/disabled state.
*/
static u8 cxgb4_getstate ( struct net_device * dev )
{
struct port_info * pi = netdev2pinfo ( dev ) ;
return pi - > dcb . enabled ;
}
/* Set DCB enabled/disabled.
*/
static u8 cxgb4_setstate ( struct net_device * dev , u8 enabled )
{
struct port_info * pi = netdev2pinfo ( dev ) ;
2014-10-23 14:37:31 -07:00
/* If DCBx is host-managed, dcb is enabled by outside lldp agents */
if ( pi - > dcb . state = = CXGB4_DCB_STATE_HOST ) {
pi - > dcb . enabled = enabled ;
return 0 ;
}
2014-06-19 21:37:12 -07:00
/* Firmware doesn't provide any mechanism to control the DCB state.
*/
if ( enabled ! = ( pi - > dcb . state = = CXGB4_DCB_STATE_FW_ALLSYNCED ) )
return 1 ;
return 0 ;
}
static void cxgb4_getpgtccfg ( struct net_device * dev , int tc ,
u8 * prio_type , u8 * pgid , u8 * bw_per ,
u8 * up_tc_map , int local )
{
struct fw_port_cmd pcmd ;
struct port_info * pi = netdev2pinfo ( dev ) ;
struct adapter * adap = pi - > adapter ;
int err ;
* prio_type = * pgid = * bw_per = * up_tc_map = 0 ;
if ( local )
INIT_PORT_DCB_READ_LOCAL_CMD ( pcmd , pi - > port_id ) ;
else
INIT_PORT_DCB_READ_PEER_CMD ( pcmd , pi - > port_id ) ;
pcmd . u . dcb . pgid . type = FW_PORT_DCB_TYPE_PGID ;
err = t4_wr_mbox ( adap , adap - > mbox , & pcmd , sizeof ( pcmd ) , & pcmd ) ;
if ( err ! = FW_PORT_DCB_CFG_SUCCESS ) {
dev_err ( adap - > pdev_dev , " DCB read PGID failed with %d \n " , - err ) ;
return ;
}
* pgid = ( be32_to_cpu ( pcmd . u . dcb . pgid . pgid ) > > ( tc * 4 ) ) & 0xf ;
2015-01-30 17:20:17 -08:00
if ( local )
INIT_PORT_DCB_READ_LOCAL_CMD ( pcmd , pi - > port_id ) ;
else
INIT_PORT_DCB_READ_PEER_CMD ( pcmd , pi - > port_id ) ;
2014-06-19 21:37:12 -07:00
pcmd . u . dcb . pgrate . type = FW_PORT_DCB_TYPE_PGRATE ;
err = t4_wr_mbox ( adap , adap - > mbox , & pcmd , sizeof ( pcmd ) , & pcmd ) ;
if ( err ! = FW_PORT_DCB_CFG_SUCCESS ) {
dev_err ( adap - > pdev_dev , " DCB read PGRATE failed with %d \n " ,
- err ) ;
return ;
}
* bw_per = pcmd . u . dcb . pgrate . pgrate [ * pgid ] ;
* up_tc_map = ( 1 < < tc ) ;
/* prio_type is link strict */
2014-11-11 23:30:51 -08:00
if ( * pgid ! = 0xF )
* prio_type = 0x2 ;
2014-06-19 21:37:12 -07:00
}
static void cxgb4_getpgtccfg_tx ( struct net_device * dev , int tc ,
u8 * prio_type , u8 * pgid , u8 * bw_per ,
u8 * up_tc_map )
{
2014-11-11 23:30:51 -08:00
/* tc 0 is written at MSB position */
return cxgb4_getpgtccfg ( dev , ( 7 - tc ) , prio_type , pgid , bw_per ,
up_tc_map , 1 ) ;
2014-06-19 21:37:12 -07:00
}
static void cxgb4_getpgtccfg_rx ( struct net_device * dev , int tc ,
u8 * prio_type , u8 * pgid , u8 * bw_per ,
u8 * up_tc_map )
{
2014-11-11 23:30:51 -08:00
/* tc 0 is written at MSB position */
return cxgb4_getpgtccfg ( dev , ( 7 - tc ) , prio_type , pgid , bw_per ,
up_tc_map , 0 ) ;
2014-06-19 21:37:12 -07:00
}
static void cxgb4_setpgtccfg_tx ( struct net_device * dev , int tc ,
u8 prio_type , u8 pgid , u8 bw_per ,
u8 up_tc_map )
{
struct fw_port_cmd pcmd ;
struct port_info * pi = netdev2pinfo ( dev ) ;
struct adapter * adap = pi - > adapter ;
2014-11-11 23:30:51 -08:00
int fw_tc = 7 - tc ;
2014-06-19 21:37:12 -07:00
u32 _pgid ;
int err ;
if ( pgid = = DCB_ATTR_VALUE_UNDEFINED )
return ;
if ( bw_per = = DCB_ATTR_VALUE_UNDEFINED )
return ;
INIT_PORT_DCB_READ_LOCAL_CMD ( pcmd , pi - > port_id ) ;
pcmd . u . dcb . pgid . type = FW_PORT_DCB_TYPE_PGID ;
err = t4_wr_mbox ( adap , adap - > mbox , & pcmd , sizeof ( pcmd ) , & pcmd ) ;
if ( err ! = FW_PORT_DCB_CFG_SUCCESS ) {
dev_err ( adap - > pdev_dev , " DCB read PGID failed with %d \n " , - err ) ;
return ;
}
_pgid = be32_to_cpu ( pcmd . u . dcb . pgid . pgid ) ;
2014-11-11 23:30:51 -08:00
_pgid & = ~ ( 0xF < < ( fw_tc * 4 ) ) ;
_pgid | = pgid < < ( fw_tc * 4 ) ;
2014-06-19 21:37:12 -07:00
pcmd . u . dcb . pgid . pgid = cpu_to_be32 ( _pgid ) ;
INIT_PORT_DCB_WRITE_CMD ( pcmd , pi - > port_id ) ;
err = t4_wr_mbox ( adap , adap - > mbox , & pcmd , sizeof ( pcmd ) , & pcmd ) ;
if ( err ! = FW_PORT_DCB_CFG_SUCCESS ) {
dev_err ( adap - > pdev_dev , " DCB write PGID failed with %d \n " ,
- err ) ;
return ;
}
memset ( & pcmd , 0 , sizeof ( struct fw_port_cmd ) ) ;
INIT_PORT_DCB_READ_LOCAL_CMD ( pcmd , pi - > port_id ) ;
pcmd . u . dcb . pgrate . type = FW_PORT_DCB_TYPE_PGRATE ;
err = t4_wr_mbox ( adap , adap - > mbox , & pcmd , sizeof ( pcmd ) , & pcmd ) ;
if ( err ! = FW_PORT_DCB_CFG_SUCCESS ) {
dev_err ( adap - > pdev_dev , " DCB read PGRATE failed with %d \n " ,
- err ) ;
return ;
}
pcmd . u . dcb . pgrate . pgrate [ pgid ] = bw_per ;
INIT_PORT_DCB_WRITE_CMD ( pcmd , pi - > port_id ) ;
if ( pi - > dcb . state = = CXGB4_DCB_STATE_HOST )
2014-11-21 12:52:04 +05:30
pcmd . op_to_portid | = cpu_to_be32 ( FW_PORT_CMD_APPLY_F ) ;
2014-06-19 21:37:12 -07:00
err = t4_wr_mbox ( adap , adap - > mbox , & pcmd , sizeof ( pcmd ) , & pcmd ) ;
if ( err ! = FW_PORT_DCB_CFG_SUCCESS )
dev_err ( adap - > pdev_dev , " DCB write PGRATE failed with %d \n " ,
- err ) ;
}
static void cxgb4_getpgbwgcfg ( struct net_device * dev , int pgid , u8 * bw_per ,
int local )
{
struct fw_port_cmd pcmd ;
struct port_info * pi = netdev2pinfo ( dev ) ;
struct adapter * adap = pi - > adapter ;
int err ;
if ( local )
INIT_PORT_DCB_READ_LOCAL_CMD ( pcmd , pi - > port_id ) ;
else
INIT_PORT_DCB_READ_PEER_CMD ( pcmd , pi - > port_id ) ;
pcmd . u . dcb . pgrate . type = FW_PORT_DCB_TYPE_PGRATE ;
err = t4_wr_mbox ( adap , adap - > mbox , & pcmd , sizeof ( pcmd ) , & pcmd ) ;
if ( err ! = FW_PORT_DCB_CFG_SUCCESS ) {
dev_err ( adap - > pdev_dev , " DCB read PGRATE failed with %d \n " ,
- err ) ;
2014-08-07 16:14:03 -07:00
return ;
2014-06-19 21:37:12 -07:00
}
2014-08-07 16:14:03 -07:00
* bw_per = pcmd . u . dcb . pgrate . pgrate [ pgid ] ;
2014-06-19 21:37:12 -07:00
}
static void cxgb4_getpgbwgcfg_tx ( struct net_device * dev , int pgid , u8 * bw_per )
{
return cxgb4_getpgbwgcfg ( dev , pgid , bw_per , 1 ) ;
}
static void cxgb4_getpgbwgcfg_rx ( struct net_device * dev , int pgid , u8 * bw_per )
{
return cxgb4_getpgbwgcfg ( dev , pgid , bw_per , 0 ) ;
}
static void cxgb4_setpgbwgcfg_tx ( struct net_device * dev , int pgid ,
u8 bw_per )
{
struct fw_port_cmd pcmd ;
struct port_info * pi = netdev2pinfo ( dev ) ;
struct adapter * adap = pi - > adapter ;
int err ;
INIT_PORT_DCB_READ_LOCAL_CMD ( pcmd , pi - > port_id ) ;
pcmd . u . dcb . pgrate . type = FW_PORT_DCB_TYPE_PGRATE ;
err = t4_wr_mbox ( adap , adap - > mbox , & pcmd , sizeof ( pcmd ) , & pcmd ) ;
if ( err ! = FW_PORT_DCB_CFG_SUCCESS ) {
dev_err ( adap - > pdev_dev , " DCB read PGRATE failed with %d \n " ,
- err ) ;
return ;
}
pcmd . u . dcb . pgrate . pgrate [ pgid ] = bw_per ;
INIT_PORT_DCB_WRITE_CMD ( pcmd , pi - > port_id ) ;
if ( pi - > dcb . state = = CXGB4_DCB_STATE_HOST )
2014-11-21 12:52:04 +05:30
pcmd . op_to_portid | = cpu_to_be32 ( FW_PORT_CMD_APPLY_F ) ;
2014-06-19 21:37:12 -07:00
err = t4_wr_mbox ( adap , adap - > mbox , & pcmd , sizeof ( pcmd ) , & pcmd ) ;
if ( err ! = FW_PORT_DCB_CFG_SUCCESS )
dev_err ( adap - > pdev_dev , " DCB write PGRATE failed with %d \n " ,
- err ) ;
}
/* Return whether the specified Traffic Class Priority has Priority Pause
* Frames enabled .
*/
static void cxgb4_getpfccfg ( struct net_device * dev , int priority , u8 * pfccfg )
{
struct port_info * pi = netdev2pinfo ( dev ) ;
struct port_dcb_info * dcb = & pi - > dcb ;
2015-07-17 13:12:31 -07:00
if ( ! cxgb4_dcb_state_synced ( dcb - > state ) | |
2014-06-19 21:37:12 -07:00
priority > = CXGB4_MAX_PRIORITY )
* pfccfg = 0 ;
else
2014-11-11 23:30:51 -08:00
* pfccfg = ( pi - > dcb . pfcen > > ( 7 - priority ) ) & 1 ;
2014-06-19 21:37:12 -07:00
}
/* Enable/disable Priority Pause Frames for the specified Traffic Class
* Priority .
*/
static void cxgb4_setpfccfg ( struct net_device * dev , int priority , u8 pfccfg )
{
struct fw_port_cmd pcmd ;
struct port_info * pi = netdev2pinfo ( dev ) ;
struct adapter * adap = pi - > adapter ;
int err ;
2015-07-17 13:12:31 -07:00
if ( ! cxgb4_dcb_state_synced ( pi - > dcb . state ) | |
2014-06-19 21:37:12 -07:00
priority > = CXGB4_MAX_PRIORITY )
return ;
INIT_PORT_DCB_WRITE_CMD ( pcmd , pi - > port_id ) ;
if ( pi - > dcb . state = = CXGB4_DCB_STATE_HOST )
2014-11-21 12:52:04 +05:30
pcmd . op_to_portid | = cpu_to_be32 ( FW_PORT_CMD_APPLY_F ) ;
2014-06-19 21:37:12 -07:00
pcmd . u . dcb . pfc . type = FW_PORT_DCB_TYPE_PFC ;
2014-06-23 23:11:09 -07:00
pcmd . u . dcb . pfc . pfcen = pi - > dcb . pfcen ;
2014-06-19 21:37:12 -07:00
if ( pfccfg )
2014-11-11 23:30:51 -08:00
pcmd . u . dcb . pfc . pfcen | = ( 1 < < ( 7 - priority ) ) ;
2014-06-19 21:37:12 -07:00
else
2014-11-11 23:30:51 -08:00
pcmd . u . dcb . pfc . pfcen & = ( ~ ( 1 < < ( 7 - priority ) ) ) ;
2014-06-19 21:37:12 -07:00
err = t4_wr_mbox ( adap , adap - > mbox , & pcmd , sizeof ( pcmd ) , & pcmd ) ;
if ( err ! = FW_PORT_DCB_CFG_SUCCESS ) {
dev_err ( adap - > pdev_dev , " DCB PFC write failed with %d \n " , - err ) ;
return ;
}
2014-06-23 23:11:09 -07:00
pi - > dcb . pfcen = pcmd . u . dcb . pfc . pfcen ;
2014-06-19 21:37:12 -07:00
}
static u8 cxgb4_setall ( struct net_device * dev )
{
return 0 ;
}
/* Return DCB capabilities.
*/
static u8 cxgb4_getcap ( struct net_device * dev , int cap_id , u8 * caps )
{
struct port_info * pi = netdev2pinfo ( dev ) ;
switch ( cap_id ) {
case DCB_CAP_ATTR_PG :
case DCB_CAP_ATTR_PFC :
* caps = true ;
break ;
case DCB_CAP_ATTR_PG_TCS :
/* 8 priorities for PG represented by bitmap */
* caps = 0x80 ;
break ;
case DCB_CAP_ATTR_PFC_TCS :
/* 8 priorities for PFC represented by bitmap */
* caps = 0x80 ;
break ;
case DCB_CAP_ATTR_GSP :
* caps = true ;
break ;
case DCB_CAP_ATTR_UP2TC :
case DCB_CAP_ATTR_BCN :
* caps = false ;
break ;
case DCB_CAP_ATTR_DCBX :
* caps = pi - > dcb . supported ;
break ;
default :
* caps = false ;
}
return 0 ;
}
/* Return the number of Traffic Classes for the indicated Traffic Class ID.
*/
static int cxgb4_getnumtcs ( struct net_device * dev , int tcs_id , u8 * num )
{
struct port_info * pi = netdev2pinfo ( dev ) ;
switch ( tcs_id ) {
case DCB_NUMTCS_ATTR_PG :
if ( pi - > dcb . msgs & CXGB4_DCB_FW_PGRATE )
* num = pi - > dcb . pg_num_tcs_supported ;
else
* num = 0x8 ;
break ;
case DCB_NUMTCS_ATTR_PFC :
* num = 0x8 ;
break ;
default :
return - EINVAL ;
}
return 0 ;
}
/* Set the number of Traffic Classes supported for the indicated Traffic Class
* ID .
*/
static int cxgb4_setnumtcs ( struct net_device * dev , int tcs_id , u8 num )
{
/* Setting the number of Traffic Classes isn't supported.
*/
return - ENOSYS ;
}
/* Return whether Priority Flow Control is enabled. */
static u8 cxgb4_getpfcstate ( struct net_device * dev )
{
struct port_info * pi = netdev2pinfo ( dev ) ;
2015-07-17 13:12:31 -07:00
if ( ! cxgb4_dcb_state_synced ( pi - > dcb . state ) )
2014-06-19 21:37:12 -07:00
return false ;
return pi - > dcb . pfcen ! = 0 ;
}
/* Enable/disable Priority Flow Control. */
static void cxgb4_setpfcstate ( struct net_device * dev , u8 state )
{
/* We can't enable/disable Priority Flow Control but we also can't
* return an error . . .
*/
}
/* Return the Application User Priority Map associated with the specified
* Application ID .
*/
static int __cxgb4_getapp ( struct net_device * dev , u8 app_idtype , u16 app_id ,
int peer )
{
struct port_info * pi = netdev2pinfo ( dev ) ;
struct adapter * adap = pi - > adapter ;
int i ;
2015-07-17 13:12:31 -07:00
if ( ! cxgb4_dcb_state_synced ( pi - > dcb . state ) )
2014-06-19 21:37:12 -07:00
return 0 ;
for ( i = 0 ; i < CXGB4_MAX_DCBX_APP_SUPPORTED ; i + + ) {
struct fw_port_cmd pcmd ;
int err ;
if ( peer )
INIT_PORT_DCB_READ_PEER_CMD ( pcmd , pi - > port_id ) ;
else
INIT_PORT_DCB_READ_LOCAL_CMD ( pcmd , pi - > port_id ) ;
pcmd . u . dcb . app_priority . type = FW_PORT_DCB_TYPE_APP_ID ;
pcmd . u . dcb . app_priority . idx = i ;
err = t4_wr_mbox ( adap , adap - > mbox , & pcmd , sizeof ( pcmd ) , & pcmd ) ;
if ( err ! = FW_PORT_DCB_CFG_SUCCESS ) {
dev_err ( adap - > pdev_dev , " DCB APP read failed with %d \n " ,
- err ) ;
return err ;
}
if ( be16_to_cpu ( pcmd . u . dcb . app_priority . protocolid ) = = app_id )
2014-08-07 16:14:03 -07:00
if ( pcmd . u . dcb . app_priority . sel_field = = app_idtype )
return pcmd . u . dcb . app_priority . user_prio_map ;
2014-06-19 21:37:12 -07:00
/* exhausted app list */
if ( ! pcmd . u . dcb . app_priority . protocolid )
break ;
}
return - EEXIST ;
}
/* Return the Application User Priority Map associated with the specified
2014-07-16 22:32:39 -07:00
* Application ID .
2014-06-19 21:37:12 -07:00
*/
2014-07-16 22:32:39 -07:00
static int cxgb4_getapp ( struct net_device * dev , u8 app_idtype , u16 app_id )
2014-06-19 21:37:12 -07:00
{
2015-07-17 13:12:30 -07:00
/* Convert app_idtype to firmware format before querying */
return __cxgb4_getapp ( dev , app_idtype = = DCB_APP_IDTYPE_ETHTYPE ?
app_idtype : 3 , app_id , 0 ) ;
2014-06-19 21:37:12 -07:00
}
2014-07-16 22:32:39 -07:00
/* Write a new Application User Priority Map for the specified Application ID
2014-06-19 21:37:12 -07:00
*/
2014-08-07 16:14:03 -07:00
static int __cxgb4_setapp ( struct net_device * dev , u8 app_idtype , u16 app_id ,
u8 app_prio )
2014-06-19 21:37:12 -07:00
{
struct fw_port_cmd pcmd ;
struct port_info * pi = netdev2pinfo ( dev ) ;
struct adapter * adap = pi - > adapter ;
int i , err ;
2015-07-17 13:12:31 -07:00
if ( ! cxgb4_dcb_state_synced ( pi - > dcb . state ) )
2014-06-19 21:37:12 -07:00
return - EINVAL ;
/* DCB info gets thrown away on link up */
if ( ! netif_carrier_ok ( dev ) )
return - ENOLINK ;
for ( i = 0 ; i < CXGB4_MAX_DCBX_APP_SUPPORTED ; i + + ) {
INIT_PORT_DCB_READ_LOCAL_CMD ( pcmd , pi - > port_id ) ;
pcmd . u . dcb . app_priority . type = FW_PORT_DCB_TYPE_APP_ID ;
pcmd . u . dcb . app_priority . idx = i ;
err = t4_wr_mbox ( adap , adap - > mbox , & pcmd , sizeof ( pcmd ) , & pcmd ) ;
if ( err ! = FW_PORT_DCB_CFG_SUCCESS ) {
dev_err ( adap - > pdev_dev , " DCB app table read failed with %d \n " ,
- err ) ;
return err ;
}
if ( be16_to_cpu ( pcmd . u . dcb . app_priority . protocolid ) = = app_id ) {
/* overwrite existing app table */
pcmd . u . dcb . app_priority . protocolid = 0 ;
break ;
}
/* find first empty slot */
if ( ! pcmd . u . dcb . app_priority . protocolid )
break ;
}
if ( i = = CXGB4_MAX_DCBX_APP_SUPPORTED ) {
/* no empty slots available */
dev_err ( adap - > pdev_dev , " DCB app table full \n " ) ;
return - EBUSY ;
}
/* write out new app table entry */
INIT_PORT_DCB_WRITE_CMD ( pcmd , pi - > port_id ) ;
if ( pi - > dcb . state = = CXGB4_DCB_STATE_HOST )
2014-11-21 12:52:04 +05:30
pcmd . op_to_portid | = cpu_to_be32 ( FW_PORT_CMD_APPLY_F ) ;
2014-06-19 21:37:12 -07:00
pcmd . u . dcb . app_priority . type = FW_PORT_DCB_TYPE_APP_ID ;
pcmd . u . dcb . app_priority . protocolid = cpu_to_be16 ( app_id ) ;
pcmd . u . dcb . app_priority . sel_field = app_idtype ;
pcmd . u . dcb . app_priority . user_prio_map = app_prio ;
pcmd . u . dcb . app_priority . idx = i ;
err = t4_wr_mbox ( adap , adap - > mbox , & pcmd , sizeof ( pcmd ) , & pcmd ) ;
if ( err ! = FW_PORT_DCB_CFG_SUCCESS ) {
dev_err ( adap - > pdev_dev , " DCB app table write failed with %d \n " ,
- err ) ;
return err ;
}
return 0 ;
}
2014-08-07 16:14:03 -07:00
/* Priority for CEE inside dcb_app is bitmask, with 0 being an invalid value */
static int cxgb4_setapp ( struct net_device * dev , u8 app_idtype , u16 app_id ,
u8 app_prio )
{
int ret ;
struct dcb_app app = {
. selector = app_idtype ,
. protocol = app_id ,
. priority = app_prio ,
} ;
if ( app_idtype ! = DCB_APP_IDTYPE_ETHTYPE & &
app_idtype ! = DCB_APP_IDTYPE_PORTNUM )
return - EINVAL ;
/* Convert app_idtype to a format that firmware understands */
ret = __cxgb4_setapp ( dev , app_idtype = = DCB_APP_IDTYPE_ETHTYPE ?
app_idtype : 3 , app_id , app_prio ) ;
if ( ret )
return ret ;
return dcb_setapp ( dev , & app ) ;
}
2014-06-19 21:37:12 -07:00
/* Return whether IEEE Data Center Bridging has been negotiated.
*/
2014-10-23 14:37:30 -07:00
static inline int
cxgb4_ieee_negotiation_complete ( struct net_device * dev ,
enum cxgb4_dcb_fw_msgs dcb_subtype )
2014-06-19 21:37:12 -07:00
{
struct port_info * pi = netdev2pinfo ( dev ) ;
struct port_dcb_info * dcb = & pi - > dcb ;
2015-07-17 13:12:31 -07:00
if ( dcb - > state = = CXGB4_DCB_STATE_FW_ALLSYNCED )
if ( dcb_subtype & & ! ( dcb - > msgs & dcb_subtype ) )
return 0 ;
2014-10-23 14:37:30 -07:00
2015-07-17 13:12:31 -07:00
return ( cxgb4_dcb_state_synced ( dcb - > state ) & &
2014-06-19 21:37:12 -07:00
( dcb - > supported & DCB_CAP_DCBX_VER_IEEE ) ) ;
}
2015-01-30 17:20:17 -08:00
static int cxgb4_ieee_read_ets ( struct net_device * dev , struct ieee_ets * ets ,
int local )
{
struct port_info * pi = netdev2pinfo ( dev ) ;
struct port_dcb_info * dcb = & pi - > dcb ;
struct adapter * adap = pi - > adapter ;
uint32_t tc_info ;
struct fw_port_cmd pcmd ;
int i , bwg , err ;
if ( ! ( dcb - > msgs & ( CXGB4_DCB_FW_PGID | CXGB4_DCB_FW_PGRATE ) ) )
return 0 ;
ets - > ets_cap = dcb - > pg_num_tcs_supported ;
if ( local ) {
ets - > willing = 1 ;
INIT_PORT_DCB_READ_LOCAL_CMD ( pcmd , pi - > port_id ) ;
} else {
INIT_PORT_DCB_READ_PEER_CMD ( pcmd , pi - > port_id ) ;
}
pcmd . u . dcb . pgid . type = FW_PORT_DCB_TYPE_PGID ;
err = t4_wr_mbox ( adap , adap - > mbox , & pcmd , sizeof ( pcmd ) , & pcmd ) ;
if ( err ! = FW_PORT_DCB_CFG_SUCCESS ) {
dev_err ( adap - > pdev_dev , " DCB read PGID failed with %d \n " , - err ) ;
return err ;
}
tc_info = be32_to_cpu ( pcmd . u . dcb . pgid . pgid ) ;
if ( local )
INIT_PORT_DCB_READ_LOCAL_CMD ( pcmd , pi - > port_id ) ;
else
INIT_PORT_DCB_READ_PEER_CMD ( pcmd , pi - > port_id ) ;
pcmd . u . dcb . pgrate . type = FW_PORT_DCB_TYPE_PGRATE ;
err = t4_wr_mbox ( adap , adap - > mbox , & pcmd , sizeof ( pcmd ) , & pcmd ) ;
if ( err ! = FW_PORT_DCB_CFG_SUCCESS ) {
dev_err ( adap - > pdev_dev , " DCB read PGRATE failed with %d \n " ,
- err ) ;
return err ;
}
for ( i = 0 ; i < IEEE_8021QAZ_MAX_TCS ; i + + ) {
bwg = ( tc_info > > ( ( 7 - i ) * 4 ) ) & 0xF ;
ets - > prio_tc [ i ] = bwg ;
ets - > tc_tx_bw [ i ] = pcmd . u . dcb . pgrate . pgrate [ i ] ;
ets - > tc_rx_bw [ i ] = ets - > tc_tx_bw [ i ] ;
ets - > tc_tsa [ i ] = pcmd . u . dcb . pgrate . tsa [ i ] ;
}
return 0 ;
}
static int cxgb4_ieee_get_ets ( struct net_device * dev , struct ieee_ets * ets )
{
return cxgb4_ieee_read_ets ( dev , ets , 1 ) ;
}
/* We reuse this for peer PFC as well, as we can't have it enabled one way */
static int cxgb4_ieee_get_pfc ( struct net_device * dev , struct ieee_pfc * pfc )
{
struct port_info * pi = netdev2pinfo ( dev ) ;
struct port_dcb_info * dcb = & pi - > dcb ;
memset ( pfc , 0 , sizeof ( struct ieee_pfc ) ) ;
if ( ! ( dcb - > msgs & CXGB4_DCB_FW_PFC ) )
return 0 ;
pfc - > pfc_cap = dcb - > pfc_num_tcs_supported ;
pfc - > pfc_en = bitswap_1 ( dcb - > pfcen ) ;
return 0 ;
}
static int cxgb4_ieee_peer_ets ( struct net_device * dev , struct ieee_ets * ets )
{
return cxgb4_ieee_read_ets ( dev , ets , 0 ) ;
}
2014-06-19 21:37:12 -07:00
/* Fill in the Application User Priority Map associated with the
* specified Application .
2014-08-07 16:14:03 -07:00
* Priority for IEEE dcb_app is an integer , with 0 being a valid value
2014-06-19 21:37:12 -07:00
*/
static int cxgb4_ieee_getapp ( struct net_device * dev , struct dcb_app * app )
{
int prio ;
2014-10-23 14:37:30 -07:00
if ( ! cxgb4_ieee_negotiation_complete ( dev , CXGB4_DCB_FW_APP_ID ) )
2014-06-19 21:37:12 -07:00
return - EINVAL ;
if ( ! ( app - > selector & & app - > protocol ) )
return - EINVAL ;
2014-08-07 16:14:03 -07:00
/* Try querying firmware first, use firmware format */
prio = __cxgb4_getapp ( dev , app - > selector - 1 , app - > protocol , 0 ) ;
if ( prio < 0 )
prio = dcb_ieee_getapp_mask ( dev , app ) ;
2014-06-19 21:37:12 -07:00
2014-08-07 16:14:03 -07:00
app - > priority = ffs ( prio ) - 1 ;
2014-06-19 21:37:12 -07:00
return 0 ;
}
2014-08-07 16:14:03 -07:00
/* Write a new Application User Priority Map for the specified Application ID.
* Priority for IEEE dcb_app is an integer , with 0 being a valid value
*/
2014-06-19 21:37:12 -07:00
static int cxgb4_ieee_setapp ( struct net_device * dev , struct dcb_app * app )
{
2014-08-07 16:14:03 -07:00
int ret ;
2014-10-23 14:37:30 -07:00
if ( ! cxgb4_ieee_negotiation_complete ( dev , CXGB4_DCB_FW_APP_ID ) )
2014-06-19 21:37:12 -07:00
return - EINVAL ;
2014-08-07 16:14:03 -07:00
if ( ! ( app - > selector & & app - > protocol ) )
return - EINVAL ;
if ( ! ( app - > selector > IEEE_8021QAZ_APP_SEL_ETHERTYPE & &
app - > selector < IEEE_8021QAZ_APP_SEL_ANY ) )
2014-06-19 21:37:12 -07:00
return - EINVAL ;
2014-08-07 16:14:03 -07:00
/* change selector to a format that firmware understands */
ret = __cxgb4_setapp ( dev , app - > selector - 1 , app - > protocol ,
( 1 < < app - > priority ) ) ;
if ( ret )
return ret ;
return dcb_ieee_setapp ( dev , app ) ;
2014-06-19 21:37:12 -07:00
}
/* Return our DCBX parameters.
*/
static u8 cxgb4_getdcbx ( struct net_device * dev )
{
struct port_info * pi = netdev2pinfo ( dev ) ;
/* This is already set by cxgb4_set_dcb_caps, so just return it */
return pi - > dcb . supported ;
}
/* Set our DCBX parameters.
*/
static u8 cxgb4_setdcbx ( struct net_device * dev , u8 dcb_request )
{
struct port_info * pi = netdev2pinfo ( dev ) ;
/* Filter out requests which exceed our capabilities.
*/
if ( ( dcb_request & ( CXGB4_DCBX_FW_SUPPORT | CXGB4_DCBX_HOST_SUPPORT ) )
! = dcb_request )
return 1 ;
2014-08-07 16:14:03 -07:00
/* Can't enable DCB if we haven't successfully negotiated it.
*/
2015-07-17 13:12:31 -07:00
if ( ! cxgb4_dcb_state_synced ( pi - > dcb . state ) )
2014-06-19 21:37:12 -07:00
return 1 ;
/* There's currently no mechanism to allow for the firmware DCBX
* negotiation to be changed from the Host Driver . If the caller
* requests exactly the same parameters that we already have then
* we ' ll allow them to be successfully " set " . . .
*/
if ( dcb_request ! = pi - > dcb . supported )
return 1 ;
pi - > dcb . supported = dcb_request ;
return 0 ;
}
static int cxgb4_getpeer_app ( struct net_device * dev ,
struct dcb_peer_app_info * info , u16 * app_count )
{
struct fw_port_cmd pcmd ;
struct port_info * pi = netdev2pinfo ( dev ) ;
struct adapter * adap = pi - > adapter ;
int i , err = 0 ;
2015-07-17 13:12:31 -07:00
if ( ! cxgb4_dcb_state_synced ( pi - > dcb . state ) )
2014-06-19 21:37:12 -07:00
return 1 ;
info - > willing = 0 ;
info - > error = 0 ;
* app_count = 0 ;
for ( i = 0 ; i < CXGB4_MAX_DCBX_APP_SUPPORTED ; i + + ) {
INIT_PORT_DCB_READ_PEER_CMD ( pcmd , pi - > port_id ) ;
pcmd . u . dcb . app_priority . type = FW_PORT_DCB_TYPE_APP_ID ;
pcmd . u . dcb . app_priority . idx = * app_count ;
err = t4_wr_mbox ( adap , adap - > mbox , & pcmd , sizeof ( pcmd ) , & pcmd ) ;
if ( err ! = FW_PORT_DCB_CFG_SUCCESS ) {
dev_err ( adap - > pdev_dev , " DCB app table read failed with %d \n " ,
- err ) ;
return err ;
}
/* find first empty slot */
if ( ! pcmd . u . dcb . app_priority . protocolid )
break ;
}
* app_count = i ;
return err ;
}
static int cxgb4_getpeerapp_tbl ( struct net_device * dev , struct dcb_app * table )
{
struct fw_port_cmd pcmd ;
struct port_info * pi = netdev2pinfo ( dev ) ;
struct adapter * adap = pi - > adapter ;
int i , err = 0 ;
2015-07-17 13:12:31 -07:00
if ( ! cxgb4_dcb_state_synced ( pi - > dcb . state ) )
2014-06-19 21:37:12 -07:00
return 1 ;
for ( i = 0 ; i < CXGB4_MAX_DCBX_APP_SUPPORTED ; i + + ) {
INIT_PORT_DCB_READ_PEER_CMD ( pcmd , pi - > port_id ) ;
pcmd . u . dcb . app_priority . type = FW_PORT_DCB_TYPE_APP_ID ;
pcmd . u . dcb . app_priority . idx = i ;
err = t4_wr_mbox ( adap , adap - > mbox , & pcmd , sizeof ( pcmd ) , & pcmd ) ;
if ( err ! = FW_PORT_DCB_CFG_SUCCESS ) {
dev_err ( adap - > pdev_dev , " DCB app table read failed with %d \n " ,
- err ) ;
return err ;
}
/* find first empty slot */
if ( ! pcmd . u . dcb . app_priority . protocolid )
break ;
2015-07-17 13:12:30 -07:00
table [ i ] . selector = ( pcmd . u . dcb . app_priority . sel_field + 1 ) ;
2014-06-19 21:37:12 -07:00
table [ i ] . protocol =
be16_to_cpu ( pcmd . u . dcb . app_priority . protocolid ) ;
2014-08-07 16:14:03 -07:00
table [ i ] . priority =
ffs ( pcmd . u . dcb . app_priority . user_prio_map ) - 1 ;
2014-06-19 21:37:12 -07:00
}
return err ;
}
/* Return Priority Group information.
*/
static int cxgb4_cee_peer_getpg ( struct net_device * dev , struct cee_pg * pg )
{
struct fw_port_cmd pcmd ;
struct port_info * pi = netdev2pinfo ( dev ) ;
struct adapter * adap = pi - > adapter ;
u32 pgid ;
int i , err ;
/* We're always "willing" -- the Switch Fabric always dictates the
* DCBX parameters to us .
*/
pg - > willing = true ;
INIT_PORT_DCB_READ_PEER_CMD ( pcmd , pi - > port_id ) ;
pcmd . u . dcb . pgid . type = FW_PORT_DCB_TYPE_PGID ;
err = t4_wr_mbox ( adap , adap - > mbox , & pcmd , sizeof ( pcmd ) , & pcmd ) ;
if ( err ! = FW_PORT_DCB_CFG_SUCCESS ) {
dev_err ( adap - > pdev_dev , " DCB read PGID failed with %d \n " , - err ) ;
return err ;
}
pgid = be32_to_cpu ( pcmd . u . dcb . pgid . pgid ) ;
for ( i = 0 ; i < CXGB4_MAX_PRIORITY ; i + + )
2014-11-20 17:11:46 -08:00
pg - > prio_pg [ 7 - i ] = ( pgid > > ( i * 4 ) ) & 0xF ;
2014-06-19 21:37:12 -07:00
INIT_PORT_DCB_READ_PEER_CMD ( pcmd , pi - > port_id ) ;
pcmd . u . dcb . pgrate . type = FW_PORT_DCB_TYPE_PGRATE ;
err = t4_wr_mbox ( adap , adap - > mbox , & pcmd , sizeof ( pcmd ) , & pcmd ) ;
if ( err ! = FW_PORT_DCB_CFG_SUCCESS ) {
dev_err ( adap - > pdev_dev , " DCB read PGRATE failed with %d \n " ,
- err ) ;
return err ;
}
for ( i = 0 ; i < CXGB4_MAX_PRIORITY ; i + + )
pg - > pg_bw [ i ] = pcmd . u . dcb . pgrate . pgrate [ i ] ;
2015-07-17 13:12:32 -07:00
pg - > tcs_supported = pcmd . u . dcb . pgrate . num_tcs_supported ;
2014-06-19 21:37:12 -07:00
return 0 ;
}
/* Return Priority Flow Control information.
*/
static int cxgb4_cee_peer_getpfc ( struct net_device * dev , struct cee_pfc * pfc )
{
struct port_info * pi = netdev2pinfo ( dev ) ;
cxgb4_getnumtcs ( dev , DCB_NUMTCS_ATTR_PFC , & ( pfc - > tcs_supported ) ) ;
2015-01-30 17:20:17 -08:00
/* Firmware sends this to us in a formwat that is a bit flipped version
* of spec , correct it before we send it to host . This is taken care of
* by bit shifting in other uses of pfcen
*/
pfc - > pfc_en = bitswap_1 ( pi - > dcb . pfcen ) ;
2014-06-19 21:37:12 -07:00
2015-07-17 13:12:32 -07:00
pfc - > tcs_supported = pi - > dcb . pfc_num_tcs_supported ;
2014-06-19 21:37:12 -07:00
return 0 ;
}
const struct dcbnl_rtnl_ops cxgb4_dcb_ops = {
2015-01-30 17:20:17 -08:00
. ieee_getets = cxgb4_ieee_get_ets ,
. ieee_getpfc = cxgb4_ieee_get_pfc ,
2014-06-19 21:37:12 -07:00
. ieee_getapp = cxgb4_ieee_getapp ,
. ieee_setapp = cxgb4_ieee_setapp ,
2015-01-30 17:20:17 -08:00
. ieee_peer_getets = cxgb4_ieee_peer_ets ,
. ieee_peer_getpfc = cxgb4_ieee_get_pfc ,
2014-06-19 21:37:12 -07:00
/* CEE std */
. getstate = cxgb4_getstate ,
. setstate = cxgb4_setstate ,
. getpgtccfgtx = cxgb4_getpgtccfg_tx ,
. getpgbwgcfgtx = cxgb4_getpgbwgcfg_tx ,
. getpgtccfgrx = cxgb4_getpgtccfg_rx ,
. getpgbwgcfgrx = cxgb4_getpgbwgcfg_rx ,
. setpgtccfgtx = cxgb4_setpgtccfg_tx ,
. setpgbwgcfgtx = cxgb4_setpgbwgcfg_tx ,
. setpfccfg = cxgb4_setpfccfg ,
. getpfccfg = cxgb4_getpfccfg ,
. setall = cxgb4_setall ,
. getcap = cxgb4_getcap ,
. getnumtcs = cxgb4_getnumtcs ,
. setnumtcs = cxgb4_setnumtcs ,
. getpfcstate = cxgb4_getpfcstate ,
. setpfcstate = cxgb4_setpfcstate ,
. getapp = cxgb4_getapp ,
. setapp = cxgb4_setapp ,
/* DCBX configuration */
. getdcbx = cxgb4_getdcbx ,
. setdcbx = cxgb4_setdcbx ,
/* peer apps */
. peer_getappinfo = cxgb4_getpeer_app ,
. peer_getapptable = cxgb4_getpeerapp_tbl ,
/* CEE peer */
. cee_peer_getpg = cxgb4_cee_peer_getpg ,
. cee_peer_getpfc = cxgb4_cee_peer_getpfc ,
} ;