Commit e98386d7 authored by Sagi Maimon's avatar Sagi Maimon Committed by Jakub Kicinski
Browse files

ptp: ocp: Fix NULL dereference in Adva board SMA sysfs operations



On Adva boards, SMA sysfs store/get operations can call
__handle_signal_outputs() or __handle_signal_inputs() while the `irig`
and `dcf` pointers are uninitialized, leading to a NULL pointer
dereference in __handle_signal() and causing a kernel crash. Adva boards
don't use `irig` or `dcf` functionality, so add Adva-specific callbacks
`ptp_ocp_sma_adva_set_outputs()` and `ptp_ocp_sma_adva_set_inputs()` that
avoid invoking `irig` or `dcf` input/output routines.

Fixes: ef61f552 ("ptp: ocp: add Adva timecard support")
Signed-off-by: default avatarSagi Maimon <maimon.sagi@gmail.com>
Reviewed-by: default avatarVadim Fedorenko <vadim.fedorenko@linux.dev>
Link: https://patch.msgid.link/20250429073320.33277-1-maimon.sagi@gmail.com


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent f920436a
Loading
Loading
Loading
Loading
+50 −2
Original line number Diff line number Diff line
@@ -2578,12 +2578,60 @@ static const struct ocp_sma_op ocp_fb_sma_op = {
	.set_output	= ptp_ocp_sma_fb_set_output,
};

static int
ptp_ocp_sma_adva_set_output(struct ptp_ocp *bp, int sma_nr, u32 val)
{
	u32 reg, mask, shift;
	unsigned long flags;
	u32 __iomem *gpio;

	gpio = sma_nr > 2 ? &bp->sma_map1->gpio2 : &bp->sma_map2->gpio2;
	shift = sma_nr & 1 ? 0 : 16;

	mask = 0xffff << (16 - shift);

	spin_lock_irqsave(&bp->lock, flags);

	reg = ioread32(gpio);
	reg = (reg & mask) | (val << shift);

	iowrite32(reg, gpio);

	spin_unlock_irqrestore(&bp->lock, flags);

	return 0;
}

static int
ptp_ocp_sma_adva_set_inputs(struct ptp_ocp *bp, int sma_nr, u32 val)
{
	u32 reg, mask, shift;
	unsigned long flags;
	u32 __iomem *gpio;

	gpio = sma_nr > 2 ? &bp->sma_map2->gpio1 : &bp->sma_map1->gpio1;
	shift = sma_nr & 1 ? 0 : 16;

	mask = 0xffff << (16 - shift);

	spin_lock_irqsave(&bp->lock, flags);

	reg = ioread32(gpio);
	reg = (reg & mask) | (val << shift);

	iowrite32(reg, gpio);

	spin_unlock_irqrestore(&bp->lock, flags);

	return 0;
}

static const struct ocp_sma_op ocp_adva_sma_op = {
	.tbl		= { ptp_ocp_adva_sma_in, ptp_ocp_adva_sma_out },
	.init		= ptp_ocp_sma_fb_init,
	.get		= ptp_ocp_sma_fb_get,
	.set_inputs	= ptp_ocp_sma_fb_set_inputs,
	.set_output	= ptp_ocp_sma_fb_set_output,
	.set_inputs	= ptp_ocp_sma_adva_set_inputs,
	.set_output	= ptp_ocp_sma_adva_set_output,
};

static int