net: hns3: Add DCB support when interacting with network stack
authorYunsheng Lin <linyunsheng@huawei.com>
Wed, 27 Sep 2017 01:45:32 +0000 (09:45 +0800)
committerDavid S. Miller <davem@davemloft.net>
Thu, 28 Sep 2017 17:35:12 +0000 (10:35 -0700)
When using lldptool to configure DCB parameter, hclge_dcb module
call the client_ops->setup_tc to tell network stack which queue
and priority is using for specific tc.

Signed-off-by: Yunsheng Lin <linyunsheng@huawei.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/hisilicon/hns3/hns3pf/hns3_enet.c

index 11dab26f35432c5cc2d60f3016be9ba37862af46..4a0890f98b70670d9d86ac63c4069409decc7e5f 100644 (file)
@@ -196,6 +196,32 @@ static void hns3_vector_gl_rl_init(struct hns3_enet_tqp_vector *tqp_vector)
        tqp_vector->tx_group.flow_level = HNS3_FLOW_LOW;
 }
 
+static int hns3_nic_set_real_num_queue(struct net_device *netdev)
+{
+       struct hns3_nic_priv *priv = netdev_priv(netdev);
+       struct hnae3_handle *h = priv->ae_handle;
+       struct hnae3_knic_private_info *kinfo = &h->kinfo;
+       unsigned int queue_size = kinfo->rss_size * kinfo->num_tc;
+       int ret;
+
+       ret = netif_set_real_num_tx_queues(netdev, queue_size);
+       if (ret) {
+               netdev_err(netdev,
+                          "netif_set_real_num_tx_queues fail, ret=%d!\n",
+                          ret);
+               return ret;
+       }
+
+       ret = netif_set_real_num_rx_queues(netdev, queue_size);
+       if (ret) {
+               netdev_err(netdev,
+                          "netif_set_real_num_rx_queues fail, ret=%d!\n", ret);
+               return ret;
+       }
+
+       return 0;
+}
+
 static int hns3_nic_net_up(struct net_device *netdev)
 {
        struct hns3_nic_priv *priv = netdev_priv(netdev);
@@ -232,26 +258,13 @@ out_start_err:
 
 static int hns3_nic_net_open(struct net_device *netdev)
 {
-       struct hns3_nic_priv *priv = netdev_priv(netdev);
-       struct hnae3_handle *h = priv->ae_handle;
        int ret;
 
        netif_carrier_off(netdev);
 
-       ret = netif_set_real_num_tx_queues(netdev, h->kinfo.num_tqps);
-       if (ret) {
-               netdev_err(netdev,
-                          "netif_set_real_num_tx_queues fail, ret=%d!\n",
-                          ret);
-               return ret;
-       }
-
-       ret = netif_set_real_num_rx_queues(netdev, h->kinfo.num_tqps);
-       if (ret) {
-               netdev_err(netdev,
-                          "netif_set_real_num_rx_queues fail, ret=%d!\n", ret);
+       ret = hns3_nic_set_real_num_queue(netdev);
+       if (ret)
                return ret;
-       }
 
        ret = hns3_nic_net_up(netdev);
        if (ret) {
@@ -2848,10 +2861,69 @@ static void hns3_link_status_change(struct hnae3_handle *handle, bool linkup)
        }
 }
 
+static int hns3_client_setup_tc(struct hnae3_handle *handle, u8 tc)
+{
+       struct hnae3_knic_private_info *kinfo = &handle->kinfo;
+       struct net_device *ndev = kinfo->netdev;
+       bool if_running = netif_running(ndev);
+       int ret;
+       u8 i;
+
+       if (tc > HNAE3_MAX_TC)
+               return -EINVAL;
+
+       if (!ndev)
+               return -ENODEV;
+
+       ret = netdev_set_num_tc(ndev, tc);
+       if (ret)
+               return ret;
+
+       if (if_running) {
+               (void)hns3_nic_net_stop(ndev);
+               msleep(100);
+       }
+
+       ret = (kinfo->dcb_ops && kinfo->dcb_ops->map_update) ?
+               kinfo->dcb_ops->map_update(handle) : -EOPNOTSUPP;
+       if (ret)
+               goto err_out;
+
+       if (tc <= 1) {
+               netdev_reset_tc(ndev);
+               goto out;
+       }
+
+       for (i = 0; i < HNAE3_MAX_TC; i++) {
+               struct hnae3_tc_info *tc_info = &kinfo->tc_info[i];
+
+               if (tc_info->enable)
+                       netdev_set_tc_queue(ndev,
+                                           tc_info->tc,
+                                           tc_info->tqp_count,
+                                           tc_info->tqp_offset);
+       }
+
+       for (i = 0; i < HNAE3_MAX_USER_PRIO; i++) {
+               netdev_set_prio_tc_map(ndev, i,
+                                      kinfo->prio_tc[i]);
+       }
+
+out:
+       ret = hns3_nic_set_real_num_queue(ndev);
+
+err_out:
+       if (if_running)
+               (void)hns3_nic_net_open(ndev);
+
+       return ret;
+}
+
 const struct hnae3_client_ops client_ops = {
        .init_instance = hns3_client_init,
        .uninit_instance = hns3_client_uninit,
        .link_status_change = hns3_link_status_change,
+       .setup_tc = hns3_client_setup_tc,
 };
 
 /* hns3_init_module - Driver registration routine