Skip to content

Commit 1d3c641

Browse files
Jiawen Wudavem330
authored andcommitted
net: txgbe: fix to control VLAN strip
When VLAN tag strip is changed to enable or disable, the hardware requires the Rx ring to be in a disabled state, otherwise the feature cannot be changed. Fixes: f3b03c6 ("net: wangxun: Implement vlan add and kill functions") Signed-off-by: Jiawen Wu <[email protected]> Reviewed-by: Simon Horman <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent ac71ab7 commit 1d3c641

File tree

7 files changed

+84
-13
lines changed

7 files changed

+84
-13
lines changed

drivers/net/ethernet/wangxun/libwx/wx_hw.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1958,6 +1958,8 @@ int wx_sw_init(struct wx *wx)
19581958
return -ENOMEM;
19591959
}
19601960

1961+
bitmap_zero(wx->state, WX_STATE_NBITS);
1962+
19611963
return 0;
19621964
}
19631965
EXPORT_SYMBOL(wx_sw_init);

drivers/net/ethernet/wangxun/libwx/wx_lib.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2692,9 +2692,9 @@ int wx_set_features(struct net_device *netdev, netdev_features_t features)
26922692

26932693
netdev->features = features;
26942694

2695-
if (changed &
2696-
(NETIF_F_HW_VLAN_CTAG_RX |
2697-
NETIF_F_HW_VLAN_STAG_RX))
2695+
if (wx->mac.type == wx_mac_sp && changed & NETIF_F_HW_VLAN_CTAG_RX)
2696+
wx->do_reset(netdev);
2697+
else if (changed & (NETIF_F_HW_VLAN_CTAG_RX | NETIF_F_HW_VLAN_CTAG_FILTER))
26982698
wx_set_rx_mode(netdev);
26992699

27002700
return 0;

drivers/net/ethernet/wangxun/libwx/wx_type.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -982,8 +982,13 @@ struct wx_hw_stats {
982982
u64 qmprc;
983983
};
984984

985+
enum wx_state {
986+
WX_STATE_RESETTING,
987+
WX_STATE_NBITS, /* must be last */
988+
};
985989
struct wx {
986990
unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)];
991+
DECLARE_BITMAP(state, WX_STATE_NBITS);
987992

988993
void *priv;
989994
u8 __iomem *hw_addr;
@@ -1071,6 +1076,8 @@ struct wx {
10711076
u64 hw_csum_rx_good;
10721077
u64 hw_csum_rx_error;
10731078
u64 alloc_rx_buff_failed;
1079+
1080+
void (*do_reset)(struct net_device *netdev);
10741081
};
10751082

10761083
#define WX_INTR_ALL (~0ULL)
@@ -1131,4 +1138,19 @@ static inline struct wx *phylink_to_wx(struct phylink_config *config)
11311138
return container_of(config, struct wx, phylink_config);
11321139
}
11331140

1141+
static inline int wx_set_state_reset(struct wx *wx)
1142+
{
1143+
u8 timeout = 50;
1144+
1145+
while (test_and_set_bit(WX_STATE_RESETTING, wx->state)) {
1146+
timeout--;
1147+
if (!timeout)
1148+
return -EBUSY;
1149+
1150+
usleep_range(1000, 2000);
1151+
}
1152+
1153+
return 0;
1154+
}
1155+
11341156
#endif /* _WX_TYPE_H_ */

