Skip to content

Commit

Permalink
can: Proper ctrlmode handling for CAN devices
Browse files Browse the repository at this point in the history
This patch adds error checking of ctrlmode values for CAN devices. As
an example all availabe bits are implemented in the mcp251x driver.

Signed-off-by: Christian Pellegrin <chripell@fsfe.org>
Acked-by: Wolfgang Grandegger <wg@grandegger.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Christian Pellegrin authored and David S. Miller committed Jan 15, 2010
1 parent 1954dc1 commit ad72c34
Show file tree
Hide file tree
Showing 9 changed files with 19 additions and 1 deletion.
1 change: 1 addition & 0 deletions drivers/net/can/at91_can.c
Original file line number Diff line number Diff line change
Expand Up @@ -1073,6 +1073,7 @@ static int __init at91_can_probe(struct platform_device *pdev)
priv->can.bittiming_const = &at91_bittiming_const;
priv->can.do_set_bittiming = at91_set_bittiming;
priv->can.do_set_mode = at91_set_mode;
priv->can.ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES;
priv->reg_base = addr;
priv->dev = dev;
priv->clk = clk;
Expand Down
1 change: 1 addition & 0 deletions drivers/net/can/bfin_can.c
Original file line number Diff line number Diff line change
Expand Up @@ -603,6 +603,7 @@ struct net_device *alloc_bfin_candev(void)
priv->can.bittiming_const = &bfin_can_bittiming_const;
priv->can.do_set_bittiming = bfin_can_set_bittiming;
priv->can.do_set_mode = bfin_can_set_mode;
priv->can.ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES;

return dev;
}
Expand Down
2 changes: 2 additions & 0 deletions drivers/net/can/dev.c
Original file line number Diff line number Diff line change
Expand Up @@ -592,6 +592,8 @@ static int can_changelink(struct net_device *dev,
if (dev->flags & IFF_UP)
return -EBUSY;
cm = nla_data(data[IFLA_CAN_CTRLMODE]);
if (cm->flags & ~priv->ctrlmode_supported)
return -EOPNOTSUPP;
priv->ctrlmode &= ~cm->mask;
priv->ctrlmode |= cm->flags;
}
Expand Down
11 changes: 10 additions & 1 deletion drivers/net/can/mcp251x.c
Original file line number Diff line number Diff line change
Expand Up @@ -539,9 +539,14 @@ static void mcp251x_set_normal_mode(struct spi_device *spi)
if (priv->can.ctrlmode & CAN_CTRLMODE_LOOPBACK) {
/* Put device into loopback mode */
mcp251x_write_reg(spi, CANCTRL, CANCTRL_REQOP_LOOPBACK);
} else if (priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY) {
/* Put device into listen-only mode */
mcp251x_write_reg(spi, CANCTRL, CANCTRL_REQOP_LISTEN_ONLY);
} else {
/* Put device into normal mode */
mcp251x_write_reg(spi, CANCTRL, CANCTRL_REQOP_NORMAL);
mcp251x_write_reg(spi, CANCTRL, CANCTRL_REQOP_NORMAL |
(priv->can.ctrlmode & CAN_CTRLMODE_ONE_SHOT ?
CANCTRL_OSM : 0));

/* Wait for the device to enter normal mode */
timeout = jiffies + HZ;
Expand Down Expand Up @@ -948,6 +953,10 @@ static int __devinit mcp251x_can_probe(struct spi_device *spi)
priv->can.bittiming_const = &mcp251x_bittiming_const;
priv->can.do_set_mode = mcp251x_do_set_mode;
priv->can.clock.freq = pdata->oscillator_frequency / 2;
priv->can.ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES |
CAN_CTRLMODE_LOOPBACK | CAN_CTRLMODE_LISTENONLY;
if (pdata->model == CAN_MCP251X_MCP2515)
priv->can.ctrlmode_supported |= CAN_CTRLMODE_ONE_SHOT;
priv->net = net;
dev_set_drvdata(&spi->dev, priv);

Expand Down
1 change: 1 addition & 0 deletions drivers/net/can/mscan/mscan.c
Original file line number Diff line number Diff line change
Expand Up @@ -686,6 +686,7 @@ struct net_device *alloc_mscandev(void)
priv->can.bittiming_const = &mscan_bittiming_const;
priv->can.do_set_bittiming = mscan_do_set_bittiming;
priv->can.do_set_mode = mscan_do_set_mode;
priv->can.ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES;

for (i = 0; i < TX_QUEUE_SIZE; i++) {
priv->tx_queue[i].id = i;
Expand Down
1 change: 1 addition & 0 deletions drivers/net/can/sja1000/sja1000.c
Original file line number Diff line number Diff line change
Expand Up @@ -567,6 +567,7 @@ struct net_device *alloc_sja1000dev(int sizeof_priv)
priv->can.bittiming_const = &sja1000_bittiming_const;
priv->can.do_set_bittiming = sja1000_set_bittiming;
priv->can.do_set_mode = sja1000_set_mode;
priv->can.ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES;

if (sizeof_priv)
priv->priv = (void *)priv + sizeof(struct sja1000_priv);
Expand Down
1 change: 1 addition & 0 deletions drivers/net/can/ti_hecc.c
Original file line number Diff line number Diff line change
Expand Up @@ -909,6 +909,7 @@ static int ti_hecc_probe(struct platform_device *pdev)
priv->can.bittiming_const = &ti_hecc_bittiming_const;
priv->can.do_set_mode = ti_hecc_do_set_mode;
priv->can.do_get_state = ti_hecc_get_state;
priv->can.ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES;

ndev->irq = irq->start;
ndev->flags |= IFF_ECHO;
Expand Down
1 change: 1 addition & 0 deletions drivers/net/can/usb/ems_usb.c
Original file line number Diff line number Diff line change
Expand Up @@ -1022,6 +1022,7 @@ static int ems_usb_probe(struct usb_interface *intf,
dev->can.bittiming_const = &ems_usb_bittiming_const;
dev->can.do_set_bittiming = ems_usb_set_bittiming;
dev->can.do_set_mode = ems_usb_set_mode;
dev->can.ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES;

netdev->flags |= IFF_ECHO; /* we support local echo */

Expand Down
1 change: 1 addition & 0 deletions include/linux/can/dev.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ struct can_priv {

enum can_state state;
u32 ctrlmode;
u32 ctrlmode_supported;

int restart_ms;
struct timer_list restart_timer;
Expand Down

0 comments on commit ad72c34

Please sign in to comment.