Skip to content

Commit b61aac0

Browse files
committed
Merge branch '1GbE' of git://git.kernel.org/pub/scm/linux/kernel/git/tnguy/net-queue
Tony Nguyen says: ==================== Intel Wired LAN Driver Updates 2023-07-05 (igc) This series contains updates to igc driver only. Husaini adds check to increment Qbv change error counter only on taprio Qbvs. He also removes delay during Tx ring configuration and resolves Tx hang that could occur when transmitting on a gate to be closed. Prasad Koya reports ethtool link mode as TP (twisted pair). Tee Min corrects value for max SDU. Aravindhan ensures that registers for PPS are always programmed to occur in future. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
2 parents 0503efe + 84a192e commit b61aac0

5 files changed

Lines changed: 118 additions & 32 deletions

File tree

drivers/net/ethernet/intel/igc/igc.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include <linux/timecounter.h>
1515
#include <linux/net_tstamp.h>
1616
#include <linux/bitfield.h>
17+
#include <linux/hrtimer.h>
1718

1819
#include "igc_hw.h"
1920

@@ -101,6 +102,8 @@ struct igc_ring {
101102
u32 start_time;
102103
u32 end_time;
103104
u32 max_sdu;
105+
bool oper_gate_closed; /* Operating gate. True if the TX Queue is closed */
106+
bool admin_gate_closed; /* Future gate. True if the TX Queue will be closed */
104107

105108
/* CBS parameters */
106109
bool cbs_enable; /* indicates if CBS is enabled */
@@ -160,6 +163,7 @@ struct igc_adapter {
160163
struct timer_list watchdog_timer;
161164
struct timer_list dma_err_timer;
162165
struct timer_list phy_info_timer;
166+
struct hrtimer hrtimer;
163167

164168
u32 wol;
165169
u32 en_mng_pt;
@@ -184,10 +188,13 @@ struct igc_adapter {
184188
u32 max_frame_size;
185189
u32 min_frame_size;
186190

191+
int tc_setup_type;
187192
ktime_t base_time;
188193
ktime_t cycle_time;
189194
bool qbv_enable;
190195
u32 qbv_config_change_errors;
196+
bool qbv_transition;
197+
unsigned int qbv_count;
191198

192199
/* OS defined structs */
193200
struct pci_dev *pdev;

drivers/net/ethernet/intel/igc/igc_ethtool.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1708,6 +1708,8 @@ static int igc_ethtool_get_link_ksettings(struct net_device *netdev,
17081708
/* twisted pair */
17091709
cmd->base.port = PORT_TP;
17101710
cmd->base.phy_address = hw->phy.addr;
1711+
ethtool_link_ksettings_add_link_mode(cmd, supported, TP);
1712+
ethtool_link_ksettings_add_link_mode(cmd, advertising, TP);
17111713

17121714
/* advertising link modes */
17131715
if (hw->phy.autoneg_advertised & ADVERTISE_10_HALF)

drivers/net/ethernet/intel/igc/igc_main.c

Lines changed: 59 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -711,7 +711,6 @@ static void igc_configure_tx_ring(struct igc_adapter *adapter,
711711
/* disable the queue */
712712
wr32(IGC_TXDCTL(reg_idx), 0);
713713
wrfl();
714-
mdelay(10);
715714

716715
wr32(IGC_TDLEN(reg_idx),
717716
ring->count * sizeof(union igc_adv_tx_desc));
@@ -1573,16 +1572,12 @@ static netdev_tx_t igc_xmit_frame_ring(struct sk_buff *skb,
15731572
first->bytecount = skb->len;
15741573
first->gso_segs = 1;
15751574

1576-
if (tx_ring->max_sdu > 0) {
1577-
u32 max_sdu = 0;
1578-
1579-
max_sdu = tx_ring->max_sdu +
1580-
(skb_vlan_tagged(first->skb) ? VLAN_HLEN : 0);
1575+
if (adapter->qbv_transition || tx_ring->oper_gate_closed)
1576+
goto out_drop;
15811577

1582-
if (first->bytecount > max_sdu) {
1583-
adapter->stats.txdrop++;
1584-
goto out_drop;
1585-
}
1578+
if (tx_ring->max_sdu > 0 && first->bytecount > tx_ring->max_sdu) {
1579+
adapter->stats.txdrop++;
1580+
goto out_drop;
15861581
}
15871582

15881583
if (unlikely(test_bit(IGC_RING_FLAG_TX_HWTSTAMP, &tx_ring->flags) &&
@@ -3012,8 +3007,8 @@ static bool igc_clean_tx_irq(struct igc_q_vector *q_vector, int napi_budget)
30123007
time_after(jiffies, tx_buffer->time_stamp +
30133008
(adapter->tx_timeout_factor * HZ)) &&
30143009
!(rd32(IGC_STATUS) & IGC_STATUS_TXOFF) &&
3015-
(rd32(IGC_TDH(tx_ring->reg_idx)) !=
3016-
readl(tx_ring->tail))) {
3010+
(rd32(IGC_TDH(tx_ring->reg_idx)) != readl(tx_ring->tail)) &&
3011+
!tx_ring->oper_gate_closed) {
30173012
/* detected Tx unit hang */
30183013
netdev_err(tx_ring->netdev,
30193014
"Detected Tx Unit Hang\n"
@@ -6103,13 +6098,17 @@ static int igc_tsn_clear_schedule(struct igc_adapter *adapter)
61036098
adapter->base_time = 0;
61046099
adapter->cycle_time = NSEC_PER_SEC;
61056100
adapter->qbv_config_change_errors = 0;
6101+
adapter->qbv_transition = false;
6102+
adapter->qbv_count = 0;
61066103

61076104
for (i = 0; i < adapter->num_tx_queues; i++) {
61086105
struct igc_ring *ring = adapter->tx_ring[i];
61096106

61106107
ring->start_time = 0;
61116108
ring->end_time = NSEC_PER_SEC;
61126109
ring->max_sdu = 0;
6110+
ring->oper_gate_closed = false;
6111+
ring->admin_gate_closed = false;
61136112
}
61146113

61156114
return 0;
@@ -6121,6 +6120,7 @@ static int igc_save_qbv_schedule(struct igc_adapter *adapter,
61216120
bool queue_configured[IGC_MAX_TX_QUEUES] = { };
61226121
struct igc_hw *hw = &adapter->hw;
61236122
u32 start_time = 0, end_time = 0;
6123+
struct timespec64 now;
61246124
size_t n;
61256125
int i;
61266126

@@ -6150,6 +6150,8 @@ static int igc_save_qbv_schedule(struct igc_adapter *adapter,
61506150
adapter->cycle_time = qopt->cycle_time;
61516151
adapter->base_time = qopt->base_time;
61526152

6153+
igc_ptp_read(adapter, &now);
6154+
61536155
for (n = 0; n < qopt->num_entries; n++) {
61546156
struct tc_taprio_sched_entry *e = &qopt->entries[n];
61556157

@@ -6184,7 +6186,10 @@ static int igc_save_qbv_schedule(struct igc_adapter *adapter,
61846186
ring->start_time = start_time;
61856187
ring->end_time = end_time;
61866188

6187-
queue_configured[i] = true;
6189+
if (ring->start_time >= adapter->cycle_time)
6190+
queue_configured[i] = false;
6191+
else
6192+
queue_configured[i] = true;
61886193
}
61896194

61906195
start_time += e->interval;
@@ -6194,8 +6199,20 @@ static int igc_save_qbv_schedule(struct igc_adapter *adapter,
61946199
* If not, set the start and end time to be end time.
61956200
*/
61966201
for (i = 0; i < adapter->num_tx_queues; i++) {
6202+
struct igc_ring *ring = adapter->tx_ring[i];
6203+
6204+
if (!is_base_time_past(qopt->base_time, &now)) {
6205+
ring->admin_gate_closed = false;
6206+
} else {
6207+
ring->oper_gate_closed = false;
6208+
ring->admin_gate_closed = false;
6209+
}
6210+
61976211
if (!queue_configured[i]) {
6198-
struct igc_ring *ring = adapter->tx_ring[i];
6212+
if (!is_base_time_past(qopt->base_time, &now))
6213+
ring->admin_gate_closed = true;
6214+
else
6215+
ring->oper_gate_closed = true;
61996216

62006217
ring->start_time = end_time;
62016218
ring->end_time = end_time;
@@ -6207,7 +6224,7 @@ static int igc_save_qbv_schedule(struct igc_adapter *adapter,
62076224
struct net_device *dev = adapter->netdev;
62086225

62096226
if (qopt->max_sdu[i])
6210-
ring->max_sdu = qopt->max_sdu[i] + dev->hard_header_len;
6227+
ring->max_sdu = qopt->max_sdu[i] + dev->hard_header_len - ETH_TLEN;
62116228
else
62126229
ring->max_sdu = 0;
62136230
}
@@ -6327,6 +6344,8 @@ static int igc_setup_tc(struct net_device *dev, enum tc_setup_type type,
63276344
{
63286345
struct igc_adapter *adapter = netdev_priv(dev);
63296346

6347+
adapter->tc_setup_type = type;
6348+
63306349
switch (type) {
63316350
case TC_QUERY_CAPS:
63326351
return igc_tc_query_caps(adapter, type_data);
@@ -6574,6 +6593,27 @@ static const struct xdp_metadata_ops igc_xdp_metadata_ops = {
65746593
.xmo_rx_timestamp = igc_xdp_rx_timestamp,
65756594
};
65766595

6596+
static enum hrtimer_restart igc_qbv_scheduling_timer(struct hrtimer *timer)
6597+
{
6598+
struct igc_adapter *adapter = container_of(timer, struct igc_adapter,
6599+
hrtimer);
6600+
unsigned int i;
6601+
6602+
adapter->qbv_transition = true;
6603+
for (i = 0; i < adapter->num_tx_queues; i++) {
6604+
struct igc_ring *tx_ring = adapter->tx_ring[i];
6605+
6606+
if (tx_ring->admin_gate_closed) {
6607+
tx_ring->admin_gate_closed = false;
6608+
tx_ring->oper_gate_closed = true;
6609+
} else {
6610+
tx_ring->oper_gate_closed = false;
6611+
}
6612+
}
6613+
adapter->qbv_transition = false;
6614+
return HRTIMER_NORESTART;
6615+
}
6616+
65776617
/**
65786618
* igc_probe - Device Initialization Routine
65796619
* @pdev: PCI device information struct
@@ -6752,6 +6792,9 @@ static int igc_probe(struct pci_dev *pdev,
67526792
INIT_WORK(&adapter->reset_task, igc_reset_task);
67536793
INIT_WORK(&adapter->watchdog_task, igc_watchdog_task);
67546794

6795+
hrtimer_init(&adapter->hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
6796+
adapter->hrtimer.function = &igc_qbv_scheduling_timer;
6797+
67556798
/* Initialize link properties that are user-changeable */
67566799
adapter->fc_autoneg = true;
67576800
hw->mac.autoneg = true;
@@ -6855,6 +6898,7 @@ static void igc_remove(struct pci_dev *pdev)
68556898

68566899
cancel_work_sync(&adapter->reset_task);
68576900
cancel_work_sync(&adapter->watchdog_task);
6901+
hrtimer_cancel(&adapter->hrtimer);
68586902

68596903
/* Release control of h/w to f/w. If f/w is AMT enabled, this
68606904
* would have already happened in close and is redundant.

drivers/net/ethernet/intel/igc/igc_ptp.c

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -356,16 +356,35 @@ static int igc_ptp_feature_enable_i225(struct ptp_clock_info *ptp,
356356
tsim &= ~IGC_TSICR_TT0;
357357
}
358358
if (on) {
359+
struct timespec64 safe_start;
359360
int i = rq->perout.index;
360361

361362
igc_pin_perout(igc, i, pin, use_freq);
362-
igc->perout[i].start.tv_sec = rq->perout.start.sec;
363+
igc_ptp_read(igc, &safe_start);
364+
365+
/* PPS output start time is triggered by Target time(TT)
366+
* register. Programming any past time value into TT
367+
* register will cause PPS to never start. Need to make
368+
* sure we program the TT register a time ahead in
369+
* future. There isn't a stringent need to fire PPS out
370+
* right away. Adding +2 seconds should take care of
371+
* corner cases. Let's say if the SYSTIML is close to
372+
* wrap up and the timer keeps ticking as we program the
373+
* register, adding +2seconds is safe bet.
374+
*/
375+
safe_start.tv_sec += 2;
376+
377+
if (rq->perout.start.sec < safe_start.tv_sec)
378+
igc->perout[i].start.tv_sec = safe_start.tv_sec;
379+
else
380+
igc->perout[i].start.tv_sec = rq->perout.start.sec;
363381
igc->perout[i].start.tv_nsec = rq->perout.start.nsec;
364382
igc->perout[i].period.tv_sec = ts.tv_sec;
365383
igc->perout[i].period.tv_nsec = ts.tv_nsec;
366-
wr32(trgttimh, rq->perout.start.sec);
384+
wr32(trgttimh, (u32)igc->perout[i].start.tv_sec);
367385
/* For now, always select timer 0 as source. */
368-
wr32(trgttiml, rq->perout.start.nsec | IGC_TT_IO_TIMER_SEL_SYSTIM0);
386+
wr32(trgttiml, (u32)(igc->perout[i].start.tv_nsec |
387+
IGC_TT_IO_TIMER_SEL_SYSTIM0));
369388
if (use_freq)
370389
wr32(freqout, ns);
371390
tsauxc |= tsauxc_mask;

drivers/net/ethernet/intel/igc/igc_tsn.c

Lines changed: 28 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,6 @@ static int igc_tsn_disable_offload(struct igc_adapter *adapter)
114114
static int igc_tsn_enable_offload(struct igc_adapter *adapter)
115115
{
116116
struct igc_hw *hw = &adapter->hw;
117-
bool tsn_mode_reconfig = false;
118117
u32 tqavctrl, baset_l, baset_h;
119118
u32 sec, nsec, cycle;
120119
ktime_t base_time, systim;
@@ -228,11 +227,10 @@ static int igc_tsn_enable_offload(struct igc_adapter *adapter)
228227

229228
tqavctrl = rd32(IGC_TQAVCTRL) & ~IGC_TQAVCTRL_FUTSCDDIS;
230229

231-
if (tqavctrl & IGC_TQAVCTRL_TRANSMIT_MODE_TSN)
232-
tsn_mode_reconfig = true;
233-
234230
tqavctrl |= IGC_TQAVCTRL_TRANSMIT_MODE_TSN | IGC_TQAVCTRL_ENHANCED_QAV;
235231

232+
adapter->qbv_count++;
233+
236234
cycle = adapter->cycle_time;
237235
base_time = adapter->base_time;
238236

@@ -249,17 +247,29 @@ static int igc_tsn_enable_offload(struct igc_adapter *adapter)
249247
* Gate Control List (GCL) is running.
250248
*/
251249
if ((rd32(IGC_BASET_H) || rd32(IGC_BASET_L)) &&
252-
tsn_mode_reconfig)
250+
(adapter->tc_setup_type == TC_SETUP_QDISC_TAPRIO) &&
251+
(adapter->qbv_count > 1))
253252
adapter->qbv_config_change_errors++;
254253
} else {
255-
/* According to datasheet section 7.5.2.9.3.3, FutScdDis bit
256-
* has to be configured before the cycle time and base time.
257-
* Tx won't hang if there is a GCL is already running,
258-
* so in this case we don't need to set FutScdDis.
259-
*/
260-
if (igc_is_device_id_i226(hw) &&
261-
!(rd32(IGC_BASET_H) || rd32(IGC_BASET_L)))
262-
tqavctrl |= IGC_TQAVCTRL_FUTSCDDIS;
254+
if (igc_is_device_id_i226(hw)) {
255+
ktime_t adjust_time, expires_time;
256+
257+
/* According to datasheet section 7.5.2.9.3.3, FutScdDis bit
258+
* has to be configured before the cycle time and base time.
259+
* Tx won't hang if a GCL is already running,
260+
* so in this case we don't need to set FutScdDis.
261+
*/
262+
if (!(rd32(IGC_BASET_H) || rd32(IGC_BASET_L)))
263+
tqavctrl |= IGC_TQAVCTRL_FUTSCDDIS;
264+
265+
nsec = rd32(IGC_SYSTIML);
266+
sec = rd32(IGC_SYSTIMH);
267+
systim = ktime_set(sec, nsec);
268+
269+
adjust_time = adapter->base_time;
270+
expires_time = ktime_sub_ns(adjust_time, systim);
271+
hrtimer_start(&adapter->hrtimer, expires_time, HRTIMER_MODE_REL);
272+
}
263273
}
264274

265275
wr32(IGC_TQAVCTRL, tqavctrl);
@@ -305,7 +315,11 @@ int igc_tsn_offload_apply(struct igc_adapter *adapter)
305315
{
306316
struct igc_hw *hw = &adapter->hw;
307317

308-
if (netif_running(adapter->netdev) && igc_is_device_id_i225(hw)) {
318+
/* Per I225/6 HW Design Section 7.5.2.1, transmit mode
319+
* cannot be changed dynamically. Require reset the adapter.
320+
*/
321+
if (netif_running(adapter->netdev) &&
322+
(igc_is_device_id_i225(hw) || !adapter->qbv_count)) {
309323
schedule_work(&adapter->reset_task);
310324
return 0;
311325
}

0 commit comments

Comments
 (0)