Merge tag 'for-linus-2' of git://git.kernel.org/pub/scm/linux/kernel/git/dledford...
authorLinus Torvalds <torvalds@linux-foundation.org>
Fri, 14 Oct 2016 20:35:05 +0000 (13:35 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Fri, 14 Oct 2016 20:35:05 +0000 (13:35 -0700)
Pull more rdma updates from Doug Ledford:
 "This merge window was the first where Huawei had to try and coordinate
  their patches between their net driver and their new roce driver
  (similar to mlx4 and mlx5).

  They didn't do horribly, but there were some issues (and we knew that
  because they simply didn't know what to do in the beginning). As a
  result, I had a set of patches that depended on some patches that
  normally would have come to you via Dave's tree. Those patches have
  been on netdev@ for a while, so I got Dave to give me his approval to
  send them to you. As such, the other 29 patches I had behind them are
  also now ready to go.

  This catches the hns and hns-roce drivers up to current, and for
  future patches we are working with them to get them up to speed on how
  to do joint driver development so that they don't have these sorts of
  cross tree dependency issues again. BTW, Dave gave me permission to
  add his Acked-by: to the patches against the net tree, but I've had
  this branch through 0day (but not linux-next since it was off by
  itself) and I didn't want to rebase the series just to add Dave's ack
  for the 8 patches in the net area.

  Updates to the hns drivers:

   - Small patch set for hns net driver that the roce patches depend on

   - Various fixes to the hns-roce driver

   - Add connection manager support to the hns-roce driver"

* tag 'for-linus-2' of git://git.kernel.org/pub/scm/linux/kernel/git/dledford/rdma: (36 commits)
  IB/hns: Fix for removal of redundant code
  IB/hns: Delete the redundant lines in hns_roce_v1_m_qp()
  IB/hns: Fix the bug when platform_get_resource() exec fail
  IB/hns: Update the rq head when modify qp state
  IB/hns: Cq has not been freed
  IB/hns: Validate mtu when modified qp
  IB/hns: Some items of qpc need to take user param
  IB/hns: The Ack timeout need a lower limit value
  IB/hns: Return bad wr while post send failed
  IB/hns: Fix bug of memory leakage for registering user mr
  IB/hns: Modify the init of iboe lock
  IB/hns: Optimize code of aeq and ceq interrupt handle and fix the bug of qpn
  IB/hns: Delete the sqp_start from the structure hns_roce_caps
  IB/hns: Fix bug of clear hem
  IB/hns: Remove unused parameter named qp_type
  IB/hns: Simplify function of pd alloc and qp alloc
  IB/hns: Fix bug of using uninit refcount and free
  IB/hns: Remove parameters of resize cq
  IB/hns: Remove unused parameters in some functions
  IB/hns: Add node_guid definition to the bindings document
  ...

1  2 
drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c
drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c
drivers/net/ethernet/hisilicon/hns/hns_enet.c
drivers/net/ethernet/hisilicon/hns/hns_ethtool.c

index 22e141005cd92df0ef615ba30ffbcc4a020150f7,151fd6e107e513ea9d4487f94338f378ec2c22d5..ec8c738af726323e92c2416a639806462f0bfe4b
@@@ -126,7 -126,7 +126,7 @@@ void hns_mac_adjust_link(struct hns_mac
                        (enum mac_speed)speed, duplex);
                if (ret) {
                        dev_err(mac_cb->dev,
 -                              "adjust_link failed,%s mac%d ret = %#x!\n",
 +                              "adjust_link failed, %s mac%d ret = %#x!\n",
                                mac_cb->dsaf_dev->ae_dev.name,
                                mac_cb->mac_id, ret);
                        return;
   *@port_num:port number
   *
   */
- static int hns_mac_get_inner_port_num(struct hns_mac_cb *mac_cb,
-                                     u8 vmid, u8 *port_num)
+ int hns_mac_get_inner_port_num(struct hns_mac_cb *mac_cb, u8 vmid, u8 *port_num)
  {
+       int q_num_per_vf, vf_num_per_port;
+       int vm_queue_id;
        u8 tmp_port;
  
        if (mac_cb->dsaf_dev->dsaf_mode <= DSAF_MODE_ENABLE) {
                if (mac_cb->mac_id != DSAF_MAX_PORT_NUM) {
                        dev_err(mac_cb->dev,
 -                              "input invalid,%s mac%d vmid%d !\n",
 +                              "input invalid, %s mac%d vmid%d !\n",
                                mac_cb->dsaf_dev->ae_dev.name,
                                mac_cb->mac_id, vmid);
                        return -EINVAL;
        } else if (mac_cb->dsaf_dev->dsaf_mode < DSAF_MODE_MAX) {
                if (mac_cb->mac_id >= DSAF_MAX_PORT_NUM) {
                        dev_err(mac_cb->dev,
 -                              "input invalid,%s mac%d vmid%d!\n",
 +                              "input invalid, %s mac%d vmid%d!\n",
                                mac_cb->dsaf_dev->ae_dev.name,
                                mac_cb->mac_id, vmid);
                        return -EINVAL;
                }
        } else {
 -              dev_err(mac_cb->dev, "dsaf mode invalid,%s mac%d!\n",
 +              dev_err(mac_cb->dev, "dsaf mode invalid, %s mac%d!\n",
                        mac_cb->dsaf_dev->ae_dev.name, mac_cb->mac_id);
                return -EINVAL;
        }
  
        if (vmid >= mac_cb->dsaf_dev->rcb_common[0]->max_vfn) {
 -              dev_err(mac_cb->dev, "input invalid,%s mac%d vmid%d !\n",
 +              dev_err(mac_cb->dev, "input invalid, %s mac%d vmid%d !\n",
                        mac_cb->dsaf_dev->ae_dev.name, mac_cb->mac_id, vmid);
                return -EINVAL;
        }
  
+       q_num_per_vf = mac_cb->dsaf_dev->rcb_common[0]->max_q_per_vf;
+       vf_num_per_port = mac_cb->dsaf_dev->rcb_common[0]->max_vfn;
+       vm_queue_id = vmid * q_num_per_vf +
+                       vf_num_per_port * q_num_per_vf * mac_cb->mac_id;
        switch (mac_cb->dsaf_dev->dsaf_mode) {
        case DSAF_MODE_ENABLE_FIX:
                tmp_port = 0;
        case DSAF_MODE_DISABLE_6PORT_2VM:
        case DSAF_MODE_DISABLE_6PORT_4VM:
        case DSAF_MODE_DISABLE_6PORT_16VM:
-               tmp_port = vmid;
+               tmp_port = vm_queue_id;
                break;
        default:
 -              dev_err(mac_cb->dev, "dsaf mode invalid,%s mac%d!\n",
 +              dev_err(mac_cb->dev, "dsaf mode invalid, %s mac%d!\n",
                        mac_cb->dsaf_dev->ae_dev.name, mac_cb->mac_id);
                return -EINVAL;
        }
@@@ -275,7 -282,7 +282,7 @@@ int hns_mac_set_multi(struct hns_mac_c
                        ret = hns_dsaf_add_mac_mc_port(dsaf_dev, &mac_entry);
                if (ret) {
                        dev_err(dsaf_dev->dev,
 -                              "set mac mc port failed,%s mac%d ret = %#x!\n",
 +                              "set mac mc port failed, %s mac%d ret = %#x!\n",
                                mac_cb->dsaf_dev->ae_dev.name,
                                mac_cb->mac_id, ret);
                        return ret;
@@@ -305,7 -312,7 +312,7 @@@ int hns_mac_del_mac(struct hns_mac_cb *
                old_mac = &mac_cb->addr_entry_idx[vfn];
        } else {
                dev_err(mac_cb->dev,
 -                      "vf queue is too large,%s mac%d queue = %#x!\n",
 +                      "vf queue is too large, %s mac%d queue = %#x!\n",
                        mac_cb->dsaf_dev->ae_dev.name, mac_cb->mac_id, vfn);
                return -EINVAL;
        }
@@@ -547,7 -554,7 +554,7 @@@ int hns_mac_set_autoneg(struct hns_mac_
        struct mac_driver *mac_ctrl_drv = hns_mac_get_drv(mac_cb);
  
        if (mac_cb->phy_if == PHY_INTERFACE_MODE_XGMII && enable) {
 -              dev_err(mac_cb->dev, "enable autoneg is not allowed!");
 +              dev_err(mac_cb->dev, "enabling autoneg is not allowed!\n");
                return -ENOTSUPP;
        }
  
@@@ -571,7 -578,7 +578,7 @@@ int hns_mac_set_pauseparam(struct hns_m
  
        if (mac_cb->mac_type == HNAE_PORT_DEBUG) {
                if (is_ver1 && (tx_en || rx_en)) {
 -                      dev_err(mac_cb->dev, "macv1 cann't enable tx/rx_pause!");
 +                      dev_err(mac_cb->dev, "macv1 can't enable tx/rx_pause!\n");
                        return -EINVAL;
                }
        }
@@@ -926,7 -933,7 +933,7 @@@ int hns_mac_get_cfg(struct dsaf_device 
        ret = hns_mac_get_mode(mac_cb->phy_if);
        if (ret < 0) {
                dev_err(dsaf_dev->dev,
 -                      "hns_mac_get_mode failed,mac%d ret = %#x!\n",
 +                      "hns_mac_get_mode failed, mac%d ret = %#x!\n",
                        mac_cb->mac_id, ret);
                return ret;
        }
index 8e5b3f51b47b80201d7c447a9f061116b69e141c,827d8fb723707571aab8f47a99563bd45b8f847d..8d70377f6624cb5d1cd55ae9916af6f75ee934b4
@@@ -116,8 -116,10 +116,8 @@@ int hns_dsaf_get_cfg(struct dsaf_devic
  
                        dsaf_dev->sc_base = devm_ioremap_resource(&pdev->dev,
                                                                  res);
 -                      if (IS_ERR(dsaf_dev->sc_base)) {
 -                              dev_err(dsaf_dev->dev, "subctrl can not map!\n");
 +                      if (IS_ERR(dsaf_dev->sc_base))
                                return PTR_ERR(dsaf_dev->sc_base);
 -                      }
  
                        res = platform_get_resource(pdev, IORESOURCE_MEM,
                                                    res_idx++);
  
                        dsaf_dev->sds_base = devm_ioremap_resource(&pdev->dev,
                                                                   res);
 -                      if (IS_ERR(dsaf_dev->sds_base)) {
 -                              dev_err(dsaf_dev->dev, "serdes-ctrl can not map!\n");
 +                      if (IS_ERR(dsaf_dev->sds_base))
                                return PTR_ERR(dsaf_dev->sds_base);
 -                      }
                } else {
                        dsaf_dev->sub_ctrl = syscon;
                }
                }
        }
        dsaf_dev->ppe_base = devm_ioremap_resource(&pdev->dev, res);
 -      if (IS_ERR(dsaf_dev->ppe_base)) {
 -              dev_err(dsaf_dev->dev, "ppe-base resource can not map!\n");
 +      if (IS_ERR(dsaf_dev->ppe_base))
                return PTR_ERR(dsaf_dev->ppe_base);
 -      }
        dsaf_dev->ppe_paddr = res->start;
  
        if (!HNS_DSAF_IS_DEBUG(dsaf_dev)) {
                        }
                }
                dsaf_dev->io_base = devm_ioremap_resource(&pdev->dev, res);
 -              if (IS_ERR(dsaf_dev->io_base)) {
 -                      dev_err(dsaf_dev->dev, "dsaf-base resource can not map!\n");
 +              if (IS_ERR(dsaf_dev->io_base))
                        return PTR_ERR(dsaf_dev->io_base);
 -              }
        }
  
        ret = device_property_read_u32(dsaf_dev->dev, "desc-num", &desc_num);
@@@ -760,16 -768,6 +760,6 @@@ void hns_dsaf_set_promisc_mode(struct d
                                 DSAF_CFG_MIX_MODE_S, !!en);
  }
  
- void hns_dsaf_set_inner_lb(struct dsaf_device *dsaf_dev, u32 mac_id, u32 en)
- {
-       if (AE_IS_VER1(dsaf_dev->dsaf_ver) ||
-           dsaf_dev->mac_cb[mac_id]->mac_type == HNAE_PORT_DEBUG)
-               return;
-       dsaf_set_dev_bit(dsaf_dev, DSAFV2_SERDES_LBK_0_REG + 4 * mac_id,
-                        DSAFV2_SERDES_LBK_EN_B, !!en);
- }
  /**
   * hns_dsaf_tbl_stat_en - tbl
   * @dsaf_id: dsa fabric id
index 059aaeda46b139492b00d645c73e51e4279fb6c6,a7abe118b5f0bae06480fa1d50f650f226085257..dff7b60345d8e94b90a53f16d2c9caadde1b449a
@@@ -574,7 -574,6 +574,6 @@@ static int hns_nic_poll_rx_skb(struct h
        struct sk_buff *skb;
        struct hnae_desc *desc;
        struct hnae_desc_cb *desc_cb;
-       struct ethhdr *eh;
        unsigned char *va;
        int bnum, length, i;
        int pull_len;
                ring->stats.sw_err_cnt++;
                return -ENOMEM;
        }
-       skb_reset_mac_header(skb);
  
        prefetchw(skb->data);
        length = le16_to_cpu(desc->rx.pkt_len);
@@@ -682,14 -680,6 +680,6 @@@ out_bnum_err
                return -EFAULT;
        }
  
-       /* filter out multicast pkt with the same src mac as this port */
-       eh = eth_hdr(skb);
-       if (unlikely(is_multicast_ether_addr(eh->h_dest) &&
-                    ether_addr_equal(ndev->dev_addr, eh->h_source))) {
-               dev_kfree_skb_any(skb);
-               return -EFAULT;
-       }
        ring->stats.rx_pkts++;
        ring->stats.rx_bytes += skb->len;
  
@@@ -747,25 -737,37 +737,37 @@@ static void hns_nic_rx_up_pro(struct hn
        ndev->last_rx = jiffies;
  }
  
+ static int hns_desc_unused(struct hnae_ring *ring)
+ {
+       int ntc = ring->next_to_clean;
+       int ntu = ring->next_to_use;
+       return ((ntc >= ntu) ? 0 : ring->desc_num) + ntc - ntu;
+ }
  static int hns_nic_rx_poll_one(struct hns_nic_ring_data *ring_data,
                               int budget, void *v)
  {
        struct hnae_ring *ring = ring_data->ring;
        struct sk_buff *skb;
-       int num, bnum, ex_num;
+       int num, bnum;
  #define RCB_NOF_ALLOC_RX_BUFF_ONCE 16
        int recv_pkts, recv_bds, clean_count, err;
+       int unused_count = hns_desc_unused(ring);
  
        num = readl_relaxed(ring->io_base + RCB_REG_FBDNUM);
        rmb(); /* make sure num taken effect before the other data is touched */
  
        recv_pkts = 0, recv_bds = 0, clean_count = 0;
- recv:
+       num -= unused_count;
        while (recv_pkts < budget && recv_bds < num) {
                /* reuse or realloc buffers */
-               if (clean_count >= RCB_NOF_ALLOC_RX_BUFF_ONCE) {
-                       hns_nic_alloc_rx_buffers(ring_data, clean_count);
+               if (clean_count + unused_count >= RCB_NOF_ALLOC_RX_BUFF_ONCE) {
+                       hns_nic_alloc_rx_buffers(ring_data,
+                                                clean_count + unused_count);
                        clean_count = 0;
+                       unused_count = hns_desc_unused(ring);
                }
  
                /* poll one pkt */
                recv_pkts++;
        }
  
-       /* make all data has been write before submit */
-       if (recv_pkts < budget) {
-               ex_num = readl_relaxed(ring->io_base + RCB_REG_FBDNUM);
-               if (ex_num > clean_count) {
-                       num += ex_num - clean_count;
-                       rmb(); /*complete read rx ring bd number*/
-                       goto recv;
-               }
-       }
  out:
        /* make all data has been write before submit */
-       if (clean_count > 0)
-               hns_nic_alloc_rx_buffers(ring_data, clean_count);
+       if (clean_count + unused_count > 0)
+               hns_nic_alloc_rx_buffers(ring_data,
+                                        clean_count + unused_count);
  
        return recv_pkts;
  }
@@@ -810,6 -802,8 +802,8 @@@ static void hns_nic_rx_fini_pro(struct 
        struct hnae_ring *ring = ring_data->ring;
        int num = 0;
  
+       ring_data->ring->q->handle->dev->ops->toggle_ring_irq(ring, 0);
        /* for hardware bug fixed */
        num = readl_relaxed(ring->io_base + RCB_REG_FBDNUM);
  
        }
  }
  
+ static void hns_nic_rx_fini_pro_v2(struct hns_nic_ring_data *ring_data)
+ {
+       struct hnae_ring *ring = ring_data->ring;
+       int num = 0;
+       num = readl_relaxed(ring->io_base + RCB_REG_FBDNUM);
+       if (num == 0)
+               ring_data->ring->q->handle->dev->ops->toggle_ring_irq(
+                       ring, 0);
+       else
+               napi_schedule(&ring_data->napi);
+ }
  static inline void hns_nic_reclaim_one_desc(struct hnae_ring *ring,
                                            int *bytes, int *pkts)
  {
@@@ -922,7 -930,11 +930,11 @@@ static int hns_nic_tx_poll_one(struct h
  static void hns_nic_tx_fini_pro(struct hns_nic_ring_data *ring_data)
  {
        struct hnae_ring *ring = ring_data->ring;
-       int head = readl_relaxed(ring->io_base + RCB_REG_HEAD);
+       int head;
+       ring_data->ring->q->handle->dev->ops->toggle_ring_irq(ring, 0);
+       head = readl_relaxed(ring->io_base + RCB_REG_HEAD);
  
        if (head != ring->next_to_clean) {
                ring_data->ring->q->handle->dev->ops->toggle_ring_irq(
        }
  }
  
+ static void hns_nic_tx_fini_pro_v2(struct hns_nic_ring_data *ring_data)
+ {
+       struct hnae_ring *ring = ring_data->ring;
+       int head = readl_relaxed(ring->io_base + RCB_REG_HEAD);
+       if (head == ring->next_to_clean)
+               ring_data->ring->q->handle->dev->ops->toggle_ring_irq(
+                       ring, 0);
+       else
+               napi_schedule(&ring_data->napi);
+ }
  static void hns_nic_tx_clr_all_bufs(struct hns_nic_ring_data *ring_data)
  {
        struct hnae_ring *ring = ring_data->ring;
@@@ -963,10 -987,7 +987,7 @@@ static int hns_nic_common_poll(struct n
  
        if (clean_complete >= 0 && clean_complete < budget) {
                napi_complete(napi);
-               ring_data->ring->q->handle->dev->ops->toggle_ring_irq(
-                       ring_data->ring, 0);
-               if (ring_data->fini_process)
-                       ring_data->fini_process(ring_data);
+               ring_data->fini_process(ring_data);
                return 0;
        }
  
@@@ -994,10 -1015,10 +1015,10 @@@ static void hns_nic_adjust_link(struct 
        struct hnae_handle *h = priv->ae_handle;
        int state = 1;
  
 -      if (priv->phy) {
 +      if (ndev->phydev) {
                h->dev->ops->adjust_link(h, ndev->phydev->speed,
                                         ndev->phydev->duplex);
 -              state = priv->phy->link;
 +              state = ndev->phydev->link;
        }
        state = state && h->dev->ops->get_status(h);
  
   */
  int hns_nic_init_phy(struct net_device *ndev, struct hnae_handle *h)
  {
 -      struct hns_nic_priv *priv = netdev_priv(ndev);
        struct phy_device *phy_dev = h->phy_dev;
        int ret;
  
        if (h->phy_if == PHY_INTERFACE_MODE_XGMII)
                phy_dev->autoneg = false;
  
 -      priv->phy = phy_dev;
 -
        return 0;
  }
  
@@@ -1221,8 -1245,8 +1242,8 @@@ static int hns_nic_net_up(struct net_de
        if (ret)
                goto out_start_err;
  
 -      if (priv->phy)
 -              phy_start(priv->phy);
 +      if (ndev->phydev)
 +              phy_start(ndev->phydev);
  
        clear_bit(NIC_STATE_DOWN, &priv->state);
        (void)mod_timer(&priv->service_timer, jiffies + SERVICE_TIMER_HZ);
@@@ -1256,8 -1280,8 +1277,8 @@@ static void hns_nic_net_down(struct net
        netif_tx_disable(ndev);
        priv->link = 0;
  
 -      if (priv->phy)
 -              phy_stop(priv->phy);
 +      if (ndev->phydev)
 +              phy_stop(ndev->phydev);
  
        ops = priv->ae_handle->dev->ops;
  
@@@ -1356,7 -1380,8 +1377,7 @@@ static void hns_nic_net_timeout(struct 
  static int hns_nic_do_ioctl(struct net_device *netdev, struct ifreq *ifr,
                            int cmd)
  {
 -      struct hns_nic_priv *priv = netdev_priv(netdev);
 -      struct phy_device *phy_dev = priv->phy;
 +      struct phy_device *phy_dev = netdev->phydev;
  
        if (!netif_running(netdev))
                return -EINVAL;
@@@ -1562,6 -1587,21 +1583,21 @@@ struct rtnl_link_stats64 *hns_nic_get_s
        return stats;
  }
  
+ static u16
+ hns_nic_select_queue(struct net_device *ndev, struct sk_buff *skb,
+                    void *accel_priv, select_queue_fallback_t fallback)
+ {
+       struct ethhdr *eth_hdr = (struct ethhdr *)skb->data;
+       struct hns_nic_priv *priv = netdev_priv(ndev);
+       /* fix hardware broadcast/multicast packets queue loopback */
+       if (!AE_IS_VER1(priv->enet_ver) &&
+           is_multicast_ether_addr(eth_hdr->h_dest))
+               return 0;
+       else
+               return fallback(ndev, skb);
+ }
  static const struct net_device_ops hns_nic_netdev_ops = {
        .ndo_open = hns_nic_net_open,
        .ndo_stop = hns_nic_net_stop,
        .ndo_poll_controller = hns_nic_poll_controller,
  #endif
        .ndo_set_rx_mode = hns_nic_set_rx_mode,
+       .ndo_select_queue = hns_nic_select_queue,
  };
  
  static void hns_nic_update_link_status(struct net_device *netdev)
@@@ -1738,7 -1779,8 +1775,8 @@@ static int hns_nic_init_ring_data(struc
                rd->queue_index = i;
                rd->ring = &h->qs[i]->tx_ring;
                rd->poll_one = hns_nic_tx_poll_one;
-               rd->fini_process = is_ver1 ? hns_nic_tx_fini_pro : NULL;
+               rd->fini_process = is_ver1 ? hns_nic_tx_fini_pro :
+                       hns_nic_tx_fini_pro_v2;
  
                netif_napi_add(priv->netdev, &rd->napi,
                               hns_nic_common_poll, NIC_TX_CLEAN_MAX_NUM);
                rd->ring = &h->qs[i - h->q_num]->rx_ring;
                rd->poll_one = hns_nic_rx_poll_one;
                rd->ex_process = hns_nic_rx_up_pro;
-               rd->fini_process = is_ver1 ? hns_nic_rx_fini_pro : NULL;
+               rd->fini_process = is_ver1 ? hns_nic_rx_fini_pro :
+                       hns_nic_rx_fini_pro_v2;
  
                netif_napi_add(priv->netdev, &rd->napi,
                               hns_nic_common_poll, NIC_RX_CLEAN_MAX_NUM);
@@@ -2013,8 -2056,9 +2052,8 @@@ static int hns_nic_dev_remove(struct pl
                hns_nic_uninit_ring_data(priv);
        priv->ring_data = NULL;
  
 -      if (priv->phy)
 -              phy_disconnect(priv->phy);
 -      priv->phy = NULL;
 +      if (ndev->phydev)
 +              phy_disconnect(ndev->phydev);
  
        if (!IS_ERR_OR_NULL(priv->ae_handle))
                hnae_put_handle(priv->ae_handle);
index 47e59bbfd061bfe1d9576b8111f92d361be599e1,fa91ce32199ea3dc955c8cae31ff1f78d470b002..87d5c94b2810230b334ddef0501644cd291b8bbf
@@@ -48,9 -48,9 +48,9 @@@ static u32 hns_nic_get_link(struct net_
  
        h = priv->ae_handle;
  
 -      if (priv->phy) {
 -              if (!genphy_read_status(priv->phy))
 -                      link_stat = priv->phy->link;
 +      if (net_dev->phydev) {
 +              if (!genphy_read_status(net_dev->phydev))
 +                      link_stat = net_dev->phydev->link;
                else
                        link_stat = 0;
        }
  }
  
  static void hns_get_mdix_mode(struct net_device *net_dev,
 -                            struct ethtool_cmd *cmd)
 +                            struct ethtool_link_ksettings *cmd)
  {
        int mdix_ctrl, mdix, retval, is_resolved;
 -      struct hns_nic_priv *priv = netdev_priv(net_dev);
 -      struct phy_device *phy_dev = priv->phy;
 +      struct phy_device *phy_dev = net_dev->phydev;
  
        if (!phy_dev || !phy_dev->mdio.bus) {
 -              cmd->eth_tp_mdix_ctrl = ETH_TP_MDI_INVALID;
 -              cmd->eth_tp_mdix = ETH_TP_MDI_INVALID;
 +              cmd->base.eth_tp_mdix_ctrl = ETH_TP_MDI_INVALID;
 +              cmd->base.eth_tp_mdix = ETH_TP_MDI_INVALID;
                return;
        }
  
  
        switch (mdix_ctrl) {
        case 0x0:
 -              cmd->eth_tp_mdix_ctrl = ETH_TP_MDI;
 +              cmd->base.eth_tp_mdix_ctrl = ETH_TP_MDI;
                break;
        case 0x1:
 -              cmd->eth_tp_mdix_ctrl = ETH_TP_MDI_X;
 +              cmd->base.eth_tp_mdix_ctrl = ETH_TP_MDI_X;
                break;
        case 0x3:
 -              cmd->eth_tp_mdix_ctrl = ETH_TP_MDI_AUTO;
 +              cmd->base.eth_tp_mdix_ctrl = ETH_TP_MDI_AUTO;
                break;
        default:
 -              cmd->eth_tp_mdix_ctrl = ETH_TP_MDI_INVALID;
 +              cmd->base.eth_tp_mdix_ctrl = ETH_TP_MDI_INVALID;
                break;
        }
  
        if (!is_resolved)
 -              cmd->eth_tp_mdix = ETH_TP_MDI_INVALID;
 +              cmd->base.eth_tp_mdix = ETH_TP_MDI_INVALID;
        else if (mdix)
 -              cmd->eth_tp_mdix = ETH_TP_MDI_X;
 +              cmd->base.eth_tp_mdix = ETH_TP_MDI_X;
        else
 -              cmd->eth_tp_mdix = ETH_TP_MDI;
 +              cmd->base.eth_tp_mdix = ETH_TP_MDI;
  }
  
  /**
 - *hns_nic_get_settings - implement ethtool get settings
 + *hns_nic_get_link_ksettings - implement ethtool get link ksettings
   *@net_dev: net_device
 - *@cmd: ethtool_cmd
 + *@cmd: ethtool_link_ksettings
   *retuen 0 - success , negative --fail
   */
 -static int hns_nic_get_settings(struct net_device *net_dev,
 -                              struct ethtool_cmd *cmd)
 +static int hns_nic_get_link_ksettings(struct net_device *net_dev,
 +                                    struct ethtool_link_ksettings *cmd)
  {
        struct hns_nic_priv *priv = netdev_priv(net_dev);
        struct hnae_handle *h;
        int ret;
        u8 duplex;
        u16 speed;
 +      u32 supported, advertising;
  
        if (!priv || !priv->ae_handle)
                return -ESRCH;
                return -EINVAL;
        }
  
 +      ethtool_convert_link_mode_to_legacy_u32(&supported,
 +                                              cmd->link_modes.supported);
 +      ethtool_convert_link_mode_to_legacy_u32(&advertising,
 +                                              cmd->link_modes.advertising);
 +
        /* When there is no phy, autoneg is off. */
 -      cmd->autoneg = false;
 -      ethtool_cmd_speed_set(cmd, speed);
 -      cmd->duplex = duplex;
 +      cmd->base.autoneg = false;
 +      cmd->base.cmd = speed;
 +      cmd->base.duplex = duplex;
  
 -      if (priv->phy)
 -              (void)phy_ethtool_gset(priv->phy, cmd);
 +      if (net_dev->phydev)
 +              (void)phy_ethtool_ksettings_get(net_dev->phydev, cmd);
  
        link_stat = hns_nic_get_link(net_dev);
        if (!link_stat) {
 -              ethtool_cmd_speed_set(cmd, (u32)SPEED_UNKNOWN);
 -              cmd->duplex = DUPLEX_UNKNOWN;
 +              cmd->base.speed = (u32)SPEED_UNKNOWN;
 +              cmd->base.duplex = DUPLEX_UNKNOWN;
        }
  
 -      if (cmd->autoneg)
 -              cmd->advertising |= ADVERTISED_Autoneg;
 +      if (cmd->base.autoneg)
 +              advertising |= ADVERTISED_Autoneg;
  
 -      cmd->supported |= h->if_support;
 +      supported |= h->if_support;
        if (h->phy_if == PHY_INTERFACE_MODE_SGMII) {
 -              cmd->supported |= SUPPORTED_TP;
 -              cmd->advertising |= ADVERTISED_1000baseT_Full;
 +              supported |= SUPPORTED_TP;
 +              advertising |= ADVERTISED_1000baseT_Full;
        } else if (h->phy_if == PHY_INTERFACE_MODE_XGMII) {
 -              cmd->supported |= SUPPORTED_FIBRE;
 -              cmd->advertising |= ADVERTISED_10000baseKR_Full;
 +              supported |= SUPPORTED_FIBRE;
 +              advertising |= ADVERTISED_10000baseKR_Full;
        }
  
        switch (h->media_type) {
        case HNAE_MEDIA_TYPE_FIBER:
 -              cmd->port = PORT_FIBRE;
 +              cmd->base.port = PORT_FIBRE;
                break;
        case HNAE_MEDIA_TYPE_COPPER:
 -              cmd->port = PORT_TP;
 +              cmd->base.port = PORT_TP;
                break;
        case HNAE_MEDIA_TYPE_UNKNOWN:
        default:
        }
  
        if (!(AE_IS_VER1(priv->enet_ver) && h->port_type == HNAE_PORT_DEBUG))
 -              cmd->supported |= SUPPORTED_Pause;
 +              supported |= SUPPORTED_Pause;
 +
 +      ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.supported,
 +                                              supported);
 +      ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.advertising,
 +                                              advertising);
  
 -      cmd->transceiver = XCVR_EXTERNAL;
 -      cmd->mdio_support = (ETH_MDIO_SUPPORTS_C45 | ETH_MDIO_SUPPORTS_C22);
 +      cmd->base.mdio_support = ETH_MDIO_SUPPORTS_C45 | ETH_MDIO_SUPPORTS_C22;
        hns_get_mdix_mode(net_dev, cmd);
  
        return 0;
  }
  
  /**
 - *hns_nic_set_settings - implement ethtool set settings
 + *hns_nic_set_link_settings - implement ethtool set link ksettings
   *@net_dev: net_device
 - *@cmd: ethtool_cmd
 + *@cmd: ethtool_link_ksettings
   *retuen 0 - success , negative --fail
   */
 -static int hns_nic_set_settings(struct net_device *net_dev,
 -                              struct ethtool_cmd *cmd)
 +static int hns_nic_set_link_ksettings(struct net_device *net_dev,
 +                                    const struct ethtool_link_ksettings *cmd)
  {
        struct hns_nic_priv *priv = netdev_priv(net_dev);
        struct hnae_handle *h;
                return -ENODEV;
  
        h = priv->ae_handle;
 -      speed = ethtool_cmd_speed(cmd);
 +      speed = cmd->base.speed;
  
        if (h->phy_if == PHY_INTERFACE_MODE_XGMII) {
 -              if (cmd->autoneg == AUTONEG_ENABLE || speed != SPEED_10000 ||
 -                  cmd->duplex != DUPLEX_FULL)
 +              if (cmd->base.autoneg == AUTONEG_ENABLE ||
 +                  speed != SPEED_10000 ||
 +                  cmd->base.duplex != DUPLEX_FULL)
                        return -EINVAL;
        } else if (h->phy_if == PHY_INTERFACE_MODE_SGMII) {
 -              if (!priv->phy && cmd->autoneg == AUTONEG_ENABLE)
 +              if (!net_dev->phydev && cmd->base.autoneg == AUTONEG_ENABLE)
                        return -EINVAL;
  
 -              if (speed == SPEED_1000 && cmd->duplex == DUPLEX_HALF)
 +              if (speed == SPEED_1000 && cmd->base.duplex == DUPLEX_HALF)
                        return -EINVAL;
 -              if (priv->phy)
 -                      return phy_ethtool_sset(priv->phy, cmd);
 +              if (net_dev->phydev)
 +                      return phy_ethtool_ksettings_set(net_dev->phydev, cmd);
  
                if ((speed != SPEED_10 && speed != SPEED_100 &&
 -                   speed != SPEED_1000) || (cmd->duplex != DUPLEX_HALF &&
 -                   cmd->duplex != DUPLEX_FULL))
 +                   speed != SPEED_1000) || (cmd->base.duplex != DUPLEX_HALF &&
 +                   cmd->base.duplex != DUPLEX_FULL))
                        return -EINVAL;
        } else {
                netdev_err(net_dev, "Not supported!");
        }
  
        if (h->dev->ops->adjust_link) {
 -              h->dev->ops->adjust_link(h, (int)speed, cmd->duplex);
 +              h->dev->ops->adjust_link(h, (int)speed, cmd->base.duplex);
                return 0;
        }
  
@@@ -315,7 -305,7 +315,7 @@@ static int __lb_setup(struct net_devic
  {
        int ret = 0;
        struct hns_nic_priv *priv = netdev_priv(ndev);
 -      struct phy_device *phy_dev = priv->phy;
 +      struct phy_device *phy_dev = ndev->phydev;
        struct hnae_handle *h = priv->ae_handle;
  
        switch (loop) {
                break;
        }
  
+       if (!ret) {
+               if (loop == MAC_LOOP_NONE)
+                       h->dev->ops->set_promisc_mode(
+                               h, ndev->flags & IFF_PROMISC);
+               else
+                       h->dev->ops->set_promisc_mode(h, 1);
+       }
        return ret;
  }
  
@@@ -920,7 -917,7 +927,7 @@@ void hns_get_strings(struct net_device 
                memcpy(buff, hns_nic_test_strs[MAC_INTERNALLOOP_SERDES],
                       ETH_GSTRING_LEN);
                buff += ETH_GSTRING_LEN;
 -              if ((priv->phy) && (!priv->phy->is_c45))
 +              if ((netdev->phydev) && (!netdev->phydev->is_c45))
                        memcpy(buff, hns_nic_test_strs[MAC_INTERNALLOOP_PHY],
                               ETH_GSTRING_LEN);
  
@@@ -1006,7 -1003,7 +1013,7 @@@ int hns_get_sset_count(struct net_devic
                if (priv->ae_handle->phy_if == PHY_INTERFACE_MODE_XGMII)
                        cnt--;
  
 -              if ((!priv->phy) || (priv->phy->is_c45))
 +              if ((!netdev->phydev) || (netdev->phydev->is_c45))
                        cnt--;
  
                return cnt;
  int hns_phy_led_set(struct net_device *netdev, int value)
  {
        int retval;
 -      struct hns_nic_priv *priv = netdev_priv(netdev);
 -      struct phy_device *phy_dev = priv->phy;
 +      struct phy_device *phy_dev = netdev->phydev;
  
        retval = phy_write(phy_dev, HNS_PHY_PAGE_REG, HNS_PHY_PAGE_LED);
        retval |= phy_write(phy_dev, HNS_LED_FC_REG, value);
@@@ -1048,7 -1046,7 +1055,7 @@@ int hns_set_phys_id(struct net_device *
  {
        struct hns_nic_priv *priv = netdev_priv(netdev);
        struct hnae_handle *h = priv->ae_handle;
 -      struct phy_device *phy_dev = priv->phy;
 +      struct phy_device *phy_dev = netdev->phydev;
        int ret;
  
        if (phy_dev)
@@@ -1168,7 -1166,8 +1175,7 @@@ static int hns_get_regs_len(struct net_
  static int hns_nic_nway_reset(struct net_device *netdev)
  {
        int ret = 0;
 -      struct hns_nic_priv *priv = netdev_priv(netdev);
 -      struct phy_device *phy = priv->phy;
 +      struct phy_device *phy = netdev->phydev;
  
        if (netif_running(netdev)) {
                if (phy)
@@@ -1272,9 -1271,11 +1279,9 @@@ static int hns_get_rxnfc(struct net_dev
        return 0;
  }
  
 -static struct ethtool_ops hns_ethtool_ops = {
 +static const struct ethtool_ops hns_ethtool_ops = {
        .get_drvinfo = hns_nic_get_drvinfo,
        .get_link  = hns_nic_get_link,
 -      .get_settings  = hns_nic_get_settings,
 -      .set_settings  = hns_nic_set_settings,
        .get_ringparam = hns_get_ringparam,
        .get_pauseparam = hns_get_pauseparam,
        .set_pauseparam = hns_set_pauseparam,
        .get_rxfh = hns_get_rss,
        .set_rxfh = hns_set_rss,
        .get_rxnfc = hns_get_rxnfc,
 +      .get_link_ksettings  = hns_nic_get_link_ksettings,
 +      .set_link_ksettings  = hns_nic_set_link_ksettings,
  };
  
  void hns_ethtool_set_ops(struct net_device *ndev)