Commit afdc8a84 authored by Michael Chan's avatar Michael Chan Committed by David S. Miller

bnxt_en: Add DCBNL DSCP application protocol support.

Expand the .ieee_setapp() and ieee_delapp() DCBNL methods to support
DSCP.  This allows DSCP values to user priority mappings instead
of using VLAN priorities.  Each DSCP mapping is added or deleted one
entry at a time using the firmware API.  The firmware call can only be
made from a PF.
Signed-off-by: default avatarMichael Chan <michael.chan@broadcom.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent cde49a42
......@@ -1281,6 +1281,7 @@ struct bnxt {
struct ieee_ets *ieee_ets;
u8 dcbx_cap;
u8 default_pri;
u8 max_dscp_value;
#endif /* CONFIG_BNXT_DCB */
u32 msg_enable;
......
......@@ -385,6 +385,61 @@ static int bnxt_hwrm_set_dcbx_app(struct bnxt *bp, struct dcb_app *app,
return rc;
}
static int bnxt_hwrm_queue_dscp_qcaps(struct bnxt *bp)
{
struct hwrm_queue_dscp_qcaps_output *resp = bp->hwrm_cmd_resp_addr;
struct hwrm_queue_dscp_qcaps_input req = {0};
int rc;
if (bp->hwrm_spec_code < 0x10800 || BNXT_VF(bp))
return 0;
bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_QUEUE_DSCP_QCAPS, -1, -1);
mutex_lock(&bp->hwrm_cmd_lock);
rc = _hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
if (!rc) {
bp->max_dscp_value = (1 << resp->num_dscp_bits) - 1;
if (bp->max_dscp_value < 0x3f)
bp->max_dscp_value = 0;
}
mutex_unlock(&bp->hwrm_cmd_lock);
return rc;
}
static int bnxt_hwrm_queue_dscp2pri_cfg(struct bnxt *bp, struct dcb_app *app,
bool add)
{
struct hwrm_queue_dscp2pri_cfg_input req = {0};
struct bnxt_dscp2pri_entry *dscp2pri;
dma_addr_t mapping;
int rc;
if (bp->hwrm_spec_code < 0x10800)
return 0;
bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_QUEUE_DSCP2PRI_CFG, -1, -1);
dscp2pri = dma_alloc_coherent(&bp->pdev->dev, sizeof(*dscp2pri),
&mapping, GFP_KERNEL);
if (!dscp2pri)
return -ENOMEM;
req.src_data_addr = cpu_to_le64(mapping);
dscp2pri->dscp = app->protocol;
if (add)
dscp2pri->mask = 0x3f;
else
dscp2pri->mask = 0;
dscp2pri->pri = app->priority;
req.entry_cnt = cpu_to_le16(1);
rc = hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
if (rc)
rc = -EIO;
dma_free_coherent(&bp->pdev->dev, sizeof(*dscp2pri), dscp2pri,
mapping);
return rc;
}
static int bnxt_ets_validate(struct bnxt *bp, struct ieee_ets *ets, u8 *tc)
{
int total_ets_bw = 0;
......@@ -551,15 +606,30 @@ static int bnxt_dcbnl_ieee_setpfc(struct net_device *dev, struct ieee_pfc *pfc)
return rc;
}
static int bnxt_dcbnl_ieee_dscp_app_prep(struct bnxt *bp, struct dcb_app *app)
{
if (app->selector == IEEE_8021QAZ_APP_SEL_DSCP) {
if (!bp->max_dscp_value)
return -ENOTSUPP;
if (app->protocol > bp->max_dscp_value)
return -EINVAL;
}
return 0;
}
static int bnxt_dcbnl_ieee_setapp(struct net_device *dev, struct dcb_app *app)
{
struct bnxt *bp = netdev_priv(dev);
int rc = -EINVAL;
int rc;
if (!(bp->dcbx_cap & DCB_CAP_DCBX_VER_IEEE) ||
!(bp->dcbx_cap & DCB_CAP_DCBX_HOST))
return -EINVAL;
rc = bnxt_dcbnl_ieee_dscp_app_prep(bp, app);
if (rc)
return rc;
rc = dcb_ieee_setapp(dev, app);
if (rc)
return rc;
......@@ -570,6 +640,9 @@ static int bnxt_dcbnl_ieee_setapp(struct net_device *dev, struct dcb_app *app)
app->protocol == ROCE_V2_UDP_DPORT))
rc = bnxt_hwrm_set_dcbx_app(bp, app, true);
if (app->selector == IEEE_8021QAZ_APP_SEL_DSCP)
rc = bnxt_hwrm_queue_dscp2pri_cfg(bp, app, true);
return rc;
}
......@@ -582,6 +655,10 @@ static int bnxt_dcbnl_ieee_delapp(struct net_device *dev, struct dcb_app *app)
!(bp->dcbx_cap & DCB_CAP_DCBX_HOST))
return -EINVAL;
rc = bnxt_dcbnl_ieee_dscp_app_prep(bp, app);
if (rc)
return rc;
rc = dcb_ieee_delapp(dev, app);
if (rc)
return rc;
......@@ -591,6 +668,9 @@ static int bnxt_dcbnl_ieee_delapp(struct net_device *dev, struct dcb_app *app)
app->protocol == ROCE_V2_UDP_DPORT))
rc = bnxt_hwrm_set_dcbx_app(bp, app, false);
if (app->selector == IEEE_8021QAZ_APP_SEL_DSCP)
rc = bnxt_hwrm_queue_dscp2pri_cfg(bp, app, false);
return rc;
}
......@@ -642,6 +722,7 @@ void bnxt_dcb_init(struct bnxt *bp)
if (bp->hwrm_spec_code < 0x10501)
return;
bnxt_hwrm_queue_dscp_qcaps(bp);
bp->dcbx_cap = DCB_CAP_DCBX_VER_IEEE;
if (BNXT_PF(bp) && !(bp->fw_cap & BNXT_FW_CAP_LLDP_AGENT))
bp->dcbx_cap |= DCB_CAP_DCBX_HOST;
......
......@@ -33,6 +33,12 @@ struct bnxt_cos2bw_cfg {
u8 unused;
};
struct bnxt_dscp2pri_entry {
u8 dscp;
u8 mask;
u8 pri;
};
#define BNXT_LLQ(q_profile) \
((q_profile) == \
QUEUE_QPORTCFG_RESP_QUEUE_ID0_SERVICE_PROFILE_LOSSLESS_ROCE)
......
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