Skip to content

Commit 310a110

Browse files
committed
Merge branch 'net-enetc-fix-some-known-issues'
Wei Fang says: ==================== net: enetc: fix some known issues There are some issues with the enetc driver, some of which are specific to the LS1028A platform, and some of which were introduced recently when i.MX95 ENETC support was added, so this patch set aims to clean up those issues. v1: https://lore.kernel.org/[email protected] v2: https://lore.kernel.org/[email protected] ==================== Link: https://patch.msgid.link/[email protected] Signed-off-by: Jakub Kicinski <[email protected]>
2 parents 85c7ca9 + 249df69 commit 310a110

File tree

3 files changed

+80
-32
lines changed

3 files changed

+80
-32
lines changed

drivers/net/ethernet/freescale/enetc/enetc.c

Lines changed: 74 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,24 @@ static bool enetc_skb_is_tcp(struct sk_buff *skb)
167167
return skb->csum_offset == offsetof(struct tcphdr, check);
168168
}
169169

170+
/**
171+
* enetc_unwind_tx_frame() - Unwind the DMA mappings of a multi-buffer Tx frame
172+
* @tx_ring: Pointer to the Tx ring on which the buffer descriptors are located
173+
* @count: Number of Tx buffer descriptors which need to be unmapped
174+
* @i: Index of the last successfully mapped Tx buffer descriptor
175+
*/
176+
static void enetc_unwind_tx_frame(struct enetc_bdr *tx_ring, int count, int i)
177+
{
178+
while (count--) {
179+
struct enetc_tx_swbd *tx_swbd = &tx_ring->tx_swbd[i];
180+
181+
enetc_free_tx_frame(tx_ring, tx_swbd);
182+
if (i == 0)
183+
i = tx_ring->bd_count;
184+
i--;
185+
}
186+
}
187+
170188
static int enetc_map_tx_buffs(struct enetc_bdr *tx_ring, struct sk_buff *skb)
171189
{
172190
bool do_vlan, do_onestep_tstamp = false, do_twostep_tstamp = false;
@@ -279,9 +297,11 @@ static int enetc_map_tx_buffs(struct enetc_bdr *tx_ring, struct sk_buff *skb)
279297
}
280298

281299
if (do_onestep_tstamp) {
282-
u32 lo, hi, val;
283-
u64 sec, nsec;
300+
__be32 new_sec_l, new_nsec;
301+
u32 lo, hi, nsec, val;
302+
__be16 new_sec_h;
284303
u8 *data;
304+
u64 sec;
285305

286306
lo = enetc_rd_hot(hw, ENETC_SICTR0);
287307
hi = enetc_rd_hot(hw, ENETC_SICTR1);
@@ -295,13 +315,38 @@ static int enetc_map_tx_buffs(struct enetc_bdr *tx_ring, struct sk_buff *skb)
295315
/* Update originTimestamp field of Sync packet
296316
* - 48 bits seconds field
297317
* - 32 bits nanseconds field
318+
*
319+
* In addition, the UDP checksum needs to be updated
320+
* by software after updating originTimestamp field,
321+
* otherwise the hardware will calculate the wrong
322+
* checksum when updating the correction field and
323+
* update it to the packet.
298324
*/
299325
data = skb_mac_header(skb);
300-
*(__be16 *)(data + offset2) =
301-
htons((sec >> 32) & 0xffff);
302-
*(__be32 *)(data + offset2 + 2) =
303-
htonl(sec & 0xffffffff);
304-
*(__be32 *)(data + offset2 + 6) = htonl(nsec);
326+
new_sec_h = htons((sec >> 32) & 0xffff);
327+
new_sec_l = htonl(sec & 0xffffffff);
328+
new_nsec = htonl(nsec);
329+
if (udp) {
330+
struct udphdr *uh = udp_hdr(skb);
331+
__be32 old_sec_l, old_nsec;
332+
__be16 old_sec_h;
333+
334+
old_sec_h = *(__be16 *)(data + offset2);
335+
inet_proto_csum_replace2(&uh->check, skb, old_sec_h,
336+
new_sec_h, false);
337+
338+
old_sec_l = *(__be32 *)(data + offset2 + 2);
339+
inet_proto_csum_replace4(&uh->check, skb, old_sec_l,
340+
new_sec_l, false);
341+
342+
old_nsec = *(__be32 *)(data + offset2 + 6);
343+
inet_proto_csum_replace4(&uh->check, skb, old_nsec,
344+
new_nsec, false);
345+
}
346+
347+
*(__be16 *)(data + offset2) = new_sec_h;
348+
*(__be32 *)(data + offset2 + 2) = new_sec_l;
349+
*(__be32 *)(data + offset2 + 6) = new_nsec;
305350

306351
/* Configure single-step register */
307352
val = ENETC_PM0_SINGLE_STEP_EN;
@@ -372,25 +417,20 @@ static int enetc_map_tx_buffs(struct enetc_bdr *tx_ring, struct sk_buff *skb)
372417
dma_err:
373418
dev_err(tx_ring->dev, "DMA map error");
374419

375-
do {
376-
tx_swbd = &tx_ring->tx_swbd[i];
377-
enetc_free_tx_frame(tx_ring, tx_swbd);
378-
if (i == 0)
379-
i = tx_ring->bd_count;
380-
i--;
381-
} while (count--);
420+
enetc_unwind_tx_frame(tx_ring, count, i);
382421

383422
return 0;
384423
}
385424

