[PATCH 0/2][Cosmic][SRU Bionic] hns: fix hang during speed or duplex change

classic Classic list List threaded Threaded
6 messages Options
Reply | Threaded
Open this post in threaded view
|

[PATCH 0/2][Cosmic][SRU Bionic] hns: fix hang during speed or duplex change

dann frazier-4
Clean cherry-picks.

BugLink: https://bugs.launchpad.net/bugs/1792209

Peng Li (2):
  net: hns: add the code for cleaning pkt in chip
  net: hns: add netif_carrier_off before change speed and duplex

 drivers/net/ethernet/hisilicon/hns/hnae.h     |  2 +
 .../net/ethernet/hisilicon/hns/hns_ae_adapt.c | 67 ++++++++++++++++++-
 .../ethernet/hisilicon/hns/hns_dsaf_gmac.c    | 36 ++++++++++
 .../net/ethernet/hisilicon/hns/hns_dsaf_mac.c | 44 ++++++++++++
 .../net/ethernet/hisilicon/hns/hns_dsaf_mac.h |  8 +++
 .../ethernet/hisilicon/hns/hns_dsaf_main.c    | 29 ++++++++
 .../ethernet/hisilicon/hns/hns_dsaf_main.h    |  3 +
 .../net/ethernet/hisilicon/hns/hns_dsaf_ppe.c | 23 +++++++
 .../net/ethernet/hisilicon/hns/hns_dsaf_ppe.h |  1 +
 .../net/ethernet/hisilicon/hns/hns_dsaf_rcb.c | 23 +++++++
 .../net/ethernet/hisilicon/hns/hns_dsaf_rcb.h |  1 +
 .../net/ethernet/hisilicon/hns/hns_dsaf_reg.h |  1 +
 drivers/net/ethernet/hisilicon/hns/hns_enet.c | 21 +++++-
 .../net/ethernet/hisilicon/hns/hns_ethtool.c  |  2 +
 14 files changed, 257 insertions(+), 4 deletions(-)

--
2.19.0


--
kernel-team mailing list
[hidden email]
https://lists.ubuntu.com/mailman/listinfo/kernel-team
Reply | Threaded
Open this post in threaded view
|

[PATCH 1/2][Cosmic][SRU Bionic] net: hns: add the code for cleaning pkt in chip

dann frazier-4
From: Peng Li <[hidden email]>

BugLink: https://bugs.launchpad.net/bugs/1792209

If there are packets in hardware when changing the speed
or duplex, it may cause hardware hang up.

This patch adds the code for waiting chip to clean the all
pkts(TX & RX) in chip when the driver uses the function named
"adjust link".

This patch cleans the pkts as follows:
1) close rx of chip, close tx of protocol stack.
2) wait rcb, ppe, mac to clean.
3) adjust link
4) open rx of chip, open tx of protocol stack.

Signed-off-by: Peng Li <[hidden email]>
Signed-off-by: David S. Miller <[hidden email]>
(cherry picked from commit 31fabbee8f5c658c3fa1603c66e9e4f51ea8c2c6)
Signed-off-by: dann frazier <[hidden email]>
---
 drivers/net/ethernet/hisilicon/hns/hnae.h     |  2 +
 .../net/ethernet/hisilicon/hns/hns_ae_adapt.c | 67 ++++++++++++++++++-
 .../ethernet/hisilicon/hns/hns_dsaf_gmac.c    | 36 ++++++++++
 .../net/ethernet/hisilicon/hns/hns_dsaf_mac.c | 44 ++++++++++++
 .../net/ethernet/hisilicon/hns/hns_dsaf_mac.h |  8 +++
 .../ethernet/hisilicon/hns/hns_dsaf_main.c    | 29 ++++++++
 .../ethernet/hisilicon/hns/hns_dsaf_main.h    |  3 +
 .../net/ethernet/hisilicon/hns/hns_dsaf_ppe.c | 23 +++++++
 .../net/ethernet/hisilicon/hns/hns_dsaf_ppe.h |  1 +
 .../net/ethernet/hisilicon/hns/hns_dsaf_rcb.c | 23 +++++++
 .../net/ethernet/hisilicon/hns/hns_dsaf_rcb.h |  1 +
 .../net/ethernet/hisilicon/hns/hns_dsaf_reg.h |  1 +
 drivers/net/ethernet/hisilicon/hns/hns_enet.c | 21 +++++-
 13 files changed, 255 insertions(+), 4 deletions(-)

diff --git a/drivers/net/ethernet/hisilicon/hns/hnae.h b/drivers/net/ethernet/hisilicon/hns/hnae.h
index fa5b30f547f66..427866b9564e4 100644
--- a/drivers/net/ethernet/hisilicon/hns/hnae.h
+++ b/drivers/net/ethernet/hisilicon/hns/hnae.h
@@ -486,6 +486,8 @@ struct hnae_ae_ops {
  u8 *auto_neg, u16 *speed, u8 *duplex);
  void (*toggle_ring_irq)(struct hnae_ring *ring, u32 val);
  void (*adjust_link)(struct hnae_handle *handle, int speed, int duplex);
+ bool (*need_adjust_link)(struct hnae_handle *handle,
+ int speed, int duplex);
  int (*set_loopback)(struct hnae_handle *handle,
     enum hnae_loop loop_mode, int en);
  void (*get_ring_bdnum_limit)(struct hnae_queue *queue,
diff --git a/drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c b/drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c
index bd68379d2beab..bf930ab3c2bde 100644
--- a/drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c
+++ b/drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c
@@ -155,6 +155,41 @@ static void hns_ae_put_handle(struct hnae_handle *handle)
  hns_ae_get_ring_pair(handle->qs[i])->used_by_vf = 0;
 }
 
+static int hns_ae_wait_flow_down(struct hnae_handle *handle)
+{
+ struct dsaf_device *dsaf_dev;
+ struct hns_ppe_cb *ppe_cb;
+ struct hnae_vf_cb *vf_cb;
+ int ret;
+ int i;
+
+ for (i = 0; i < handle->q_num; i++) {
+ ret = hns_rcb_wait_tx_ring_clean(handle->qs[i]);
+ if (ret)
+ return ret;
+ }
+
+ ppe_cb = hns_get_ppe_cb(handle);
+ ret = hns_ppe_wait_tx_fifo_clean(ppe_cb);
+ if (ret)
+ return ret;
+
+ dsaf_dev = hns_ae_get_dsaf_dev(handle->dev);
+ if (!dsaf_dev)
+ return -EINVAL;
+ ret = hns_dsaf_wait_pkt_clean(dsaf_dev, handle->dport_id);
+ if (ret)
+ return ret;
+
+ vf_cb = hns_ae_get_vf_cb(handle);
+ ret = hns_mac_wait_fifo_clean(vf_cb->mac_cb);
+ if (ret)
+ return ret;
+
+ mdelay(10);
+ return 0;
+}
+
 static void hns_ae_ring_enable_all(struct hnae_handle *handle, int val)
 {
  int q_num = handle->q_num;
@@ -399,12 +434,41 @@ static int hns_ae_get_mac_info(struct hnae_handle *handle,
  return hns_mac_get_port_info(mac_cb, auto_neg, speed, duplex);
 }
 
+static bool hns_ae_need_adjust_link(struct hnae_handle *handle, int speed,
+    int duplex)
+{
+ struct hns_mac_cb *mac_cb = hns_get_mac_cb(handle);
+
+ return hns_mac_need_adjust_link(mac_cb, speed, duplex);
+}
+
 static void hns_ae_adjust_link(struct hnae_handle *handle, int speed,
        int duplex)
 {
  struct hns_mac_cb *mac_cb = hns_get_mac_cb(handle);
 
- hns_mac_adjust_link(mac_cb, speed, duplex);
+ switch (mac_cb->dsaf_dev->dsaf_ver) {
+ case AE_VERSION_1:
+ hns_mac_adjust_link(mac_cb, speed, duplex);
+ break;
+
+ case AE_VERSION_2:
+ /* chip need to clear all pkt inside */
+ hns_mac_disable(mac_cb, MAC_COMM_MODE_RX);
+ if (hns_ae_wait_flow_down(handle)) {
+ hns_mac_enable(mac_cb, MAC_COMM_MODE_RX);
+ break;
+ }
+
+ hns_mac_adjust_link(mac_cb, speed, duplex);
+ hns_mac_enable(mac_cb, MAC_COMM_MODE_RX);
+ break;
+
+ default:
+ break;
+ }
+
+ return;
 }
 
 static void hns_ae_get_ring_bdnum_limit(struct hnae_queue *queue,
@@ -902,6 +966,7 @@ static struct hnae_ae_ops hns_dsaf_ops = {
  .get_status = hns_ae_get_link_status,
  .get_info = hns_ae_get_mac_info,
  .adjust_link = hns_ae_adjust_link,
+ .need_adjust_link = hns_ae_need_adjust_link,
  .set_loopback = hns_ae_config_loopback,
  .get_ring_bdnum_limit = hns_ae_get_ring_bdnum_limit,
  .get_pauseparam = hns_ae_get_pauseparam,
diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_gmac.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_gmac.c
index 74bd260ca02a8..8c7bc5cf193c3 100644
--- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_gmac.c
+++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_gmac.c
@@ -257,6 +257,16 @@ static void hns_gmac_get_pausefrm_cfg(void *mac_drv, u32 *rx_pause_en,
  *tx_pause_en = dsaf_get_bit(pause_en, GMAC_PAUSE_EN_TX_FDFC_B);
 }
 
+static bool hns_gmac_need_adjust_link(void *mac_drv, enum mac_speed speed,
+      int duplex)
+{
+ struct mac_driver *drv = (struct mac_driver *)mac_drv;
+ struct hns_mac_cb *mac_cb = drv->mac_cb;
+
+ return (mac_cb->speed != speed) ||
+ (mac_cb->half_duplex == duplex);
+}
+
 static int hns_gmac_adjust_link(void *mac_drv, enum mac_speed speed,
  u32 full_duplex)
 {
@@ -309,6 +319,30 @@ static void hns_gmac_set_promisc(void *mac_drv, u8 en)
  hns_gmac_set_uc_match(mac_drv, en);
 }
 
+int hns_gmac_wait_fifo_clean(void *mac_drv)
+{
+ struct mac_driver *drv = (struct mac_driver *)mac_drv;
+ int wait_cnt;
+ u32 val;
+
+ wait_cnt = 0;
+ while (wait_cnt++ < HNS_MAX_WAIT_CNT) {
+ val = dsaf_read_dev(drv, GMAC_FIFO_STATE_REG);
+ /* bit5~bit0 is not send complete pkts */
+ if ((val & 0x3f) == 0)
+ break;
+ usleep_range(100, 200);
+ }
+
+ if (wait_cnt >= HNS_MAX_WAIT_CNT) {
+ dev_err(drv->dev,
+ "hns ge %d fifo was not idle.\n", drv->mac_id);
+ return -EBUSY;
+ }
+
+ return 0;
+}
+
 static void hns_gmac_init(void *mac_drv)
 {
  u32 port;
@@ -690,6 +724,7 @@ void *hns_gmac_config(struct hns_mac_cb *mac_cb, struct mac_params *mac_param)
  mac_drv->mac_disable = hns_gmac_disable;
  mac_drv->mac_free = hns_gmac_free;
  mac_drv->adjust_link = hns_gmac_adjust_link;
+ mac_drv->need_adjust_link = hns_gmac_need_adjust_link;
  mac_drv->set_tx_auto_pause_frames = hns_gmac_set_tx_auto_pause_frames;
  mac_drv->config_max_frame_length = hns_gmac_config_max_frame_length;
  mac_drv->mac_pausefrm_cfg = hns_gmac_pause_frm_cfg;
@@ -717,6 +752,7 @@ void *hns_gmac_config(struct hns_mac_cb *mac_cb, struct mac_params *mac_param)
  mac_drv->get_strings = hns_gmac_get_strings;
  mac_drv->update_stats = hns_gmac_update_stats;
  mac_drv->set_promiscuous = hns_gmac_set_promisc;
+ mac_drv->wait_fifo_clean = hns_gmac_wait_fifo_clean;
 
  return (void *)mac_drv;
 }
diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c
index 9dcc5765f11fa..5c6b880c3eb71 100644
--- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c
+++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c
@@ -114,6 +114,26 @@ int hns_mac_get_port_info(struct hns_mac_cb *mac_cb,
  return 0;
 }
 
+/**
+ *hns_mac_is_adjust_link - check is need change mac speed and duplex register
+ *@mac_cb: mac device
+ *@speed: phy device speed
+ *@duplex:phy device duplex
+ *
+ */
+bool hns_mac_need_adjust_link(struct hns_mac_cb *mac_cb, int speed, int duplex)
+{
+ struct mac_driver *mac_ctrl_drv;
+
+ mac_ctrl_drv = (struct mac_driver *)(mac_cb->priv.mac);
+
+ if (mac_ctrl_drv->need_adjust_link)
+ return mac_ctrl_drv->need_adjust_link(mac_ctrl_drv,
+ (enum mac_speed)speed, duplex);
+ else
+ return true;
+}
+
 void hns_mac_adjust_link(struct hns_mac_cb *mac_cb, int speed, int duplex)
 {
  int ret;
@@ -430,6 +450,16 @@ int hns_mac_vm_config_bc_en(struct hns_mac_cb *mac_cb, u32 vmid, bool enable)
  return 0;
 }
 
+int hns_mac_wait_fifo_clean(struct hns_mac_cb *mac_cb)
+{
+ struct mac_driver *drv = hns_mac_get_drv(mac_cb);
+
+ if (drv->wait_fifo_clean)
+ return drv->wait_fifo_clean(drv);
+
+ return 0;
+}
+
 void hns_mac_reset(struct hns_mac_cb *mac_cb)
 {
  struct mac_driver *drv = hns_mac_get_drv(mac_cb);
@@ -999,6 +1029,20 @@ static int hns_mac_get_max_port_num(struct dsaf_device *dsaf_dev)
  return  DSAF_MAX_PORT_NUM;
 }
 
+void hns_mac_enable(struct hns_mac_cb *mac_cb, enum mac_commom_mode mode)
+{
+ struct mac_driver *mac_ctrl_drv = hns_mac_get_drv(mac_cb);
+
+ mac_ctrl_drv->mac_enable(mac_cb->priv.mac, mode);
+}
+
+void hns_mac_disable(struct hns_mac_cb *mac_cb, enum mac_commom_mode mode)
+{
+ struct mac_driver *mac_ctrl_drv = hns_mac_get_drv(mac_cb);
+
+ mac_ctrl_drv->mac_disable(mac_cb->priv.mac, mode);
+}
+
 /**
  * hns_mac_init - init mac
  * @dsaf_dev: dsa fabric device struct pointer
diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.h b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.h
index bbc0a98e7ca32..fbc75341bef76 100644
--- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.h
+++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.h
@@ -356,6 +356,9 @@ struct mac_driver {
  /*adjust mac mode of port,include speed and duplex*/
  int (*adjust_link)(void *mac_drv, enum mac_speed speed,
    u32 full_duplex);
+ /* need adjust link */
+ bool (*need_adjust_link)(void *mac_drv, enum mac_speed speed,
+ int duplex);
  /* config autoegotaite mode of port*/
  void (*set_an_mode)(void *mac_drv, u8 enable);
  /* config loopbank mode */
@@ -394,6 +397,7 @@ struct mac_driver {
  void (*get_info)(void *mac_drv, struct mac_info *mac_info);
 
  void (*update_stats)(void *mac_drv);
+ int (*wait_fifo_clean)(void *mac_drv);
 
  enum mac_mode mac_mode;
  u8 mac_id;
@@ -427,6 +431,7 @@ void *hns_xgmac_config(struct hns_mac_cb *mac_cb,
 
 int hns_mac_init(struct dsaf_device *dsaf_dev);
 void mac_adjust_link(struct net_device *net_dev);
+bool hns_mac_need_adjust_link(struct hns_mac_cb *mac_cb, int speed, int duplex);
 void hns_mac_get_link_status(struct hns_mac_cb *mac_cb, u32 *link_status);
 int hns_mac_change_vf_addr(struct hns_mac_cb *mac_cb, u32 vmid, char *addr);
 int hns_mac_set_multi(struct hns_mac_cb *mac_cb,
@@ -463,5 +468,8 @@ int hns_mac_add_uc_addr(struct hns_mac_cb *mac_cb, u8 vf_id,
 int hns_mac_rm_uc_addr(struct hns_mac_cb *mac_cb, u8 vf_id,
        const unsigned char *addr);
 int hns_mac_clr_multicast(struct hns_mac_cb *mac_cb, int vfn);
+void hns_mac_enable(struct hns_mac_cb *mac_cb, enum mac_commom_mode mode);
+void hns_mac_disable(struct hns_mac_cb *mac_cb, enum mac_commom_mode mode);
+int hns_mac_wait_fifo_clean(struct hns_mac_cb *mac_cb);
 
 #endif /* _HNS_DSAF_MAC_H */
diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c
index 0ce07f6eb1e62..0ef6d429308fa 100644
--- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c
+++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c
@@ -2733,6 +2733,35 @@ void hns_dsaf_set_promisc_tcam(struct dsaf_device *dsaf_dev,
  soft_mac_entry->index = enable ? entry_index : DSAF_INVALID_ENTRY_IDX;
 }
 
+int hns_dsaf_wait_pkt_clean(struct dsaf_device *dsaf_dev, int port)
+{
+ u32 val, val_tmp;
+ int wait_cnt;
+
+ if (port >= DSAF_SERVICE_NW_NUM)
+ return 0;
+
+ wait_cnt = 0;
+ while (wait_cnt++ < HNS_MAX_WAIT_CNT) {
+ val = dsaf_read_dev(dsaf_dev, DSAF_VOQ_IN_PKT_NUM_0_REG +
+ (port + DSAF_XGE_NUM) * 0x40);
+ val_tmp = dsaf_read_dev(dsaf_dev, DSAF_VOQ_OUT_PKT_NUM_0_REG +
+ (port + DSAF_XGE_NUM) * 0x40);
+ if (val == val_tmp)
+ break;
+
+ usleep_range(100, 200);
+ }
+
+ if (wait_cnt >= HNS_MAX_WAIT_CNT) {
+ dev_err(dsaf_dev->dev, "hns dsaf clean wait timeout(%u - %u).\n",
+ val, val_tmp);
+ return -EBUSY;
+ }
+
+ return 0;
+}
+
 /**
  * dsaf_probe - probo dsaf dev
  * @pdev: dasf platform device
diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.h b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.h
index 4507e8222683c..0e1cd99831a60 100644
--- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.h
+++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.h
@@ -44,6 +44,8 @@ struct hns_mac_cb;
 #define DSAF_ROCE_CREDIT_CHN 8
 #define DSAF_ROCE_CHAN_MODE 3
 
+#define HNS_MAX_WAIT_CNT 10000
+
 enum dsaf_roce_port_mode {
  DSAF_ROCE_6PORT_MODE,
  DSAF_ROCE_4PORT_MODE,
@@ -463,5 +465,6 @@ int hns_dsaf_rm_mac_addr(
 
 int hns_dsaf_clr_mac_mc_port(struct dsaf_device *dsaf_dev,
      u8 mac_id, u8 port_num);
+int hns_dsaf_wait_pkt_clean(struct dsaf_device *dsaf_dev, int port);
 
 #endif /* __HNS_DSAF_MAIN_H__ */
diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_ppe.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_ppe.c
index 93e71e27401b4..a19932aeb9d7e 100644
--- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_ppe.c
+++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_ppe.c
@@ -274,6 +274,29 @@ static void hns_ppe_exc_irq_en(struct hns_ppe_cb *ppe_cb, int en)
  dsaf_write_dev(ppe_cb, PPE_INTEN_REG, msk_vlue & vld_msk);
 }
 
+int hns_ppe_wait_tx_fifo_clean(struct hns_ppe_cb *ppe_cb)
+{
+ int wait_cnt;
+ u32 val;
+
+ wait_cnt = 0;
+ while (wait_cnt++ < HNS_MAX_WAIT_CNT) {
+ val = dsaf_read_dev(ppe_cb, PPE_CURR_TX_FIFO0_REG) & 0x3ffU;
+ if (!val)
+ break;
+
+ usleep_range(100, 200);
+ }
+
+ if (wait_cnt >= HNS_MAX_WAIT_CNT) {
+ dev_err(ppe_cb->dev, "hns ppe tx fifo clean wait timeout, still has %u pkt.\n",
+ val);
+ return -EBUSY;
+ }
+
+ return 0;
+}
+
 /**
  * ppe_init_hw - init ppe
  * @ppe_cb: ppe device
diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_ppe.h b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_ppe.h
index 9d8e643e8aa6f..f670e63a5a018 100644
--- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_ppe.h
+++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_ppe.h
@@ -100,6 +100,7 @@ struct ppe_common_cb {
 
 };
 
+int hns_ppe_wait_tx_fifo_clean(struct hns_ppe_cb *ppe_cb);
 int hns_ppe_init(struct dsaf_device *dsaf_dev);
 
 void hns_ppe_uninit(struct dsaf_device *dsaf_dev);
diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.c
index e2e28532e4dc2..1e43d7a3ca868 100644
--- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.c
+++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.c
@@ -66,6 +66,29 @@ void hns_rcb_wait_fbd_clean(struct hnae_queue **qs, int q_num, u32 flag)
  "queue(%d) wait fbd(%d) clean fail!!\n", i, fbd_num);
 }
 
+int hns_rcb_wait_tx_ring_clean(struct hnae_queue *qs)
+{
+ u32 head, tail;
+ int wait_cnt;
+
+ tail = dsaf_read_dev(&qs->tx_ring, RCB_REG_TAIL);
+ wait_cnt = 0;
+ while (wait_cnt++ < HNS_MAX_WAIT_CNT) {
+ head = dsaf_read_dev(&qs->tx_ring, RCB_REG_HEAD);
+ if (tail == head)
+ break;
+
+ usleep_range(100, 200);
+ }
+
+ if (wait_cnt >= HNS_MAX_WAIT_CNT) {
+ dev_err(qs->dev->dev, "rcb wait timeout, head not equal to tail.\n");
+ return -EBUSY;
+ }
+
+ return 0;
+}
+
 /**
  *hns_rcb_reset_ring_hw - ring reset
  *@q: ring struct pointer
diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.h b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.h
index 602816498c8dd..2319b772a271e 100644
--- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.h
+++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.h
@@ -136,6 +136,7 @@ void hns_rcbv2_int_clr_hw(struct hnae_queue *q, u32 flag);
 void hns_rcb_init_hw(struct ring_pair_cb *ring);
 void hns_rcb_reset_ring_hw(struct hnae_queue *q);
 void hns_rcb_wait_fbd_clean(struct hnae_queue **qs, int q_num, u32 flag);
+int hns_rcb_wait_tx_ring_clean(struct hnae_queue *qs);
 u32 hns_rcb_get_rx_coalesced_frames(
  struct rcb_common_cb *rcb_common, u32 port_idx);
 u32 hns_rcb_get_tx_coalesced_frames(
diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_reg.h b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_reg.h
index 886cbbf25761a..74d935d82cbc6 100644
--- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_reg.h
+++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_reg.h
@@ -464,6 +464,7 @@
 #define RCB_RING_INTMSK_TX_OVERTIME_REG 0x000C4
 #define RCB_RING_INTSTS_TX_OVERTIME_REG 0x000C8
 
+#define GMAC_FIFO_STATE_REG 0x0000UL
 #define GMAC_DUPLEX_TYPE_REG 0x0008UL
 #define GMAC_FD_FC_TYPE_REG 0x000CUL
 #define GMAC_TX_WATER_LINE_REG 0x0010UL
diff --git a/drivers/net/ethernet/hisilicon/hns/hns_enet.c b/drivers/net/ethernet/hisilicon/hns/hns_enet.c
index ef9ef703d13a0..48397d4e180fe 100644
--- a/drivers/net/ethernet/hisilicon/hns/hns_enet.c
+++ b/drivers/net/ethernet/hisilicon/hns/hns_enet.c
@@ -1212,11 +1212,26 @@ static void hns_nic_adjust_link(struct net_device *ndev)
  struct hnae_handle *h = priv->ae_handle;
  int state = 1;
 
+ /* If there is no phy, do not need adjust link */
  if (ndev->phydev) {
- h->dev->ops->adjust_link(h, ndev->phydev->speed,
- ndev->phydev->duplex);
- state = ndev->phydev->link;
+ /* When phy link down, do nothing */
+ if (ndev->phydev->link == 0)
+ return;
+
+ if (h->dev->ops->need_adjust_link(h, ndev->phydev->speed,
+  ndev->phydev->duplex)) {
+ /* because Hi161X chip don't support to change gmac
+ * speed and duplex with traffic. Delay 200ms to
+ * make sure there is no more data in chip FIFO.
+ */
+ netif_carrier_off(ndev);
+ msleep(200);
+ h->dev->ops->adjust_link(h, ndev->phydev->speed,
+ ndev->phydev->duplex);
+ netif_carrier_on(ndev);
+ }
  }
+
  state = state && h->dev->ops->get_status(h);
 
  if (state != priv->link) {
--
2.19.0


--
kernel-team mailing list
[hidden email]
https://lists.ubuntu.com/mailman/listinfo/kernel-team
Reply | Threaded
Open this post in threaded view
|

[PATCH 2/2][Cosmic][SRU Bionic] net: hns: add netif_carrier_off before change speed and duplex

dann frazier-4
In reply to this post by dann frazier-4
From: Peng Li <[hidden email]>

BugLink: https://bugs.launchpad.net/bugs/1792209

If there are packets in hardware when changing the speed
or duplex, it may cause hardware hang up.

This patch adds netif_carrier_off before change speed and
duplex in ethtool_ops.set_link_ksettings, and adds
netif_carrier_on after complete the change.

Signed-off-by: Peng Li <[hidden email]>
Signed-off-by: David S. Miller <[hidden email]>
(cherry picked from commit 455c4401fe7a538facaffb35b906ce19f1ece474)
Signed-off-by: dann frazier <[hidden email]>
---
 drivers/net/ethernet/hisilicon/hns/hns_ethtool.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/net/ethernet/hisilicon/hns/hns_ethtool.c b/drivers/net/ethernet/hisilicon/hns/hns_ethtool.c
index 2e14a3ae1d8be..c1e947bb852ff 100644
--- a/drivers/net/ethernet/hisilicon/hns/hns_ethtool.c
+++ b/drivers/net/ethernet/hisilicon/hns/hns_ethtool.c
@@ -243,7 +243,9 @@ static int hns_nic_set_link_ksettings(struct net_device *net_dev,
  }
 
  if (h->dev->ops->adjust_link) {
+ netif_carrier_off(net_dev);
  h->dev->ops->adjust_link(h, (int)speed, cmd->base.duplex);
+ netif_carrier_on(net_dev);
  return 0;
  }
 
--
2.19.0


--
kernel-team mailing list
[hidden email]
https://lists.ubuntu.com/mailman/listinfo/kernel-team
Reply | Threaded
Open this post in threaded view
|

ACK / APPLIED[C]: [PATCH 0/2][Cosmic][SRU Bionic] hns: fix hang during speed or duplex change

Seth Forshee
In reply to this post by dann frazier-4
On Thu, Sep 13, 2018 at 12:47:11PM -0600, dann frazier wrote:
> Clean cherry-picks.
>
> BugLink: https://bugs.launchpad.net/bugs/1792209

Acked-by: Seth Forshee <[hidden email]>

Applied to cosmic/master-next, thanks!

--
kernel-team mailing list
[hidden email]
https://lists.ubuntu.com/mailman/listinfo/kernel-team
Reply | Threaded
Open this post in threaded view
|

ACK: [PATCH 0/2][Cosmic][SRU Bionic] hns: fix hang during speed or duplex change

Kleber Souza
In reply to this post by dann frazier-4
On 09/13/18 20:47, dann frazier wrote:

> Clean cherry-picks.
>
> BugLink: https://bugs.launchpad.net/bugs/1792209
>
> Peng Li (2):
>   net: hns: add the code for cleaning pkt in chip
>   net: hns: add netif_carrier_off before change speed and duplex
>
>  drivers/net/ethernet/hisilicon/hns/hnae.h     |  2 +
>  .../net/ethernet/hisilicon/hns/hns_ae_adapt.c | 67 ++++++++++++++++++-
>  .../ethernet/hisilicon/hns/hns_dsaf_gmac.c    | 36 ++++++++++
>  .../net/ethernet/hisilicon/hns/hns_dsaf_mac.c | 44 ++++++++++++
>  .../net/ethernet/hisilicon/hns/hns_dsaf_mac.h |  8 +++
>  .../ethernet/hisilicon/hns/hns_dsaf_main.c    | 29 ++++++++
>  .../ethernet/hisilicon/hns/hns_dsaf_main.h    |  3 +
>  .../net/ethernet/hisilicon/hns/hns_dsaf_ppe.c | 23 +++++++
>  .../net/ethernet/hisilicon/hns/hns_dsaf_ppe.h |  1 +
>  .../net/ethernet/hisilicon/hns/hns_dsaf_rcb.c | 23 +++++++
>  .../net/ethernet/hisilicon/hns/hns_dsaf_rcb.h |  1 +
>  .../net/ethernet/hisilicon/hns/hns_dsaf_reg.h |  1 +
>  drivers/net/ethernet/hisilicon/hns/hns_enet.c | 21 +++++-
>  .../net/ethernet/hisilicon/hns/hns_ethtool.c  |  2 +
>  14 files changed, 257 insertions(+), 4 deletions(-)
>

Clean cherry-picks, tested to fix the issue and affecting only the
platform driver.

Acked-by: Kleber Sacilotto de Souza <[hidden email]>

--
kernel-team mailing list
[hidden email]
https://lists.ubuntu.com/mailman/listinfo/kernel-team
Reply | Threaded
Open this post in threaded view
|

APPLIED[B]: [PATCH 0/2][Cosmic][SRU Bionic] hns: fix hang during speed or duplex change

Stefan Bader-2
In reply to this post by dann frazier-4
On 13.09.2018 20:47, dann frazier wrote:

> Clean cherry-picks.
>
> BugLink: https://bugs.launchpad.net/bugs/1792209
>
> Peng Li (2):
>   net: hns: add the code for cleaning pkt in chip
>   net: hns: add netif_carrier_off before change speed and duplex
>
>  drivers/net/ethernet/hisilicon/hns/hnae.h     |  2 +
>  .../net/ethernet/hisilicon/hns/hns_ae_adapt.c | 67 ++++++++++++++++++-
>  .../ethernet/hisilicon/hns/hns_dsaf_gmac.c    | 36 ++++++++++
>  .../net/ethernet/hisilicon/hns/hns_dsaf_mac.c | 44 ++++++++++++
>  .../net/ethernet/hisilicon/hns/hns_dsaf_mac.h |  8 +++
>  .../ethernet/hisilicon/hns/hns_dsaf_main.c    | 29 ++++++++
>  .../ethernet/hisilicon/hns/hns_dsaf_main.h    |  3 +
>  .../net/ethernet/hisilicon/hns/hns_dsaf_ppe.c | 23 +++++++
>  .../net/ethernet/hisilicon/hns/hns_dsaf_ppe.h |  1 +
>  .../net/ethernet/hisilicon/hns/hns_dsaf_rcb.c | 23 +++++++
>  .../net/ethernet/hisilicon/hns/hns_dsaf_rcb.h |  1 +
>  .../net/ethernet/hisilicon/hns/hns_dsaf_reg.h |  1 +
>  drivers/net/ethernet/hisilicon/hns/hns_enet.c | 21 +++++-
>  .../net/ethernet/hisilicon/hns/hns_ethtool.c  |  2 +
>  14 files changed, 257 insertions(+), 4 deletions(-)
>
Applied to bionic/master-next. Thanks.

-Stefan


--
kernel-team mailing list
[hidden email]
https://lists.ubuntu.com/mailman/listinfo/kernel-team

signature.asc (836 bytes) Download Attachment