Skip to content

Commit 82e71b2

Browse files
kolacinskikarolanguy11
authored andcommitted
ice: Enable SW interrupt from FW for LL TS
Introduce new capability - Low Latency Timestamping with Interrupt. On supported devices, driver can request a single timestamp from FW without polling the register afterwards. Instead, FW can issue a dedicated interrupt when the timestamp was read from the PHY register and its value is available to read from the register. This eliminates the need of bottom half scheduling, which results in minimal delay for timestamping. For this mode, allocate TS indices sequentially, so that timestamps are always completed in FIFO manner. Co-developed-by: Yochai Hagvi <yochai.hagvi@intel.com> Signed-off-by: Yochai Hagvi <yochai.hagvi@intel.com> Reviewed-by: Przemek Kitszel <przemyslaw.kitszel@intel.com> Signed-off-by: Karol Kolacinski <karol.kolacinski@intel.com> Tested-by: Pucha Himasekhar Reddy <himasekharx.reddy.pucha@intel.com> (A Contingent worker at Intel) Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
1 parent 00d5000 commit 82e71b2

File tree

8 files changed

+274
-28
lines changed

8 files changed

+274
-28
lines changed

drivers/net/ethernet/intel/ice/ice.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -608,6 +608,7 @@ struct ice_pf {
608608
u32 hw_csum_rx_error;
609609
u32 oicr_err_reg;
610610
struct msi_map oicr_irq; /* Other interrupt cause MSIX vector */
611+
struct msi_map ll_ts_irq; /* LL_TS interrupt MSIX vector */
611612
u16 max_pf_txqs; /* Total Tx queues PF wide */
612613
u16 max_pf_rxqs; /* Total Rx queues PF wide */
613614
u16 num_lan_msix; /* Total MSIX vectors for base driver */
@@ -632,6 +633,7 @@ struct ice_pf {
632633
unsigned long tx_timeout_last_recovery;
633634
u32 tx_timeout_recovery_level;
634635
char int_name[ICE_INT_NAME_STR_LEN];
636+
char int_name_ll_ts[ICE_INT_NAME_STR_LEN];
635637
struct auxiliary_device *adev;
636638
int aux_idx;
637639
u32 sw_int_count;

drivers/net/ethernet/intel/ice/ice_common.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2451,6 +2451,7 @@ ice_parse_1588_dev_caps(struct ice_hw *hw, struct ice_hw_dev_caps *dev_p,
24512451
info->tmr1_ena = ((number & ICE_TS_TMR1_ENA_M) != 0);
24522452

24532453
info->ts_ll_read = ((number & ICE_TS_LL_TX_TS_READ_M) != 0);
2454+
info->ts_ll_int_read = ((number & ICE_TS_LL_TX_TS_INT_READ_M) != 0);
24542455

24552456
info->ena_ports = logical_id;
24562457
info->tmr_own_map = phys_id;
@@ -2471,6 +2472,8 @@ ice_parse_1588_dev_caps(struct ice_hw *hw, struct ice_hw_dev_caps *dev_p,
24712472
info->tmr1_ena);
24722473
ice_debug(hw, ICE_DBG_INIT, "dev caps: ts_ll_read = %u\n",
24732474
info->ts_ll_read);
2475+
ice_debug(hw, ICE_DBG_INIT, "dev caps: ts_ll_int_read = %u\n",
2476+
info->ts_ll_int_read);
24742477
ice_debug(hw, ICE_DBG_INIT, "dev caps: ieee_1588 ena_ports = %u\n",
24752478
info->ena_ports);
24762479
ice_debug(hw, ICE_DBG_INIT, "dev caps: tmr_own_map = %u\n",

drivers/net/ethernet/intel/ice/ice_hw_autogen.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,8 @@
200200
#define GLINT_VECT2FUNC_PF_NUM_M ICE_M(0x7, 12)
201201
#define GLINT_VECT2FUNC_IS_PF_S 16
202202
#define GLINT_VECT2FUNC_IS_PF_M BIT(16)
203+
#define PFINT_ALLOC 0x001D2600
204+
#define PFINT_ALLOC_FIRST ICE_M(0x7FF, 0)
203205
#define PFINT_FW_CTL 0x0016C800
204206
#define PFINT_FW_CTL_MSIX_INDX_M ICE_M(0x7FF, 0)
205207
#define PFINT_FW_CTL_ITR_INDX_S 11

drivers/net/ethernet/intel/ice/ice_main.c

Lines changed: 110 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3046,6 +3046,7 @@ static int ice_xdp(struct net_device *dev, struct netdev_bpf *xdp)
30463046
static void ice_ena_misc_vector(struct ice_pf *pf)
30473047
{
30483048
struct ice_hw *hw = &pf->hw;
3049+
u32 pf_intr_start_offset;
30493050
u32 val;
30503051

30513052
/* Disable anti-spoof detection interrupt to prevent spurious event
@@ -3074,6 +3075,47 @@ static void ice_ena_misc_vector(struct ice_pf *pf)
30743075
/* SW_ITR_IDX = 0, but don't change INTENA */
30753076
wr32(hw, GLINT_DYN_CTL(pf->oicr_irq.index),
30763077
GLINT_DYN_CTL_SW_ITR_INDX_M | GLINT_DYN_CTL_INTENA_MSK_M);
3078+
3079+
if (!pf->hw.dev_caps.ts_dev_info.ts_ll_int_read)
3080+
return;
3081+
pf_intr_start_offset = rd32(hw, PFINT_ALLOC) & PFINT_ALLOC_FIRST;
3082+
wr32(hw, GLINT_DYN_CTL(pf->ll_ts_irq.index + pf_intr_start_offset),
3083+
GLINT_DYN_CTL_SW_ITR_INDX_M | GLINT_DYN_CTL_INTENA_MSK_M);
3084+
}
3085+
3086+
/**
3087+
* ice_ll_ts_intr - ll_ts interrupt handler
3088+
* @irq: interrupt number
3089+
* @data: pointer to a q_vector
3090+
*/
3091+
static irqreturn_t ice_ll_ts_intr(int __always_unused irq, void *data)
3092+
{
3093+
struct ice_pf *pf = data;
3094+
u32 pf_intr_start_offset;
3095+
struct ice_ptp_tx *tx;
3096+
unsigned long flags;
3097+
struct ice_hw *hw;
3098+
u32 val;
3099+
u8 idx;
3100+
3101+
hw = &pf->hw;
3102+
tx = &pf->ptp.port.tx;
3103+
spin_lock_irqsave(&tx->lock, flags);
3104+
ice_ptp_complete_tx_single_tstamp(tx);
3105+
3106+
idx = find_next_bit_wrap(tx->in_use, tx->len,
3107+
tx->last_ll_ts_idx_read + 1);
3108+
if (idx != tx->len)
3109+
ice_ptp_req_tx_single_tstamp(tx, idx);
3110+
spin_unlock_irqrestore(&tx->lock, flags);
3111+
3112+
val = GLINT_DYN_CTL_INTENA_M | GLINT_DYN_CTL_CLEARPBA_M |
3113+
(ICE_ITR_NONE << GLINT_DYN_CTL_ITR_INDX_S);
3114+
pf_intr_start_offset = rd32(hw, PFINT_ALLOC) & PFINT_ALLOC_FIRST;
3115+
wr32(hw, GLINT_DYN_CTL(pf->ll_ts_irq.index + pf_intr_start_offset),
3116+
val);
3117+
3118+
return IRQ_HANDLED;
30773119
}
30783120

30793121
/**
@@ -3166,7 +3208,19 @@ static irqreturn_t ice_misc_intr(int __always_unused irq, void *data)
31663208

31673209
if (oicr & PFINT_OICR_TSYN_TX_M) {
31683210
ena_mask &= ~PFINT_OICR_TSYN_TX_M;
3169-
if (ice_ptp_pf_handles_tx_interrupt(pf)) {
3211+
if (ice_pf_state_is_nominal(pf) &&
3212+
pf->hw.dev_caps.ts_dev_info.ts_ll_int_read) {
3213+
struct ice_ptp_tx *tx = &pf->ptp.port.tx;
3214+
unsigned long flags;
3215+
u8 idx;
3216+
3217+
spin_lock_irqsave(&tx->lock, flags);
3218+
idx = find_next_bit_wrap(tx->in_use, tx->len,
3219+
tx->last_ll_ts_idx_read + 1);
3220+
if (idx != tx->len)
3221+
ice_ptp_req_tx_single_tstamp(tx, idx);
3222+
spin_unlock_irqrestore(&tx->lock, flags);
3223+
} else if (ice_ptp_pf_handles_tx_interrupt(pf)) {
31703224
set_bit(ICE_MISC_THREAD_TX_TSTAMP, pf->misc_thread);
31713225
ret = IRQ_WAKE_THREAD;
31723226
}
@@ -3270,6 +3324,20 @@ static void ice_dis_ctrlq_interrupts(struct ice_hw *hw)
32703324
ice_flush(hw);
32713325
}
32723326

3327+
/**
3328+
* ice_free_irq_msix_ll_ts- Unroll ll_ts vector setup
3329+
* @pf: board private structure
3330+
*/
3331+
static void ice_free_irq_msix_ll_ts(struct ice_pf *pf)
3332+
{
3333+
int irq_num = pf->ll_ts_irq.virq;
3334+
3335+
synchronize_irq(irq_num);
3336+
devm_free_irq(ice_pf_to_dev(pf), irq_num, pf);
3337+
3338+
ice_free_irq(pf, pf->ll_ts_irq);
3339+
}
3340+
32733341
/**
32743342
* ice_free_irq_msix_misc - Unroll misc vector setup
32753343
* @pf: board private structure
@@ -3289,6 +3357,8 @@ static void ice_free_irq_msix_misc(struct ice_pf *pf)
32893357
devm_free_irq(ice_pf_to_dev(pf), misc_irq_num, pf);
32903358

32913359
ice_free_irq(pf, pf->oicr_irq);
3360+
if (pf->hw.dev_caps.ts_dev_info.ts_ll_int_read)
3361+
ice_free_irq_msix_ll_ts(pf);
32923362
}
32933363

32943364
/**
@@ -3314,10 +3384,12 @@ static void ice_ena_ctrlq_interrupts(struct ice_hw *hw, u16 reg_idx)
33143384
PFINT_MBX_CTL_CAUSE_ENA_M);
33153385
wr32(hw, PFINT_MBX_CTL, val);
33163386

3317-
/* This enables Sideband queue Interrupt causes */
3318-
val = ((reg_idx & PFINT_SB_CTL_MSIX_INDX_M) |
3319-
PFINT_SB_CTL_CAUSE_ENA_M);
3320-
wr32(hw, PFINT_SB_CTL, val);
3387+
if (!hw->dev_caps.ts_dev_info.ts_ll_int_read) {
3388+
/* enable Sideband queue Interrupt causes */
3389+
val = ((reg_idx & PFINT_SB_CTL_MSIX_INDX_M) |
3390+
PFINT_SB_CTL_CAUSE_ENA_M);
3391+
wr32(hw, PFINT_SB_CTL, val);
3392+
}
33213393

33223394
ice_flush(hw);
33233395
}
@@ -3334,13 +3406,17 @@ static int ice_req_irq_msix_misc(struct ice_pf *pf)
33343406
{
33353407
struct device *dev = ice_pf_to_dev(pf);
33363408
struct ice_hw *hw = &pf->hw;
3337-
struct msi_map oicr_irq;
3409+
u32 pf_intr_start_offset;
3410+
struct msi_map irq;
33383411
int err = 0;
33393412

33403413
if (!pf->int_name[0])
33413414
snprintf(pf->int_name, sizeof(pf->int_name) - 1, "%s-%s:misc",
33423415
dev_driver_string(dev), dev_name(dev));
33433416

3417+
if (!pf->int_name_ll_ts[0])
3418+
snprintf(pf->int_name_ll_ts, sizeof(pf->int_name_ll_ts) - 1,
3419+
"%s-%s:ll_ts", dev_driver_string(dev), dev_name(dev));
33443420
/* Do not request IRQ but do enable OICR interrupt since settings are
33453421
* lost during reset. Note that this function is called only during
33463422
* rebuild path and not while reset is in progress.
@@ -3349,11 +3425,11 @@ static int ice_req_irq_msix_misc(struct ice_pf *pf)
33493425
goto skip_req_irq;
33503426

33513427
/* reserve one vector in irq_tracker for misc interrupts */
3352-
oicr_irq = ice_alloc_irq(pf, false);
3353-
if (oicr_irq.index < 0)
3354-
return oicr_irq.index;
3428+
irq = ice_alloc_irq(pf, false);
3429+
if (irq.index < 0)
3430+
return irq.index;
33553431

3356-
pf->oicr_irq = oicr_irq;
3432+
pf->oicr_irq = irq;
33573433
err = devm_request_threaded_irq(dev, pf->oicr_irq.virq, ice_misc_intr,
33583434
ice_misc_intr_thread_fn, 0,
33593435
pf->int_name, pf);
@@ -3364,10 +3440,34 @@ static int ice_req_irq_msix_misc(struct ice_pf *pf)
33643440
return err;
33653441
}
33663442

3443+
/* reserve one vector in irq_tracker for ll_ts interrupt */
3444+
if (!pf->hw.dev_caps.ts_dev_info.ts_ll_int_read)
3445+
goto skip_req_irq;
3446+
3447+
irq = ice_alloc_irq(pf, false);
3448+
if (irq.index < 0)
3449+
return irq.index;
3450+
3451+
pf->ll_ts_irq = irq;
3452+
err = devm_request_irq(dev, pf->ll_ts_irq.virq, ice_ll_ts_intr, 0,
3453+
pf->int_name_ll_ts, pf);
3454+
if (err) {
3455+
dev_err(dev, "devm_request_irq for %s failed: %d\n",
3456+
pf->int_name_ll_ts, err);
3457+
ice_free_irq(pf, pf->ll_ts_irq);
3458+
return err;
3459+
}
3460+
33673461
skip_req_irq:
33683462
ice_ena_misc_vector(pf);
33693463

33703464
ice_ena_ctrlq_interrupts(hw, pf->oicr_irq.index);
3465+
/* This enables LL TS interrupt */
3466+
pf_intr_start_offset = rd32(hw, PFINT_ALLOC) & PFINT_ALLOC_FIRST;
3467+
if (pf->hw.dev_caps.ts_dev_info.ts_ll_int_read)
3468+
wr32(hw, PFINT_SB_CTL,
3469+
((pf->ll_ts_irq.index + pf_intr_start_offset) &
3470+
PFINT_SB_CTL_MSIX_INDX_M) | PFINT_SB_CTL_CAUSE_ENA_M);
33713471
wr32(hw, GLINT_ITR(ICE_RX_ITR, pf->oicr_irq.index),
33723472
ITR_REG_ALIGN(ICE_ITR_8K) >> ICE_ITR_GRAN_S);
33733473

0 commit comments

Comments
 (0)