diff options
Diffstat (limited to 'drivers/net/ethernet/hisilicon/hns3/hns3_enet.c')
-rw-r--r-- | drivers/net/ethernet/hisilicon/hns3/hns3_enet.c | 286 |
1 files changed, 195 insertions, 91 deletions
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c index 601b6295d3f8..94f0b92ead38 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c @@ -168,8 +168,8 @@ void hns3_set_vector_coalesce_rl(struct hns3_enet_tqp_vector *tqp_vector, * GL and RL(Rate Limiter) are 2 ways to acheive interrupt coalescing */ - if (rl_reg > 0 && !tqp_vector->tx_group.gl_adapt_enable && - !tqp_vector->rx_group.gl_adapt_enable) + if (rl_reg > 0 && !tqp_vector->tx_group.coal.gl_adapt_enable && + !tqp_vector->rx_group.coal.gl_adapt_enable) /* According to the hardware, the range of rl_reg is * 0-59 and the unit is 4. */ @@ -205,23 +205,29 @@ static void hns3_vector_gl_rl_init(struct hns3_enet_tqp_vector *tqp_vector, */ /* Default: enable interrupt coalescing self-adaptive and GL */ - tqp_vector->tx_group.gl_adapt_enable = 1; - tqp_vector->rx_group.gl_adapt_enable = 1; + tqp_vector->tx_group.coal.gl_adapt_enable = 1; + tqp_vector->rx_group.coal.gl_adapt_enable = 1; - tqp_vector->tx_group.int_gl = HNS3_INT_GL_50K; - tqp_vector->rx_group.int_gl = HNS3_INT_GL_50K; - - hns3_set_vector_coalesce_tx_gl(tqp_vector, - tqp_vector->tx_group.int_gl); - hns3_set_vector_coalesce_rx_gl(tqp_vector, - tqp_vector->rx_group.int_gl); + tqp_vector->tx_group.coal.int_gl = HNS3_INT_GL_50K; + tqp_vector->rx_group.coal.int_gl = HNS3_INT_GL_50K; /* Default: disable RL */ h->kinfo.int_rl_setting = 0; - hns3_set_vector_coalesce_rl(tqp_vector, h->kinfo.int_rl_setting); - tqp_vector->rx_group.flow_level = HNS3_FLOW_LOW; - tqp_vector->tx_group.flow_level = HNS3_FLOW_LOW; + tqp_vector->rx_group.coal.flow_level = HNS3_FLOW_LOW; + tqp_vector->tx_group.coal.flow_level = HNS3_FLOW_LOW; +} + +static void hns3_vector_gl_rl_init_hw(struct hns3_enet_tqp_vector *tqp_vector, + struct hns3_nic_priv *priv) +{ + struct hnae3_handle *h = priv->ae_handle; + + hns3_set_vector_coalesce_tx_gl(tqp_vector, + tqp_vector->tx_group.coal.int_gl); + hns3_set_vector_coalesce_rx_gl(tqp_vector, + tqp_vector->rx_group.coal.int_gl); + hns3_set_vector_coalesce_rl(tqp_vector, h->kinfo.int_rl_setting); } static int hns3_nic_set_real_num_queue(struct net_device *netdev) @@ -249,6 +255,16 @@ static int hns3_nic_set_real_num_queue(struct net_device *netdev) return 0; } +static u16 hns3_get_max_available_channels(struct hnae3_handle *h) +{ + 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_nic_net_up(struct net_device *netdev) { struct hns3_nic_priv *priv = netdev_priv(netdev); @@ -1104,7 +1120,7 @@ static int hns3_nic_net_set_mac_address(struct net_device *netdev, void *p) if (!mac_addr || !is_valid_ether_addr((const u8 *)mac_addr->sa_data)) return -EADDRNOTAVAIL; - ret = h->ae_algo->ops->set_mac_addr(h, mac_addr->sa_data); + ret = h->ae_algo->ops->set_mac_addr(h, mac_addr->sa_data, false); if (ret) { netdev_err(netdev, "set_mac_address fail, ret=%d!\n", ret); return ret; @@ -2064,15 +2080,13 @@ static void hns3_nic_reuse_page(struct sk_buff *skb, int i, desc = &ring->desc[ring->next_to_clean]; size = le16_to_cpu(desc->rx.size); - if (twobufs) { - truesize = hnae_buf_size(ring); - } else { - truesize = ALIGN(size, L1_CACHE_BYTES); + truesize = hnae_buf_size(ring); + + if (!twobufs) last_offset = hnae_page_size(ring) - hnae_buf_size(ring); - } skb_add_rx_frag(skb, i, desc_cb->priv, desc_cb->page_offset + pull_len, - size - pull_len, truesize - pull_len); + size - pull_len, truesize); /* Avoid re-using remote pages,flag default unreuse */ if (unlikely(page_to_nid(desc_cb->priv) != numa_node_id())) @@ -2377,12 +2391,12 @@ static bool hns3_get_new_int_gl(struct hns3_enet_ring_group *ring_group) u16 new_int_gl; int usecs; - if (!ring_group->int_gl) + if (!ring_group->coal.int_gl) return false; if (ring_group->total_packets == 0) { - ring_group->int_gl = HNS3_INT_GL_50K; - ring_group->flow_level = HNS3_FLOW_LOW; + ring_group->coal.int_gl = HNS3_INT_GL_50K; + ring_group->coal.flow_level = HNS3_FLOW_LOW; return true; } @@ -2392,10 +2406,10 @@ static bool hns3_get_new_int_gl(struct hns3_enet_ring_group *ring_group) * 20-1249MB/s high (18000 ints/s) * > 40000pps ultra (8000 ints/s) */ - new_flow_level = ring_group->flow_level; - new_int_gl = ring_group->int_gl; + new_flow_level = ring_group->coal.flow_level; + new_int_gl = ring_group->coal.int_gl; tqp_vector = ring_group->ring->tqp_vector; - usecs = (ring_group->int_gl << 1); + usecs = (ring_group->coal.int_gl << 1); bytes_per_usecs = ring_group->total_bytes / usecs; /* 1000000 microseconds */ packets_per_secs = ring_group->total_packets * 1000000 / usecs; @@ -2442,9 +2456,9 @@ static bool hns3_get_new_int_gl(struct hns3_enet_ring_group *ring_group) ring_group->total_bytes = 0; ring_group->total_packets = 0; - ring_group->flow_level = new_flow_level; - if (new_int_gl != ring_group->int_gl) { - ring_group->int_gl = new_int_gl; + ring_group->coal.flow_level = new_flow_level; + if (new_int_gl != ring_group->coal.int_gl) { + ring_group->coal.int_gl = new_int_gl; return true; } return false; @@ -2456,18 +2470,18 @@ static void hns3_update_new_int_gl(struct hns3_enet_tqp_vector *tqp_vector) struct hns3_enet_ring_group *tx_group = &tqp_vector->tx_group; bool rx_update, tx_update; - if (rx_group->gl_adapt_enable) { + if (rx_group->coal.gl_adapt_enable) { rx_update = hns3_get_new_int_gl(rx_group); if (rx_update) hns3_set_vector_coalesce_rx_gl(tqp_vector, - rx_group->int_gl); + rx_group->coal.int_gl); } - if (tx_group->gl_adapt_enable) { + if (tx_group->coal.gl_adapt_enable) { tx_update = hns3_get_new_int_gl(&tqp_vector->tx_group); if (tx_update) hns3_set_vector_coalesce_tx_gl(tqp_vector, - tx_group->int_gl); + tx_group->coal.int_gl); } } @@ -2615,32 +2629,18 @@ static int hns3_nic_init_vector_data(struct hns3_nic_priv *priv) struct hnae3_ring_chain_node vector_ring_chain; struct hnae3_handle *h = priv->ae_handle; struct hns3_enet_tqp_vector *tqp_vector; - struct hnae3_vector_info *vector; - struct pci_dev *pdev = h->pdev; - u16 tqp_num = h->kinfo.num_tqps; - u16 vector_num; int ret = 0; u16 i; - /* RSS size, cpu online and vector_num should be the same */ - /* Should consider 2p/4p later */ - vector_num = min_t(u16, num_online_cpus(), tqp_num); - vector = devm_kcalloc(&pdev->dev, vector_num, sizeof(*vector), - GFP_KERNEL); - if (!vector) - return -ENOMEM; - - vector_num = h->ae_algo->ops->get_vector(h, vector_num, vector); - - priv->vector_num = vector_num; - priv->tqp_vector = (struct hns3_enet_tqp_vector *) - devm_kcalloc(&pdev->dev, vector_num, sizeof(*priv->tqp_vector), - GFP_KERNEL); - if (!priv->tqp_vector) - return -ENOMEM; + for (i = 0; i < priv->vector_num; i++) { + tqp_vector = &priv->tqp_vector[i]; + hns3_vector_gl_rl_init_hw(tqp_vector, priv); + tqp_vector->num_tqps = 0; + } - for (i = 0; i < tqp_num; i++) { - u16 vector_i = i % vector_num; + for (i = 0; i < h->kinfo.num_tqps; i++) { + u16 vector_i = i % priv->vector_num; + u16 tqp_num = h->kinfo.num_tqps; tqp_vector = &priv->tqp_vector[vector_i]; @@ -2650,52 +2650,94 @@ static int hns3_nic_init_vector_data(struct hns3_nic_priv *priv) hns3_add_ring_to_group(&tqp_vector->rx_group, priv->ring_data[i + tqp_num].ring); - tqp_vector->idx = vector_i; - tqp_vector->mask_addr = vector[vector_i].io_addr; - tqp_vector->vector_irq = vector[vector_i].vector; - tqp_vector->num_tqps++; - priv->ring_data[i].ring->tqp_vector = tqp_vector; priv->ring_data[i + tqp_num].ring->tqp_vector = tqp_vector; + tqp_vector->num_tqps++; } - for (i = 0; i < vector_num; i++) { + for (i = 0; i < priv->vector_num; i++) { tqp_vector = &priv->tqp_vector[i]; tqp_vector->rx_group.total_bytes = 0; tqp_vector->rx_group.total_packets = 0; tqp_vector->tx_group.total_bytes = 0; tqp_vector->tx_group.total_packets = 0; - hns3_vector_gl_rl_init(tqp_vector, priv); tqp_vector->handle = h; ret = hns3_get_vector_ring_chain(tqp_vector, &vector_ring_chain); if (ret) - goto out; + return ret; ret = h->ae_algo->ops->map_ring_to_vector(h, tqp_vector->vector_irq, &vector_ring_chain); - if (ret) - goto out; hns3_free_vector_ring_chain(tqp_vector, &vector_ring_chain); + if (ret) + return ret; + netif_napi_add(priv->netdev, &tqp_vector->napi, hns3_nic_common_poll, NAPI_POLL_WEIGHT); } + return 0; +} + +static int hns3_nic_alloc_vector_data(struct hns3_nic_priv *priv) +{ + struct hnae3_handle *h = priv->ae_handle; + struct hns3_enet_tqp_vector *tqp_vector; + struct hnae3_vector_info *vector; + struct pci_dev *pdev = h->pdev; + u16 tqp_num = h->kinfo.num_tqps; + u16 vector_num; + int ret = 0; + u16 i; + + /* RSS size, cpu online and vector_num should be the same */ + /* Should consider 2p/4p later */ + vector_num = min_t(u16, num_online_cpus(), tqp_num); + vector = devm_kcalloc(&pdev->dev, vector_num, sizeof(*vector), + GFP_KERNEL); + if (!vector) + return -ENOMEM; + + vector_num = h->ae_algo->ops->get_vector(h, vector_num, vector); + + priv->vector_num = vector_num; + priv->tqp_vector = (struct hns3_enet_tqp_vector *) + devm_kcalloc(&pdev->dev, vector_num, sizeof(*priv->tqp_vector), + GFP_KERNEL); + if (!priv->tqp_vector) { + ret = -ENOMEM; + goto out; + } + + for (i = 0; i < priv->vector_num; i++) { + tqp_vector = &priv->tqp_vector[i]; + tqp_vector->idx = i; + tqp_vector->mask_addr = vector[i].io_addr; + tqp_vector->vector_irq = vector[i].vector; + hns3_vector_gl_rl_init(tqp_vector, priv); + } + out: devm_kfree(&pdev->dev, vector); return ret; } +static void hns3_clear_ring_group(struct hns3_enet_ring_group *group) +{ + group->ring = NULL; + group->count = 0; +} + static int hns3_nic_uninit_vector_data(struct hns3_nic_priv *priv) { struct hnae3_ring_chain_node vector_ring_chain; struct hnae3_handle *h = priv->ae_handle; struct hns3_enet_tqp_vector *tqp_vector; - struct pci_dev *pdev = h->pdev; int i, ret; for (i = 0; i < priv->vector_num; i++) { @@ -2711,6 +2753,10 @@ static int hns3_nic_uninit_vector_data(struct hns3_nic_priv *priv) if (ret) return ret; + ret = h->ae_algo->ops->put_vector(h, tqp_vector->vector_irq); + if (ret) + return ret; + hns3_free_vector_ring_chain(tqp_vector, &vector_ring_chain); if (priv->tqp_vector[i].irq_init_flag == HNS3_VECTOR_INITED) { @@ -2722,12 +2768,30 @@ static int hns3_nic_uninit_vector_data(struct hns3_nic_priv *priv) } priv->ring_data[i].ring->irq_init_flag = HNS3_VECTOR_NOT_INITED; - + hns3_clear_ring_group(&tqp_vector->rx_group); + hns3_clear_ring_group(&tqp_vector->tx_group); netif_napi_del(&priv->tqp_vector[i].napi); } - devm_kfree(&pdev->dev, priv->tqp_vector); + return 0; +} + +static int hns3_nic_dealloc_vector_data(struct hns3_nic_priv *priv) +{ + struct hnae3_handle *h = priv->ae_handle; + struct pci_dev *pdev = h->pdev; + int i, ret; + + for (i = 0; i < priv->vector_num; i++) { + struct hns3_enet_tqp_vector *tqp_vector; + + tqp_vector = &priv->tqp_vector[i]; + ret = h->ae_algo->ops->put_vector(h, tqp_vector->vector_irq); + if (ret) + return ret; + } + devm_kfree(&pdev->dev, priv->tqp_vector); return 0; } @@ -2957,13 +3021,8 @@ int hns3_uninit_all_ring(struct hns3_nic_priv *priv) h->ae_algo->ops->reset_queue(h, i); hns3_fini_ring(priv->ring_data[i].ring); - devm_kfree(priv->dev, priv->ring_data[i].ring); hns3_fini_ring(priv->ring_data[i + h->kinfo.num_tqps].ring); - devm_kfree(priv->dev, - priv->ring_data[i + h->kinfo.num_tqps].ring); } - devm_kfree(priv->dev, priv->ring_data); - return 0; } @@ -2987,7 +3046,7 @@ static void hns3_init_mac_addr(struct net_device *netdev) } if (h->ae_algo->ops->set_mac_addr) - h->ae_algo->ops->set_mac_addr(h, netdev->dev_addr); + h->ae_algo->ops->set_mac_addr(h, netdev->dev_addr, true); } @@ -3013,7 +3072,7 @@ static int hns3_client_init(struct hnae3_handle *handle) int ret; netdev = alloc_etherdev_mq(sizeof(struct hns3_nic_priv), - handle->kinfo.num_tqps); + hns3_get_max_available_channels(handle)); if (!netdev) return -ENOMEM; @@ -3048,6 +3107,12 @@ static int hns3_client_init(struct hnae3_handle *handle) goto out_get_ring_cfg; } + ret = hns3_nic_alloc_vector_data(priv); + if (ret) { + ret = -ENOMEM; + goto out_alloc_vector_data; + } + ret = hns3_nic_init_vector_data(priv); if (ret) { ret = -ENOMEM; @@ -3076,8 +3141,10 @@ static int hns3_client_init(struct hnae3_handle *handle) out_reg_netdev_fail: out_init_ring_data: (void)hns3_nic_uninit_vector_data(priv); - priv->ring_data = NULL; out_init_vector_data: + hns3_nic_dealloc_vector_data(priv); +out_alloc_vector_data: + priv->ring_data = NULL; out_get_ring_cfg: priv->ae_handle = NULL; free_netdev(netdev); @@ -3097,10 +3164,16 @@ static void hns3_client_uninit(struct hnae3_handle *handle, bool reset) if (ret) netdev_err(netdev, "uninit vector error\n"); + ret = hns3_nic_dealloc_vector_data(priv); + if (ret) + netdev_err(netdev, "dealloc vector error\n"); + ret = hns3_uninit_all_ring(priv); if (ret) netdev_err(netdev, "uninit ring error\n"); + hns3_put_ring_config(priv); + priv->ring_data = NULL; free_netdev(netdev); @@ -3306,6 +3379,8 @@ static int hns3_reset_notify_uninit_enet(struct hnae3_handle *handle) if (ret) netdev_err(netdev, "uninit ring error\n"); + hns3_put_ring_config(priv); + priv->ring_data = NULL; return ret; @@ -3336,18 +3411,24 @@ static int hns3_reset_notify(struct hnae3_handle *handle, return ret; } -static u16 hns3_get_max_available_channels(struct net_device *netdev) +static void hns3_restore_coal(struct hns3_nic_priv *priv, + struct hns3_enet_coalesce *tx, + struct hns3_enet_coalesce *rx) { - 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; + u16 vector_num = priv->vector_num; + int i; - return min_t(u16, max_tqps, (free_tqps + h->kinfo.num_tqps)); + for (i = 0; i < vector_num; i++) { + memcpy(&priv->tqp_vector[i].tx_group.coal, tx, + sizeof(struct hns3_enet_coalesce)); + memcpy(&priv->tqp_vector[i].rx_group.coal, rx, + sizeof(struct hns3_enet_coalesce)); + } } -static int hns3_modify_tqp_num(struct net_device *netdev, u16 new_tqp_num) +static int hns3_modify_tqp_num(struct net_device *netdev, u16 new_tqp_num, + struct hns3_enet_coalesce *tx, + struct hns3_enet_coalesce *rx) { struct hns3_nic_priv *priv = netdev_priv(netdev); struct hnae3_handle *h = hns3_get_handle(netdev); @@ -3361,6 +3442,12 @@ static int hns3_modify_tqp_num(struct net_device *netdev, u16 new_tqp_num) if (ret) return ret; + ret = hns3_nic_alloc_vector_data(priv); + if (ret) + goto err_alloc_vector; + + hns3_restore_coal(priv, tx, rx); + ret = hns3_nic_init_vector_data(priv); if (ret) goto err_uninit_vector; @@ -3375,6 +3462,8 @@ err_put_ring: hns3_put_ring_config(priv); err_uninit_vector: hns3_nic_uninit_vector_data(priv); +err_alloc_vector: + hns3_nic_dealloc_vector_data(priv); return ret; } @@ -3389,6 +3478,7 @@ int hns3_set_channels(struct net_device *netdev, struct hns3_nic_priv *priv = netdev_priv(netdev); struct hnae3_handle *h = hns3_get_handle(netdev); struct hnae3_knic_private_info *kinfo = &h->kinfo; + struct hns3_enet_coalesce tx_coal, rx_coal; bool if_running = netif_running(netdev); u32 new_tqp_num = ch->combined_count; u16 org_tqp_num; @@ -3397,12 +3487,12 @@ int hns3_set_channels(struct net_device *netdev, if (ch->rx_count || ch->tx_count) return -EINVAL; - if (new_tqp_num > hns3_get_max_available_channels(netdev) || + if (new_tqp_num > hns3_get_max_available_channels(h) || 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)); + hns3_get_max_available_channels(h)); return -EINVAL; } @@ -3411,7 +3501,7 @@ int hns3_set_channels(struct net_device *netdev, return 0; if (if_running) - dev_close(netdev); + hns3_nic_net_stop(netdev); hns3_clear_all_ring(h); @@ -3422,12 +3512,26 @@ int hns3_set_channels(struct net_device *netdev, goto open_netdev; } + /* Changing the tqp num may also change the vector num, + * ethtool only support setting and querying one coal + * configuation for now, so save the vector 0' coal + * configuation here in order to restore it. + */ + memcpy(&tx_coal, &priv->tqp_vector[0].tx_group.coal, + sizeof(struct hns3_enet_coalesce)); + memcpy(&rx_coal, &priv->tqp_vector[0].rx_group.coal, + sizeof(struct hns3_enet_coalesce)); + + hns3_nic_dealloc_vector_data(priv); + hns3_uninit_all_ring(priv); + hns3_put_ring_config(priv); org_tqp_num = h->kinfo.num_tqps; - ret = hns3_modify_tqp_num(netdev, new_tqp_num); + ret = hns3_modify_tqp_num(netdev, new_tqp_num, &tx_coal, &rx_coal); if (ret) { - ret = hns3_modify_tqp_num(netdev, org_tqp_num); + ret = hns3_modify_tqp_num(netdev, org_tqp_num, + &tx_coal, &rx_coal); if (ret) { /* If revert to old tqp failed, fatal error occurred */ dev_err(&netdev->dev, @@ -3440,7 +3544,7 @@ int hns3_set_channels(struct net_device *netdev, open_netdev: if (if_running) - dev_open(netdev); + hns3_nic_net_open(netdev); return ret; } |