mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-12-26 02:55:11 +07:00
net: hns3: add support to modify tqps number
This patch adds the support to change tqps number for PF driver by using ehtool -L command. Signed-off-by: Peng Li <lipeng321@huawei.com> Signed-off-by: Mingguang Qu <qumingguang@huawei.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
482d2e9c1c
commit
09f2af6405
@ -388,6 +388,9 @@ struct hnae3_ae_ops {
|
||||
enum hnae3_reset_type reset);
|
||||
void (*get_channels)(struct hnae3_handle *handle,
|
||||
struct ethtool_channels *ch);
|
||||
void (*get_tqps_and_rss_info)(struct hnae3_handle *h,
|
||||
u16 *free_tqps, u16 *max_rss_size);
|
||||
int (*set_channels)(struct hnae3_handle *handle, u32 new_tqps_num);
|
||||
};
|
||||
|
||||
struct hnae3_dcb_ops {
|
||||
|
@ -2651,6 +2651,19 @@ static int hns3_get_ring_config(struct hns3_nic_priv *priv)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void hns3_put_ring_config(struct hns3_nic_priv *priv)
|
||||
{
|
||||
struct hnae3_handle *h = priv->ae_handle;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < h->kinfo.num_tqps; i++) {
|
||||
devm_kfree(priv->dev, priv->ring_data[i].ring);
|
||||
devm_kfree(priv->dev,
|
||||
priv->ring_data[i + h->kinfo.num_tqps].ring);
|
||||
}
|
||||
devm_kfree(priv->dev, priv->ring_data);
|
||||
}
|
||||
|
||||
static int hns3_alloc_ring_memory(struct hns3_enet_ring *ring)
|
||||
{
|
||||
int ret;
|
||||
@ -3162,6 +3175,115 @@ static int hns3_reset_notify(struct hnae3_handle *handle,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static u16 hns3_get_max_available_channels(struct net_device *netdev)
|
||||
{
|
||||
struct hnae3_handle *h = hns3_get_handle(netdev);
|
||||
u16 free_tqps, max_rss_size, max_tqps;
|
||||
|
||||
h->ae_algo->ops->get_tqps_and_rss_info(h, &free_tqps, &max_rss_size);
|
||||
max_tqps = h->kinfo.num_tc * max_rss_size;
|
||||
|
||||
return min_t(u16, max_tqps, (free_tqps + h->kinfo.num_tqps));
|
||||
}
|
||||
|
||||
static int hns3_modify_tqp_num(struct net_device *netdev, u16 new_tqp_num)
|
||||
{
|
||||
struct hns3_nic_priv *priv = netdev_priv(netdev);
|
||||
struct hnae3_handle *h = hns3_get_handle(netdev);
|
||||
int ret;
|
||||
|
||||
ret = h->ae_algo->ops->set_channels(h, new_tqp_num);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = hns3_get_ring_config(priv);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = hns3_nic_init_vector_data(priv);
|
||||
if (ret)
|
||||
goto err_uninit_vector;
|
||||
|
||||
ret = hns3_init_all_ring(priv);
|
||||
if (ret)
|
||||
goto err_put_ring;
|
||||
|
||||
return 0;
|
||||
|
||||
err_put_ring:
|
||||
hns3_put_ring_config(priv);
|
||||
err_uninit_vector:
|
||||
hns3_nic_uninit_vector_data(priv);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int hns3_adjust_tqps_num(u8 num_tc, u32 new_tqp_num)
|
||||
{
|
||||
return (new_tqp_num / num_tc) * num_tc;
|
||||
}
|
||||
|
||||
int hns3_set_channels(struct net_device *netdev,
|
||||
struct ethtool_channels *ch)
|
||||
{
|
||||
struct hns3_nic_priv *priv = netdev_priv(netdev);
|
||||
struct hnae3_handle *h = hns3_get_handle(netdev);
|
||||
struct hnae3_knic_private_info *kinfo = &h->kinfo;
|
||||
bool if_running = netif_running(netdev);
|
||||
u32 new_tqp_num = ch->combined_count;
|
||||
u16 org_tqp_num;
|
||||
int ret;
|
||||
|
||||
if (ch->rx_count || ch->tx_count)
|
||||
return -EINVAL;
|
||||
|
||||
if (new_tqp_num > hns3_get_max_available_channels(netdev) ||
|
||||
new_tqp_num < kinfo->num_tc) {
|
||||
dev_err(&netdev->dev,
|
||||
"Change tqps fail, the tqp range is from %d to %d",
|
||||
kinfo->num_tc,
|
||||
hns3_get_max_available_channels(netdev));
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
new_tqp_num = hns3_adjust_tqps_num(kinfo->num_tc, new_tqp_num);
|
||||
if (kinfo->num_tqps == new_tqp_num)
|
||||
return 0;
|
||||
|
||||
if (if_running)
|
||||
dev_close(netdev);
|
||||
|
||||
hns3_clear_all_ring(h);
|
||||
|
||||
ret = hns3_nic_uninit_vector_data(priv);
|
||||
if (ret) {
|
||||
dev_err(&netdev->dev,
|
||||
"Unbind vector with tqp fail, nothing is changed");
|
||||
goto open_netdev;
|
||||
}
|
||||
|
||||
hns3_uninit_all_ring(priv);
|
||||
|
||||
org_tqp_num = h->kinfo.num_tqps;
|
||||
ret = hns3_modify_tqp_num(netdev, new_tqp_num);
|
||||
if (ret) {
|
||||
ret = hns3_modify_tqp_num(netdev, org_tqp_num);
|
||||
if (ret) {
|
||||
/* If revert to old tqp failed, fatal error occurred */
|
||||
dev_err(&netdev->dev,
|
||||
"Revert to old tqp num fail, ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
dev_info(&netdev->dev,
|
||||
"Change tqp num fail, Revert to old tqp num");
|
||||
}
|
||||
|
||||
open_netdev:
|
||||
if (if_running)
|
||||
dev_open(netdev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct hnae3_client_ops client_ops = {
|
||||
.init_instance = hns3_client_init,
|
||||
.uninit_instance = hns3_client_uninit,
|
||||
|
@ -595,6 +595,8 @@ static inline void hns3_write_reg(void __iomem *base, u32 reg, u32 value)
|
||||
(((struct hns3_nic_priv *)netdev_priv(ndev))->ae_handle)
|
||||
|
||||
void hns3_ethtool_set_ops(struct net_device *netdev);
|
||||
int hns3_set_channels(struct net_device *netdev,
|
||||
struct ethtool_channels *ch);
|
||||
|
||||
bool hns3_clean_tx_ring(struct hns3_enet_ring *ring, int budget);
|
||||
int hns3_init_all_ring(struct hns3_nic_priv *priv);
|
||||
|
@ -893,6 +893,7 @@ static const struct ethtool_ops hns3_ethtool_ops = {
|
||||
.set_link_ksettings = hns3_set_link_ksettings,
|
||||
.nway_reset = hns3_nway_reset,
|
||||
.get_channels = hns3_get_channels,
|
||||
.set_channels = hns3_set_channels,
|
||||
};
|
||||
|
||||
void hns3_ethtool_set_ops(struct net_device *netdev)
|
||||
|
@ -5022,6 +5022,116 @@ static void hclge_get_channels(struct hnae3_handle *handle,
|
||||
ch->combined_count = vport->alloc_tqps;
|
||||
}
|
||||
|
||||
static void hclge_get_tqps_and_rss_info(struct hnae3_handle *handle,
|
||||
u16 *free_tqps, u16 *max_rss_size)
|
||||
{
|
||||
struct hclge_vport *vport = hclge_get_vport(handle);
|
||||
struct hclge_dev *hdev = vport->back;
|
||||
u16 temp_tqps = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < hdev->num_tqps; i++) {
|
||||
if (!hdev->htqp[i].alloced)
|
||||
temp_tqps++;
|
||||
}
|
||||
*free_tqps = temp_tqps;
|
||||
*max_rss_size = hdev->rss_size_max;
|
||||
}
|
||||
|
||||
static void hclge_release_tqp(struct hclge_vport *vport)
|
||||
{
|
||||
struct hnae3_knic_private_info *kinfo = &vport->nic.kinfo;
|
||||
struct hclge_dev *hdev = vport->back;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < kinfo->num_tqps; i++) {
|
||||
struct hclge_tqp *tqp =
|
||||
container_of(kinfo->tqp[i], struct hclge_tqp, q);
|
||||
|
||||
tqp->q.handle = NULL;
|
||||
tqp->q.tqp_index = 0;
|
||||
tqp->alloced = false;
|
||||
}
|
||||
|
||||
devm_kfree(&hdev->pdev->dev, kinfo->tqp);
|
||||
kinfo->tqp = NULL;
|
||||
}
|
||||
|
||||
static int hclge_set_channels(struct hnae3_handle *handle, u32 new_tqps_num)
|
||||
{
|
||||
struct hclge_vport *vport = hclge_get_vport(handle);
|
||||
struct hnae3_knic_private_info *kinfo = &vport->nic.kinfo;
|
||||
struct hclge_dev *hdev = vport->back;
|
||||
int cur_rss_size = kinfo->rss_size;
|
||||
int cur_tqps = kinfo->num_tqps;
|
||||
u16 tc_offset[HCLGE_MAX_TC_NUM];
|
||||
u16 tc_valid[HCLGE_MAX_TC_NUM];
|
||||
u16 tc_size[HCLGE_MAX_TC_NUM];
|
||||
u16 roundup_size;
|
||||
u32 *rss_indir;
|
||||
int ret, i;
|
||||
|
||||
hclge_release_tqp(vport);
|
||||
|
||||
ret = hclge_knic_setup(vport, new_tqps_num);
|
||||
if (ret) {
|
||||
dev_err(&hdev->pdev->dev, "setup nic fail, ret =%d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = hclge_map_tqp_to_vport(hdev, vport);
|
||||
if (ret) {
|
||||
dev_err(&hdev->pdev->dev, "map vport tqp fail, ret =%d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = hclge_tm_schd_init(hdev);
|
||||
if (ret) {
|
||||
dev_err(&hdev->pdev->dev, "tm schd init fail, ret =%d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
roundup_size = roundup_pow_of_two(kinfo->rss_size);
|
||||
roundup_size = ilog2(roundup_size);
|
||||
/* Set the RSS TC mode according to the new RSS size */
|
||||
for (i = 0; i < HCLGE_MAX_TC_NUM; i++) {
|
||||
tc_valid[i] = 0;
|
||||
|
||||
if (!(hdev->hw_tc_map & BIT(i)))
|
||||
continue;
|
||||
|
||||
tc_valid[i] = 1;
|
||||
tc_size[i] = roundup_size;
|
||||
tc_offset[i] = kinfo->rss_size * i;
|
||||
}
|
||||
ret = hclge_set_rss_tc_mode(hdev, tc_valid, tc_size, tc_offset);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Reinitializes the rss indirect table according to the new RSS size */
|
||||
rss_indir = kcalloc(HCLGE_RSS_IND_TBL_SIZE, sizeof(u32), GFP_KERNEL);
|
||||
if (!rss_indir)
|
||||
return -ENOMEM;
|
||||
|
||||
for (i = 0; i < HCLGE_RSS_IND_TBL_SIZE; i++)
|
||||
rss_indir[i] = i % kinfo->rss_size;
|
||||
|
||||
ret = hclge_set_rss(handle, rss_indir, NULL, 0);
|
||||
if (ret)
|
||||
dev_err(&hdev->pdev->dev, "set rss indir table fail, ret=%d\n",
|
||||
ret);
|
||||
|
||||
kfree(rss_indir);
|
||||
|
||||
if (!ret)
|
||||
dev_info(&hdev->pdev->dev,
|
||||
"Channels changed, rss_size from %d to %d, tqps from %d to %d",
|
||||
cur_rss_size, kinfo->rss_size,
|
||||
cur_tqps, kinfo->rss_size * kinfo->num_tc);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct hnae3_ae_ops hclge_ops = {
|
||||
.init_ae_dev = hclge_init_ae_dev,
|
||||
.uninit_ae_dev = hclge_uninit_ae_dev,
|
||||
@ -5066,6 +5176,8 @@ static const struct hnae3_ae_ops hclge_ops = {
|
||||
.set_vlan_filter = hclge_set_port_vlan_filter,
|
||||
.set_vf_vlan_filter = hclge_set_vf_vlan_filter,
|
||||
.reset_event = hclge_reset_event,
|
||||
.get_tqps_and_rss_info = hclge_get_tqps_and_rss_info,
|
||||
.set_channels = hclge_set_channels,
|
||||
.get_channels = hclge_get_channels,
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user