386-
static void enetc_map_tx_tso_hdr(struct enetc_bdr *tx_ring, struct sk_buff *skb,
387-
struct enetc_tx_swbd *tx_swbd,
388-
union enetc_tx_bd *txbd, int *i, int hdr_len,
389-
int data_len)
425+
static int enetc_map_tx_tso_hdr(struct enetc_bdr *tx_ring, struct sk_buff *skb,
426+
struct enetc_tx_swbd *tx_swbd,
427+
union enetc_tx_bd *txbd, int *i, int hdr_len,
428+
int data_len)
390429
{
391430
union enetc_tx_bd txbd_tmp;
392431
u8 flags = 0, e_flags = 0;
393432
dma_addr_t addr;
433+
int count = 1;
394434

395435
enetc_clear_tx_bd(&txbd_tmp);
396436
addr = tx_ring->tso_headers_dma + *i * TSO_HEADER_SIZE;
@@ -433,7 +473,10 @@ static void enetc_map_tx_tso_hdr(struct enetc_bdr *tx_ring, struct sk_buff *skb,
433473
/* Write the BD */
434474
txbd_tmp.ext.e_flags = e_flags;
435475
*txbd = txbd_tmp;
476+
count++;
436477
}
478+
479+
return count;
437480
}
438481

439482
static int enetc_map_tx_tso_data(struct enetc_bdr *tx_ring, struct sk_buff *skb,
@@ -790,9 +833,9 @@ static int enetc_map_tx_tso_buffs(struct enetc_bdr *tx_ring, struct sk_buff *skb
790833

791834
/* compute the csum over the L4 header */
792835
csum = enetc_tso_hdr_csum(&tso, skb, hdr, hdr_len, &pos);
793-
enetc_map_tx_tso_hdr(tx_ring, skb, tx_swbd, txbd, &i, hdr_len, data_len);
836+
count += enetc_map_tx_tso_hdr(tx_ring, skb, tx_swbd, txbd,
837+
&i, hdr_len, data_len);
794838
bd_data_num = 0;
795-
count++;
796839

797840
while (data_len > 0) {
798841
int size;
@@ -816,8 +859,13 @@ static int enetc_map_tx_tso_buffs(struct enetc_bdr *tx_ring, struct sk_buff *skb
816859
err = enetc_map_tx_tso_data(tx_ring, skb, tx_swbd, txbd,
817860
tso.data, size,
818861
size == data_len);
819-
if (err)
862+
if (err) {
863+
if (i == 0)
864+
i = tx_ring->bd_count;
865+
i--;
866+
820867
goto err_map_data;
868+
}
821869

822870
data_len -= size;
823871
count++;
@@ -846,13 +894,7 @@ static int enetc_map_tx_tso_buffs(struct enetc_bdr *tx_ring, struct sk_buff *skb
846894
dev_err(tx_ring->dev, "DMA map error");
847895

848896
err_chained_bd:
849-
do {
850-
tx_swbd = &tx_ring->tx_swbd[i];
851-
enetc_free_tx_frame(tx_ring, tx_swbd);
852-
if (i == 0)
853-
i = tx_ring->bd_count;
854-
i--;
855-
} while (count--);
897+
enetc_unwind_tx_frame(tx_ring, count, i);
856898

857899
return 0;
858900
}
@@ -1901,7 +1943,7 @@ static int enetc_clean_rx_ring_xdp(struct enetc_bdr *rx_ring,
19011943
enetc_xdp_drop(rx_ring, orig_i, i);
19021944
tx_ring->stats.xdp_tx_drops++;
19031945
} else {
1904-
tx_ring->stats.xdp_tx += xdp_tx_bd_cnt;
1946+
tx_ring->stats.xdp_tx++;
19051947
rx_ring->xdp.xdp_tx_in_flight += xdp_tx_bd_cnt;
19061948
xdp_tx_frm_cnt++;
19071949
/* The XDP_TX enqueue was successful, so we
@@ -3228,6 +3270,9 @@ static int enetc_hwtstamp_set(struct net_device *ndev, struct ifreq *ifr)
32283270
new_offloads |= ENETC_F_TX_TSTAMP;
32293271
break;
32303272
case HWTSTAMP_TX_ONESTEP_SYNC:
3273+
if (!enetc_si_is_pf(priv->si))
3274+
return -EOPNOTSUPP;
3275+
32313276
new_offloads &= ~ENETC_F_TX_TSTAMP_MASK;
32323277
new_offloads |= ENETC_F_TX_ONESTEP_SYNC_TSTAMP;
32333278
break;

drivers/net/ethernet/freescale/enetc/enetc4_pf.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -672,7 +672,6 @@ static int enetc4_pf_netdev_create(struct enetc_si *si)
672672
err_alloc_msix:
673673
err_config_si:
674674
err_clk_get:
675-
mutex_destroy(&priv->mm_lock);
676675
free_netdev(ndev);
677676

678677
return err;
@@ -684,6 +683,7 @@ static void enetc4_pf_netdev_destroy(struct enetc_si *si)
684683
struct net_device *ndev = si->ndev;
685684

686685
unregister_netdev(ndev);
686+
enetc4_link_deinit(priv);
687687
enetc_free_msix(priv);
688688
free_netdev(ndev);
689689
}

drivers/net/ethernet/freescale/enetc/enetc_ethtool.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -832,6 +832,7 @@ static int enetc_set_coalesce(struct net_device *ndev,
832832
static int enetc_get_ts_info(struct net_device *ndev,
833833
struct kernel_ethtool_ts_info *info)
834834
{
835+
struct enetc_ndev_priv *priv = netdev_priv(ndev);
835836
int *phc_idx;
836837

837838
phc_idx = symbol_get(enetc_phc_index);
@@ -852,8 +853,10 @@ static int enetc_get_ts_info(struct net_device *ndev,
852853
SOF_TIMESTAMPING_TX_SOFTWARE;
853854

854855
info->tx_types = (1 << HWTSTAMP_TX_OFF) |
855-
(1 << HWTSTAMP_TX_ON) |
856-
(1 << HWTSTAMP_TX_ONESTEP_SYNC);
856+
(1 << HWTSTAMP_TX_ON);
857+
858+
if (enetc_si_is_pf(priv->si))
859+
info->tx_types |= (1 << HWTSTAMP_TX_ONESTEP_SYNC);
857860

858861
info->rx_filters = (1 << HWTSTAMP_FILTER_NONE) |
859862
(1 << HWTSTAMP_FILTER_ALL);

0 commit comments

Comments
 (0)