Skip to content

Commit 00d3b4f

Browse files
mwolechkuba-moo
authored andcommitted
ice: Fix improper extts handling
Extts events are disabled and enabled by the application ts2phc. However, in case where the driver is removed when the application is running, a specific extts event remains enabled and can cause a kernel crash. As a side effect, when the driver is reloaded and application is started again, remaining extts event for the channel from a previous run will keep firing and the message "extts on unexpected channel" might be printed to the user. To avoid that, extts events shall be disabled when PTP is released. Fixes: 172db5f ("ice: add support for auxiliary input/output pins") Reviewed-by: Przemek Kitszel <przemyslaw.kitszel@intel.com> Co-developed-by: Jacob Keller <jacob.e.keller@intel.com> Signed-off-by: Jacob Keller <jacob.e.keller@intel.com> Signed-off-by: Milena Olech <milena.olech@intel.com> Signed-off-by: Karol Kolacinski <karol.kolacinski@intel.com> Reviewed-by: Simon Horman <horms@kernel.org> 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> Link: https://patch.msgid.link/20240702171459.2606611-2-anthony.l.nguyen@intel.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
1 parent 2a79651 commit 00d3b4f

2 files changed

Lines changed: 91 additions & 22 deletions

File tree

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

Lines changed: 83 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1584,27 +1584,24 @@ void ice_ptp_extts_event(struct ice_pf *pf)
15841584
/**
15851585
* ice_ptp_cfg_extts - Configure EXTTS pin and channel
15861586
* @pf: Board private structure
1587-
* @ena: true to enable; false to disable
15881587
* @chan: GPIO channel (0-3)
1589-
* @gpio_pin: GPIO pin
1590-
* @extts_flags: request flags from the ptp_extts_request.flags
1588+
* @config: desired EXTTS configuration.
1589+
* @store: If set to true, the values will be stored
1590+
*
1591+
* Configure an external timestamp event on the requested channel.
15911592
*/
1592-
static int
1593-
ice_ptp_cfg_extts(struct ice_pf *pf, bool ena, unsigned int chan, u32 gpio_pin,
1594-
unsigned int extts_flags)
1593+
static void ice_ptp_cfg_extts(struct ice_pf *pf, unsigned int chan,
1594+
struct ice_extts_channel *config, bool store)
15951595
{
15961596
u32 func, aux_reg, gpio_reg, irq_reg;
15971597
struct ice_hw *hw = &pf->hw;
15981598
u8 tmr_idx;
15991599

1600-
if (chan > (unsigned int)pf->ptp.info.n_ext_ts)
1601-
return -EINVAL;
1602-
16031600
tmr_idx = hw->func_caps.ts_func_info.tmr_index_owned;
16041601

16051602
irq_reg = rd32(hw, PFINT_OICR_ENA);
16061603

1607-
if (ena) {
1604+
if (config->ena) {
16081605
/* Enable the interrupt */
16091606
irq_reg |= PFINT_OICR_TSYN_EVNT_M;
16101607
aux_reg = GLTSYN_AUX_IN_0_INT_ENA_M;
@@ -1613,9 +1610,9 @@ ice_ptp_cfg_extts(struct ice_pf *pf, bool ena, unsigned int chan, u32 gpio_pin,
16131610
#define GLTSYN_AUX_IN_0_EVNTLVL_FALLING_EDGE BIT(1)
16141611

16151612
/* set event level to requested edge */
1616-
if (extts_flags & PTP_FALLING_EDGE)
1613+
if (config->flags & PTP_FALLING_EDGE)
16171614
aux_reg |= GLTSYN_AUX_IN_0_EVNTLVL_FALLING_EDGE;
1618-
if (extts_flags & PTP_RISING_EDGE)
1615+
if (config->flags & PTP_RISING_EDGE)
16191616
aux_reg |= GLTSYN_AUX_IN_0_EVNTLVL_RISING_EDGE;
16201617

16211618
/* Write GPIO CTL reg.
@@ -1636,9 +1633,47 @@ ice_ptp_cfg_extts(struct ice_pf *pf, bool ena, unsigned int chan, u32 gpio_pin,
16361633

16371634
wr32(hw, PFINT_OICR_ENA, irq_reg);
16381635
wr32(hw, GLTSYN_AUX_IN(chan, tmr_idx), aux_reg);
1639-
wr32(hw, GLGEN_GPIO_CTL(gpio_pin), gpio_reg);
1636+
wr32(hw, GLGEN_GPIO_CTL(config->gpio_pin), gpio_reg);
16401637

1641-
return 0;
1638+
if (store)
1639+
memcpy(&pf->ptp.extts_channels[chan], config, sizeof(*config));
1640+
}
1641+
1642+
/**
1643+
* ice_ptp_disable_all_extts - Disable all EXTTS channels
1644+
* @pf: Board private structure
1645+
*/
1646+
static void ice_ptp_disable_all_extts(struct ice_pf *pf)
1647+
{
1648+
struct ice_extts_channel extts_cfg = {};
1649+
int i;
1650+
1651+
for (i = 0; i < pf->ptp.info.n_ext_ts; i++) {
1652+
if (pf->ptp.extts_channels[i].ena) {
1653+
extts_cfg.gpio_pin = pf->ptp.extts_channels[i].gpio_pin;
1654+
extts_cfg.ena = false;
1655+
ice_ptp_cfg_extts(pf, i, &extts_cfg, false);
1656+
}
1657+
}
1658+
1659+
synchronize_irq(pf->oicr_irq.virq);
1660+
}
1661+
1662+
/**
1663+
* ice_ptp_enable_all_extts - Enable all EXTTS channels
1664+
* @pf: Board private structure
1665+
*
1666+
* Called during reset to restore user configuration.
1667+
*/
1668+
static void ice_ptp_enable_all_extts(struct ice_pf *pf)
1669+
{
1670+
int i;
1671+
1672+
for (i = 0; i < pf->ptp.info.n_ext_ts; i++) {
1673+
if (pf->ptp.extts_channels[i].ena)
1674+
ice_ptp_cfg_extts(pf, i, &pf->ptp.extts_channels[i],
1675+
false);
1676+
}
16421677
}
16431678

16441679
/**
@@ -1795,7 +1830,6 @@ ice_ptp_gpio_enable_e810(struct ptp_clock_info *info,
17951830
struct ptp_clock_request *rq, int on)
17961831
{
17971832
struct ice_pf *pf = ptp_info_to_pf(info);
1798-
struct ice_perout_channel clk_cfg = {0};
17991833
bool sma_pres = false;
18001834
unsigned int chan;
18011835
u32 gpio_pin;
@@ -1806,6 +1840,9 @@ ice_ptp_gpio_enable_e810(struct ptp_clock_info *info,
18061840

18071841
switch (rq->type) {
18081842
case PTP_CLK_REQ_PEROUT:
1843+
{
1844+
struct ice_perout_channel clk_cfg = {};
1845+
18091846
chan = rq->perout.index;
18101847
if (sma_pres) {
18111848
if (chan == ice_pin_desc_e810t[SMA1].chan)
@@ -1833,7 +1870,11 @@ ice_ptp_gpio_enable_e810(struct ptp_clock_info *info,
18331870

18341871
err = ice_ptp_cfg_clkout(pf, chan, &clk_cfg, true);
18351872
break;
1873+
}
18361874
case PTP_CLK_REQ_EXTTS:
1875+
{
1876+
struct ice_extts_channel extts_cfg = {};
1877+
18371878
chan = rq->extts.index;
18381879
if (sma_pres) {
18391880
if (chan < ice_pin_desc_e810t[SMA2].chan)
@@ -1849,9 +1890,13 @@ ice_ptp_gpio_enable_e810(struct ptp_clock_info *info,
18491890
gpio_pin = chan;
18501891
}
18511892

1852-
err = ice_ptp_cfg_extts(pf, !!on, chan, gpio_pin,
1853-
rq->extts.flags);
1854-
break;
1893+
extts_cfg.flags = rq->extts.flags;
1894+
extts_cfg.gpio_pin = gpio_pin;
1895+
extts_cfg.ena = !!on;
1896+
1897+
ice_ptp_cfg_extts(pf, chan, &extts_cfg, true);
1898+
return 0;
1899+
}
18551900
default:
18561901
return -EOPNOTSUPP;
18571902
}
@@ -1869,21 +1914,31 @@ static int ice_ptp_gpio_enable_e823(struct ptp_clock_info *info,
18691914
struct ptp_clock_request *rq, int on)
18701915
{
18711916
struct ice_pf *pf = ptp_info_to_pf(info);
1872-
struct ice_perout_channel clk_cfg = {0};
18731917
int err;
18741918

18751919
switch (rq->type) {
18761920
case PTP_CLK_REQ_PPS:
1921+
{
1922+
struct ice_perout_channel clk_cfg = {};
1923+
18771924
clk_cfg.gpio_pin = PPS_PIN_INDEX;
18781925
clk_cfg.period = NSEC_PER_SEC;
18791926
clk_cfg.ena = !!on;
18801927

18811928
err = ice_ptp_cfg_clkout(pf, PPS_CLK_GEN_CHAN, &clk_cfg, true);
18821929
break;
1930+
}
18831931
case PTP_CLK_REQ_EXTTS:
1884-
err = ice_ptp_cfg_extts(pf, !!on, rq->extts.index,
1885-
TIME_SYNC_PIN_INDEX, rq->extts.flags);
1886-
break;
1932+
{
1933+
struct ice_extts_channel extts_cfg = {};
1934+
1935+
extts_cfg.flags = rq->extts.flags;
1936+
extts_cfg.gpio_pin = TIME_SYNC_PIN_INDEX;
1937+
extts_cfg.ena = !!on;
1938+
1939+
ice_ptp_cfg_extts(pf, rq->extts.index, &extts_cfg, true);
1940+
return 0;
1941+
}
18871942
default:
18881943
return -EOPNOTSUPP;
18891944
}
@@ -2720,6 +2775,10 @@ static int ice_ptp_rebuild_owner(struct ice_pf *pf)
27202775
ice_ptp_restart_all_phy(pf);
27212776
}
27222777

2778+
/* Re-enable all periodic outputs and external timestamp events */
2779+
ice_ptp_enable_all_clkout(pf);
2780+
ice_ptp_enable_all_extts(pf);
2781+
27232782
return 0;
27242783
}
27252784

@@ -3275,6 +3334,8 @@ void ice_ptp_release(struct ice_pf *pf)
32753334

32763335
ice_ptp_release_tx_tracker(pf, &pf->ptp.port.tx);
32773336

3337+
ice_ptp_disable_all_extts(pf);
3338+
32783339
kthread_cancel_delayed_work_sync(&pf->ptp.work);
32793340

32803341
ice_ptp_port_phy_stop(&pf->ptp.port);

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,12 @@ struct ice_perout_channel {
3333
u64 start_time;
3434
};
3535

36+
struct ice_extts_channel {
37+
bool ena;
38+
u32 gpio_pin;
39+
u32 flags;
40+
};
41+
3642
/* The ice hardware captures Tx hardware timestamps in the PHY. The timestamp
3743
* is stored in a buffer of registers. Depending on the specific hardware,
3844
* this buffer might be shared across multiple PHY ports.
@@ -226,6 +232,7 @@ enum ice_ptp_state {
226232
* @ext_ts_irq: the external timestamp IRQ in use
227233
* @kworker: kwork thread for handling periodic work
228234
* @perout_channels: periodic output data
235+
* @extts_channels: channels for external timestamps
229236
* @info: structure defining PTP hardware capabilities
230237
* @clock: pointer to registered PTP clock device
231238
* @tstamp_config: hardware timestamping configuration
@@ -249,6 +256,7 @@ struct ice_ptp {
249256
u8 ext_ts_irq;
250257
struct kthread_worker *kworker;
251258
struct ice_perout_channel perout_channels[GLTSYN_TGT_H_IDX_MAX];
259+
struct ice_extts_channel extts_channels[GLTSYN_TGT_H_IDX_MAX];
252260
struct ptp_clock_info info;
253261
struct ptp_clock *clock;
254262
struct hwtstamp_config tstamp_config;

0 commit comments

Comments
 (0)