Commit a9edcded authored by Oliver Hartkopp's avatar Oliver Hartkopp Committed by Marc Kleine-Budde

can: sja1000_isa: add locking for indirect register access mode

When accessing the SJA1000 controller registers in the indirect access mode,
writing the register number and reading/writing the data has to be an atomic
attempt.

As the sja1000_isa driver is an old style driver with a fixed number of
instances the locking variable depends on the same index like all the other
configuration elements given on the module command line.

As a positive side effect dev->dev_id is populated by the instance index,
which was missing in 3e66d013 ("can: populate netdev::dev_id for udev
discrimination").
Reported-by: default avatarMarc Kleine-Budde <mkl@pengutronix.de>
Signed-off-by: default avatarOliver Hartkopp <socketcan@hartkopp.net>
Signed-off-by: default avatarMarc Kleine-Budde <mkl@pengutronix.de>
parent 78c181bc
...@@ -46,6 +46,7 @@ static int clk[MAXDEV]; ...@@ -46,6 +46,7 @@ static int clk[MAXDEV];
static unsigned char cdr[MAXDEV] = {[0 ... (MAXDEV - 1)] = 0xff}; static unsigned char cdr[MAXDEV] = {[0 ... (MAXDEV - 1)] = 0xff};
static unsigned char ocr[MAXDEV] = {[0 ... (MAXDEV - 1)] = 0xff}; static unsigned char ocr[MAXDEV] = {[0 ... (MAXDEV - 1)] = 0xff};
static int indirect[MAXDEV] = {[0 ... (MAXDEV - 1)] = -1}; static int indirect[MAXDEV] = {[0 ... (MAXDEV - 1)] = -1};
static spinlock_t indirect_lock[MAXDEV]; /* lock for indirect access mode */
module_param_array(port, ulong, NULL, S_IRUGO); module_param_array(port, ulong, NULL, S_IRUGO);
MODULE_PARM_DESC(port, "I/O port number"); MODULE_PARM_DESC(port, "I/O port number");
...@@ -101,19 +102,26 @@ static void sja1000_isa_port_write_reg(const struct sja1000_priv *priv, ...@@ -101,19 +102,26 @@ static void sja1000_isa_port_write_reg(const struct sja1000_priv *priv,
static u8 sja1000_isa_port_read_reg_indirect(const struct sja1000_priv *priv, static u8 sja1000_isa_port_read_reg_indirect(const struct sja1000_priv *priv,
int reg) int reg)
{ {
unsigned long base = (unsigned long)priv->reg_base; unsigned long flags, base = (unsigned long)priv->reg_base;
u8 readval;
spin_lock_irqsave(&indirect_lock[priv->dev->dev_id], flags);
outb(reg, base); outb(reg, base);
return inb(base + 1); readval = inb(base + 1);
spin_unlock_irqrestore(&indirect_lock[priv->dev->dev_id], flags);
return readval;
} }
static void sja1000_isa_port_write_reg_indirect(const struct sja1000_priv *priv, static void sja1000_isa_port_write_reg_indirect(const struct sja1000_priv *priv,
int reg, u8 val) int reg, u8 val)
{ {
unsigned long base = (unsigned long)priv->reg_base; unsigned long flags, base = (unsigned long)priv->reg_base;
spin_lock_irqsave(&indirect_lock[priv->dev->dev_id], flags);
outb(reg, base); outb(reg, base);
outb(val, base + 1); outb(val, base + 1);
spin_unlock_irqrestore(&indirect_lock[priv->dev->dev_id], flags);
} }
static int sja1000_isa_probe(struct platform_device *pdev) static int sja1000_isa_probe(struct platform_device *pdev)
...@@ -169,6 +177,7 @@ static int sja1000_isa_probe(struct platform_device *pdev) ...@@ -169,6 +177,7 @@ static int sja1000_isa_probe(struct platform_device *pdev)
if (iosize == SJA1000_IOSIZE_INDIRECT) { if (iosize == SJA1000_IOSIZE_INDIRECT) {
priv->read_reg = sja1000_isa_port_read_reg_indirect; priv->read_reg = sja1000_isa_port_read_reg_indirect;
priv->write_reg = sja1000_isa_port_write_reg_indirect; priv->write_reg = sja1000_isa_port_write_reg_indirect;
spin_lock_init(&indirect_lock[idx]);
} else { } else {
priv->read_reg = sja1000_isa_port_read_reg; priv->read_reg = sja1000_isa_port_read_reg;
priv->write_reg = sja1000_isa_port_write_reg; priv->write_reg = sja1000_isa_port_write_reg;
...@@ -198,6 +207,7 @@ static int sja1000_isa_probe(struct platform_device *pdev) ...@@ -198,6 +207,7 @@ static int sja1000_isa_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, dev); platform_set_drvdata(pdev, dev);
SET_NETDEV_DEV(dev, &pdev->dev); SET_NETDEV_DEV(dev, &pdev->dev);
dev->dev_id = idx;
err = register_sja1000dev(dev); err = register_sja1000dev(dev);
if (err) { if (err) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment