/** * ixgbe_dcbnl_getapp - retrieve the DCBX application user priority * @netdev : the corresponding netdev * @idtype : identifies the id as ether type or TCP/UDP port number * @id: id is either ether type or TCP/UDP port number * * Returns : on success, returns a non-zero 802.1p user priority bitmap * otherwise returns 0 as the invalid user priority bitmap to indicate an * error. */ static u8 ixgbe_dcbnl_getapp(struct net_device *netdev, u8 idtype, u16 id) { u8 rval = 0; #ifdef HAVE_DCBNL_IEEE struct dcb_app app = { .selector = idtype, .protocol = id, }; rval = dcb_getapp(netdev, &app); #endif switch (idtype) { case DCB_APP_IDTYPE_ETHTYPE: #ifdef IXGBE_FCOE if (id == ETH_P_FCOE) rval = ixgbe_fcoe_getapp(netdev_priv(netdev)); #endif break; case DCB_APP_IDTYPE_PORTNUM: break; default: break; } return rval; }
/** * ixgbe_dcbnl_getapp - retrieve the DCBX application user priority * @netdev : the corresponding netdev * @idtype : identifies the id as ether type or TCP/UDP port number * @id: id is either ether type or TCP/UDP port number * * Returns : on success, returns a non-zero 802.1p user priority bitmap * otherwise returns 0 as the invalid user priority bitmap to indicate an * error. */ static u8 ixgbe_dcbnl_getapp(struct net_device *netdev, u8 idtype, u16 id) { struct ixgbe_adapter *adapter = netdev_priv(netdev); struct dcb_app app = { .selector = idtype, .protocol = id, }; if (!(adapter->dcbx_cap & DCB_CAP_DCBX_VER_CEE)) return 0; return dcb_getapp(netdev, &app); }
static int ixgbe_copy_dcb_cfg(struct ixgbe_adapter *adapter, int tc_max) { struct ixgbe_dcb_config *scfg = &adapter->temp_dcb_cfg; struct ixgbe_dcb_config *dcfg = &adapter->dcb_cfg; struct tc_configuration *src = NULL; struct tc_configuration *dst = NULL; int i, j; int tx = DCB_TX_CONFIG; int rx = DCB_RX_CONFIG; int changes = 0; #ifdef IXGBE_FCOE struct dcb_app app = { .selector = DCB_APP_IDTYPE_ETHTYPE, .protocol = ETH_P_FCOE, }; u8 up = dcb_getapp(adapter->netdev, &app); if (up && !(up & (1 << adapter->fcoe.up))) changes |= BIT_APP_UPCHG; #endif for (i = DCB_PG_ATTR_TC_0; i < tc_max + DCB_PG_ATTR_TC_0; i++) { src = &scfg->tc_config[i - DCB_PG_ATTR_TC_0]; dst = &dcfg->tc_config[i - DCB_PG_ATTR_TC_0]; if (dst->path[tx].prio_type != src->path[tx].prio_type) { dst->path[tx].prio_type = src->path[tx].prio_type; changes |= BIT_PG_TX; } if (dst->path[tx].bwg_id != src->path[tx].bwg_id) { dst->path[tx].bwg_id = src->path[tx].bwg_id; changes |= BIT_PG_TX; } if (dst->path[tx].bwg_percent != src->path[tx].bwg_percent) { dst->path[tx].bwg_percent = src->path[tx].bwg_percent; changes |= BIT_PG_TX; } if (dst->path[tx].up_to_tc_bitmap != src->path[tx].up_to_tc_bitmap) { dst->path[tx].up_to_tc_bitmap = src->path[tx].up_to_tc_bitmap; changes |= (BIT_PG_TX | BIT_PFC | BIT_APP_UPCHG); } if (dst->path[rx].prio_type != src->path[rx].prio_type) { dst->path[rx].prio_type = src->path[rx].prio_type; changes |= BIT_PG_RX; } if (dst->path[rx].bwg_id != src->path[rx].bwg_id) { dst->path[rx].bwg_id = src->path[rx].bwg_id; changes |= BIT_PG_RX; } if (dst->path[rx].bwg_percent != src->path[rx].bwg_percent) { dst->path[rx].bwg_percent = src->path[rx].bwg_percent; changes |= BIT_PG_RX; } if (dst->path[rx].up_to_tc_bitmap != src->path[rx].up_to_tc_bitmap) { dst->path[rx].up_to_tc_bitmap = src->path[rx].up_to_tc_bitmap; changes |= (BIT_PG_RX | BIT_PFC | BIT_APP_UPCHG); } } for (i = DCB_PG_ATTR_BW_ID_0; i < DCB_PG_ATTR_BW_ID_MAX; i++) { j = i - DCB_PG_ATTR_BW_ID_0; if (dcfg->bw_percentage[tx][j] != scfg->bw_percentage[tx][j]) { dcfg->bw_percentage[tx][j] = scfg->bw_percentage[tx][j]; changes |= BIT_PG_TX; } if (dcfg->bw_percentage[rx][j] != scfg->bw_percentage[rx][j]) { dcfg->bw_percentage[rx][j] = scfg->bw_percentage[rx][j]; changes |= BIT_PG_RX; } } for (i = DCB_PFC_UP_ATTR_0; i < DCB_PFC_UP_ATTR_MAX; i++) { j = i - DCB_PFC_UP_ATTR_0; if (dcfg->tc_config[j].dcb_pfc != scfg->tc_config[j].dcb_pfc) { dcfg->tc_config[j].dcb_pfc = scfg->tc_config[j].dcb_pfc; changes |= BIT_PFC; } } if (dcfg->pfc_mode_enable != scfg->pfc_mode_enable) { dcfg->pfc_mode_enable = scfg->pfc_mode_enable; changes |= BIT_PFC; } return changes; }
static u8 ixgbe_dcbnl_set_all(struct net_device *netdev) { struct ixgbe_adapter *adapter = netdev_priv(netdev); struct ixgbe_dcb_config *dcb_cfg = &adapter->dcb_cfg; struct ixgbe_hw *hw = &adapter->hw; int ret = DCB_NO_HW_CHG; int i; /* Fail command if not in CEE mode */ if (!(adapter->dcbx_cap & DCB_CAP_DCBX_VER_CEE)) return ret; adapter->dcb_set_bitmap |= ixgbe_copy_dcb_cfg(adapter, MAX_TRAFFIC_CLASS); if (!adapter->dcb_set_bitmap) return ret; if (adapter->dcb_set_bitmap & (BIT_PG_TX|BIT_PG_RX)) { u16 refill[MAX_TRAFFIC_CLASS], max[MAX_TRAFFIC_CLASS]; u8 bwg_id[MAX_TRAFFIC_CLASS], prio_type[MAX_TRAFFIC_CLASS]; /* Priority to TC mapping in CEE case default to 1:1 */ u8 prio_tc[MAX_USER_PRIORITY]; int max_frame = adapter->netdev->mtu + ETH_HLEN + ETH_FCS_LEN; #ifdef IXGBE_FCOE if (adapter->netdev->features & NETIF_F_FCOE_MTU) max_frame = max(max_frame, IXGBE_FCOE_JUMBO_FRAME_SIZE); #endif ixgbe_dcb_calculate_tc_credits(hw, dcb_cfg, max_frame, DCB_TX_CONFIG); ixgbe_dcb_calculate_tc_credits(hw, dcb_cfg, max_frame, DCB_RX_CONFIG); ixgbe_dcb_unpack_refill(dcb_cfg, DCB_TX_CONFIG, refill); ixgbe_dcb_unpack_max(dcb_cfg, max); ixgbe_dcb_unpack_bwgid(dcb_cfg, DCB_TX_CONFIG, bwg_id); ixgbe_dcb_unpack_prio(dcb_cfg, DCB_TX_CONFIG, prio_type); ixgbe_dcb_unpack_map(dcb_cfg, DCB_TX_CONFIG, prio_tc); ixgbe_dcb_hw_ets_config(hw, refill, max, bwg_id, prio_type, prio_tc); for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) netdev_set_prio_tc_map(netdev, i, prio_tc[i]); ret = DCB_HW_CHG_RST; } if (adapter->dcb_set_bitmap & BIT_PFC) { if (dcb_cfg->pfc_mode_enable) { u8 pfc_en; u8 prio_tc[MAX_USER_PRIORITY]; ixgbe_dcb_unpack_map(dcb_cfg, DCB_TX_CONFIG, prio_tc); ixgbe_dcb_unpack_pfc(dcb_cfg, &pfc_en); ixgbe_dcb_hw_pfc_config(hw, pfc_en, prio_tc); } else { hw->mac.ops.fc_enable(hw); } ixgbe_set_rx_drop_en(adapter); ret = DCB_HW_CHG; } #ifdef IXGBE_FCOE /* Reprogam FCoE hardware offloads when the traffic class * FCoE is using changes. This happens if the APP info * changes or the up2tc mapping is updated. */ if (adapter->dcb_set_bitmap & BIT_APP_UPCHG) { struct dcb_app app = { .selector = DCB_APP_IDTYPE_ETHTYPE, .protocol = ETH_P_FCOE, }; u8 up = dcb_getapp(netdev, &app); adapter->fcoe.up = ffs(up) - 1; ixgbe_dcbnl_devreset(netdev); ret = DCB_HW_CHG_RST; } #endif adapter->dcb_set_bitmap = 0x00; return ret; }
static u8 ixgbe_dcbnl_set_all(struct net_device *netdev) { struct ixgbe_adapter *adapter = netdev_priv(netdev); int ret, i; #ifdef IXGBE_FCOE struct dcb_app app = { .selector = DCB_APP_IDTYPE_ETHTYPE, .protocol = ETH_P_FCOE, }; u8 up = dcb_getapp(netdev, &app); #endif /* Fail command if not in CEE mode */ if (!(adapter->dcbx_cap & DCB_CAP_DCBX_VER_CEE)) return 1; ret = ixgbe_copy_dcb_cfg(&adapter->temp_dcb_cfg, &adapter->dcb_cfg, MAX_TRAFFIC_CLASS); if (ret) return DCB_NO_HW_CHG; #ifdef IXGBE_FCOE if (up && (up != (1 << adapter->fcoe.up))) adapter->dcb_set_bitmap |= BIT_APP_UPCHG; /* * Only take down the adapter if an app change occurred. FCoE * may shuffle tx rings in this case and this can not be done * without a reset currently. */ if (adapter->dcb_set_bitmap & BIT_APP_UPCHG) { while (test_and_set_bit(__IXGBE_RESETTING, &adapter->state)) usleep_range(1000, 2000); adapter->fcoe.up = ffs(up) - 1; if (netif_running(netdev)) netdev->netdev_ops->ndo_stop(netdev); ixgbe_clear_interrupt_scheme(adapter); } #endif if (adapter->dcb_cfg.pfc_mode_enable) { switch (adapter->hw.mac.type) { case ixgbe_mac_82599EB: case ixgbe_mac_X540: if (adapter->hw.fc.current_mode != ixgbe_fc_pfc) adapter->last_lfc_mode = adapter->hw.fc.current_mode; break; default: break; } adapter->hw.fc.requested_mode = ixgbe_fc_pfc; } else { switch (adapter->hw.mac.type) { case ixgbe_mac_82598EB: adapter->hw.fc.requested_mode = ixgbe_fc_none; break; case ixgbe_mac_82599EB: case ixgbe_mac_X540: adapter->hw.fc.requested_mode = adapter->last_lfc_mode; break; default: break; } } #ifdef IXGBE_FCOE if (adapter->dcb_set_bitmap & BIT_APP_UPCHG) { ixgbe_init_interrupt_scheme(adapter); if (netif_running(netdev)) netdev->netdev_ops->ndo_open(netdev); ret = DCB_HW_CHG_RST; } #endif if (adapter->dcb_set_bitmap & (BIT_PG_TX|BIT_PG_RX)) { u16 refill[MAX_TRAFFIC_CLASS], max[MAX_TRAFFIC_CLASS]; u8 bwg_id[MAX_TRAFFIC_CLASS], prio_type[MAX_TRAFFIC_CLASS]; /* Priority to TC mapping in CEE case default to 1:1 */ u8 prio_tc[MAX_USER_PRIORITY]; int max_frame = adapter->netdev->mtu + ETH_HLEN + ETH_FCS_LEN; #ifdef IXGBE_FCOE if (adapter->netdev->features & NETIF_F_FCOE_MTU) max_frame = max(max_frame, IXGBE_FCOE_JUMBO_FRAME_SIZE); #endif ixgbe_dcb_calculate_tc_credits(&adapter->hw, &adapter->dcb_cfg, max_frame, DCB_TX_CONFIG); ixgbe_dcb_calculate_tc_credits(&adapter->hw, &adapter->dcb_cfg, max_frame, DCB_RX_CONFIG); ixgbe_dcb_unpack_refill(&adapter->dcb_cfg, DCB_TX_CONFIG, refill); ixgbe_dcb_unpack_max(&adapter->dcb_cfg, max); ixgbe_dcb_unpack_bwgid(&adapter->dcb_cfg, DCB_TX_CONFIG, bwg_id); ixgbe_dcb_unpack_prio(&adapter->dcb_cfg, DCB_TX_CONFIG, prio_type); ixgbe_dcb_unpack_map(&adapter->dcb_cfg, DCB_TX_CONFIG, prio_tc); ixgbe_dcb_hw_ets_config(&adapter->hw, refill, max, bwg_id, prio_type, prio_tc); for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) netdev_set_prio_tc_map(netdev, i, prio_tc[i]); } if (adapter->dcb_set_bitmap & BIT_PFC) { u8 pfc_en; u8 prio_tc[MAX_USER_PRIORITY]; ixgbe_dcb_unpack_map(&adapter->dcb_cfg, DCB_TX_CONFIG, prio_tc); ixgbe_dcb_unpack_pfc(&adapter->dcb_cfg, &pfc_en); ixgbe_dcb_hw_pfc_config(&adapter->hw, pfc_en, prio_tc); ret = DCB_HW_CHG; } if (adapter->dcb_cfg.pfc_mode_enable) adapter->hw.fc.current_mode = ixgbe_fc_pfc; if (adapter->dcb_set_bitmap & BIT_APP_UPCHG) clear_bit(__IXGBE_RESETTING, &adapter->state); adapter->dcb_set_bitmap = 0x00; return ret; }