drivers/net/ethernet/wangxun/ngbe/ngbe_ethtool.c

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ static int ngbe_set_ringparam(struct net_device *netdev,
5252
struct wx *wx = netdev_priv(netdev);
5353
u32 new_rx_count, new_tx_count;
5454
struct wx_ring *temp_ring;
55-
int i;
55+
int i, err = 0;
5656

5757
new_tx_count = clamp_t(u32, ring->tx_pending, WX_MIN_TXD, WX_MAX_TXD);
5858
new_tx_count = ALIGN(new_tx_count, WX_REQ_TX_DESCRIPTOR_MULTIPLE);
@@ -64,6 +64,10 @@ static int ngbe_set_ringparam(struct net_device *netdev,
6464
new_rx_count == wx->rx_ring_count)
6565
return 0;
6666

67+
err = wx_set_state_reset(wx);
68+
if (err)
69+
return err;
70+
6771
if (!netif_running(wx->netdev)) {
6872
for (i = 0; i < wx->num_tx_queues; i++)
6973
wx->tx_ring[i]->count = new_tx_count;
@@ -72,14 +76,16 @@ static int ngbe_set_ringparam(struct net_device *netdev,
7276
wx->tx_ring_count = new_tx_count;
7377
wx->rx_ring_count = new_rx_count;
7478

75-
return 0;
79+
goto clear_reset;
7680
}
7781

7882
/* allocate temporary buffer to store rings in */
7983
i = max_t(int, wx->num_tx_queues, wx->num_rx_queues);
8084
temp_ring = kvmalloc_array(i, sizeof(struct wx_ring), GFP_KERNEL);
81-
if (!temp_ring)
82-
return -ENOMEM;
85+
if (!temp_ring) {
86+
err = -ENOMEM;
87+
goto clear_reset;
88+
}
8389

8490
ngbe_down(wx);
8591

@@ -89,7 +95,9 @@ static int ngbe_set_ringparam(struct net_device *netdev,
8995
wx_configure(wx);
9096
ngbe_up(wx);
9197

92-
return 0;
98+
clear_reset:
99+
clear_bit(WX_STATE_RESETTING, wx->state);
100+
return err;
93101
}
94102

95103
static int ngbe_set_channels(struct net_device *dev,

drivers/net/ethernet/wangxun/txgbe/txgbe_ethtool.c

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ static int txgbe_set_ringparam(struct net_device *netdev,
1919
struct wx *wx = netdev_priv(netdev);
2020
u32 new_rx_count, new_tx_count;
2121
struct wx_ring *temp_ring;
22-
int i;
22+
int i, err = 0;
2323

2424
new_tx_count = clamp_t(u32, ring->tx_pending, WX_MIN_TXD, WX_MAX_TXD);
2525
new_tx_count = ALIGN(new_tx_count, WX_REQ_TX_DESCRIPTOR_MULTIPLE);
@@ -31,6 +31,10 @@ static int txgbe_set_ringparam(struct net_device *netdev,
3131
new_rx_count == wx->rx_ring_count)
3232
return 0;
3333

34+
err = wx_set_state_reset(wx);
35+
if (err)
36+
return err;
37+
3438
if (!netif_running(wx->netdev)) {
3539
for (i = 0; i < wx->num_tx_queues; i++)
3640
wx->tx_ring[i]->count = new_tx_count;
@@ -39,14 +43,16 @@ static int txgbe_set_ringparam(struct net_device *netdev,
3943
wx->tx_ring_count = new_tx_count;
4044
wx->rx_ring_count = new_rx_count;
4145

42-
return 0;
46+
goto clear_reset;
4347
}
4448

4549
/* allocate temporary buffer to store rings in */
4650
i = max_t(int, wx->num_tx_queues, wx->num_rx_queues);
4751
temp_ring = kvmalloc_array(i, sizeof(struct wx_ring), GFP_KERNEL);
48-
if (!temp_ring)
49-
return -ENOMEM;
52+
if (!temp_ring) {
53+
err = -ENOMEM;
54+
goto clear_reset;
55+
}
5056

5157
txgbe_down(wx);
5258

@@ -55,7 +61,9 @@ static int txgbe_set_ringparam(struct net_device *netdev,
5561

5662
txgbe_up(wx);
5763

58-
return 0;
64+
clear_reset:
65+
clear_bit(WX_STATE_RESETTING, wx->state);
66+
return err;
5967
}
6068

6169
static int txgbe_set_channels(struct net_device *dev,

drivers/net/ethernet/wangxun/txgbe/txgbe_main.c

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,8 @@ static int txgbe_sw_init(struct wx *wx)
269269
wx->tx_work_limit = TXGBE_DEFAULT_TX_WORK;
270270
wx->rx_work_limit = TXGBE_DEFAULT_RX_WORK;
271271

272+
wx->do_reset = txgbe_do_reset;
273+
272274
return 0;
273275
}
274276

@@ -421,6 +423,34 @@ int txgbe_setup_tc(struct net_device *dev, u8 tc)
421423
return 0;
422424
}
423425

426+
static void txgbe_reinit_locked(struct wx *wx)
427+
{
428+
int err = 0;
429+
430+
netif_trans_update(wx->netdev);
431+
432+
err = wx_set_state_reset(wx);
433+
if (err) {
434+
wx_err(wx, "wait device reset timeout\n");
435+
return;
436+
}
437+
438+
txgbe_down(wx);
439+
txgbe_up(wx);
440+
441+
clear_bit(WX_STATE_RESETTING, wx->state);
442+
}
443+
444+
void txgbe_do_reset(struct net_device *netdev)
445+
{
446+
struct wx *wx = netdev_priv(netdev);
447+
448+
if (netif_running(netdev))
449+
txgbe_reinit_locked(wx);
450+
else
451+
txgbe_reset(wx);
452+
}
453+
424454
static const struct net_device_ops txgbe_netdev_ops = {
425455
.ndo_open = txgbe_open,
426456
.ndo_stop = txgbe_close,

drivers/net/ethernet/wangxun/txgbe/txgbe_type.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,7 @@ extern char txgbe_driver_name[];
134134
void txgbe_down(struct wx *wx);
135135
void txgbe_up(struct wx *wx);
136136
int txgbe_setup_tc(struct net_device *dev, u8 tc);
137+
void txgbe_do_reset(struct net_device *netdev);
137138

138139
#define NODE_PROP(_NAME, _PROP) \
139140
(const struct software_node) { \

0 commit comments

Comments
 (0)