Skip to content

Commit 0aacec4

Browse files
jacob-kellerdavem330
authored andcommitted
ice: avoid executing commands on other ports when driving sync
The ice hardware has a synchronization mechanism used to drive the simultaneous application of commands on both PHY ports and the source timer in the MAC. When issuing a sync via ice_ptp_exec_tmr_cmd(), the hardware will simultaneously apply the commands programmed for the main timer and each PHY port. Neither the main timer command register, nor the PHY port command registers auto clear on command execution. During the execution of a timer command intended for a single port on E822 devices, such as those used to configure a PHY during link up, the driver is not correctly clearing the previous commands. This results in unintentionally executing the last programmed command on the main timer and other PHY ports whenever performing reconfiguration on E822 ports after link up. This results in unintended side effects on other timers, depending on what command was previously programmed. To fix this, the driver must ensure that the main timer and all other PHY ports are properly initialized to perform no action. The enumeration for timer commands does not include an enumeration value for doing nothing. Introduce ICE_PTP_NOP for this purpose. When writing a timer command to hardware, leave the command bits set to zero which indicates that no operation should be performed on that port. Modify ice_ptp_one_port_cmd() to always initialize all ports. For all ports other than the one being configured, write their timer command register to ICE_PTP_NOP. This ensures that no side effect happens on the timer command. To fix this for the PHY ports, modify ice_ptp_one_port_cmd() to always initialize all other ports to ICE_PTP_NOP. This ensures that no side effects happen on the other ports. Call ice_ptp_src_cmd() with a command value if ICE_PTP_NOP in ice_sync_phy_timer_e822() and ice_start_phy_timer_e822(). With both of these changes, the driver should no longer execute a stale command on the main timer or another PHY port when reconfiguring one of the PHY ports after link up. Fixes: 3a74962 ("ice: implement basic E822 PTP support") Signed-off-by: Siddaraju DH <siddaraju.dh@intel.com> Signed-off-by: Jacob Keller <jacob.e.keller@intel.com> Tested-by: Sunitha Mekala <sunithax.d.mekala@intel.com> (A Contingent worker at Intel) Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com> Reviewed-by: Simon Horman <horms@kernel.org> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent a4f39c9 commit 0aacec4

2 files changed

Lines changed: 52 additions & 6 deletions

File tree

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

Lines changed: 50 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,8 @@ static void ice_ptp_src_cmd(struct ice_hw *hw, enum ice_ptp_tmr_cmd cmd)
131131
case READ_TIME:
132132
cmd_val |= GLTSYN_CMD_READ_TIME;
133133
break;
134+
case ICE_PTP_NOP:
135+
break;
134136
}
135137

136138
wr32(hw, GLTSYN_CMD, cmd_val);
@@ -1226,18 +1228,18 @@ ice_ptp_read_port_capture(struct ice_hw *hw, u8 port, u64 *tx_ts, u64 *rx_ts)
12261228
}
12271229

12281230
/**
1229-
* ice_ptp_one_port_cmd - Prepare a single PHY port for a timer command
1231+
* ice_ptp_write_port_cmd_e822 - Prepare a single PHY port for a timer command
12301232
* @hw: pointer to HW struct
12311233
* @port: Port to which cmd has to be sent
12321234
* @cmd: Command to be sent to the port
12331235
*
12341236
* Prepare the requested port for an upcoming timer sync command.
12351237
*
1236-
* Note there is no equivalent of this operation on E810, as that device
1237-
* always handles all external PHYs internally.
1238+
* Do not use this function directly. If you want to configure exactly one
1239+
* port, use ice_ptp_one_port_cmd() instead.
12381240
*/
12391241
static int
1240-
ice_ptp_one_port_cmd(struct ice_hw *hw, u8 port, enum ice_ptp_tmr_cmd cmd)
1242+
ice_ptp_write_port_cmd_e822(struct ice_hw *hw, u8 port, enum ice_ptp_tmr_cmd cmd)
12411243
{
12421244
u32 cmd_val, val;
12431245
u8 tmr_idx;
@@ -1261,6 +1263,8 @@ ice_ptp_one_port_cmd(struct ice_hw *hw, u8 port, enum ice_ptp_tmr_cmd cmd)
12611263
case ADJ_TIME_AT_TIME:
12621264
cmd_val |= PHY_CMD_ADJ_TIME_AT_TIME;
12631265
break;
1266+
case ICE_PTP_NOP:
1267+
break;
12641268
}
12651269

