static int bnxt_req_msix_vecs(struct bnxt_en_dev *edev, int ulp_id, struct bnxt_msix_entry *ent, int num_msix) { struct net_device *dev = edev->net; struct bnxt *bp = netdev_priv(dev); int max_idx, max_cp_rings; int avail_msix, idx; int rc = 0; ASSERT_RTNL(); if (ulp_id != BNXT_ROCE_ULP) return -EINVAL; if (!(bp->flags & BNXT_FLAG_USING_MSIX)) return -ENODEV; if (edev->ulp_tbl[ulp_id].msix_requested) return -EAGAIN; max_cp_rings = bnxt_get_max_func_cp_rings(bp); avail_msix = bnxt_get_avail_msix(bp, num_msix); if (!avail_msix) return -ENOMEM; if (avail_msix > num_msix) avail_msix = num_msix; if (BNXT_NEW_RM(bp)) { idx = bp->cp_nr_rings; } else { max_idx = min_t(int, bp->total_irqs, max_cp_rings); idx = max_idx - avail_msix; } edev->ulp_tbl[ulp_id].msix_base = idx; edev->ulp_tbl[ulp_id].msix_requested = avail_msix; if (bp->total_irqs < (idx + avail_msix)) { if (netif_running(dev)) { bnxt_close_nic(bp, true, false); rc = bnxt_open_nic(bp, true, false); } else { rc = bnxt_reserve_rings(bp); } } if (rc) { edev->ulp_tbl[ulp_id].msix_requested = 0; return -EAGAIN; } if (BNXT_NEW_RM(bp)) { struct bnxt_hw_resc *hw_resc = &bp->hw_resc; avail_msix = hw_resc->resv_cp_rings - bp->cp_nr_rings; edev->ulp_tbl[ulp_id].msix_requested = avail_msix; } bnxt_fill_msix_vecs(bp, ent); edev->flags |= BNXT_EN_FLAG_MSIX_REQUESTED; return avail_msix; }
static int bnxt_set_channels(struct net_device *dev, struct ethtool_channels *channel) { struct bnxt *bp = netdev_priv(dev); int max_rx_rings, max_tx_rings, tcs; u32 rc = 0; if (channel->other_count || channel->combined_count || !channel->rx_count || !channel->tx_count) return -EINVAL; bnxt_get_max_rings(bp, &max_rx_rings, &max_tx_rings); tcs = netdev_get_num_tc(dev); if (tcs > 1) max_tx_rings /= tcs; if (channel->rx_count > max_rx_rings || channel->tx_count > max_tx_rings) return -EINVAL; if (netif_running(dev)) { if (BNXT_PF(bp)) { /* TODO CHIMP_FW: Send message to all VF's * before PF unload */ } rc = bnxt_close_nic(bp, true, false); if (rc) { netdev_err(bp->dev, "Set channel failure rc :%x\n", rc); return rc; } } bp->rx_nr_rings = channel->rx_count; bp->tx_nr_rings_per_tc = channel->tx_count; bp->tx_nr_rings = bp->tx_nr_rings_per_tc; if (tcs > 1) bp->tx_nr_rings = bp->tx_nr_rings_per_tc * tcs; bp->cp_nr_rings = max_t(int, bp->tx_nr_rings, bp->rx_nr_rings); bp->num_stat_ctxs = bp->cp_nr_rings; if (netif_running(dev)) { rc = bnxt_open_nic(bp, true, false); if ((!rc) && BNXT_PF(bp)) { /* TODO CHIMP_FW: Send message to all VF's * to renable */ } } return rc; }
static int bnxt_free_msix_vecs(struct bnxt_en_dev *edev, int ulp_id) { struct net_device *dev = edev->net; struct bnxt *bp = netdev_priv(dev); ASSERT_RTNL(); if (ulp_id != BNXT_ROCE_ULP) return -EINVAL; if (!(edev->flags & BNXT_EN_FLAG_MSIX_REQUESTED)) return 0; edev->ulp_tbl[ulp_id].msix_requested = 0; edev->flags &= ~BNXT_EN_FLAG_MSIX_REQUESTED; if (netif_running(dev)) { bnxt_close_nic(bp, true, false); bnxt_open_nic(bp, true, false); } return 0; }
static int bnxt_set_ringparam(struct net_device *dev, struct ethtool_ringparam *ering) { struct bnxt *bp = netdev_priv(dev); if ((ering->rx_pending > BNXT_MAX_RX_DESC_CNT) || (ering->tx_pending > BNXT_MAX_TX_DESC_CNT) || (ering->tx_pending <= MAX_SKB_FRAGS)) return -EINVAL; if (netif_running(dev)) bnxt_close_nic(bp, false, false); bp->rx_ring_size = ering->rx_pending; bp->tx_ring_size = ering->tx_pending; bnxt_set_ring_params(bp); if (netif_running(dev)) return bnxt_open_nic(bp, false, false); return 0; }
static int bnxt_set_channels(struct net_device *dev, struct ethtool_channels *channel) { struct bnxt *bp = netdev_priv(dev); int max_rx_rings, max_tx_rings, tcs; u32 rc = 0; bool sh = false; if (channel->other_count) return -EINVAL; if (!channel->combined_count && (!channel->rx_count || !channel->tx_count)) return -EINVAL; if (channel->combined_count && (channel->rx_count || channel->tx_count)) return -EINVAL; if (channel->combined_count) sh = true; bnxt_get_max_rings(bp, &max_rx_rings, &max_tx_rings, sh); tcs = netdev_get_num_tc(dev); if (tcs > 1) max_tx_rings /= tcs; if (sh && (channel->combined_count > max_rx_rings || channel->combined_count > max_tx_rings)) return -ENOMEM; if (!sh && (channel->rx_count > max_rx_rings || channel->tx_count > max_tx_rings)) return -ENOMEM; if (netif_running(dev)) { if (BNXT_PF(bp)) { /* TODO CHIMP_FW: Send message to all VF's * before PF unload */ } rc = bnxt_close_nic(bp, true, false); if (rc) { netdev_err(bp->dev, "Set channel failure rc :%x\n", rc); return rc; } } if (sh) { bp->flags |= BNXT_FLAG_SHARED_RINGS; bp->rx_nr_rings = channel->combined_count; bp->tx_nr_rings_per_tc = channel->combined_count; } else { bp->flags &= ~BNXT_FLAG_SHARED_RINGS; bp->rx_nr_rings = channel->rx_count; bp->tx_nr_rings_per_tc = channel->tx_count; } bp->tx_nr_rings = bp->tx_nr_rings_per_tc; if (tcs > 1) bp->tx_nr_rings = bp->tx_nr_rings_per_tc * tcs; bp->cp_nr_rings = sh ? max_t(int, bp->tx_nr_rings, bp->rx_nr_rings) : bp->tx_nr_rings + bp->rx_nr_rings; bp->num_stat_ctxs = bp->cp_nr_rings; /* After changing number of rx channels, update NTUPLE feature. */ netdev_update_features(dev); if (netif_running(dev)) { rc = bnxt_open_nic(bp, true, false); if ((!rc) && BNXT_PF(bp)) { /* TODO CHIMP_FW: Send message to all VF's * to renable */ } } return rc; }