/* * Copyright (C) 2008-2017 Chelsio Communications. All rights reserved. * * Written by Anish Bhatt (anish@chelsio.com) * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the LICENSE file included in this * release for licensing terms and conditions. */ #ifndef __CXGB4_DCB_H #define __CXGB4_DCB_H #include #include #include #ifdef CONFIG_CXGB4_DCB #if !defined(CONFIG_DCB) && !defined(CONFIG_DCB_MODULE) #error Cannot build cxgb4 for DCBX support without kernel DCBX configured #endif #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38) #define CXGB4_DCBX_FW_SUPPORT \ (DCB_CAP_DCBX_VER_CEE | \ DCB_CAP_DCBX_VER_IEEE | \ DCB_CAP_DCBX_LLD_MANAGED) #define CXGB4_DCBX_HOST_SUPPORT \ (DCB_CAP_DCBX_VER_CEE | \ DCB_CAP_DCBX_VER_IEEE | \ DCB_CAP_DCBX_HOST) #else #define CXGB4_DCBX_FW_SUPPORT 1 #define CXGB4_DCBX_HOST_SUPPORT 1 #endif #define CXGB4_MAX_PRIORITY CXGB4_MAX_DCBX_APP_SUPPORTED #define CXGB4_MAX_TCS CXGB4_MAX_DCBX_APP_SUPPORTED #define INIT_PORT_DCB_CMD(__pcmd, __port, __op, __action) \ do { \ memset(&(__pcmd), 0, sizeof(__pcmd)); \ (__pcmd).op_to_portid = \ cpu_to_be32(V_FW_CMD_OP(FW_PORT_CMD) | \ F_FW_CMD_REQUEST | \ F_FW_CMD_##__op | \ V_FW_PORT_CMD_PORTID(__port)); \ (__pcmd).action_to_len16 = \ cpu_to_be32(V_FW_PORT_CMD_ACTION(__action) | \ FW_LEN16(pcmd)); \ } while (0) #define INIT_PORT_DCB_READ_PEER_CMD(__pcmd, __port) \ INIT_PORT_DCB_CMD(__pcmd, __port, READ, FW_PORT_ACTION_DCB_READ_RECV) #define INIT_PORT_DCB_READ_LOCAL_CMD(__pcmd, __port) \ INIT_PORT_DCB_CMD(__pcmd, __port, READ, FW_PORT_ACTION_DCB_READ_TRANS) #define INIT_PORT_DCB_READ_SYNC_CMD(__pcmd, __port) \ INIT_PORT_DCB_CMD(__pcmd, __port, READ, FW_PORT_ACTION_DCB_READ_DET) #define INIT_PORT_DCB_WRITE_CMD(__pcmd, __port) \ INIT_PORT_DCB_CMD(__pcmd, __port, EXEC, FW_PORT_ACTION_L2_DCB_CFG) #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38) #define IEEE_FAUX_SYNC(__dev, __dcb) \ do { \ if ((__dcb)->dcb_version == FW_PORT_DCB_VER_IEEE) \ cxgb4_dcb_state_fsm((__dev), CXGB4_DCB_STATE_FW_ALLSYNCED); \ } while(0) #else #define IEEE_FAUX_SYNC(__dev, __dcb) #endif /* States we can be in for a port's Data Center Bridging. */ enum cxgb4_dcb_state { CXGB4_DCB_STATE_START, /* initial unknown state */ CXGB4_DCB_STATE_HOST, /* we're using Host DCB (if at all) */ CXGB4_DCB_STATE_FW_INCOMPLETE, /* using firmware DCB, incomplete */ CXGB4_DCB_STATE_FW_ALLSYNCED, /* using firmware DCB, all sync'ed */ }; /* * Data Center Bridging state input for the Finite State Machine. */ enum cxgb4_dcb_state_input { /* * Input from the firmware. */ CXGB4_DCB_INPUT_FW_DISABLED, /* firmware DCB disabled */ CXGB4_DCB_INPUT_FW_ENABLED, /* firmware DCB enabled */ CXGB4_DCB_INPUT_FW_INCOMPLETE, /* firmware reports incomplete DCB */ CXGB4_DCB_INPUT_FW_ALLSYNCED, /* firmware reports all sync'ed */ /* * Input from the host. */ /* none yet */ }; /* * Firmware DCB messages that we've received so far ... */ enum cxgb4_dcb_fw_msgs { CXGB4_DCB_FW_PGID = 0x01, CXGB4_DCB_FW_PGRATE = 0x02, CXGB4_DCB_FW_PRIORATE = 0x04, CXGB4_DCB_FW_PFC = 0x08, CXGB4_DCB_FW_APP_ID = 0x10, }; #define CXGB4_MAX_DCBX_APP_SUPPORTED 8 /* * Data Center Bridging support; */ struct port_dcb_info { enum cxgb4_dcb_state state; /* DCB State Machine */ enum cxgb4_dcb_fw_msgs msgs; /* DCB Firmware messages received */ unsigned int supported; /* OS DCB capabilities supported */ bool enabled; /* OS Enabled state */ /* * Cached copies of DCB information sent by the firmware (in Host * Native Endian format). */ u32 pgid; /* Priority Group[0..7] */ u8 dcb_version; /* Running DCBx version */ u8 pfcen; /* Priority Flow Control[0..7] */ u8 pg_num_tcs_supported; /* max PG Traffic Classes */ u8 pfc_num_tcs_supported; /* max PFC Traffic Classes */ u8 pgrate[8]; /* Priority Group Rate[0..7] */ u8 priorate[8]; /* Priority Rate[0..7] */ u8 tsa[8]; /* TSA Algorithm[0..7] */ struct app_priority { /* Application Information */ u8 user_prio_map; /* Priority Map bitfield */ u8 sel_field; /* Protocol ID interpretation */ u16 protocolid; /* Protocol ID */ } app_priority[CXGB4_MAX_DCBX_APP_SUPPORTED]; }; void cxgb4_dcb_state_init(struct net_device *); void cxgb4_dcb_version_init(struct net_device *); void cxgb4_dcb_state_fsm(struct net_device *, enum cxgb4_dcb_state_input); void cxgb4_dcb_handle_fw_update(struct adapter *, const struct fw_port_cmd *); void cxgb4_dcb_set_caps(struct adapter *, const struct fw_port_cmd *); extern const struct dcbnl_rtnl_ops cxgb4_dcb_ops; static inline __u8 bitswap_1(unsigned char val) { return ((val & 0x80) >> 7) | ((val & 0x40) >> 5) | ((val & 0x20) >> 3) | ((val & 0x10) >> 1) | ((val & 0x08) << 1) | ((val & 0x04) << 3) | ((val & 0x02) << 5) | ((val & 0x01) << 7); } #define CXGB4_DCB_ENABLED true #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,38) int cxgb4_getapp_external(struct net_device *dev, u8 app_idtype, u16 app_id); #endif #else /* !CONFIG_CXGB4_DCB */ static inline void cxgb4_dcb_state_init(struct net_device *dev) { } #define CXGB4_DCB_ENABLED false #endif /* !CONFIG_CXGB4_DCB */ #endif /* __CXGB4_DCB_H */