12661270
/* Tx case */
@@ -1306,6 +1310,39 @@ ice_ptp_one_port_cmd(struct ice_hw *hw, u8 port, enum ice_ptp_tmr_cmd cmd)
13061310
return 0;
13071311
}
13081312

1313+
/**
1314+
* ice_ptp_one_port_cmd - Prepare one port for a timer command
1315+
* @hw: pointer to the HW struct
1316+
* @configured_port: the port to configure with configured_cmd
1317+
* @configured_cmd: timer command to prepare on the configured_port
1318+
*
1319+
* Prepare the configured_port for the configured_cmd, and prepare all other
1320+
* ports for ICE_PTP_NOP. This causes the configured_port to execute the
1321+
* desired command while all other ports perform no operation.
1322+
*/
1323+
static int
1324+
ice_ptp_one_port_cmd(struct ice_hw *hw, u8 configured_port,
1325+
enum ice_ptp_tmr_cmd configured_cmd)
1326+
{
1327+
u8 port;
1328+
1329+
for (port = 0; port < ICE_NUM_EXTERNAL_PORTS; port++) {
1330+
enum ice_ptp_tmr_cmd cmd;
1331+
int err;
1332+
1333+
if (port == configured_port)
1334+
cmd = configured_cmd;
1335+
else
1336+
cmd = ICE_PTP_NOP;
1337+
1338+
err = ice_ptp_write_port_cmd_e822(hw, port, cmd);
1339+
if (err)
1340+
return err;
1341+
}
1342+
1343+
return 0;
1344+
}
1345+
13091346
/**
13101347
* ice_ptp_port_cmd_e822 - Prepare all ports for a timer command
13111348
* @hw: pointer to the HW struct
@@ -1322,7 +1359,7 @@ ice_ptp_port_cmd_e822(struct ice_hw *hw, enum ice_ptp_tmr_cmd cmd)
13221359
for (port = 0; port < ICE_NUM_EXTERNAL_PORTS; port++) {
13231360
int err;
13241361

1325-
err = ice_ptp_one_port_cmd(hw, port, cmd);
1362+
err = ice_ptp_write_port_cmd_e822(hw, port, cmd);
13261363
if (err)
13271364
return err;
13281365
}
@@ -2252,6 +2289,9 @@ static int ice_sync_phy_timer_e822(struct ice_hw *hw, u8 port)
22522289
if (err)
22532290
goto err_unlock;
22542291

2292+
/* Do not perform any action on the main timer */
2293+
ice_ptp_src_cmd(hw, ICE_PTP_NOP);
2294+
22552295
/* Issue the sync to activate the time adjustment */
22562296
ice_ptp_exec_tmr_cmd(hw);
22572297

@@ -2372,6 +2412,9 @@ int ice_start_phy_timer_e822(struct ice_hw *hw, u8 port)
23722412
if (err)
23732413
return err;
23742414

2415+
/* Do not perform any action on the main timer */
2416+
ice_ptp_src_cmd(hw, ICE_PTP_NOP);
2417+
23752418
ice_ptp_exec_tmr_cmd(hw);
23762419

23772420
err = ice_read_phy_reg_e822(hw, port, P_REG_PS, &val);
@@ -2847,6 +2890,8 @@ static int ice_ptp_port_cmd_e810(struct ice_hw *hw, enum ice_ptp_tmr_cmd cmd)
28472890
case ADJ_TIME_AT_TIME:
28482891
cmd_val = GLTSYN_CMD_ADJ_INIT_TIME;
28492892
break;
2893+
case ICE_PTP_NOP:
2894+
return 0;
28502895
}
28512896

28522897
/* Read, modify, write */

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@ enum ice_ptp_tmr_cmd {
99
INIT_INCVAL,
1010
ADJ_TIME,
1111
ADJ_TIME_AT_TIME,
12-
READ_TIME
12+
READ_TIME,
13+
ICE_PTP_NOP,
1314
};
1415

1516
enum ice_ptp_serdes {

0 commit comments

Comments
 (0)