Skip to content

Commit 43a4166

Browse files
vladimirolteankuba-moo
authored andcommitted
net: mscc: ocelot: perform error cleanup in ocelot_hwstamp_set()
An unsupported RX filter will leave the port with TX timestamping still applied as per the new request, rather than the old setting. When parsing the tx_type, don't apply it just yet, but delay that until after we've parsed the rx_filter as well (and potentially returned -ERANGE for that). Similarly, copy_to_user() may fail, which is a rare occurrence, but should still be treated by unwinding what was done. Fixes: 96ca08c ("net: mscc: ocelot: set up traps for PTP packets") Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com> Link: https://patch.msgid.link/20241205145519.1236778-6-vladimir.oltean@nxp.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
1 parent b454abf commit 43a4166

File tree

1 file changed

+42
-17
lines changed

1 file changed

+42
-17
lines changed

drivers/net/ethernet/mscc/ocelot_ptp.c

Lines changed: 42 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -497,6 +497,28 @@ static int ocelot_traps_to_ptp_rx_filter(unsigned int proto)
497497
return HWTSTAMP_FILTER_NONE;
498498
}
499499

500+
static int ocelot_ptp_tx_type_to_cmd(int tx_type, int *ptp_cmd)
501+
{
502+
switch (tx_type) {
503+
case HWTSTAMP_TX_ON:
504+
*ptp_cmd = IFH_REW_OP_TWO_STEP_PTP;
505+
break;
506+
case HWTSTAMP_TX_ONESTEP_SYNC:
507+
/* IFH_REW_OP_ONE_STEP_PTP updates the correctionField,
508+
* what we need to update is the originTimestamp.
509+
*/
510+
*ptp_cmd = IFH_REW_OP_ORIGIN_PTP;
511+
break;
512+
case HWTSTAMP_TX_OFF:
513+
*ptp_cmd = 0;
514+
break;
515+
default:
516+
return -ERANGE;
517+
}
518+
519+
return 0;
520+
}
521+
500522
int ocelot_hwstamp_get(struct ocelot *ocelot, int port, struct ifreq *ifr)
501523
{
502524
struct ocelot_port *ocelot_port = ocelot->ports[port];
@@ -523,30 +545,19 @@ EXPORT_SYMBOL(ocelot_hwstamp_get);
523545
int ocelot_hwstamp_set(struct ocelot *ocelot, int port, struct ifreq *ifr)
524546
{
525547
struct ocelot_port *ocelot_port = ocelot->ports[port];
548+
int ptp_cmd, old_ptp_cmd = ocelot_port->ptp_cmd;
526549
bool l2 = false, l4 = false;
527550
struct hwtstamp_config cfg;
551+
bool old_l2, old_l4;
528552
int err;
529553

530554
if (copy_from_user(&cfg, ifr->ifr_data, sizeof(cfg)))
531555
return -EFAULT;
532556

533557
/* Tx type sanity check */
534-
switch (cfg.tx_type) {
535-
case HWTSTAMP_TX_ON:
536-
ocelot_port->ptp_cmd = IFH_REW_OP_TWO_STEP_PTP;
537-
break;
538-
case HWTSTAMP_TX_ONESTEP_SYNC:
539-
/* IFH_REW_OP_ONE_STEP_PTP updates the correctional field, we
540-
* need to update the origin time.
541-
*/
542-
ocelot_port->ptp_cmd = IFH_REW_OP_ORIGIN_PTP;
543-
break;
544-
case HWTSTAMP_TX_OFF:
545-
ocelot_port->ptp_cmd = 0;
546-
break;
547-
default:
548-
return -ERANGE;
549-
}
558+
err = ocelot_ptp_tx_type_to_cmd(cfg.tx_type, &ptp_cmd);
559+
if (err)
560+
return err;
550561

551562
switch (cfg.rx_filter) {
552563
case HWTSTAMP_FILTER_NONE:
@@ -571,13 +582,27 @@ int ocelot_hwstamp_set(struct ocelot *ocelot, int port, struct ifreq *ifr)
571582
return -ERANGE;
572583
}
573584

585+
old_l2 = ocelot_port->trap_proto & OCELOT_PROTO_PTP_L2;
586+
old_l4 = ocelot_port->trap_proto & OCELOT_PROTO_PTP_L4;
587+
574588
err = ocelot_setup_ptp_traps(ocelot, port, l2, l4);
575589
if (err)
576590
return err;
577591

592+
ocelot_port->ptp_cmd = ptp_cmd;
593+
578594
cfg.rx_filter = ocelot_traps_to_ptp_rx_filter(ocelot_port->trap_proto);
579595

580-
return copy_to_user(ifr->ifr_data, &cfg, sizeof(cfg)) ? -EFAULT : 0;
596+
if (copy_to_user(ifr->ifr_data, &cfg, sizeof(cfg))) {
597+
err = -EFAULT;
598+
goto out_restore_ptp_traps;
599+
}
600+
601+
return 0;
602+
out_restore_ptp_traps:
603+
ocelot_setup_ptp_traps(ocelot, port, old_l2, old_l4);
604+
ocelot_port->ptp_cmd = old_ptp_cmd;
605+
return err;
581606
}
582607
EXPORT_SYMBOL(ocelot_hwstamp_set);
583608

0 commit comments

Comments
 (0)