]> bbs.cooldavid.org Git - net-next-2.6.git/commitdiff
can: Proper ctrlmode handling for CAN devices
authorChristian Pellegrin <chripell@fsfe.org>
Thu, 14 Jan 2010 07:08:34 +0000 (07:08 +0000)
committerDavid S. Miller <davem@davemloft.net>
Fri, 15 Jan 2010 09:39:17 +0000 (01:39 -0800)
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>
drivers/net/can/at91_can.c
drivers/net/can/bfin_can.c
drivers/net/can/dev.c
drivers/net/can/mcp251x.c
drivers/net/can/mscan/mscan.c
drivers/net/can/sja1000/sja1000.c
drivers/net/can/ti_hecc.c
drivers/net/can/usb/ems_usb.c
include/linux/can/dev.h

index f7287497ba6e70a4b57074151bcccaa8e38c5e10..a2f29a38798a4de2fe9ae631749afa81279ce449 100644 (file)
@@ -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;
index 7e1926e79e9805fa2dbc38b8e7b43dfad92906f3..bf7f9ba2d903a34c439c953a659a7d31e5d89815 100644 (file)
@@ -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;
 }
index c1bb29f0322b388193fa5d874fdabea87206cb75..f08f1202ff003cbe4f1854e2e2ebea44779118dd 100644 (file)
@@ -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;
        }
index afa2fa45fed97c41fbee4b1ce96fed01d7099016..bbe186b5a0ed76ab5c4b5dcd36224a18dcde5846 100644 (file)
@@ -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;
@@ -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);
 
index 40827c128b65ba108ff16aa94576ef31c98cccb8..6b7dd578d417b55c65e5eeb47439b5c604e76500 100644 (file)
@@ -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;
index 345304d779b927361abb8d62633b61a25c0a7876..ace103a44833378aef5d8b5027bb4a1db79ce19f 100644 (file)
@@ -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);
index 7d370e32a7a8c995f155aa41f43fbaa75c3bf471..8332e242b0bedaaf9543de780649d38f0db184f3 100644 (file)
@@ -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;
index ddb17e256656172a89de71a22c6de100e98d0ef1..bfab283ba9b18ebe8459ce247aa9a485a72a5f48 100644 (file)
@@ -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 */
 
index 7e7c98a3e908b833ebb250e989e64e5a9bd8535b..c8c660a79f907657af7349fd78d0eb21099a88a0 100644 (file)
@@ -38,6 +38,7 @@ struct can_priv {
 
        enum can_state state;
        u32 ctrlmode;
+       u32 ctrlmode_supported;
 
        int restart_ms;
        struct timer_list restart_timer;