Commit 49f01349 authored by David S. Miller's avatar David S. Miller

Merge branch '100GbE' of git://git.kernel.org/pub/scm/linux/kernel/git/tnguy/nex

t-queue

Tony Nguyen says:

====================
100GbE Intel Wired LAN Driver Updates 2021-09-28

This series contains updates to ice driver only.

Dave adds support for QoS DSCP allowing for DSCP to TC mapping via APP
TLVs.

Ani adds enforcement of DSCP to only supported devices with the
introduction of a feature bitmap and corrects messaging of unsupported
modules based on link mode.

Jake refactors devlink info functions to be void as the functions no
longer return errors.

Jeff fixes a macro name to properly reflect the value.

Len Baker converts a kzalloc allocation to, the preferred, kcalloc.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 096d19f3 30cba287
...@@ -158,6 +158,11 @@ ...@@ -158,6 +158,11 @@
#define ice_pf_to_dev(pf) (&((pf)->pdev->dev)) #define ice_pf_to_dev(pf) (&((pf)->pdev->dev))
enum ice_feature {
ICE_F_DSCP,
ICE_F_MAX
};
struct ice_txq_meta { struct ice_txq_meta {
u32 q_teid; /* Tx-scheduler element identifier */ u32 q_teid; /* Tx-scheduler element identifier */
u16 q_id; /* Entry in VSI's txq_map bitmap */ u16 q_id; /* Entry in VSI's txq_map bitmap */
...@@ -443,6 +448,7 @@ struct ice_pf { ...@@ -443,6 +448,7 @@ struct ice_pf {
/* used to ratelimit the MDD event logging */ /* used to ratelimit the MDD event logging */
unsigned long last_printed_mdd_jiffies; unsigned long last_printed_mdd_jiffies;
DECLARE_BITMAP(malvfs, ICE_MAX_VF_COUNT); DECLARE_BITMAP(malvfs, ICE_MAX_VF_COUNT);
DECLARE_BITMAP(features, ICE_F_MAX);
DECLARE_BITMAP(state, ICE_STATE_NBITS); DECLARE_BITMAP(state, ICE_STATE_NBITS);
DECLARE_BITMAP(flags, ICE_PF_FLAGS_NBITS); DECLARE_BITMAP(flags, ICE_PF_FLAGS_NBITS);
unsigned long *avail_txqs; /* bitmap to track PF Tx queue usage */ unsigned long *avail_txqs; /* bitmap to track PF Tx queue usage */
......
...@@ -671,6 +671,16 @@ struct ice_aqc_sw_rules_elem { ...@@ -671,6 +671,16 @@ struct ice_aqc_sw_rules_elem {
} __packed pdata; } __packed pdata;
}; };
/* Query PFC Mode (direct 0x0302)
* Set PFC Mode (direct 0x0303)
*/
struct ice_aqc_set_query_pfc_mode {
u8 pfc_mode;
/* For Query Command response, reserved in all other cases */
#define ICE_AQC_PFC_VLAN_BASED_PFC 1
#define ICE_AQC_PFC_DSCP_BASED_PFC 2
u8 rsvd[15];
};
/* Get Default Topology (indirect 0x0400) */ /* Get Default Topology (indirect 0x0400) */
struct ice_aqc_get_topo { struct ice_aqc_get_topo {
u8 port_num; u8 port_num;
...@@ -1936,6 +1946,7 @@ struct ice_aq_desc { ...@@ -1936,6 +1946,7 @@ struct ice_aq_desc {
struct ice_aqc_nvm_pkg_data pkg_data; struct ice_aqc_nvm_pkg_data pkg_data;
struct ice_aqc_nvm_pass_comp_tbl pass_comp_tbl; struct ice_aqc_nvm_pass_comp_tbl pass_comp_tbl;
struct ice_aqc_pf_vf_msg virt; struct ice_aqc_pf_vf_msg virt;
struct ice_aqc_set_query_pfc_mode set_query_pfc_mode;
struct ice_aqc_lldp_get_mib lldp_get_mib; struct ice_aqc_lldp_get_mib lldp_get_mib;
struct ice_aqc_lldp_set_mib_change lldp_set_event; struct ice_aqc_lldp_set_mib_change lldp_set_event;
struct ice_aqc_lldp_stop lldp_stop; struct ice_aqc_lldp_stop lldp_stop;
...@@ -2040,6 +2051,10 @@ enum ice_adminq_opc { ...@@ -2040,6 +2051,10 @@ enum ice_adminq_opc {
ice_aqc_opc_clear_pf_cfg = 0x02A4, ice_aqc_opc_clear_pf_cfg = 0x02A4,
/* DCB commands */
ice_aqc_opc_query_pfc_mode = 0x0302,
ice_aqc_opc_set_pfc_mode = 0x0303,
/* transmit scheduler commands */ /* transmit scheduler commands */
ice_aqc_opc_get_dflt_topo = 0x0400, ice_aqc_opc_get_dflt_topo = 0x0400,
ice_aqc_opc_add_sched_elems = 0x0401, ice_aqc_opc_add_sched_elems = 0x0401,
......
...@@ -513,7 +513,7 @@ void ice_init_arfs(struct ice_vsi *vsi) ...@@ -513,7 +513,7 @@ void ice_init_arfs(struct ice_vsi *vsi)
if (!vsi || vsi->type != ICE_VSI_PF) if (!vsi || vsi->type != ICE_VSI_PF)
return; return;
arfs_fltr_list = kzalloc(sizeof(*arfs_fltr_list) * ICE_MAX_ARFS_LIST, arfs_fltr_list = kcalloc(ICE_MAX_ARFS_LIST, sizeof(*arfs_fltr_list),
GFP_KERNEL); GFP_KERNEL);
if (!arfs_fltr_list) if (!arfs_fltr_list)
return; return;
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
/* Copyright (c) 2019, Intel Corporation. */ /* Copyright (c) 2019, Intel Corporation. */
#include "ice_common.h" #include "ice_common.h"
#include "ice_lib.h"
#include "ice_sched.h" #include "ice_sched.h"
#include "ice_dcb.h" #include "ice_dcb.h"
...@@ -735,6 +736,45 @@ ice_aq_get_cee_dcb_cfg(struct ice_hw *hw, ...@@ -735,6 +736,45 @@ ice_aq_get_cee_dcb_cfg(struct ice_hw *hw,
return ice_aq_send_cmd(hw, &desc, (void *)buff, sizeof(*buff), cd); return ice_aq_send_cmd(hw, &desc, (void *)buff, sizeof(*buff), cd);
} }
/**
* ice_aq_set_pfc_mode - Set PFC mode
* @hw: pointer to the HW struct
* @pfc_mode: value of PFC mode to set
* @cd: pointer to command details structure or NULL
*
* This AQ call configures the PFC mode to DSCP-based PFC mode or
* VLAN-based PFC (0x0303)
*/
int ice_aq_set_pfc_mode(struct ice_hw *hw, u8 pfc_mode, struct ice_sq_cd *cd)
{
struct ice_aqc_set_query_pfc_mode *cmd;
struct ice_aq_desc desc;
enum ice_status status;
if (pfc_mode > ICE_AQC_PFC_DSCP_BASED_PFC)
return -EINVAL;
cmd = &desc.params.set_query_pfc_mode;
ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_set_pfc_mode);
cmd->pfc_mode = pfc_mode;
status = ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
if (status)
return ice_status_to_errno(status);
/* FW will write the PFC mode set back into cmd->pfc_mode, but if DCB is
* disabled, FW will write back 0 to cmd->pfc_mode. After the AQ has
* been executed, check if cmd->pfc_mode is what was requested. If not,
* return an error.
*/
if (cmd->pfc_mode != pfc_mode)
return -EOPNOTSUPP;
return 0;
}
/** /**
* ice_cee_to_dcb_cfg * ice_cee_to_dcb_cfg
* @cee_cfg: pointer to CEE configuration struct * @cee_cfg: pointer to CEE configuration struct
...@@ -1207,7 +1247,140 @@ ice_add_ieee_app_pri_tlv(struct ice_lldp_org_tlv *tlv, ...@@ -1207,7 +1247,140 @@ ice_add_ieee_app_pri_tlv(struct ice_lldp_org_tlv *tlv,
} }
/** /**
* ice_add_dcb_tlv - Add all IEEE TLVs * ice_add_dscp_up_tlv - Prepare DSCP to UP TLV
* @tlv: location to build the TLV data
* @dcbcfg: location of data to convert to TLV
*/
static void
ice_add_dscp_up_tlv(struct ice_lldp_org_tlv *tlv, struct ice_dcbx_cfg *dcbcfg)
{
u8 *buf = tlv->tlvinfo;
u32 ouisubtype;
u16 typelen;
int i;
typelen = ((ICE_TLV_TYPE_ORG << ICE_LLDP_TLV_TYPE_S) |
ICE_DSCP_UP_TLV_LEN);
tlv->typelen = htons(typelen);
ouisubtype = (u32)((ICE_DSCP_OUI << ICE_LLDP_TLV_OUI_S) |
ICE_DSCP_SUBTYPE_DSCP2UP);
tlv->ouisubtype = htonl(ouisubtype);
/* bytes 0 - 63 - IPv4 DSCP2UP LUT */
for (i = 0; i < ICE_DSCP_NUM_VAL; i++) {
/* IPv4 mapping */
buf[i] = dcbcfg->dscp_map[i];
/* IPv6 mapping */
buf[i + ICE_DSCP_IPV6_OFFSET] = dcbcfg->dscp_map[i];
}
/* byte 64 - IPv4 untagged traffic */
buf[i] = 0;
/* byte 144 - IPv6 untagged traffic */
buf[i + ICE_DSCP_IPV6_OFFSET] = 0;
}
#define ICE_BYTES_PER_TC 8
/**
* ice_add_dscp_enf_tlv - Prepare DSCP Enforcement TLV
* @tlv: location to build the TLV data
*/
static void
ice_add_dscp_enf_tlv(struct ice_lldp_org_tlv *tlv)
{
u8 *buf = tlv->tlvinfo;
u32 ouisubtype;
u16 typelen;
typelen = ((ICE_TLV_TYPE_ORG << ICE_LLDP_TLV_TYPE_S) |
ICE_DSCP_ENF_TLV_LEN);
tlv->typelen = htons(typelen);
ouisubtype = (u32)((ICE_DSCP_OUI << ICE_LLDP_TLV_OUI_S) |
ICE_DSCP_SUBTYPE_ENFORCE);
tlv->ouisubtype = htonl(ouisubtype);
/* Allow all DSCP values to be valid for all TC's (IPv4 and IPv6) */
memset(buf, 0, 2 * (ICE_MAX_TRAFFIC_CLASS * ICE_BYTES_PER_TC));
}
/**
* ice_add_dscp_tc_bw_tlv - Prepare DSCP BW for TC TLV
* @tlv: location to build the TLV data
* @dcbcfg: location of the data to convert to TLV
*/
static void
ice_add_dscp_tc_bw_tlv(struct ice_lldp_org_tlv *tlv,
struct ice_dcbx_cfg *dcbcfg)
{
struct ice_dcb_ets_cfg *etscfg;
u8 *buf = tlv->tlvinfo;
u32 ouisubtype;
u8 offset = 0;
u16 typelen;
int i;
typelen = ((ICE_TLV_TYPE_ORG << ICE_LLDP_TLV_TYPE_S) |
ICE_DSCP_TC_BW_TLV_LEN);
tlv->typelen = htons(typelen);
ouisubtype = (u32)((ICE_DSCP_OUI << ICE_LLDP_TLV_OUI_S) |
ICE_DSCP_SUBTYPE_TCBW);
tlv->ouisubtype = htonl(ouisubtype);
/* First Octect after subtype
* ----------------------------
* | RSV | CBS | RSV | Max TCs |
* | 1b | 1b | 3b | 3b |
* ----------------------------
*/
etscfg = &dcbcfg->etscfg;
buf[0] = etscfg->maxtcs & ICE_IEEE_ETS_MAXTC_M;
/* bytes 1 - 4 reserved */
offset = 5;
/* TC BW table
* bytes 0 - 7 for TC 0 - 7
*
* TSA Assignment table
* bytes 8 - 15 for TC 0 - 7
*/
for (i = 0; i < ICE_MAX_TRAFFIC_CLASS; i++) {
buf[offset] = etscfg->tcbwtable[i];
buf[offset + ICE_MAX_TRAFFIC_CLASS] = etscfg->tsatable[i];
offset++;
}
}
/**
* ice_add_dscp_pfc_tlv - Prepare DSCP PFC TLV
* @tlv: Fill PFC TLV in IEEE format
* @dcbcfg: Local store which holds the PFC CFG data
*/
static void
ice_add_dscp_pfc_tlv(struct ice_lldp_org_tlv *tlv, struct ice_dcbx_cfg *dcbcfg)
{
u8 *buf = tlv->tlvinfo;
u32 ouisubtype;
u16 typelen;
typelen = ((ICE_TLV_TYPE_ORG << ICE_LLDP_TLV_TYPE_S) |
ICE_DSCP_PFC_TLV_LEN);
tlv->typelen = htons(typelen);
ouisubtype = (u32)((ICE_DSCP_OUI << ICE_LLDP_TLV_OUI_S) |
ICE_DSCP_SUBTYPE_PFC);
tlv->ouisubtype = htonl(ouisubtype);
buf[0] = dcbcfg->pfc.pfccap & 0xF;
buf[1] = dcbcfg->pfc.pfcena & 0xF;
}
/**
* ice_add_dcb_tlv - Add all IEEE or DSCP TLVs
* @tlv: Fill TLV data in IEEE format * @tlv: Fill TLV data in IEEE format
* @dcbcfg: Local store which holds the DCB Config * @dcbcfg: Local store which holds the DCB Config
* @tlvid: Type of IEEE TLV * @tlvid: Type of IEEE TLV
...@@ -1218,21 +1391,41 @@ static void ...@@ -1218,21 +1391,41 @@ static void
ice_add_dcb_tlv(struct ice_lldp_org_tlv *tlv, struct ice_dcbx_cfg *dcbcfg, ice_add_dcb_tlv(struct ice_lldp_org_tlv *tlv, struct ice_dcbx_cfg *dcbcfg,
u16 tlvid) u16 tlvid)
{ {
switch (tlvid) { if (dcbcfg->pfc_mode == ICE_QOS_MODE_VLAN) {
case ICE_IEEE_TLV_ID_ETS_CFG: switch (tlvid) {
ice_add_ieee_ets_tlv(tlv, dcbcfg); case ICE_IEEE_TLV_ID_ETS_CFG:
break; ice_add_ieee_ets_tlv(tlv, dcbcfg);
case ICE_IEEE_TLV_ID_ETS_REC: break;
ice_add_ieee_etsrec_tlv(tlv, dcbcfg); case ICE_IEEE_TLV_ID_ETS_REC:
break; ice_add_ieee_etsrec_tlv(tlv, dcbcfg);
case ICE_IEEE_TLV_ID_PFC_CFG: break;
ice_add_ieee_pfc_tlv(tlv, dcbcfg); case ICE_IEEE_TLV_ID_PFC_CFG:
break; ice_add_ieee_pfc_tlv(tlv, dcbcfg);
case ICE_IEEE_TLV_ID_APP_PRI: break;
ice_add_ieee_app_pri_tlv(tlv, dcbcfg); case ICE_IEEE_TLV_ID_APP_PRI:
break; ice_add_ieee_app_pri_tlv(tlv, dcbcfg);
default: break;
break; default:
break;
}
} else {
/* pfc_mode == ICE_QOS_MODE_DSCP */
switch (tlvid) {
case ICE_TLV_ID_DSCP_UP:
ice_add_dscp_up_tlv(tlv, dcbcfg);
break;
case ICE_TLV_ID_DSCP_ENF:
ice_add_dscp_enf_tlv(tlv);
break;
case ICE_TLV_ID_DSCP_TC_BW:
ice_add_dscp_tc_bw_tlv(tlv, dcbcfg);
break;
case ICE_TLV_ID_DSCP_TO_PFC:
ice_add_dscp_pfc_tlv(tlv, dcbcfg);
break;
default:
break;
}
} }
} }
......
...@@ -22,6 +22,14 @@ ...@@ -22,6 +22,14 @@
#define ICE_CEE_DCBX_OUI 0x001B21 #define ICE_CEE_DCBX_OUI 0x001B21
#define ICE_CEE_DCBX_TYPE 2 #define ICE_CEE_DCBX_TYPE 2
#define ICE_DSCP_OUI 0xFFFFFF
#define ICE_DSCP_SUBTYPE_DSCP2UP 0x41
#define ICE_DSCP_SUBTYPE_ENFORCE 0x42
#define ICE_DSCP_SUBTYPE_TCBW 0x43
#define ICE_DSCP_SUBTYPE_PFC 0x44
#define ICE_DSCP_IPV6_OFFSET 80
#define ICE_CEE_SUBTYPE_PG_CFG 2 #define ICE_CEE_SUBTYPE_PG_CFG 2
#define ICE_CEE_SUBTYPE_PFC_CFG 3 #define ICE_CEE_SUBTYPE_PFC_CFG 3
#define ICE_CEE_SUBTYPE_APP_PRI 4 #define ICE_CEE_SUBTYPE_APP_PRI 4
...@@ -78,11 +86,20 @@ ...@@ -78,11 +86,20 @@
#define ICE_IEEE_TLV_ID_APP_PRI 6 #define ICE_IEEE_TLV_ID_APP_PRI 6
#define ICE_TLV_ID_END_OF_LLDPPDU 7 #define ICE_TLV_ID_END_OF_LLDPPDU 7
#define ICE_TLV_ID_START ICE_IEEE_TLV_ID_ETS_CFG #define ICE_TLV_ID_START ICE_IEEE_TLV_ID_ETS_CFG
#define ICE_TLV_ID_DSCP_UP 3
#define ICE_TLV_ID_DSCP_ENF 4
#define ICE_TLV_ID_DSCP_TC_BW 5
#define ICE_TLV_ID_DSCP_TO_PFC 6
#define ICE_IEEE_ETS_TLV_LEN 25 #define ICE_IEEE_ETS_TLV_LEN 25
#define ICE_IEEE_PFC_TLV_LEN 6 #define ICE_IEEE_PFC_TLV_LEN 6
#define ICE_IEEE_APP_TLV_LEN 11 #define ICE_IEEE_APP_TLV_LEN 11
#define ICE_DSCP_UP_TLV_LEN 148
#define ICE_DSCP_ENF_TLV_LEN 132
#define ICE_DSCP_TC_BW_TLV_LEN 25
#define ICE_DSCP_PFC_TLV_LEN 6
/* IEEE 802.1AB LLDP Organization specific TLV */ /* IEEE 802.1AB LLDP Organization specific TLV */
struct ice_lldp_org_tlv { struct ice_lldp_org_tlv {
__be16 typelen; __be16 typelen;
...@@ -120,6 +137,7 @@ struct ice_cee_app_prio { ...@@ -120,6 +137,7 @@ struct ice_cee_app_prio {
u8 prio_map; u8 prio_map;
} __packed; } __packed;
int ice_aq_set_pfc_mode(struct ice_hw *hw, u8 pfc_mode, struct ice_sq_cd *cd);
enum ice_status enum ice_status
ice_aq_get_dcb_cfg(struct ice_hw *hw, u8 mib_type, u8 bridgetype, ice_aq_get_dcb_cfg(struct ice_hw *hw, u8 mib_type, u8 bridgetype,
struct ice_dcbx_cfg *dcbcfg); struct ice_dcbx_cfg *dcbcfg);
......
...@@ -544,7 +544,7 @@ static int ice_dcb_init_cfg(struct ice_pf *pf, bool locked) ...@@ -544,7 +544,7 @@ static int ice_dcb_init_cfg(struct ice_pf *pf, bool locked)
* @ets_willing: configure ETS willing * @ets_willing: configure ETS willing
* @locked: was this function called with RTNL held * @locked: was this function called with RTNL held
*/ */
static int ice_dcb_sw_dflt_cfg(struct ice_pf *pf, bool ets_willing, bool locked) int ice_dcb_sw_dflt_cfg(struct ice_pf *pf, bool ets_willing, bool locked)
{ {
struct ice_aqc_port_ets_elem buf = { 0 }; struct ice_aqc_port_ets_elem buf = { 0 };
struct ice_dcbx_cfg *dcbcfg; struct ice_dcbx_cfg *dcbcfg;
...@@ -726,6 +726,11 @@ int ice_init_pf_dcb(struct ice_pf *pf, bool locked) ...@@ -726,6 +726,11 @@ int ice_init_pf_dcb(struct ice_pf *pf, bool locked)
/* FW LLDP is disabled, activate SW DCBX/LLDP mode */ /* FW LLDP is disabled, activate SW DCBX/LLDP mode */
dev_info(dev, "FW LLDP is disabled, DCBx/LLDP in SW mode.\n"); dev_info(dev, "FW LLDP is disabled, DCBx/LLDP in SW mode.\n");
clear_bit(ICE_FLAG_FW_LLDP_AGENT, pf->flags); clear_bit(ICE_FLAG_FW_LLDP_AGENT, pf->flags);
err = ice_aq_set_pfc_mode(&pf->hw, ICE_AQC_PFC_VLAN_BASED_PFC,
NULL);
if (err)
dev_info(dev, "Failed to set VLAN PFC mode\n");
err = ice_dcb_sw_dflt_cfg(pf, true, locked); err = ice_dcb_sw_dflt_cfg(pf, true, locked);
if (err) { if (err) {
dev_err(dev, "Failed to set local DCB config %d\n", dev_err(dev, "Failed to set local DCB config %d\n",
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#define ICE_DCB_HW_CHG 2 /* DCB configuration changed, no reset */ #define ICE_DCB_HW_CHG 2 /* DCB configuration changed, no reset */
void ice_dcb_rebuild(struct ice_pf *pf); void ice_dcb_rebuild(struct ice_pf *pf);
int ice_dcb_sw_dflt_cfg(struct ice_pf *pf, bool ets_willing, bool locked);
u8 ice_dcb_get_ena_tc(struct ice_dcbx_cfg *dcbcfg); u8 ice_dcb_get_ena_tc(struct ice_dcbx_cfg *dcbcfg);
u8 ice_dcb_get_num_tc(struct ice_dcbx_cfg *dcbcfg); u8 ice_dcb_get_num_tc(struct ice_dcbx_cfg *dcbcfg);
void ice_vsi_set_dcb_tc_cfg(struct ice_vsi *vsi); void ice_vsi_set_dcb_tc_cfg(struct ice_vsi *vsi);
...@@ -59,6 +60,12 @@ static inline bool ice_is_dcb_active(struct ice_pf *pf) ...@@ -59,6 +60,12 @@ static inline bool ice_is_dcb_active(struct ice_pf *pf)
return (test_bit(ICE_FLAG_FW_LLDP_AGENT, pf->flags) || return (test_bit(ICE_FLAG_FW_LLDP_AGENT, pf->flags) ||
test_bit(ICE_FLAG_DCB_ENA, pf->flags)); test_bit(ICE_FLAG_DCB_ENA, pf->flags));
} }
static inline u8 ice_get_pfc_mode(struct ice_pf *pf)
{
return pf->hw.port_info->qos_cfg.local_dcbx_cfg.pfc_mode;
}
#else #else
static inline void ice_dcb_rebuild(struct ice_pf *pf) { } static inline void ice_dcb_rebuild(struct ice_pf *pf) { }
...@@ -113,6 +120,11 @@ ice_is_pfc_causing_hung_q(struct ice_pf __always_unused *pf, ...@@ -113,6 +120,11 @@ ice_is_pfc_causing_hung_q(struct ice_pf __always_unused *pf,
return false; return false;
} }
static inline u8 ice_get_pfc_mode(struct ice_pf *pf)
{
return 0;
}
static inline void ice_pf_dcb_recfg(struct ice_pf *pf) { } static inline void ice_pf_dcb_recfg(struct ice_pf *pf) { }
static inline void ice_vsi_cfg_dcb_rings(struct ice_vsi *vsi) { } static inline void ice_vsi_cfg_dcb_rings(struct ice_vsi *vsi) { }
static inline void ice_update_dcb_stats(struct ice_pf *pf) { } static inline void ice_update_dcb_stats(struct ice_pf *pf) { }
......
...@@ -64,7 +64,7 @@ static int ice_dcbnl_setets(struct net_device *netdev, struct ieee_ets *ets) ...@@ -64,7 +64,7 @@ static int ice_dcbnl_setets(struct net_device *netdev, struct ieee_ets *ets)
struct ice_pf *pf = ice_netdev_to_pf(netdev); struct ice_pf *pf = ice_netdev_to_pf(netdev);
struct ice_dcbx_cfg *new_cfg; struct ice_dcbx_cfg *new_cfg;
int bwcfg = 0, bwrec = 0; int bwcfg = 0, bwrec = 0;
int err, i, max_tc = 0; int err, i;
if ((pf->dcbx_cap & DCB_CAP_DCBX_LLD_MANAGED) || if ((pf->dcbx_cap & DCB_CAP_DCBX_LLD_MANAGED) ||
!(pf->dcbx_cap & DCB_CAP_DCBX_VER_IEEE)) !(pf->dcbx_cap & DCB_CAP_DCBX_VER_IEEE))
...@@ -80,13 +80,14 @@ static int ice_dcbnl_setets(struct net_device *netdev, struct ieee_ets *ets) ...@@ -80,13 +80,14 @@ static int ice_dcbnl_setets(struct net_device *netdev, struct ieee_ets *ets)
new_cfg->etscfg.tcbwtable[i] = ets->tc_tx_bw[i]; new_cfg->etscfg.tcbwtable[i] = ets->tc_tx_bw[i];
bwcfg += ets->tc_tx_bw[i]; bwcfg += ets->tc_tx_bw[i];
new_cfg->etscfg.tsatable[i] = ets->tc_tsa[i]; new_cfg->etscfg.tsatable[i] = ets->tc_tsa[i];
new_cfg->etscfg.prio_table[i] = ets->prio_tc[i]; if (new_cfg->pfc_mode == ICE_QOS_MODE_VLAN) {
if (ets->prio_tc[i] > max_tc) /* in DSCP mode up->tc mapping cannot change */
max_tc = ets->prio_tc[i]; new_cfg->etscfg.prio_table[i] = ets->prio_tc[i];
new_cfg->etsrec.prio_table[i] = ets->reco_prio_tc[i];
}
new_cfg->etsrec.tcbwtable[i] = ets->tc_reco_bw[i]; new_cfg->etsrec.tcbwtable[i] = ets->tc_reco_bw[i];
bwrec += ets->tc_reco_bw[i]; bwrec += ets->tc_reco_bw[i];
new_cfg->etsrec.tsatable[i] = ets->tc_reco_tsa[i]; new_cfg->etsrec.tsatable[i] = ets->tc_reco_tsa[i];
new_cfg->etsrec.prio_table[i] = ets->reco_prio_tc[i];
} }
if (ice_dcb_bwchk(pf, new_cfg)) { if (ice_dcb_bwchk(pf, new_cfg)) {
...@@ -94,12 +95,7 @@ static int ice_dcbnl_setets(struct net_device *netdev, struct ieee_ets *ets) ...@@ -94,12 +95,7 @@ static int ice_dcbnl_setets(struct net_device *netdev, struct ieee_ets *ets)
goto ets_out; goto ets_out;
} }
max_tc = pf->hw.func_caps.common_cap.maxtc; new_cfg->etscfg.maxtcs = pf->hw.func_caps.common_cap.maxtc;
new_cfg->etscfg.maxtcs = max_tc;
if (!bwcfg)
new_cfg->etscfg.tcbwtable[0] = 100;
if (!bwrec) if (!bwrec)
new_cfg->etsrec.tcbwtable[0] = 100; new_cfg->etsrec.tcbwtable[0] = 100;
...@@ -173,10 +169,13 @@ static u8 ice_dcbnl_setdcbx(struct net_device *netdev, u8 mode) ...@@ -173,10 +169,13 @@ static u8 ice_dcbnl_setdcbx(struct net_device *netdev, u8 mode)
pf->dcbx_cap = mode; pf->dcbx_cap = mode;
qos_cfg = &pf->hw.port_info->qos_cfg; qos_cfg = &pf->hw.port_info->qos_cfg;
if (mode & DCB_CAP_DCBX_VER_CEE) if (mode & DCB_CAP_DCBX_VER_CEE) {
if (qos_cfg->local_dcbx_cfg.pfc_mode == ICE_QOS_MODE_DSCP)
return ICE_DCB_NO_HW_CHG;
qos_cfg->local_dcbx_cfg.dcbx_mode = ICE_DCBX_MODE_CEE; qos_cfg->local_dcbx_cfg.dcbx_mode = ICE_DCBX_MODE_CEE;
else } else {
qos_cfg->local_dcbx_cfg.dcbx_mode = ICE_DCBX_MODE_IEEE; qos_cfg->local_dcbx_cfg.dcbx_mode = ICE_DCBX_MODE_IEEE;
}
dev_info(ice_pf_to_dev(pf), "DCBx mode = 0x%x\n", mode); dev_info(ice_pf_to_dev(pf), "DCBx mode = 0x%x\n", mode);
return ICE_DCB_HW_CHG_RST; return ICE_DCB_HW_CHG_RST;
...@@ -683,6 +682,8 @@ ice_dcbnl_find_app(struct ice_dcbx_cfg *cfg, ...@@ -683,6 +682,8 @@ ice_dcbnl_find_app(struct ice_dcbx_cfg *cfg,
return false; return false;
} }
#define ICE_BYTES_PER_DSCP_VAL 8
/** /**
* ice_dcbnl_setapp - set local IEEE App config * ice_dcbnl_setapp - set local IEEE App config
* @netdev: relevant netdev struct * @netdev: relevant netdev struct
...@@ -693,42 +694,117 @@ static int ice_dcbnl_setapp(struct net_device *netdev, struct dcb_app *app) ...@@ -693,42 +694,117 @@ static int ice_dcbnl_setapp(struct net_device *netdev, struct dcb_app *app)
struct ice_pf *pf = ice_netdev_to_pf(netdev); struct ice_pf *pf = ice_netdev_to_pf(netdev);
struct ice_dcb_app_priority_table new_app; struct ice_dcb_app_priority_table new_app;
struct ice_dcbx_cfg *old_cfg, *new_cfg; struct ice_dcbx_cfg *old_cfg, *new_cfg;
u8 max_tc;
int ret; int ret;
if ((pf->dcbx_cap & DCB_CAP_DCBX_LLD_MANAGED) || /* ONLY DSCP APP TLVs have operational significance */
!(pf->dcbx_cap & DCB_CAP_DCBX_VER_IEEE)) if (app->selector != IEEE_8021QAZ_APP_SEL_DSCP)
return -EINVAL; return -EINVAL;
mutex_lock(&pf->tc_mutex); /* only allow APP TLVs in SW Mode */
if (pf->dcbx_cap & DCB_CAP_DCBX_LLD_MANAGED) {
netdev_err(netdev, "can't do DSCP QoS when FW DCB agent active\n");
return -EINVAL;
}
new_cfg = &pf->hw.port_info->qos_cfg.desired_dcbx_cfg; if (!(pf->dcbx_cap & DCB_CAP_DCBX_VER_IEEE))
return -EINVAL;
old_cfg = &pf->hw.port_info->qos_cfg.local_dcbx_cfg; if (!ice_is_feature_supported(pf, ICE_F_DSCP))
return -EOPNOTSUPP;
if (old_cfg->numapps == ICE_DCBX_MAX_APPS) { if (app->protocol >= ICE_DSCP_NUM_VAL) {
ret = -EINVAL; netdev_err(netdev, "DSCP value 0x%04X out of range\n",
goto setapp_out; app->protocol);
return -EINVAL;
}
max_tc = pf->hw.func_caps.common_cap.maxtc;
if (app->priority >= max_tc) {
netdev_err(netdev, "TC %d out of range, max TC %d\n",
app->priority, max_tc);
return -EINVAL;
} }
/* grab TC mutex */
mutex_lock(&pf->tc_mutex);
new_cfg = &pf->hw.port_info->qos_cfg.desired_dcbx_cfg;
old_cfg = &pf->hw.port_info->qos_cfg.local_dcbx_cfg;
ret = dcb_ieee_setapp(netdev, app); ret = dcb_ieee_setapp(netdev, app);
if (ret) if (ret)
goto setapp_out; goto setapp_out;
if (test_and_set_bit(app->protocol, new_cfg->dscp_mapped)) {
netdev_err(netdev, "DSCP value 0x%04X already user mapped\n",
app->protocol);
ret = dcb_ieee_delapp(netdev, app);
if (ret)
netdev_err(netdev, "Failed to delete re-mapping TLV\n");
ret = -EINVAL;
goto setapp_out;
}
new_app.selector = app->selector; new_app.selector = app->selector;
new_app.prot_id = app->protocol; new_app.prot_id = app->protocol;
new_app.priority = app->priority; new_app.priority = app->priority;
if (ice_dcbnl_find_app(old_cfg, &new_app)) {
ret = 0;
goto setapp_out;
}
/* If port is not in DSCP mode, need to set */
if (old_cfg->pfc_mode == ICE_QOS_MODE_VLAN) {
int i, j;
/* set DSCP mode */
ret = ice_aq_set_pfc_mode(&pf->hw, ICE_AQC_PFC_DSCP_BASED_PFC,
NULL);
if (ret) {
netdev_err(netdev, "Failed to set DSCP PFC mode %d\n",
ret);
goto setapp_out;
}
netdev_info(netdev, "Switched QoS to L3 DSCP mode\n");
new_cfg->pfc_mode = ICE_QOS_MODE_DSCP;
/* set default DSCP QoS values */
new_cfg->etscfg.willing = 0;
new_cfg->pfc.pfccap = max_tc;
new_cfg->pfc.willing = 0;
for (i = 0; i < max_tc; i++)
for (j = 0; j < ICE_BYTES_PER_DSCP_VAL; j++) {
int dscp, offset;
dscp = (i * max_tc) + j;
offset = max_tc * ICE_BYTES_PER_DSCP_VAL;
new_cfg->dscp_map[dscp] = i;
/* if less that 8 TCs supported */
if (max_tc < ICE_MAX_TRAFFIC_CLASS)
new_cfg->dscp_map[dscp + offset] = i;
}
new_cfg->etscfg.tcbwtable[0] = 100;
new_cfg->etscfg.tsatable[0] = ICE_IEEE_TSA_ETS;
new_cfg->etscfg.prio_table[0] = 0;
for (i = 1; i < max_tc; i++) {
new_cfg->etscfg.tcbwtable[i] = 0;
new_cfg->etscfg.tsatable[i] = ICE_IEEE_TSA_ETS;
new_cfg->etscfg.prio_table[i] = i;
}
} /* end of switching to DSCP mode */
/* apply new mapping for this DSCP value */
new_cfg->dscp_map[app->protocol] = app->priority;
new_cfg->app[new_cfg->numapps++] = new_app; new_cfg->app[new_cfg->numapps++] = new_app;
ret = ice_pf_dcb_cfg(pf, new_cfg, true); ret = ice_pf_dcb_cfg(pf, new_cfg, true);
/* return of zero indicates new cfg applied */ /* return of zero indicates new cfg applied */
if (ret == ICE_DCB_HW_CHG_RST) if (ret == ICE_DCB_HW_CHG_RST)
ice_dcbnl_devreset(netdev); ice_dcbnl_devreset(netdev);
if (ret == ICE_DCB_NO_HW_CHG) else
ret = ICE_DCB_HW_CHG_RST; ret = ICE_DCB_NO_HW_CHG;
setapp_out: setapp_out:
mutex_unlock(&pf->tc_mutex); mutex_unlock(&pf->tc_mutex);
...@@ -749,22 +825,21 @@ static int ice_dcbnl_delapp(struct net_device *netdev, struct dcb_app *app) ...@@ -749,22 +825,21 @@ static int ice_dcbnl_delapp(struct net_device *netdev, struct dcb_app *app)
unsigned int i, j; unsigned int i, j;
int ret = 0; int ret = 0;
if (pf->dcbx_cap & DCB_CAP_DCBX_LLD_MANAGED) if (pf->dcbx_cap & DCB_CAP_DCBX_LLD_MANAGED) {
netdev_err(netdev, "can't delete DSCP netlink app when FW DCB agent is active\n");
return -EINVAL; return -EINVAL;
}
mutex_lock(&pf->tc_mutex); mutex_lock(&pf->tc_mutex);
old_cfg = &pf->hw.port_info->qos_cfg.local_dcbx_cfg; old_cfg = &pf->hw.port_info->qos_cfg.local_dcbx_cfg;
if (old_cfg->numapps <= 1)
goto delapp_out;
ret = dcb_ieee_delapp(netdev, app); ret = dcb_ieee_delapp(netdev, app);
if (ret) if (ret)
goto delapp_out; goto delapp_out;
new_cfg = &pf->hw.port_info->qos_cfg.desired_dcbx_cfg; new_cfg = &pf->hw.port_info->qos_cfg.desired_dcbx_cfg;
for (i = 1; i < new_cfg->numapps; i++) { for (i = 0; i < new_cfg->numapps; i++) {
if (app->selector == new_cfg->app[i].selector && if (app->selector == new_cfg->app[i].selector &&
app->protocol == new_cfg->app[i].prot_id && app->protocol == new_cfg->app[i].prot_id &&
app->priority == new_cfg->app[i].priority) { app->priority == new_cfg->app[i].priority) {
...@@ -784,17 +859,58 @@ static int ice_dcbnl_delapp(struct net_device *netdev, struct dcb_app *app) ...@@ -784,17 +859,58 @@ static int ice_dcbnl_delapp(struct net_device *netdev, struct dcb_app *app)
new_cfg->numapps--; new_cfg->numapps--;
for (j = i; j < new_cfg->numapps; j++) { for (j = i; j < new_cfg->numapps; j++) {
new_cfg->app[i].selector = old_cfg->app[j + 1].selector; new_cfg->app[j].selector = old_cfg->app[j + 1].selector;
new_cfg->app[i].prot_id = old_cfg->app[j + 1].prot_id; new_cfg->app[j].prot_id = old_cfg->app[j + 1].prot_id;
new_cfg->app[i].priority = old_cfg->app[j + 1].priority; new_cfg->app[j].priority = old_cfg->app[j + 1].priority;
} }
ret = ice_pf_dcb_cfg(pf, new_cfg, true); /* if not a DSCP APP TLV or DSCP is not supported, we are done */
/* return of zero indicates new cfg applied */ if (app->selector != IEEE_8021QAZ_APP_SEL_DSCP ||
!ice_is_feature_supported(pf, ICE_F_DSCP)) {
ret = ICE_DCB_HW_CHG;
goto delapp_out;
}
/* if DSCP TLV, then need to address change in mapping */
clear_bit(app->protocol, new_cfg->dscp_mapped);
/* remap this DSCP value to default value */
new_cfg->dscp_map[app->protocol] = app->protocol %
ICE_BYTES_PER_DSCP_VAL;
/* if the last DSCP mapping just got deleted, need to switch
* to L2 VLAN QoS mode
*/
if (bitmap_empty(new_cfg->dscp_mapped, ICE_DSCP_NUM_VAL) &&
new_cfg->pfc_mode == ICE_QOS_MODE_DSCP) {
ret = ice_aq_set_pfc_mode(&pf->hw,
ICE_AQC_PFC_VLAN_BASED_PFC,
NULL);
if (ret) {
netdev_info(netdev, "Failed to set VLAN PFC mode %d\n",
ret);
goto delapp_out;
}
netdev_info(netdev, "Switched QoS to L2 VLAN mode\n");
new_cfg->pfc_mode = ICE_QOS_MODE_VLAN;
ret = ice_dcb_sw_dflt_cfg(pf, true, true);
} else {
ret = ice_pf_dcb_cfg(pf, new_cfg, true);
}
/* return of ICE_DCB_HW_CHG_RST indicates new cfg applied
* and reset needs to be performed
*/
if (ret == ICE_DCB_HW_CHG_RST) if (ret == ICE_DCB_HW_CHG_RST)
ice_dcbnl_devreset(netdev); ice_dcbnl_devreset(netdev);
/* if the change was not siginificant enough to actually call
* the reconfiguration flow, we still need to tell caller that
* their request was successfully handled
*/
if (ret == ICE_DCB_NO_HW_CHG) if (ret == ICE_DCB_NO_HW_CHG)
ret = ICE_DCB_HW_CHG_RST; ret = ICE_DCB_HW_CHG;
delapp_out: delapp_out:
mutex_unlock(&pf->tc_mutex); mutex_unlock(&pf->tc_mutex);
......
...@@ -22,7 +22,7 @@ struct ice_info_ctx { ...@@ -22,7 +22,7 @@ struct ice_info_ctx {
* *
* If a version does not exist, for example when attempting to get the * If a version does not exist, for example when attempting to get the
* inactive version of flash when there is no pending update, the function * inactive version of flash when there is no pending update, the function
* should leave the buffer in the ctx structure empty and return 0. * should leave the buffer in the ctx structure empty.
*/ */
static void ice_info_get_dsn(struct ice_pf *pf, struct ice_info_ctx *ctx) static void ice_info_get_dsn(struct ice_pf *pf, struct ice_info_ctx *ctx)
...@@ -35,7 +35,7 @@ static void ice_info_get_dsn(struct ice_pf *pf, struct ice_info_ctx *ctx) ...@@ -35,7 +35,7 @@ static void ice_info_get_dsn(struct ice_pf *pf, struct ice_info_ctx *ctx)
snprintf(ctx->buf, sizeof(ctx->buf), "%8phD", dsn); snprintf(ctx->buf, sizeof(ctx->buf), "%8phD", dsn);
} }
static int ice_info_pba(struct ice_pf *pf, struct ice_info_ctx *ctx) static void ice_info_pba(struct ice_pf *pf, struct ice_info_ctx *ctx)
{ {
struct ice_hw *hw = &pf->hw; struct ice_hw *hw = &pf->hw;
enum ice_status status; enum ice_status status;
...@@ -45,148 +45,127 @@ static int ice_info_pba(struct ice_pf *pf, struct ice_info_ctx *ctx) ...@@ -45,148 +45,127 @@ static int ice_info_pba(struct ice_pf *pf, struct ice_info_ctx *ctx)
/* We failed to locate the PBA, so just skip this entry */ /* We failed to locate the PBA, so just skip this entry */
dev_dbg(ice_pf_to_dev(pf), "Failed to read Product Board Assembly string, status %s\n", dev_dbg(ice_pf_to_dev(pf), "Failed to read Product Board Assembly string, status %s\n",
ice_stat_str(status)); ice_stat_str(status));
return 0;
} }
static int ice_info_fw_mgmt(struct ice_pf *pf, struct ice_info_ctx *ctx) static void ice_info_fw_mgmt(struct ice_pf *pf, struct ice_info_ctx *ctx)
{ {
struct ice_hw *hw = &pf->hw; struct ice_hw *hw = &pf->hw;
snprintf(ctx->buf, sizeof(ctx->buf), "%u.%u.%u", hw->fw_maj_ver, hw->fw_min_ver, snprintf(ctx->buf, sizeof(ctx->buf), "%u.%u.%u",
hw->fw_patch); hw->fw_maj_ver, hw->fw_min_ver, hw->fw_patch);
return 0;
} }
static int ice_info_fw_api(struct ice_pf *pf, struct ice_info_ctx *ctx) static void ice_info_fw_api(struct ice_pf *pf, struct ice_info_ctx *ctx)
{ {
struct ice_hw *hw = &pf->hw; struct ice_hw *hw = &pf->hw;
snprintf(ctx->buf, sizeof(ctx->buf), "%u.%u", hw->api_maj_ver, hw->api_min_ver); snprintf(ctx->buf, sizeof(ctx->buf), "%u.%u",
hw->api_maj_ver, hw->api_min_ver);
return 0;
} }
static int ice_info_fw_build(struct ice_pf *pf, struct ice_info_ctx *ctx) static void ice_info_fw_build(struct ice_pf *pf, struct ice_info_ctx *ctx)
{ {
struct ice_hw *hw = &pf->hw; struct ice_hw *hw = &pf->hw;
snprintf(ctx->buf, sizeof(ctx->buf), "0x%08x", hw->fw_build); snprintf(ctx->buf, sizeof(ctx->buf), "0x%08x", hw->fw_build);
return 0;
} }
static int ice_info_orom_ver(struct ice_pf *pf, struct ice_info_ctx *ctx) static void ice_info_orom_ver(struct ice_pf *pf, struct ice_info_ctx *ctx)
{ {
struct ice_orom_info *orom = &pf->hw.flash.orom; struct ice_orom_info *orom = &pf->hw.flash.orom;
snprintf(ctx->buf, sizeof(ctx->buf), "%u.%u.%u", orom->major, orom->build, orom->patch); snprintf(ctx->buf, sizeof(ctx->buf), "%u.%u.%u",
orom->major, orom->build, orom->patch);
return 0;
} }
static int static void
ice_info_pending_orom_ver(struct ice_pf __always_unused *pf, struct ice_info_ctx *ctx) ice_info_pending_orom_ver(struct ice_pf __always_unused *pf,
struct ice_info_ctx *ctx)
{ {
struct ice_orom_info *orom = &ctx->pending_orom; struct ice_orom_info *orom = &ctx->pending_orom;
if (ctx->dev_caps.common_cap.nvm_update_pending_orom) if (ctx->dev_caps.common_cap.nvm_update_pending_orom)
snprintf(ctx->buf, sizeof(ctx->buf), "%u.%u.%u", snprintf(ctx->buf, sizeof(ctx->buf), "%u.%u.%u",
orom->major, orom->build, orom->patch); orom->major, orom->build, orom->patch);
return 0;
} }
static int ice_info_nvm_ver(struct ice_pf *pf, struct ice_info_ctx *ctx) static void ice_info_nvm_ver(struct ice_pf *pf, struct ice_info_ctx *ctx)
{ {
struct ice_nvm_info *nvm = &pf->hw.flash.nvm; struct ice_nvm_info *nvm = &pf->hw.flash.nvm;
snprintf(ctx->buf, sizeof(ctx->buf), "%x.%02x", nvm->major, nvm->minor); snprintf(ctx->buf, sizeof(ctx->buf), "%x.%02x", nvm->major, nvm->minor);
return 0;
} }
static int static void
ice_info_pending_nvm_ver(struct ice_pf __always_unused *pf, struct ice_info_ctx *ctx) ice_info_pending_nvm_ver(struct ice_pf __always_unused *pf,
struct ice_info_ctx *ctx)
{ {
struct ice_nvm_info *nvm = &ctx->pending_nvm; struct ice_nvm_info *nvm = &ctx->pending_nvm;
if (ctx->dev_caps.common_cap.nvm_update_pending_nvm) if (ctx->dev_caps.common_cap.nvm_update_pending_nvm)
snprintf(ctx->buf, sizeof(ctx->buf), "%x.%02x", nvm->major, nvm->minor); snprintf(ctx->buf, sizeof(ctx->buf), "%x.%02x",
nvm->major, nvm->minor);
return 0;
} }
static int ice_info_eetrack(struct ice_pf *pf, struct ice_info_ctx *ctx) static void ice_info_eetrack(struct ice_pf *pf, struct ice_info_ctx *ctx)
{ {
struct ice_nvm_info *nvm = &pf->hw.flash.nvm; struct ice_nvm_info *nvm = &pf->hw.flash.nvm;
snprintf(ctx->buf, sizeof(ctx->buf), "0x%08x", nvm->eetrack); snprintf(ctx->buf, sizeof(ctx->buf), "0x%08x", nvm->eetrack);
return 0;
} }
static int static void
ice_info_pending_eetrack(struct ice_pf __always_unused *pf, struct ice_info_ctx *ctx) ice_info_pending_eetrack(struct ice_pf *pf, struct ice_info_ctx *ctx)
{ {
struct ice_nvm_info *nvm = &ctx->pending_nvm; struct ice_nvm_info *nvm = &ctx->pending_nvm;
if (ctx->dev_caps.common_cap.nvm_update_pending_nvm) if (ctx->dev_caps.common_cap.nvm_update_pending_nvm)
snprintf(ctx->buf, sizeof(ctx->buf), "0x%08x", nvm->eetrack); snprintf(ctx->buf, sizeof(ctx->buf), "0x%08x", nvm->eetrack);
return 0;
} }
static int ice_info_ddp_pkg_name(struct ice_pf *pf, struct ice_info_ctx *ctx) static void ice_info_ddp_pkg_name(struct ice_pf *pf, struct ice_info_ctx *ctx)
{ {
struct ice_hw *hw = &pf->hw; struct ice_hw *hw = &pf->hw;
snprintf(ctx->buf, sizeof(ctx->buf), "%s", hw->active_pkg_name); snprintf(ctx->buf, sizeof(ctx->buf), "%s", hw->active_pkg_name);
return 0;
} }
static int ice_info_ddp_pkg_version(struct ice_pf *pf, struct ice_info_ctx *ctx) static void
ice_info_ddp_pkg_version(struct ice_pf *pf, struct ice_info_ctx *ctx)
{ {
struct ice_pkg_ver *pkg = &pf->hw.active_pkg_ver; struct ice_pkg_ver *pkg = &pf->hw.active_pkg_ver;
snprintf(ctx->buf, sizeof(ctx->buf), "%u.%u.%u.%u", pkg->major, pkg->minor, pkg->update, snprintf(ctx->buf, sizeof(ctx->buf), "%u.%u.%u.%u",
pkg->draft); pkg->major, pkg->minor, pkg->update, pkg->draft);
return 0;
} }
static int ice_info_ddp_pkg_bundle_id(struct ice_pf *pf, struct ice_info_ctx *ctx) static void
ice_info_ddp_pkg_bundle_id(struct ice_pf *pf, struct ice_info_ctx *ctx)
{ {
snprintf(ctx->buf, sizeof(ctx->buf), "0x%08x", pf->hw.active_track_id); snprintf(ctx->buf, sizeof(ctx->buf), "0x%08x", pf->hw.active_track_id);
return 0;
} }
static int ice_info_netlist_ver(struct ice_pf *pf, struct ice_info_ctx *ctx) static void ice_info_netlist_ver(struct ice_pf *pf, struct ice_info_ctx *ctx)
{ {
struct ice_netlist_info *netlist = &pf->hw.flash.netlist; struct ice_netlist_info *netlist = &pf->hw.flash.netlist;
/* The netlist version fields are BCD formatted */ /* The netlist version fields are BCD formatted */
snprintf(ctx->buf, sizeof(ctx->buf), "%x.%x.%x-%x.%x.%x", netlist->major, netlist->minor, snprintf(ctx->buf, sizeof(ctx->buf), "%x.%x.%x-%x.%x.%x",
netlist->type >> 16, netlist->type & 0xFFFF, netlist->rev, netlist->major, netlist->minor,
netlist->cust_ver); netlist->type >> 16, netlist->type & 0xFFFF,
netlist->rev, netlist->cust_ver);
return 0;
} }
static int ice_info_netlist_build(struct ice_pf *pf, struct ice_info_ctx *ctx) static void ice_info_netlist_build(struct ice_pf *pf, struct ice_info_ctx *ctx)
{ {
struct ice_netlist_info *netlist = &pf->hw.flash.netlist; struct ice_netlist_info *netlist = &pf->hw.flash.netlist;
snprintf(ctx->buf, sizeof(ctx->buf), "0x%08x", netlist->hash); snprintf(ctx->buf, sizeof(ctx->buf), "0x%08x", netlist->hash);
return 0;
} }
static int static void
ice_info_pending_netlist_ver(struct ice_pf __always_unused *pf, struct ice_info_ctx *ctx) ice_info_pending_netlist_ver(struct ice_pf __always_unused *pf,
struct ice_info_ctx *ctx)
{ {
struct ice_netlist_info *netlist = &ctx->pending_netlist; struct ice_netlist_info *netlist = &ctx->pending_netlist;
...@@ -194,21 +173,18 @@ ice_info_pending_netlist_ver(struct ice_pf __always_unused *pf, struct ice_info_ ...@@ -194,21 +173,18 @@ ice_info_pending_netlist_ver(struct ice_pf __always_unused *pf, struct ice_info_
if (ctx->dev_caps.common_cap.nvm_update_pending_netlist) if (ctx->dev_caps.common_cap.nvm_update_pending_netlist)
snprintf(ctx->buf, sizeof(ctx->buf), "%x.%x.%x-%x.%x.%x", snprintf(ctx->buf, sizeof(ctx->buf), "%x.%x.%x-%x.%x.%x",
netlist->major, netlist->minor, netlist->major, netlist->minor,
netlist->type >> 16, netlist->type & 0xFFFF, netlist->rev, netlist->type >> 16, netlist->type & 0xFFFF,
netlist->cust_ver); netlist->rev, netlist->cust_ver);
return 0;
} }
static int static void
ice_info_pending_netlist_build(struct ice_pf __always_unused *pf, struct ice_info_ctx *ctx) ice_info_pending_netlist_build(struct ice_pf __always_unused *pf,
struct ice_info_ctx *ctx)
{ {
struct ice_netlist_info *netlist = &ctx->pending_netlist; struct ice_netlist_info *netlist = &ctx->pending_netlist;
if (ctx->dev_caps.common_cap.nvm_update_pending_netlist) if (ctx->dev_caps.common_cap.nvm_update_pending_netlist)
snprintf(ctx->buf, sizeof(ctx->buf), "0x%08x", netlist->hash); snprintf(ctx->buf, sizeof(ctx->buf), "0x%08x", netlist->hash);
return 0;
} }
#define fixed(key, getter) { ICE_VERSION_FIXED, key, getter, NULL } #define fixed(key, getter) { ICE_VERSION_FIXED, key, getter, NULL }
...@@ -238,8 +214,8 @@ enum ice_version_type { ...@@ -238,8 +214,8 @@ enum ice_version_type {
static const struct ice_devlink_version { static const struct ice_devlink_version {
enum ice_version_type type; enum ice_version_type type;
const char *key; const char *key;
int (*getter)(struct ice_pf *pf, struct ice_info_ctx *ctx); void (*getter)(struct ice_pf *pf, struct ice_info_ctx *ctx);
int (*fallback)(struct ice_pf *pf, struct ice_info_ctx *ctx); void (*fallback)(struct ice_pf *pf, struct ice_info_ctx *ctx);
} ice_devlink_versions[] = { } ice_devlink_versions[] = {
fixed(DEVLINK_INFO_VERSION_GENERIC_BOARD_ID, ice_info_pba), fixed(DEVLINK_INFO_VERSION_GENERIC_BOARD_ID, ice_info_pba),
running(DEVLINK_INFO_VERSION_GENERIC_FW_MGMT, ice_info_fw_mgmt), running(DEVLINK_INFO_VERSION_GENERIC_FW_MGMT, ice_info_fw_mgmt),
...@@ -351,24 +327,15 @@ static int ice_devlink_info_get(struct devlink *devlink, ...@@ -351,24 +327,15 @@ static int ice_devlink_info_get(struct devlink *devlink,
memset(ctx->buf, 0, sizeof(ctx->buf)); memset(ctx->buf, 0, sizeof(ctx->buf));
err = ice_devlink_versions[i].getter(pf, ctx); ice_devlink_versions[i].getter(pf, ctx);
if (err) {
NL_SET_ERR_MSG_MOD(extack, "Unable to obtain version info");
goto out_free_ctx;
}
/* If the default getter doesn't report a version, use the /* If the default getter doesn't report a version, use the
* fallback function. This is primarily useful in the case of * fallback function. This is primarily useful in the case of
* "stored" versions that want to report the same value as the * "stored" versions that want to report the same value as the
* running version in the normal case of no pending update. * running version in the normal case of no pending update.
*/ */
if (ctx->buf[0] == '\0' && ice_devlink_versions[i].fallback) { if (ctx->buf[0] == '\0' && ice_devlink_versions[i].fallback)
err = ice_devlink_versions[i].fallback(pf, ctx); ice_devlink_versions[i].fallback(pf, ctx);
if (err) {
NL_SET_ERR_MSG_MOD(extack, "Unable to obtain version info");
goto out_free_ctx;
}
}
/* Do not report missing versions */ /* Do not report missing versions */
if (ctx->buf[0] == '\0') if (ctx->buf[0] == '\0')
......
...@@ -1215,6 +1215,13 @@ static int ice_set_priv_flags(struct net_device *netdev, u32 flags) ...@@ -1215,6 +1215,13 @@ static int ice_set_priv_flags(struct net_device *netdev, u32 flags)
enum ice_status status; enum ice_status status;
bool dcbx_agent_status; bool dcbx_agent_status;
if (ice_get_pfc_mode(pf) == ICE_QOS_MODE_DSCP) {
clear_bit(ICE_FLAG_FW_LLDP_AGENT, pf->flags);
dev_err(dev, "QoS in L3 DSCP mode, FW Agent not allowed to start\n");
ret = -EOPNOTSUPP;
goto ethtool_exit;
}
/* Remove rule to direct LLDP packets to default VSI. /* Remove rule to direct LLDP packets to default VSI.
* The FW LLDP engine will now be consuming them. * The FW LLDP engine will now be consuming them.
*/ */
......
...@@ -952,7 +952,7 @@ ice_fdir_get_gen_prgm_pkt(struct ice_hw *hw, struct ice_fdir_fltr *input, ...@@ -952,7 +952,7 @@ ice_fdir_get_gen_prgm_pkt(struct ice_hw *hw, struct ice_fdir_fltr *input,
ice_pkt_insert_u8(loc, ICE_IPV4_TTL_OFFSET, input->ip.v4.ttl); ice_pkt_insert_u8(loc, ICE_IPV4_TTL_OFFSET, input->ip.v4.ttl);
ice_pkt_insert_mac_addr(loc, input->ext_data.dst_mac); ice_pkt_insert_mac_addr(loc, input->ext_data.dst_mac);
if (frag) if (frag)
loc[20] = ICE_FDIR_IPV4_PKT_FLAG_DF; loc[20] = ICE_FDIR_IPV4_PKT_FLAG_MF;
break; break;
case ICE_FLTR_PTYPE_NONF_IPV4_UDP: case ICE_FLTR_PTYPE_NONF_IPV4_UDP:
ice_pkt_insert_u32(loc, ICE_IPV4_DST_ADDR_OFFSET, ice_pkt_insert_u32(loc, ICE_IPV4_DST_ADDR_OFFSET,
......
...@@ -48,7 +48,7 @@ ...@@ -48,7 +48,7 @@
* requests that the packet not be fragmented. MF indicates that a packet has * requests that the packet not be fragmented. MF indicates that a packet has
* been fragmented. * been fragmented.
*/ */
#define ICE_FDIR_IPV4_PKT_FLAG_DF 0x20 #define ICE_FDIR_IPV4_PKT_FLAG_MF 0x20
enum ice_fltr_prgm_desc_dest { enum ice_fltr_prgm_desc_dest {
ICE_FLTR_PRGM_DESC_DEST_DROP_PKT, ICE_FLTR_PRGM_DESC_DEST_DROP_PKT,
......
...@@ -3573,3 +3573,50 @@ int ice_set_link(struct ice_vsi *vsi, bool ena) ...@@ -3573,3 +3573,50 @@ int ice_set_link(struct ice_vsi *vsi, bool ena)
return 0; return 0;
} }
/**
* ice_is_feature_supported
* @pf: pointer to the struct ice_pf instance
* @f: feature enum to be checked
*
* returns true if feature is supported, false otherwise
*/
bool ice_is_feature_supported(struct ice_pf *pf, enum ice_feature f)
{
if (f < 0 || f >= ICE_F_MAX)
return false;
return test_bit(f, pf->features);
}
/**
* ice_set_feature_support
* @pf: pointer to the struct ice_pf instance
* @f: feature enum to set
*/
static void ice_set_feature_support(struct ice_pf *pf, enum ice_feature f)
{
if (f < 0 || f >= ICE_F_MAX)
return;
set_bit(f, pf->features);
}
/**
* ice_init_feature_support
* @pf: pointer to the struct ice_pf instance
*
* called during init to setup supported feature
*/
void ice_init_feature_support(struct ice_pf *pf)
{
switch (pf->hw.device_id) {
case ICE_DEV_ID_E810C_BACKPLANE:
case ICE_DEV_ID_E810C_QSFP:
case ICE_DEV_ID_E810C_SFP:
ice_set_feature_support(pf, ICE_F_DSCP);
break;
default:
break;
}
}
...@@ -116,4 +116,6 @@ bool ice_is_vsi_dflt_vsi(struct ice_sw *sw, struct ice_vsi *vsi); ...@@ -116,4 +116,6 @@ bool ice_is_vsi_dflt_vsi(struct ice_sw *sw, struct ice_vsi *vsi);
int ice_set_dflt_vsi(struct ice_sw *sw, struct ice_vsi *vsi); int ice_set_dflt_vsi(struct ice_sw *sw, struct ice_vsi *vsi);
int ice_clear_dflt_vsi(struct ice_sw *sw); int ice_clear_dflt_vsi(struct ice_sw *sw);
bool ice_is_feature_supported(struct ice_pf *pf, enum ice_feature f);
void ice_init_feature_support(struct ice_pf *pf);
#endif /* !_ICE_LIB_H_ */ #endif /* !_ICE_LIB_H_ */
...@@ -624,7 +624,10 @@ static void ice_print_topo_conflict(struct ice_vsi *vsi) ...@@ -624,7 +624,10 @@ static void ice_print_topo_conflict(struct ice_vsi *vsi)
netdev_info(vsi->netdev, "Potential misconfiguration of the Ethernet port detected. If it was not intended, please use the Intel (R) Ethernet Port Configuration Tool to address the issue.\n"); netdev_info(vsi->netdev, "Potential misconfiguration of the Ethernet port detected. If it was not intended, please use the Intel (R) Ethernet Port Configuration Tool to address the issue.\n");
break; break;
case ICE_AQ_LINK_TOPO_UNSUPP_MEDIA: case ICE_AQ_LINK_TOPO_UNSUPP_MEDIA:
netdev_info(vsi->netdev, "Rx/Tx is disabled on this device because an unsupported module type was detected. Refer to the Intel(R) Ethernet Adapters and Devices User Guide for a list of supported modules.\n"); if (test_bit(ICE_FLAG_LINK_LENIENT_MODE_ENA, vsi->back->flags))
netdev_warn(vsi->netdev, "An unsupported module type was detected. Refer to the Intel(R) Ethernet Adapters and Devices User Guide for a list of supported modules\n");
else
netdev_err(vsi->netdev, "Rx/Tx is disabled on this device because an unsupported module type was detected. Refer to the Intel(R) Ethernet Adapters and Devices User Guide for a list of supported modules.\n");
break; break;
default: default:
break; break;
...@@ -1965,7 +1968,8 @@ static int ice_configure_phy(struct ice_vsi *vsi) ...@@ -1965,7 +1968,8 @@ static int ice_configure_phy(struct ice_vsi *vsi)
ice_print_topo_conflict(vsi); ice_print_topo_conflict(vsi);
if (phy->link_info.topo_media_conflict == ICE_AQ_LINK_TOPO_UNSUPP_MEDIA) if (!test_bit(ICE_FLAG_LINK_LENIENT_MODE_ENA, pf->flags) &&
phy->link_info.topo_media_conflict == ICE_AQ_LINK_TOPO_UNSUPP_MEDIA)
return -EPERM; return -EPERM;
if (test_bit(ICE_FLAG_LINK_DOWN_ON_CLOSE_ENA, pf->flags)) if (test_bit(ICE_FLAG_LINK_DOWN_ON_CLOSE_ENA, pf->flags))
...@@ -4270,6 +4274,8 @@ ice_probe(struct pci_dev *pdev, const struct pci_device_id __always_unused *ent) ...@@ -4270,6 +4274,8 @@ ice_probe(struct pci_dev *pdev, const struct pci_device_id __always_unused *ent)
goto err_exit_unroll; goto err_exit_unroll;
} }
ice_init_feature_support(pf);
ice_request_fw(pf); ice_request_fw(pf);
/* if ice_request_fw fails, ICE_FLAG_ADV_FEATURES bit won't be /* if ice_request_fw fails, ICE_FLAG_ADV_FEATURES bit won't be
...@@ -7230,6 +7236,7 @@ static const struct net_device_ops ice_netdev_ops = { ...@@ -7230,6 +7236,7 @@ static const struct net_device_ops ice_netdev_ops = {
.ndo_open = ice_open, .ndo_open = ice_open,
.ndo_stop = ice_stop, .ndo_stop = ice_stop,
.ndo_start_xmit = ice_start_xmit, .ndo_start_xmit = ice_start_xmit,
.ndo_select_queue = ice_select_queue,
.ndo_features_check = ice_features_check, .ndo_features_check = ice_features_check,
.ndo_set_rx_mode = ice_set_rx_mode, .ndo_set_rx_mode = ice_set_rx_mode,
.ndo_set_mac_address = ice_set_mac_address, .ndo_set_mac_address = ice_set_mac_address,
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
#include <linux/prefetch.h> #include <linux/prefetch.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/bpf_trace.h> #include <linux/bpf_trace.h>
#include <net/dsfield.h>
#include <net/xdp.h> #include <net/xdp.h>
#include "ice_txrx_lib.h" #include "ice_txrx_lib.h"
#include "ice_lib.h" #include "ice_lib.h"
...@@ -2295,6 +2296,39 @@ netdev_tx_t ice_start_xmit(struct sk_buff *skb, struct net_device *netdev) ...@@ -2295,6 +2296,39 @@ netdev_tx_t ice_start_xmit(struct sk_buff *skb, struct net_device *netdev)
return ice_xmit_frame_ring(skb, tx_ring); return ice_xmit_frame_ring(skb, tx_ring);
} }
/**
* ice_get_dscp_up - return the UP/TC value for a SKB
* @dcbcfg: DCB config that contains DSCP to UP/TC mapping
* @skb: SKB to query for info to determine UP/TC
*
* This function is to only be called when the PF is in L3 DSCP PFC mode
*/
static u8 ice_get_dscp_up(struct ice_dcbx_cfg *dcbcfg, struct sk_buff *skb)
{
u8 dscp = 0;
if (skb->protocol == htons(ETH_P_IP))
dscp = ipv4_get_dsfield(ip_hdr(skb)) >> 2;
else if (skb->protocol == htons(ETH_P_IPV6))
dscp = ipv6_get_dsfield(ipv6_hdr(skb)) >> 2;
return dcbcfg->dscp_map[dscp];
}
u16
ice_select_queue(struct net_device *netdev, struct sk_buff *skb,
struct net_device *sb_dev)
{
struct ice_pf *pf = ice_netdev_to_pf(netdev);
struct ice_dcbx_cfg *dcbcfg;
dcbcfg = &pf->hw.port_info->qos_cfg.local_dcbx_cfg;
if (dcbcfg->pfc_mode == ICE_QOS_MODE_DSCP)
skb->priority = ice_get_dscp_up(dcbcfg, skb);
return netdev_pick_tx(netdev, skb, sb_dev);
}
/** /**
* ice_clean_ctrl_tx_irq - interrupt handler for flow director Tx queue * ice_clean_ctrl_tx_irq - interrupt handler for flow director Tx queue
* @tx_ring: tx_ring to clean * @tx_ring: tx_ring to clean
......
...@@ -378,6 +378,9 @@ union ice_32b_rx_flex_desc; ...@@ -378,6 +378,9 @@ union ice_32b_rx_flex_desc;
bool ice_alloc_rx_bufs(struct ice_ring *rxr, u16 cleaned_count); bool ice_alloc_rx_bufs(struct ice_ring *rxr, u16 cleaned_count);
netdev_tx_t ice_start_xmit(struct sk_buff *skb, struct net_device *netdev); netdev_tx_t ice_start_xmit(struct sk_buff *skb, struct net_device *netdev);
u16
ice_select_queue(struct net_device *dev, struct sk_buff *skb,
struct net_device *sb_dev);
void ice_clean_tx_ring(struct ice_ring *tx_ring); void ice_clean_tx_ring(struct ice_ring *tx_ring);
void ice_clean_rx_ring(struct ice_ring *rx_ring); void ice_clean_rx_ring(struct ice_ring *rx_ring);
int ice_setup_tx_ring(struct ice_ring *tx_ring); int ice_setup_tx_ring(struct ice_ring *tx_ring);
......
...@@ -604,7 +604,8 @@ struct ice_dcb_app_priority_table { ...@@ -604,7 +604,8 @@ struct ice_dcb_app_priority_table {
}; };
#define ICE_MAX_USER_PRIORITY 8 #define ICE_MAX_USER_PRIORITY 8
#define ICE_DCBX_MAX_APPS 32 #define ICE_DCBX_MAX_APPS 64
#define ICE_DSCP_NUM_VAL 64
#define ICE_LLDPDU_SIZE 1500 #define ICE_LLDPDU_SIZE 1500
#define ICE_TLV_STATUS_OPER 0x1 #define ICE_TLV_STATUS_OPER 0x1
#define ICE_TLV_STATUS_SYNC 0x2 #define ICE_TLV_STATUS_SYNC 0x2
...@@ -622,7 +623,14 @@ struct ice_dcbx_cfg { ...@@ -622,7 +623,14 @@ struct ice_dcbx_cfg {
struct ice_dcb_ets_cfg etscfg; struct ice_dcb_ets_cfg etscfg;
struct ice_dcb_ets_cfg etsrec; struct ice_dcb_ets_cfg etsrec;
struct ice_dcb_pfc_cfg pfc; struct ice_dcb_pfc_cfg pfc;
#define ICE_QOS_MODE_VLAN 0x0
#define ICE_QOS_MODE_DSCP 0x1
u8 pfc_mode;
struct ice_dcb_app_priority_table app[ICE_DCBX_MAX_APPS]; struct ice_dcb_app_priority_table app[ICE_DCBX_MAX_APPS];
/* when DSCP mapping defined by user set its bit to 1 */
DECLARE_BITMAP(dscp_mapped, ICE_DSCP_NUM_VAL);
/* array holding DSCP -> UP/TC values for DSCP L3 QoS mode */
u8 dscp_map[ICE_DSCP_NUM_VAL];
u8 dcbx_mode; u8 dcbx_mode;
#define ICE_DCBX_MODE_CEE 0x1 #define ICE_DCBX_MODE_CEE 0x1
#define ICE_DCBX_MODE_IEEE 0x2 #define ICE_DCBX_MODE_IEEE 0x2
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment