Skip to content

Commit def70b6

Browse files
committed
Merge branch 'hns-fixes'
Peng Li says: ==================== net: hns: fix some bugs about speed and duplex change If there are packets in hardware when changing the spped or duplex, it may cause hardware hang up. This patchset 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 patchset 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: David S. Miller <[email protected]>
2 parents 05212ba + 455c440 commit def70b6

File tree

14 files changed

+257
-4
lines changed

14 files changed

+257
-4
lines changed

drivers/net/ethernet/hisilicon/hns/hnae.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -486,6 +486,8 @@ struct hnae_ae_ops {
486486
u8 *auto_neg, u16 *speed, u8 *duplex);
487487
void (*toggle_ring_irq)(struct hnae_ring *ring, u32 val);
488488
void (*adjust_link)(struct hnae_handle *handle, int speed, int duplex);
489+
bool (*need_adjust_link)(struct hnae_handle *handle,
490+
int speed, int duplex);
489491
int (*set_loopback)(struct hnae_handle *handle,
490492
enum hnae_loop loop_mode, int en);
491493
void (*get_ring_bdnum_limit)(struct hnae_queue *queue,

drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c

Lines changed: 66 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,41 @@ static void hns_ae_put_handle(struct hnae_handle *handle)
155155
hns_ae_get_ring_pair(handle->qs[i])->used_by_vf = 0;
156156
}
157157

158+
static int hns_ae_wait_flow_down(struct hnae_handle *handle)
159+
{
160+
struct dsaf_device *dsaf_dev;
161+
struct hns_ppe_cb *ppe_cb;
162+
struct hnae_vf_cb *vf_cb;
163+
int ret;
164+
int i;
165+
166+
for (i = 0; i < handle->q_num; i++) {
167+
ret = hns_rcb_wait_tx_ring_clean(handle->qs[i]);
168+
if (ret)
169+
return ret;
170+
}
171+
172+
ppe_cb = hns_get_ppe_cb(handle);
173+
ret = hns_ppe_wait_tx_fifo_clean(ppe_cb);
174+
if (ret)
175+
return ret;
176+
177+
dsaf_dev = hns_ae_get_dsaf_dev(handle->dev);
178+
if (!dsaf_dev)
179+
return -EINVAL;
180+
ret = hns_dsaf_wait_pkt_clean(dsaf_dev, handle->dport_id);
181+
if (ret)
182+
return ret;
183+
184+
vf_cb = hns_ae_get_vf_cb(handle);
185+
ret = hns_mac_wait_fifo_clean(vf_cb->mac_cb);
186+
if (ret)
187+
return ret;
188+
189+
mdelay(10);
190+
return 0;
191+
}
192+
158193
static void hns_ae_ring_enable_all(struct hnae_handle *handle, int val)
159194
{
160195
int q_num = handle->q_num;
@@ -399,12 +434,41 @@ static int hns_ae_get_mac_info(struct hnae_handle *handle,
399434
return hns_mac_get_port_info(mac_cb, auto_neg, speed, duplex);
400435
}
401436

437+
static bool hns_ae_need_adjust_link(struct hnae_handle *handle, int speed,
438+
int duplex)
439+
{
440+
struct hns_mac_cb *mac_cb = hns_get_mac_cb(handle);
441+
442+
return hns_mac_need_adjust_link(mac_cb, speed, duplex);
443+
}
444+
402445
static void hns_ae_adjust_link(struct hnae_handle *handle, int speed,
403446
int duplex)
404447
{
405448
struct hns_mac_cb *mac_cb = hns_get_mac_cb(handle);
406449

407-
hns_mac_adjust_link(mac_cb, speed, duplex);
450+
switch (mac_cb->dsaf_dev->dsaf_ver) {
451+
case AE_VERSION_1:
452+
hns_mac_adjust_link(mac_cb, speed, duplex);
453+
break;
454+
455+
case AE_VERSION_2:
456+
/* chip need to clear all pkt inside */
457+
hns_mac_disable(mac_cb, MAC_COMM_MODE_RX);
458+
if (hns_ae_wait_flow_down(handle)) {
459+
hns_mac_enable(mac_cb, MAC_COMM_MODE_RX);
460+
break;
461+
}
462+
463+
hns_mac_adjust_link(mac_cb, speed, duplex);
464+
hns_mac_enable(mac_cb, MAC_COMM_MODE_RX);
465+
break;
466+
467+
default:
468+
break;
469+
}
470+
471+
return;
408472
}
409473

410474
static void hns_ae_get_ring_bdnum_limit(struct hnae_queue *queue,
@@ -902,6 +966,7 @@ static struct hnae_ae_ops hns_dsaf_ops = {
902966
.get_status = hns_ae_get_link_status,
903967
.get_info = hns_ae_get_mac_info,
904968
.adjust_link = hns_ae_adjust_link,
969+
.need_adjust_link = hns_ae_need_adjust_link,
905970
.set_loopback = hns_ae_config_loopback,
906971
.get_ring_bdnum_limit = hns_ae_get_ring_bdnum_limit,
907972
.get_pauseparam = hns_ae_get_pauseparam,

drivers/net/ethernet/hisilicon/hns/hns_dsaf_gmac.c

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,16 @@ static void hns_gmac_get_pausefrm_cfg(void *mac_drv, u32 *rx_pause_en,
257257
*tx_pause_en = dsaf_get_bit(pause_en, GMAC_PAUSE_EN_TX_FDFC_B);
258258
}
259259

260+
static bool hns_gmac_need_adjust_link(void *mac_drv, enum mac_speed speed,
261+
int duplex)
262+
{
263+
struct mac_driver *drv = (struct mac_driver *)mac_drv;
264+
struct hns_mac_cb *mac_cb = drv->mac_cb;
265+
266+
return (mac_cb->speed != speed) ||
267+
(mac_cb->half_duplex == duplex);
268+
}
269+
260270
static int hns_gmac_adjust_link(void *mac_drv, enum mac_speed speed,
261271
u32 full_duplex)
262272
{
@@ -309,6 +319,30 @@ static void hns_gmac_set_promisc(void *mac_drv, u8 en)
309319
hns_gmac_set_uc_match(mac_drv, en);
310320
}
311321

322+
int hns_gmac_wait_fifo_clean(void *mac_drv)
323+
{
324+
struct mac_driver *drv = (struct mac_driver *)mac_drv;
325+
int wait_cnt;
326+
u32 val;
327+
328+
wait_cnt = 0;
329+
while (wait_cnt++ < HNS_MAX_WAIT_CNT) {
330+
val = dsaf_read_dev(drv, GMAC_FIFO_STATE_REG);
331+
/* bit5~bit0 is not send complete pkts */
332+
if ((val & 0x3f) == 0)
333+
break;
334+
usleep_range(100, 200);
335+
}
336+
337+
if (wait_cnt >= HNS_MAX_WAIT_CNT) {
338+
dev_err(drv->dev,
339+
"hns ge %d fifo was not idle.\n", drv->mac_id);
340+
return -EBUSY;
341+
}
342+
343+
return 0;
344+
}
345+
312346
static void hns_gmac_init(void *mac_drv)
313347
{
314348
u32 port;
@@ -690,6 +724,7 @@ void *hns_gmac_config(struct hns_mac_cb *mac_cb, struct mac_params *mac_param)
690724
mac_drv->mac_disable = hns_gmac_disable;
691725
mac_drv->mac_free = hns_gmac_free;
692726
mac_drv->adjust_link = hns_gmac_adjust_link;
727+
mac_drv->need_adjust_link = hns_gmac_need_adjust_link;
693728
mac_drv->set_tx_auto_pause_frames = hns_gmac_set_tx_auto_pause_frames;
694729
mac_drv->config_max_frame_length = hns_gmac_config_max_frame_length;
695730
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)
717752
mac_drv->get_strings = hns_gmac_get_strings;
718753
mac_drv->update_stats = hns_gmac_update_stats;
719754
mac_drv->set_promiscuous = hns_gmac_set_promisc;
755+
mac_drv->wait_fifo_clean = hns_gmac_wait_fifo_clean;
720756

721757
return (void *)mac_drv;
722758
}

drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,26 @@ int hns_mac_get_port_info(struct hns_mac_cb *mac_cb,
114114
return 0;
115115
}
116116

117+
/**
118+
*hns_mac_is_adjust_link - check is need change mac speed and duplex register
119+
*@mac_cb: mac device
120+
*@speed: phy device speed
121+
*@duplex:phy device duplex
122+
*
123+
*/
124+
bool hns_mac_need_adjust_link(struct hns_mac_cb *mac_cb, int speed, int duplex)
125+
{
126+
struct mac_driver *mac_ctrl_drv;
127+
128+
mac_ctrl_drv = (struct mac_driver *)(mac_cb->priv.mac);
129+
130+
if (mac_ctrl_drv->need_adjust_link)
131+
return mac_ctrl_drv->need_adjust_link(mac_ctrl_drv,
132+
(enum mac_speed)speed, duplex);
133+
else
134+
return true;
135+
}
136+
117137
void hns_mac_adjust_link(struct hns_mac_cb *mac_cb, int speed, int duplex)
118138
{
119139
int ret;
@@ -430,6 +450,16 @@ int hns_mac_vm_config_bc_en(struct hns_mac_cb *mac_cb, u32 vmid, bool enable)
430450
return 0;
431451
}
432452

453+
int hns_mac_wait_fifo_clean(struct hns_mac_cb *mac_cb)
454+
{
455+
struct mac_driver *drv = hns_mac_get_drv(mac_cb);
456+
457+
if (drv->wait_fifo_clean)
458+
return drv->wait_fifo_clean(drv);
459+
460+
return 0;
461+
}
462+
433463
void hns_mac_reset(struct hns_mac_cb *mac_cb)
434464
{
435465
struct mac_driver *drv = hns_mac_get_drv(mac_cb);
@@ -998,6 +1028,20 @@ static int hns_mac_get_max_port_num(struct dsaf_device *dsaf_dev)
9981028
return DSAF_MAX_PORT_NUM;
9991029
}
10001030

1031+
void hns_mac_enable(struct hns_mac_cb *mac_cb, enum mac_commom_mode mode)
1032+
{
1033+
struct mac_driver *mac_ctrl_drv = hns_mac_get_drv(mac_cb);
1034+
1035+
mac_ctrl_drv->mac_enable(mac_cb->priv.mac, mode);
1036+
}
1037+
1038+
void hns_mac_disable(struct hns_mac_cb *mac_cb, enum mac_commom_mode mode)
1039+
{
1040+
struct mac_driver *mac_ctrl_drv = hns_mac_get_drv(mac_cb);
1041+
1042+
mac_ctrl_drv->mac_disable(mac_cb->priv.mac, mode);
1043+
}
1044+
10011045
/**
10021046
* hns_mac_init - init mac
10031047
* @dsaf_dev: dsa fabric device struct pointer

drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -356,6 +356,9 @@ struct mac_driver {
356356
/*adjust mac mode of port,include speed and duplex*/
357357
int (*adjust_link)(void *mac_drv, enum mac_speed speed,
358358
u32 full_duplex);
359+
/* need adjust link */
360+
bool (*need_adjust_link)(void *mac_drv, enum mac_speed speed,
361+
int duplex);
359362
/* config autoegotaite mode of port*/
360363
void (*set_an_mode)(void *mac_drv, u8 enable);
361364
/* config loopbank mode */
@@ -394,6 +397,7 @@ struct mac_driver {
394397
void (*get_info)(void *mac_drv, struct mac_info *mac_info);
395398

396399
void (*update_stats)(void *mac_drv);
400+
int (*wait_fifo_clean)(void *mac_drv);
397401

398402
enum mac_mode mac_mode;
399403
u8 mac_id;
@@ -427,6 +431,7 @@ void *hns_xgmac_config(struct hns_mac_cb *mac_cb,
427431

428432
int hns_mac_init(struct dsaf_device *dsaf_dev);
429433
void mac_adjust_link(struct net_device *net_dev);
434+
bool hns_mac_need_adjust_link(struct hns_mac_cb *mac_cb, int speed, int duplex);
430435
void hns_mac_get_link_status(struct hns_mac_cb *mac_cb, u32 *link_status);
431436
int hns_mac_change_vf_addr(struct hns_mac_cb *mac_cb, u32 vmid, char *addr);
432437
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,
463468
int hns_mac_rm_uc_addr(struct hns_mac_cb *mac_cb, u8 vf_id,
464469
const unsigned char *addr);
465470
int hns_mac_clr_multicast(struct hns_mac_cb *mac_cb, int vfn);
471+
void hns_mac_enable(struct hns_mac_cb *mac_cb, enum mac_commom_mode mode);
472+
void hns_mac_disable(struct hns_mac_cb *mac_cb, enum mac_commom_mode mode);
473+
int hns_mac_wait_fifo_clean(struct hns_mac_cb *mac_cb);
466474

467475
#endif /* _HNS_DSAF_MAC_H */

drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2727,6 +2727,35 @@ void hns_dsaf_set_promisc_tcam(struct dsaf_device *dsaf_dev,
27272727
soft_mac_entry->index = enable ? entry_index : DSAF_INVALID_ENTRY_IDX;
27282728
}
27292729

2730+
int hns_dsaf_wait_pkt_clean(struct dsaf_device *dsaf_dev, int port)
2731+
{
2732+
u32 val, val_tmp;
2733+
int wait_cnt;
2734+
2735+
if (port >= DSAF_SERVICE_NW_NUM)
2736+
return 0;
2737+
2738+
wait_cnt = 0;
2739+
while (wait_cnt++ < HNS_MAX_WAIT_CNT) {
2740+
val = dsaf_read_dev(dsaf_dev, DSAF_VOQ_IN_PKT_NUM_0_REG +
2741+
(port + DSAF_XGE_NUM) * 0x40);
2742+
val_tmp = dsaf_read_dev(dsaf_dev, DSAF_VOQ_OUT_PKT_NUM_0_REG +
2743+
(port + DSAF_XGE_NUM) * 0x40);
2744+
if (val == val_tmp)
2745+
break;
2746+
2747+
usleep_range(100, 200);
2748+
}
2749+
2750+
if (wait_cnt >= HNS_MAX_WAIT_CNT) {
2751+
dev_err(dsaf_dev->dev, "hns dsaf clean wait timeout(%u - %u).\n",
2752+
val, val_tmp);
2753+
return -EBUSY;
2754+
}
2755+
2756+
return 0;
2757+
}
2758+
27302759
/**
27312760
* dsaf_probe - probo dsaf dev
27322761
* @pdev: dasf platform device

drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ struct hns_mac_cb;
4444
#define DSAF_ROCE_CREDIT_CHN 8
4545
#define DSAF_ROCE_CHAN_MODE 3
4646

47+
#define HNS_MAX_WAIT_CNT 10000
48+
4749
enum dsaf_roce_port_mode {
4850
DSAF_ROCE_6PORT_MODE,
4951
DSAF_ROCE_4PORT_MODE,
@@ -463,5 +465,6 @@ int hns_dsaf_rm_mac_addr(
463465

464466
int hns_dsaf_clr_mac_mc_port(struct dsaf_device *dsaf_dev,
465467
u8 mac_id, u8 port_num);
468+
int hns_dsaf_wait_pkt_clean(struct dsaf_device *dsaf_dev, int port);
466469

467470
#endif /* __HNS_DSAF_MAIN_H__ */

drivers/net/ethernet/hisilicon/hns/hns_dsaf_ppe.c

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -275,6 +275,29 @@ static void hns_ppe_exc_irq_en(struct hns_ppe_cb *ppe_cb, int en)
275275
dsaf_write_dev(ppe_cb, PPE_INTEN_REG, msk_vlue & vld_msk);
276276
}
277277

278+
int hns_ppe_wait_tx_fifo_clean(struct hns_ppe_cb *ppe_cb)
279+
{
280+
int wait_cnt;
281+
u32 val;
282+
283+
wait_cnt = 0;
284+
while (wait_cnt++ < HNS_MAX_WAIT_CNT) {
285+
val = dsaf_read_dev(ppe_cb, PPE_CURR_TX_FIFO0_REG) & 0x3ffU;
286+
if (!val)
287+
break;
288+
289+
usleep_range(100, 200);
290+
}
291+
292+
if (wait_cnt >= HNS_MAX_WAIT_CNT) {
293+
dev_err(ppe_cb->dev, "hns ppe tx fifo clean wait timeout, still has %u pkt.\n",
294+
val);
295+
return -EBUSY;
296+
}
297+
298+
return 0;
299+
}
300+
278301
/**
279302
* ppe_init_hw - init ppe
280303
* @ppe_cb: ppe device

drivers/net/ethernet/hisilicon/hns/hns_dsaf_ppe.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ struct ppe_common_cb {
100100

101101
};
102102

103+
int hns_ppe_wait_tx_fifo_clean(struct hns_ppe_cb *ppe_cb);
103104
int hns_ppe_init(struct dsaf_device *dsaf_dev);
104105

105106
void hns_ppe_uninit(struct dsaf_device *dsaf_dev);

drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.c

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,29 @@ void hns_rcb_wait_fbd_clean(struct hnae_queue **qs, int q_num, u32 flag)
6666
"queue(%d) wait fbd(%d) clean fail!!\n", i, fbd_num);
6767
}
6868

69+
int hns_rcb_wait_tx_ring_clean(struct hnae_queue *qs)
70+
{
71+
u32 head, tail;
72+
int wait_cnt;
73+
74+
tail = dsaf_read_dev(&qs->tx_ring, RCB_REG_TAIL);
75+
wait_cnt = 0;
76+
while (wait_cnt++ < HNS_MAX_WAIT_CNT) {
77+
head = dsaf_read_dev(&qs->tx_ring, RCB_REG_HEAD);
78+
if (tail == head)
79+
break;
80+
81+
usleep_range(100, 200);
82+
}
83+
84+
if (wait_cnt >= HNS_MAX_WAIT_CNT) {
85+
dev_err(qs->dev->dev, "rcb wait timeout, head not equal to tail.\n");
86+
return -EBUSY;
87+
}
88+
89+
return 0;
90+
}
91+
6992
/**
7093
*hns_rcb_reset_ring_hw - ring reset
7194
*@q: ring struct pointer

drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,7 @@ void hns_rcbv2_int_clr_hw(struct hnae_queue *q, u32 flag);
136136
void hns_rcb_init_hw(struct ring_pair_cb *ring);
137137
void hns_rcb_reset_ring_hw(struct hnae_queue *q);
138138
void hns_rcb_wait_fbd_clean(struct hnae_queue **qs, int q_num, u32 flag);
139+
int hns_rcb_wait_tx_ring_clean(struct hnae_queue *qs);
139140
u32 hns_rcb_get_rx_coalesced_frames(
140141
struct rcb_common_cb *rcb_common, u32 port_idx);
141142
u32 hns_rcb_get_tx_coalesced_frames(

0 commit comments

Comments
 (0)