Commit 3032309b authored by John Fastabend's avatar John Fastabend Committed by Jeff Kirsher

ixgbe: DCB, implement capabilities flags

This implements dcbnl get and set capabilities ops. The
devices supported by ixgbe can be configured to run in
IEEE or CEE modes but not both.

With the DCBX set capabilities bit we add an explicit
signal that must be used to toggle between these modes.
This patch adds logic to fail the CEE command set_hw_all()
which programs the device with a CEE configuration if
the CEE caps bit is not set. Similarly, IEEE set
commands will fail if the IEEE caps bit is not set. We
allow most CEE config set commands to occur because they
do not touch the hardware until set_hw_all() is called.

The one exception to the above is the {set|get}app routines.
These must always be protected by caps bits to ensure
side effects do not corrupt the current configured mode.

By requiring the caps bit to be set correctly we can
maintain a consistent configuration in the hardware
for CEE or IEEE modes and prevent partial hardware
configurations that may occur if user space does
not send a complete IEEE or CEE configurations.

It is expected that user space will signal a DCBX mode
before programming device.
Signed-off-by: default avatarJohn Fastabend <john.r.fastabend@intel.com>
Tested-by: default avatarRoss Brattain <ross.b.brattain@intel.com>
Signed-off-by: default avatarJeff Kirsher <jeffrey.t.kirsher@intel.com>
parent 0d1fe82d
...@@ -341,6 +341,7 @@ struct ixgbe_adapter { ...@@ -341,6 +341,7 @@ struct ixgbe_adapter {
struct ixgbe_dcb_config dcb_cfg; struct ixgbe_dcb_config dcb_cfg;
struct ixgbe_dcb_config temp_dcb_cfg; struct ixgbe_dcb_config temp_dcb_cfg;
u8 dcb_set_bitmap; u8 dcb_set_bitmap;
u8 dcbx_cap;
enum ixgbe_fc_mode last_lfc_mode; enum ixgbe_fc_mode last_lfc_mode;
/* Interrupt Throttle Rate */ /* Interrupt Throttle Rate */
......
...@@ -346,7 +346,8 @@ static u8 ixgbe_dcbnl_set_all(struct net_device *netdev) ...@@ -346,7 +346,8 @@ static u8 ixgbe_dcbnl_set_all(struct net_device *netdev)
struct ixgbe_adapter *adapter = netdev_priv(netdev); struct ixgbe_adapter *adapter = netdev_priv(netdev);
int ret; int ret;
if (!adapter->dcb_set_bitmap) if (!adapter->dcb_set_bitmap ||
!(adapter->dcbx_cap & DCB_CAP_DCBX_VER_CEE))
return DCB_NO_HW_CHG; return DCB_NO_HW_CHG;
ret = ixgbe_copy_dcb_cfg(&adapter->temp_dcb_cfg, &adapter->dcb_cfg, ret = ixgbe_copy_dcb_cfg(&adapter->temp_dcb_cfg, &adapter->dcb_cfg,
...@@ -448,9 +449,7 @@ static u8 ixgbe_dcbnl_set_all(struct net_device *netdev) ...@@ -448,9 +449,7 @@ static u8 ixgbe_dcbnl_set_all(struct net_device *netdev)
static u8 ixgbe_dcbnl_getcap(struct net_device *netdev, int capid, u8 *cap) static u8 ixgbe_dcbnl_getcap(struct net_device *netdev, int capid, u8 *cap)
{ {
struct ixgbe_adapter *adapter = netdev_priv(netdev); struct ixgbe_adapter *adapter = netdev_priv(netdev);
u8 rval = 0;
if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) {
switch (capid) { switch (capid) {
case DCB_CAP_ATTR_PG: case DCB_CAP_ATTR_PG:
*cap = true; *cap = true;
...@@ -473,15 +472,15 @@ static u8 ixgbe_dcbnl_getcap(struct net_device *netdev, int capid, u8 *cap) ...@@ -473,15 +472,15 @@ static u8 ixgbe_dcbnl_getcap(struct net_device *netdev, int capid, u8 *cap)
case DCB_CAP_ATTR_BCN: case DCB_CAP_ATTR_BCN:
*cap = false; *cap = false;
break; break;
case DCB_CAP_ATTR_DCBX:
*cap = adapter->dcbx_cap;
break;
default: default:
rval = -EINVAL; *cap = false;
break; break;
} }
} else {
rval = -EINVAL;
}
return rval; return 0;
} }
static u8 ixgbe_dcbnl_getnumtcs(struct net_device *netdev, int tcid, u8 *num) static u8 ixgbe_dcbnl_getnumtcs(struct net_device *netdev, int tcid, u8 *num)
...@@ -542,13 +541,17 @@ static void ixgbe_dcbnl_setpfcstate(struct net_device *netdev, u8 state) ...@@ -542,13 +541,17 @@ static void ixgbe_dcbnl_setpfcstate(struct net_device *netdev, u8 state)
*/ */
static u8 ixgbe_dcbnl_getapp(struct net_device *netdev, u8 idtype, u16 id) static u8 ixgbe_dcbnl_getapp(struct net_device *netdev, u8 idtype, u16 id)
{ {
struct ixgbe_adapter *adapter = netdev_priv(netdev);
u8 rval = 0; u8 rval = 0;
if (!(adapter->dcbx_cap & DCB_CAP_DCBX_VER_CEE))
return rval;
switch (idtype) { switch (idtype) {
case DCB_APP_IDTYPE_ETHTYPE: case DCB_APP_IDTYPE_ETHTYPE:
#ifdef IXGBE_FCOE #ifdef IXGBE_FCOE
if (id == ETH_P_FCOE) if (id == ETH_P_FCOE)
rval = ixgbe_fcoe_getapp(netdev_priv(netdev)); rval = ixgbe_fcoe_getapp(adapter);
#endif #endif
break; break;
case DCB_APP_IDTYPE_PORTNUM: case DCB_APP_IDTYPE_PORTNUM:
...@@ -571,14 +574,17 @@ static u8 ixgbe_dcbnl_getapp(struct net_device *netdev, u8 idtype, u16 id) ...@@ -571,14 +574,17 @@ static u8 ixgbe_dcbnl_getapp(struct net_device *netdev, u8 idtype, u16 id)
static u8 ixgbe_dcbnl_setapp(struct net_device *netdev, static u8 ixgbe_dcbnl_setapp(struct net_device *netdev,
u8 idtype, u16 id, u8 up) u8 idtype, u16 id, u8 up)
{ {
struct ixgbe_adapter *adapter = netdev_priv(netdev);
u8 rval = 1; u8 rval = 1;
if (!(adapter->dcbx_cap & DCB_CAP_DCBX_VER_CEE))
return rval;
switch (idtype) { switch (idtype) {
case DCB_APP_IDTYPE_ETHTYPE: case DCB_APP_IDTYPE_ETHTYPE:
#ifdef IXGBE_FCOE #ifdef IXGBE_FCOE
if (id == ETH_P_FCOE) { if (id == ETH_P_FCOE) {
u8 old_tc; u8 old_tc;
struct ixgbe_adapter *adapter = netdev_priv(netdev);
/* Get current programmed tc */ /* Get current programmed tc */
old_tc = adapter->fcoe.tc; old_tc = adapter->fcoe.tc;
...@@ -640,6 +646,9 @@ static int ixgbe_dcbnl_ieee_setets(struct net_device *dev, ...@@ -640,6 +646,9 @@ static int ixgbe_dcbnl_ieee_setets(struct net_device *dev,
/* naively give each TC a bwg to map onto CEE hardware */ /* naively give each TC a bwg to map onto CEE hardware */
__u8 bwg_id[IEEE_8021QAZ_MAX_TCS] = {0, 1, 2, 3, 4, 5, 6, 7}; __u8 bwg_id[IEEE_8021QAZ_MAX_TCS] = {0, 1, 2, 3, 4, 5, 6, 7};
if (!(adapter->dcbx_cap & DCB_CAP_DCBX_VER_IEEE))
return -EINVAL;
if (!adapter->ixgbe_ieee_ets) { if (!adapter->ixgbe_ieee_ets) {
adapter->ixgbe_ieee_ets = kmalloc(sizeof(struct ieee_ets), adapter->ixgbe_ieee_ets = kmalloc(sizeof(struct ieee_ets),
GFP_KERNEL); GFP_KERNEL);
...@@ -647,7 +656,6 @@ static int ixgbe_dcbnl_ieee_setets(struct net_device *dev, ...@@ -647,7 +656,6 @@ static int ixgbe_dcbnl_ieee_setets(struct net_device *dev,
return -ENOMEM; return -ENOMEM;
} }
memcpy(adapter->ixgbe_ieee_ets, ets, sizeof(*adapter->ixgbe_ieee_ets)); memcpy(adapter->ixgbe_ieee_ets, ets, sizeof(*adapter->ixgbe_ieee_ets));
ixgbe_ieee_credits(ets->tc_tx_bw, refill, max, max_frame); ixgbe_ieee_credits(ets->tc_tx_bw, refill, max, max_frame);
...@@ -686,6 +694,9 @@ static int ixgbe_dcbnl_ieee_setpfc(struct net_device *dev, ...@@ -686,6 +694,9 @@ static int ixgbe_dcbnl_ieee_setpfc(struct net_device *dev,
struct ixgbe_adapter *adapter = netdev_priv(dev); struct ixgbe_adapter *adapter = netdev_priv(dev);
int err; int err;
if (!(adapter->dcbx_cap & DCB_CAP_DCBX_VER_IEEE))
return -EINVAL;
if (!adapter->ixgbe_ieee_pfc) { if (!adapter->ixgbe_ieee_pfc) {
adapter->ixgbe_ieee_pfc = kmalloc(sizeof(struct ieee_pfc), adapter->ixgbe_ieee_pfc = kmalloc(sizeof(struct ieee_pfc),
GFP_KERNEL); GFP_KERNEL);
...@@ -698,6 +709,51 @@ static int ixgbe_dcbnl_ieee_setpfc(struct net_device *dev, ...@@ -698,6 +709,51 @@ static int ixgbe_dcbnl_ieee_setpfc(struct net_device *dev,
return err; return err;
} }
static u8 ixgbe_dcbnl_getdcbx(struct net_device *dev)
{
struct ixgbe_adapter *adapter = netdev_priv(dev);
return adapter->dcbx_cap;
}
static u8 ixgbe_dcbnl_setdcbx(struct net_device *dev, u8 mode)
{
struct ixgbe_adapter *adapter = netdev_priv(dev);
struct ieee_ets ets = {0};
struct ieee_pfc pfc = {0};
/* no support for LLD_MANAGED modes or CEE+IEEE */
if ((mode & DCB_CAP_DCBX_LLD_MANAGED) ||
((mode & DCB_CAP_DCBX_VER_IEEE) && (mode & DCB_CAP_DCBX_VER_CEE)) ||
!(mode & DCB_CAP_DCBX_HOST))
return 1;
if (mode == adapter->dcbx_cap)
return 0;
adapter->dcbx_cap = mode;
/* ETS and PFC defaults */
ets.ets_cap = 8;
pfc.pfc_cap = 8;
if (mode & DCB_CAP_DCBX_VER_IEEE) {
ixgbe_dcbnl_ieee_setets(dev, &ets);
ixgbe_dcbnl_ieee_setpfc(dev, &pfc);
} else if (mode & DCB_CAP_DCBX_VER_CEE) {
adapter->dcb_set_bitmap |= (BIT_PFC & BIT_PG_TX & BIT_PG_RX);
ixgbe_dcbnl_set_all(dev);
} else {
/* Drop into single TC mode strict priority as this
* indicates CEE and IEEE versions are disabled
*/
ixgbe_dcbnl_ieee_setets(dev, &ets);
ixgbe_dcbnl_ieee_setpfc(dev, &pfc);
ixgbe_dcbnl_set_state(dev, 0);
}
return 0;
}
const struct dcbnl_rtnl_ops dcbnl_ops = { const struct dcbnl_rtnl_ops dcbnl_ops = {
.ieee_getets = ixgbe_dcbnl_ieee_getets, .ieee_getets = ixgbe_dcbnl_ieee_getets,
.ieee_setets = ixgbe_dcbnl_ieee_setets, .ieee_setets = ixgbe_dcbnl_ieee_setets,
...@@ -724,5 +780,6 @@ const struct dcbnl_rtnl_ops dcbnl_ops = { ...@@ -724,5 +780,6 @@ const struct dcbnl_rtnl_ops dcbnl_ops = {
.setpfcstate = ixgbe_dcbnl_setpfcstate, .setpfcstate = ixgbe_dcbnl_setpfcstate,
.getapp = ixgbe_dcbnl_getapp, .getapp = ixgbe_dcbnl_getapp,
.setapp = ixgbe_dcbnl_setapp, .setapp = ixgbe_dcbnl_setapp,
.getdcbx = ixgbe_dcbnl_getdcbx,
.setdcbx = ixgbe_dcbnl_setdcbx,
}; };
...@@ -5190,6 +5190,7 @@ static int __devinit ixgbe_sw_init(struct ixgbe_adapter *adapter) ...@@ -5190,6 +5190,7 @@ static int __devinit ixgbe_sw_init(struct ixgbe_adapter *adapter)
adapter->dcb_cfg.rx_pba_cfg = pba_equal; adapter->dcb_cfg.rx_pba_cfg = pba_equal;
adapter->dcb_cfg.pfc_mode_enable = false; adapter->dcb_cfg.pfc_mode_enable = false;
adapter->dcb_set_bitmap = 0x00; adapter->dcb_set_bitmap = 0x00;
adapter->dcbx_cap = DCB_CAP_DCBX_HOST | DCB_CAP_DCBX_VER_CEE;
ixgbe_copy_dcb_cfg(&adapter->dcb_cfg, &adapter->temp_dcb_cfg, ixgbe_copy_dcb_cfg(&adapter->dcb_cfg, &adapter->temp_dcb_cfg,
adapter->ring_feature[RING_F_DCB].indices); adapter->ring_feature[RING_F_DCB].indices);
......
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