Hi Christian,

here's my quick review of the MPC251x driver. First some general comments:

- Use proper Linux style for comments.

- Use a consistent style for indention of function declarations and
  multi-line expressions.

- Use macro definitions for constant values.

- Check the proper usage of brackets { } for if, for, etc.

- Remove extended debugging message.

- Consider replacing ret with err but only if err==success and
  !err=failure (minor issue). Then use "if ([!]err) ...".

- Don't use __func__ but a meaning full error message.

More comments inline:

> /*
>  * CAN bus driver for Microchip 251x CAN Controller with SPI Interface
>  *
>  * MCP2510 support and bug fixes by Christian Pellegrin
>  * <[email protected]>
>  *
>  * Copyright 2007 Raymarine UK, Ltd. All Rights Reserved.
>  * Written under contract by:
>  *   Chris Elston, Katalix Systems, Ltd.
>  *
>  * Based on Microchip MCP251x CAN controller driver written by
>  * David Vrabel, Copyright 2006 Arcom Control Systems Ltd.
>  *
>  * Based on CAN bus driver for the CCAN controller written by
>  * - Sascha Hauer, Marc Kleine-Budde, Pengutronix
>  * - Simon Kallweit, intefo AG
>  * Copyright 2007
>  *
>  * This program is free software; you can redistribute it and/or modify
>  * it under the terms of the version 2 of the GNU General Public License
>  * as published by the Free Software Foundation
>  *
>  * This program is distributed in the hope that it will be useful,
>  * but WITHOUT ANY WARRANTY; without even the implied warranty of
>  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
>  * GNU General Public License for more details.
>  *
>  * You should have received a copy of the GNU General Public License
>  * along with this program; if not, write to the Free Software
>  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
>  *
>  *
>  *
>  * Your platform definition file should specify something like:
>  *
>  * static struct mcp251x_platform_data mcp251x_info = {
>  *         .oscillator_frequency = 8000000,
>  *         .board_specific_setup = &mcp251x_setup,
>  *         .model = CAN_MCP251X_MCP2510,
>  *         .power_enable = mcp251x_power_enable,
>  *         .transceiver_enable = NULL,
>  * };
>  *
>  * static struct spi_board_info spi_board_info[] = {
>  *         {
>  *                 .modalias      = "mcp251x",
>  *                 .platform_data = &mcp251x_info,
>  *                 .irq           = IRQ_EINT13,
>  *                 .max_speed_hz  = 2*1000*1000,
>  *                 .chip_select   = 2,
>  *         },
>  * };
>  *
>  * Please see mcp251x.h for a description of the fields in
>  * struct mcp251x_platform_data.
>  *
>  */
> 
> #include <linux/device.h>
> #include <linux/kernel.h>
> #include <linux/module.h>
> #include <linux/interrupt.h>
> #include <linux/platform_device.h>
> #include <linux/netdevice.h>
> #include <socketcan/can.h>
> #include <linux/spi/spi.h>
> #include <socketcan/can/dev.h>
> #include <socketcan/can/core.h>
> #include <linux/if_arp.h>
> #include <linux/dma-mapping.h>
> #include <linux/delay.h>
> #include <linux/completion.h>
> #include <linux/freezer.h>
> #include <linux/uaccess.h>
> #include <linux/io.h>
> #include <socketcan/can/platform/mcp251x.h>
> 
> #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22)
> #error This driver does not support Kernel versions < 2.6.22
> #endif
> 
> /* SPI interface instruction set */
> #define INSTRUCTION_WRITE     0x02
> #define INSTRUCTION_READ      0x03
> #define INSTRUCTION_BIT_MODIFY        0x05
> #define INSTRUCTION_LOAD_TXB(n)       (0x40 + 2 * (n))
> #define INSTRUCTION_READ_RXB(n)       (((n) == 0) ? 0x90 : 0x94)
> #define INSTRUCTION_RESET     0xC0
> 
> /* MPC251x registers */
> #define CANSTAT             0x0e
> #define CANCTRL             0x0f
> #  define CANCTRL_REQOP_MASK      0xe0
> #  define CANCTRL_REQOP_CONF      0x80
> #  define CANCTRL_REQOP_LISTEN_ONLY 0x60
> #  define CANCTRL_REQOP_LOOPBACK    0x40
> #  define CANCTRL_REQOP_SLEEP     0x20
> #  define CANCTRL_REQOP_NORMAL            0x00
> #  define CANCTRL_OSM             0x08
> #  define CANCTRL_ABAT                    0x10
> #define TEC         0x1c
> #define REC         0x1d
> #define CNF1        0x2a
> #define CNF2        0x29
> #  define CNF2_BTLMODE        0x80
> #define CNF3        0x28
> #  define CNF3_SOF       0x08
> #  define CNF3_WAKFIL    0x04
> #  define CNF3_PHSEG2_MASK 0x07
> #define CANINTE             0x2b
> #  define CANINTE_MERRE 0x80
> #  define CANINTE_WAKIE 0x40
> #  define CANINTE_ERRIE 0x20
> #  define CANINTE_TX2IE 0x10
> #  define CANINTE_TX1IE 0x08
> #  define CANINTE_TX0IE 0x04
> #  define CANINTE_RX1IE 0x02
> #  define CANINTE_RX0IE 0x01
> #define CANINTF             0x2c
> #  define CANINTF_MERRF 0x80
> #  define CANINTF_WAKIF 0x40
> #  define CANINTF_ERRIF 0x20
> #  define CANINTF_TX2IF 0x10
> #  define CANINTF_TX1IF 0x08
> #  define CANINTF_TX0IF 0x04
> #  define CANINTF_RX1IF 0x02
> #  define CANINTF_RX0IF 0x01
> #define EFLG        0x2d
> #  define EFLG_EWARN  0x01
> #  define EFLG_RXWAR  0x02
> #  define EFLG_TXWAR  0x04
> #  define EFLG_RXEP   0x08
> #  define EFLG_TXEP   0x10
> #  define EFLG_TXBO   0x20
> #  define EFLG_RX0OVR 0x40
> #  define EFLG_RX1OVR 0x80
> #define TXBCTRL(n)  ((n * 0x10) + 0x30)
> #  define TXBCTRL_ABTF        0x40
> #  define TXBCTRL_MLOA        0x20
> #  define TXBCTRL_TXERR 0x10
> #  define TXBCTRL_TXREQ 0x08
> #define RXBCTRL(n)  ((n * 0x10) + 0x60)
> #  define RXBCTRL_BUKT        0x04
> #  define RXBCTRL_RXM0        0x20
> #  define RXBCTRL_RXM1        0x40
> 
> /* Buffer size required for the largest SPI transfer (i.e., reading a
>  * frame). */

See general comments.

> #define CAN_FRAME_MAX_DATA_LEN        8
> #define SPI_TRANSFER_BUF_LEN  (2*(6 + CAN_FRAME_MAX_DATA_LEN))
> #define CAN_FRAME_MAX_BITS    128
> 
> #define TX_ECHO_SKB_MAX       1
> 
> #define DEVICE_NAME "mcp251x"
> 
> static int mcp251x_enable_dma; /* Enable SPI DMA. Default: 0 (Off) */
> module_param(mcp251x_enable_dma, int, S_IRUGO);
> MODULE_PARM_DESC(mcp251x_enable_dma, "Enable SPI DMA. Default: 0 (Off)");
> 
> static struct can_bittiming_const mcp251x_bittiming_const = {
>       .tseg1_min = 3,
>       .tseg1_max = 16,
>       .tseg2_min = 2,
>       .tseg2_max = 8,
>       .sjw_max = 4,
>       .brp_min = 1,
>       .brp_max = 64,
>       .brp_inc = 1,
> };
> 
> struct mcp251x_priv {
>       struct can_priv    can;
>       struct net_device *net;
>       struct spi_device *spi;
> 
>       struct mutex spi_lock; /* SPI buffer lock */
>       u8 *spi_tx_buf;
>       u8 *spi_rx_buf;
>       dma_addr_t spi_tx_dma;
>       dma_addr_t spi_rx_dma;
> 
>       struct sk_buff *tx_skb;
>       int tx_len;
>       struct workqueue_struct *wq;
>       struct work_struct tx_work;
>       struct work_struct irq_work;
>       struct completion awake;
>       int wake;
>       int force_quit;
>       int after_suspend;
> #define AFTER_SUSPEND_UP 1
> #define AFTER_SUSPEND_DOWN 2
> #define AFTER_SUSPEND_POWER 4
>       int restart_tx;
> };
> 
> static void mcp251x_clean(struct mcp251x_priv *priv)
> {
>       if (priv->tx_skb)
>               dev_kfree_skb(priv->tx_skb);
>       if (priv->tx_len)
>               can_free_echo_skb(priv->net, 0);
>       priv->tx_skb = NULL;
>       priv->tx_len = 0;
> }
> 
> /*
>   Note about handling of error return of mcp251x_spi_trans: accessing
>   registers via SPI is not really different conceptually than using
>   normal I/O assembler instructions, although it's much more
>   complicated from a practical POV. So it's not advisable to always
>   check the return value of this function. Imagine that every
>   read{b,l}, write{b,l} and friends would be bracketed in "if ( < 0)
>   error();", it would be a great mess (well there are some situation
>   when exception handling C++ like could be useful after all). So we
>   just check that transfers are OK at the beginning of our
>   conversation with the chip and to avoid doing really nasty things
>   (like injecting bogus packets in the network stack).
>  */

See general comments.

> static int mcp251x_spi_trans(struct spi_device *spi, int len)
> {
>       struct mcp251x_priv *priv = dev_get_drvdata(&spi->dev);
>       struct spi_transfer t = {
>               .tx_buf = priv->spi_tx_buf,
>               .rx_buf = priv->spi_rx_buf,
>               .len = len,
>               .cs_change = 0,
>       };
>       struct spi_message m;
>       int ret;
> 
>       spi_message_init(&m);
> 
>       if (mcp251x_enable_dma) {
>               t.tx_dma = priv->spi_tx_dma;
>               t.rx_dma = priv->spi_rx_dma;
>               m.is_dma_mapped = 1;
>       }
> 
>       spi_message_add_tail(&t, &m);
> 
>       ret = spi_sync(spi, &m);
>       if (ret < 0)
>               dev_err(&spi->dev, "%s: failed: ret = %d\n", __func__, ret);
>       return ret;
> }
> 
> static u8 mcp251x_read_reg(struct spi_device *spi, uint8_t reg)
> {
>       struct mcp251x_priv *priv = dev_get_drvdata(&spi->dev);
>       u8 val = 0;
> 
>       mutex_lock(&priv->spi_lock);
> 
>       priv->spi_tx_buf[0] = INSTRUCTION_READ;
>       priv->spi_tx_buf[1] = reg;
> 
>       mcp251x_spi_trans(spi, 3);
>       val = priv->spi_rx_buf[2];
> 
>       mutex_unlock(&priv->spi_lock);
> 
>       return val;
> }
> 
> static void mcp251x_write_reg(struct spi_device *spi, u8 reg, uint8_t val)
> {
>       struct mcp251x_priv *priv = dev_get_drvdata(&spi->dev);
> 
>       mutex_lock(&priv->spi_lock);
> 
>       priv->spi_tx_buf[0] = INSTRUCTION_WRITE;
>       priv->spi_tx_buf[1] = reg;
>       priv->spi_tx_buf[2] = val;
> 
>       mcp251x_spi_trans(spi, 3);
> 
>       mutex_unlock(&priv->spi_lock);
> }
> 
> static void mcp251x_write_bits(struct spi_device *spi, u8 reg,
>                              u8 mask, uint8_t val)
> {
>       struct mcp251x_priv *priv = dev_get_drvdata(&spi->dev);
> 
>       mutex_lock(&priv->spi_lock);
> 
>       priv->spi_tx_buf[0] = INSTRUCTION_BIT_MODIFY;
>       priv->spi_tx_buf[1] = reg;
>       priv->spi_tx_buf[2] = mask;
>       priv->spi_tx_buf[3] = val;
> 
>       mcp251x_spi_trans(spi, 4);
> 
>       mutex_unlock(&priv->spi_lock);
> }
> 
> static void mcp251x_hw_tx(struct spi_device *spi, struct can_frame *frame,
>                         int tx_buf_idx)
> {
>       struct mcp251x_platform_data *pdata = spi->dev.platform_data;
>       struct mcp251x_priv *priv = dev_get_drvdata(&spi->dev);
>       u32 sid, eid, exide, rtr;
> 
>       exide = (frame->can_id & CAN_EFF_FLAG) ? 1 : 0; /* Extended ID Enable */
>       if (exide)
>               sid = (frame->can_id & CAN_EFF_MASK) >> 18;
>       else
>               sid = frame->can_id & CAN_SFF_MASK; /* Standard ID */
>       eid = frame->can_id & CAN_EFF_MASK; /* Extended ID */
>       rtr = (frame->can_id & CAN_RTR_FLAG) ? 1 : 0; /* Remote transmission */
> 
>       if (pdata->model == CAN_MCP251X_MCP2510) {
>               int i;
> 
>               mcp251x_write_reg(spi, TXBCTRL(tx_buf_idx) + 1, sid >> 3);
>               mcp251x_write_reg(spi, TXBCTRL(tx_buf_idx) + 2,
>                                 ((sid & 7) << 5) | (exide << 3) |
>                                 ((eid >> 16) & 3));
>               mcp251x_write_reg(spi, TXBCTRL(tx_buf_idx) + 3,
>                                 (eid >> 8) & 0xff);
>               mcp251x_write_reg(spi, TXBCTRL(tx_buf_idx) + 4, eid & 0xff);
>               mcp251x_write_reg(spi, TXBCTRL(tx_buf_idx) + 5,
>                                 (rtr << 6) | frame->can_dlc);
> 
>               for (i = 0; i < frame->can_dlc ; i++) {
>                       mcp251x_write_reg(spi, TXBCTRL(tx_buf_idx) + 6 + i,
>                                         frame->data[i]);
>               }

Please remove brackets.

>       } else {
>               u8 *tx_buf = priv->spi_tx_buf;
> 
>               mutex_lock(&priv->spi_lock);
> 
>               tx_buf[0] = INSTRUCTION_LOAD_TXB(tx_buf_idx);
>               tx_buf[1] = sid >> 3;
>               tx_buf[2] = ((sid & 7) << 5) | (exide << 3) |
>                 ((eid >> 16) & 3);
>               tx_buf[3] = (eid >> 8) & 0xff;
>               tx_buf[4] = eid & 0xff;
>               tx_buf[5] = (rtr << 6) | frame->can_dlc;
> 
>               memcpy(tx_buf + 6, frame->data, frame->can_dlc);
> 
>               mcp251x_spi_trans(spi, 6 + CAN_FRAME_MAX_DATA_LEN);
> 
>               mutex_unlock(&priv->spi_lock);
>       }

I see redundant code above. What about implementing mcp251x_write_regs()
and mcp251x_read_regs() allowing to read and write successive bytes with
one SPI transfer, or many for the MCP2510. This might be used in other
places as well.

>       mcp251x_write_reg(spi, TXBCTRL(tx_buf_idx), TXBCTRL_TXREQ);
> }
> 
> static void mcp251x_hw_rx(struct spi_device *spi, int buf_idx)
> {
>       struct mcp251x_priv *priv = dev_get_drvdata(&spi->dev);
>       struct mcp251x_platform_data *pdata = spi->dev.platform_data;
>       struct sk_buff *skb;
>       struct can_frame *frame;
> 
>       skb = alloc_can_skb(priv->net, &frame);
>       if (!skb) {
>               dev_err(&spi->dev, "%s: out of memory for Rx'd frame\n",
>                       __func__);
>               priv->net->stats.rx_dropped++;
>               return;
>       }
> 
>       if (pdata->model == CAN_MCP251X_MCP2510) {
>               int i;
>               u8 rx_buf[6];
> 
>               rx_buf[1] = mcp251x_read_reg(spi, RXBCTRL(buf_idx) + 1);
>               rx_buf[2] = mcp251x_read_reg(spi, RXBCTRL(buf_idx) + 2);
>               rx_buf[3] = mcp251x_read_reg(spi, RXBCTRL(buf_idx) + 3);
>               rx_buf[4] = mcp251x_read_reg(spi, RXBCTRL(buf_idx) + 4);
>               rx_buf[5] = mcp251x_read_reg(spi, RXBCTRL(buf_idx) + 5);
> 
>               if ((rx_buf[2] >> 3) & 0x1) {
>                       /* Extended ID format */
>                       frame->can_id = CAN_EFF_FLAG;
>                       frame->can_id |= ((rx_buf[2] & 3) << 16) |
>                         (rx_buf[3] << 8) | rx_buf[4] |
>                         (((rx_buf[1] << 3) | (rx_buf[2] >> 5)) << 18);
>               } else {
>                       /* Standard ID format */
>                       frame->can_id = (rx_buf[1] << 3) | (rx_buf[2] >> 5);
>               }

Ditto. Also please use macro definitons to make the code more readable.

>               if ((rx_buf[5] >> 6) & 0x1) {
>                       /* Remote transmission request */
>                       frame->can_id |= CAN_RTR_FLAG;
>               }

Please remove brackets.

>               /* Data length */
>               frame->can_dlc = rx_buf[5] & 0x0f;
>               if (frame->can_dlc > 8) {
>                       dev_warn(&spi->dev, "invalid frame recevied\n");
>                       priv->net->stats.rx_errors++;
>                       dev_kfree_skb(skb);
>                       return;
>               }
> 
>               for (i = 0; i < frame->can_dlc; i++) {
>                       frame->data[i] = mcp251x_read_reg(spi,
>                                                         RXBCTRL(buf_idx) +
>                                                         6 + i);

Please remove brackets.

>               }
>       } else {
>               u8 *tx_buf = priv->spi_tx_buf;
>               u8 *rx_buf = priv->spi_rx_buf;
>               int ret;
> 
>               mutex_lock(&priv->spi_lock);
> 
>               tx_buf[0] = INSTRUCTION_READ_RXB(buf_idx);
> 
>               ret = mcp251x_spi_trans(spi, 14);
>               if (ret < 0) {
>                       priv->net->stats.rx_errors++;
>                       mutex_unlock(&priv->spi_lock);
>                       return;
>               }
> 
>               if ((rx_buf[2] >> 3) & 0x1) {
>                       /* Extended ID format */
>                       frame->can_id = CAN_EFF_FLAG;
>                       frame->can_id |= ((rx_buf[2] & 3) << 16) |
>                         (rx_buf[3] << 8) | rx_buf[4] |
>                         (((rx_buf[1] << 3) | (rx_buf[2] >> 5)) << 18);
>               } else {
>                       /* Standard ID format */
>                       frame->can_id = (rx_buf[1] << 3) | (rx_buf[2] >> 5);
>               }
> 
>               if ((rx_buf[5] >> 6) & 0x1) {
>                       /* Remote transmission request */
>                       frame->can_id |= CAN_RTR_FLAG;
>               }

Please remove brackets.

> 
>               /* Data length */
>               frame->can_dlc = rx_buf[5] & 0x0f;
>               if (frame->can_dlc > 8) {
>                       dev_warn(&spi->dev, "invalid frame recevied\n");
>                       priv->net->stats.rx_errors++;
>                       dev_kfree_skb(skb);
>                       mutex_unlock(&priv->spi_lock);
>                       return;
>               }
> 
>               memcpy(frame->data, rx_buf + 6, CAN_FRAME_MAX_DATA_LEN);
> 
>               mutex_unlock(&priv->spi_lock);
>       }
> 
>       priv->net->stats.rx_packets++;
>       priv->net->stats.rx_bytes += frame->can_dlc;
> 
>       netif_rx(skb);
> }
> 
> static void mcp251x_hw_sleep(struct spi_device *spi)
> {
>       mcp251x_write_reg(spi, CANCTRL, CANCTRL_REQOP_SLEEP);
> }
> 
> static void mcp251x_hw_wakeup(struct spi_device *spi)
> {
>       struct mcp251x_priv *priv = dev_get_drvdata(&spi->dev);
> 
>       priv->wake = 1;
> 
>       /* Can only wake up by generating a wake-up interrupt. */
>       mcp251x_write_bits(spi, CANINTE, CANINTE_WAKIE, CANINTE_WAKIE);
>       mcp251x_write_bits(spi, CANINTF, CANINTF_WAKIF, CANINTF_WAKIF);
> 
>       /* Wait until the device is awake */
>       if (!wait_for_completion_timeout(&priv->awake, HZ))
>               dev_err(&spi->dev, "MCP251x didn't wake-up\n");
> }
> 
> #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,32)
> static int mcp251x_hard_start_xmit(struct sk_buff *skb, struct net_device 
> *net)
> #else
> static netdev_tx_t mcp251x_hard_start_xmit(struct sk_buff *skb,
>                       struct net_device *net)
> #endif
> {
>       struct mcp251x_priv *priv = netdev_priv(net);
>       struct spi_device *spi = priv->spi;
> 
>       if (priv->tx_skb || priv->tx_len) {
>               dev_warn(&spi->dev, "hard_xmit called while tx busy\n");
>               netif_stop_queue(net);
>               return NETDEV_TX_BUSY;
>       }
> 
>       if (skb->len != sizeof(struct can_frame)) {
>               dev_err(&spi->dev, "dropping packet - bad length\n");
>               dev_kfree_skb(skb);
>               net->stats.tx_dropped++;
>               return 0;
>       }
> 
>       netif_stop_queue(net);
>       priv->tx_skb = skb;
>       net->trans_start = jiffies;
>       queue_work(priv->wq, &priv->tx_work);
> 
>       return NETDEV_TX_OK;
> }
> 
> static int mcp251x_do_set_mode(struct net_device *net, enum can_mode mode)
> {
>       struct mcp251x_priv *priv = netdev_priv(net);
> 
>       switch (mode) {
>       case CAN_MODE_START:
>               /* we have to delay work since SPI I/O may sleep */
>               priv->restart_tx = 1;
>               queue_work(priv->wq, &priv->irq_work);
>               break;
>       default:
>               return -EOPNOTSUPP;
>       }
> 
>       return 0;
> }
> 
> static void mcp251x_set_normal_mode(struct spi_device *spi)
> {
>       struct mcp251x_priv *priv = dev_get_drvdata(&spi->dev);
>       unsigned long timeout;
> 
>       /* Enable interrupts */
>       mcp251x_write_reg(spi, CANINTE,
>               CANINTE_ERRIE | CANINTE_TX2IE | CANINTE_TX1IE |
>               CANINTE_TX0IE | CANINTE_RX1IE | CANINTE_RX0IE);
> 
>       if (priv->can.ctrlmode & CAN_CTRLMODE_LOOPBACK) {
>               /* Put device into loopback mode */
>               mcp251x_write_reg(spi, CANCTRL, CANCTRL_REQOP_LOOPBACK);
>       } else {
>               /* Put device into normal mode */
>               mcp251x_write_reg(spi, CANCTRL, CANCTRL_REQOP_NORMAL);
> 
>               /* Wait for the device to enter normal mode */
>               timeout = jiffies + HZ;
>               while (mcp251x_read_reg(spi, CANSTAT) & 0xE0) {
>                       schedule();
>                       if (time_after(jiffies, timeout)) {
>                               dev_err(&spi->dev, "MCP251x didn't"
>                                       " enter in normal mode\n");
>                               return;
>                       }
>               }
>       }
>       priv->can.state = CAN_STATE_ERROR_ACTIVE;
> }
> 
> static int mcp251x_do_set_bittiming(struct net_device *net)
> {
>       struct mcp251x_priv *priv = netdev_priv(net);
>       struct can_bittiming *bt = &priv->can.bittiming;
>       struct spi_device *spi = priv->spi;
>       u8 state;
> 
>       dev_dbg(&spi->dev, "%s: BRP = %d, PropSeg = %d, PS1 = %d,"
>               " PS2 = %d, SJW = %d\n", __func__, bt->brp,
>               bt->prop_seg, bt->phase_seg1, bt->phase_seg2,
>               bt->sjw);

Just for development?

> 
>       /* Store original mode and set mode to config */
>       state = mcp251x_read_reg(spi, CANCTRL);
>       state = mcp251x_read_reg(spi, CANSTAT) & CANCTRL_REQOP_MASK;
>       mcp251x_write_bits(spi, CANCTRL, CANCTRL_REQOP_MASK,
>                          CANCTRL_REQOP_CONF);
> 
>       mcp251x_write_reg(spi, CNF1, ((bt->sjw - 1) << 6) | (bt->brp - 1));
>       mcp251x_write_reg(spi, CNF2, CNF2_BTLMODE |
>                         ((bt->phase_seg1 - 1) << 3) |
>                         (bt->prop_seg - 1));
>       mcp251x_write_bits(spi, CNF3, CNF3_PHSEG2_MASK,
>                          (bt->phase_seg2 - 1));

Is triple sampling supported?

Also, please add a dev_info("Setting CNF1=...) call.

>       /* Restore original state */
>       mcp251x_write_bits(spi, CANCTRL, CANCTRL_REQOP_MASK, state);

>       return 0;
> }
> 
> static int mcp251x_setup(struct net_device *net, struct mcp251x_priv *priv,
>                         struct spi_device *spi)
> {
>       int ret;
> 
>       /* Set initial baudrate. Make sure that registers are updated
>          always by explicitly calling mcp251x_do_set_bittiming */
>       ret = open_candev(net);
>       if (ret) {
>               dev_err(&spi->dev, "unable to set initial baudrate!\n");
>               return ret;
>       }
> 
>       /* Enable RX0->RX1 buffer roll over and disable filters */
>       mcp251x_write_bits(spi, RXBCTRL(0),
>                          RXBCTRL_BUKT | RXBCTRL_RXM0 | RXBCTRL_RXM1,
>                          RXBCTRL_BUKT | RXBCTRL_RXM0 | RXBCTRL_RXM1);
>       mcp251x_write_bits(spi, RXBCTRL(1),
>                          RXBCTRL_RXM0 | RXBCTRL_RXM1,
>                          RXBCTRL_RXM0 | RXBCTRL_RXM1);
>       return 0;
> }
> 
> static void mcp251x_hw_reset(struct spi_device *spi)
> {
>       struct mcp251x_priv *priv = dev_get_drvdata(&spi->dev);
>       int ret;
> 
>       mutex_lock(&priv->spi_lock);
> 
>       priv->spi_tx_buf[0] = INSTRUCTION_RESET;
> 
>       ret = spi_write(spi, priv->spi_tx_buf, 1);
> 
>       mutex_unlock(&priv->spi_lock);
> 
>       if (ret < 0)
>               dev_err(&spi->dev, "%s: failed: ret = %d\n", __func__, ret);
>       /* wait for reset to finish */
>       mdelay(10);
> }
> 
> static int mcp251x_hw_probe(struct spi_device *spi)
> {
>       int st1, st2;
> 
>       mcp251x_hw_reset(spi);
> 
>       st1 = mcp251x_read_reg(spi, CANSTAT) & 0xEE;
>       st2 = mcp251x_read_reg(spi, CANCTRL) & 0x17;
> 
>       dev_dbg(&spi->dev, "%s: 0x%02x - 0x%02x\n", __func__,
>               st1, st2);
> 
>       /* check for power up default values */
>       return (st1 == 0x80 && st2 == 0x07) ? 1 : 0;
> }
> 
> static int mcp251x_open(struct net_device *net)
> {
>       struct mcp251x_priv *priv = netdev_priv(net);
>       struct spi_device *spi = priv->spi;
>       struct mcp251x_platform_data *pdata = spi->dev.platform_data;
>       int ret;
> 
>       if (pdata->transceiver_enable)
>               pdata->transceiver_enable(1);

This driver also need to handle the tranceiver. And this implementation
is quite efficient.

>       priv->force_quit = 0;
>       priv->tx_skb = NULL;
>       priv->tx_len = 0;
>       enable_irq(spi->irq);
>       mcp251x_hw_wakeup(spi);
>       mcp251x_hw_reset(spi);
>       ret = mcp251x_setup(net, priv, spi);
>       if (ret < 0) {
>               disable_irq(spi->irq);
>               return ret;
>       }
>       mcp251x_set_normal_mode(spi);
>       netif_wake_queue(net);
> 
>       return 0;
> }
> 
> static int mcp251x_stop(struct net_device *net)
> {
>       struct mcp251x_priv *priv = netdev_priv(net);
>       struct spi_device *spi = priv->spi;
>       struct mcp251x_platform_data *pdata = spi->dev.platform_data;
> 
>       /* Disable and clear pending interrupts */
>       mcp251x_write_reg(spi, CANINTE, 0x00);
>       mcp251x_write_reg(spi, CANINTF, 0x00);
> 
>       priv->force_quit = 1;
>       disable_irq(spi->irq);
>       flush_workqueue(priv->wq);
> 
>       mcp251x_write_reg(spi, TXBCTRL(0), 0);
>       if (priv->tx_skb || priv->tx_len) {
>               net->stats.tx_errors++;

Do we need to increase tx_dropped as well? Could/should be done in
mcp251x_clean(). What type of TX error is that. As we don't increase
statistics, a dev_dbg message would be nice to have.

>               mcp251x_clean(priv);
>       }
> 
>       mcp251x_hw_sleep(spi);
> 
>       if (pdata->transceiver_enable)
>               pdata->transceiver_enable(0);
> 
>       priv->can.state = CAN_STATE_STOPPED;
>       close_candev(net);
> 
>       return 0;
> }
> 
> static void mcp251x_tx_work_handler(struct work_struct *ws)
> {
>       struct mcp251x_priv *priv = container_of(ws, struct mcp251x_priv,
>                                                tx_work);
>       struct spi_device *spi = priv->spi;
>       struct net_device *net = priv->net;
>       struct can_frame *frame;
> 
>       WARN_ON(!priv->tx_skb);
>       WARN_ON(priv->tx_len);
>       if (priv->tx_skb) {
>               frame = (struct can_frame *)priv->tx_skb->data;
>               if (frame->can_dlc > CAN_FRAME_MAX_DATA_LEN)
>                       frame->can_dlc = CAN_FRAME_MAX_DATA_LEN;
>               mcp251x_hw_tx(spi, frame, 0);
>               priv->tx_len = 1 + frame->can_dlc;
>               can_put_echo_skb(priv->tx_skb, net, 0);
>               priv->tx_skb = NULL;
>       }
> }
> 
> static void mcp251x_irq_work_handler(struct work_struct *ws)
> {
>       struct mcp251x_priv *priv = container_of(ws, struct mcp251x_priv,
>                                                irq_work);
>       struct spi_device *spi = priv->spi;
>       struct net_device *net = priv->net;
>       u8 intf;
>       u8 txbnctrl;
>       enum can_state new_state;
> 
>       if (priv->after_suspend) {
>               /* Wait whilst the device wakes up WARN_ON */
>               mdelay(10);
>               mcp251x_hw_reset(spi);
>               mcp251x_setup(net, priv, spi);
>               if (priv->after_suspend & AFTER_SUSPEND_UP) {
>                       netif_device_attach(net);
>                       /* clear since we lost tx buffer */
>                       if (priv->tx_skb || priv->tx_len) {
>                               net->stats.tx_errors++;
>                               mcp251x_clean(priv);
>                               netif_wake_queue(net);
>                       }
>                       mcp251x_set_normal_mode(spi);
>               } else
>                       mcp251x_hw_sleep(spi);

Please add brackets above.

>               priv->after_suspend = 0;
>               return;
>       }
> 
>       while (!priv->force_quit && !freezing(current)) {
>               if (priv->restart_tx) {
>                       priv->restart_tx = 0;
>                       dev_dbg(&spi->dev,
>                               "timeout in txing a packet, restarting\n");
>                       mcp251x_write_reg(spi, TXBCTRL(0), 0);
>                       if (priv->tx_skb || priv->tx_len) {
>                               net->stats.tx_errors++;
>                               mcp251x_clean(priv);
>                       }
>                       priv->can.can_stats.restarts++;
>                       netif_wake_queue(net);
>               }
> 
>               if (priv->wake) {
>                       /* Wait whilst the device wakes up */
>                       mdelay(10);
>                       priv->wake = 0;
>               }
> 
>               intf = mcp251x_read_reg(spi, CANINTF);
>               if (intf == 0x00)
>                       break;
>               mcp251x_write_bits(spi, CANINTF, intf, 0x00);
> 
>               if (intf & CANINTF_WAKIF)
>                       complete(&priv->awake);
> 
>               if (intf & CANINTF_MERRF) {
>                       /* if there are pending Tx buffers, restart queue */
>                       txbnctrl = mcp251x_read_reg(spi, TXBCTRL(0));
>                       if (!(txbnctrl & TXBCTRL_TXREQ)) {
>                               WARN_ON(priv->tx_skb);
>                               WARN_ON(!priv->tx_len);
>                               if (priv->tx_skb || priv->tx_len) {
>                                       net->stats.tx_errors++;
>                                       mcp251x_clean(priv);
>                               }
>                               netif_wake_queue(net);
>                       }
>               }
> 
>               if (intf & CANINTF_ERRIF) {
>                       struct sk_buff *skb;
>                       struct can_frame *frame = NULL;
>                       u8 eflag = mcp251x_read_reg(spi, EFLG);
> 
>                       /* create error frame */
>                       skb = alloc_can_err_skb(net, &frame);

An error message for !skb would be nice, like for normal messages.

>                       if (skb) {
>                               /* Set error frame flags based on bus state */
>                               if (eflag & EFLG_TXBO) {
>                                       frame->can_id |= CAN_ERR_BUSOFF;
>                               } else if (eflag & EFLG_TXEP) {
>                                       frame->can_id |= CAN_ERR_CRTL;
>                                       frame->data[1] |=
>                                         CAN_ERR_CRTL_TX_PASSIVE;
>                               } else if (eflag & EFLG_RXEP) {
>                                       frame->can_id |= CAN_ERR_CRTL;
>                                       frame->data[1] |=
>                                         CAN_ERR_CRTL_RX_PASSIVE;
>                               } else if (eflag & EFLG_TXWAR) {
>                                       frame->can_id |= CAN_ERR_CRTL;
>                                       frame->data[1] |=
>                                         CAN_ERR_CRTL_TX_WARNING;
>                               } else if (eflag & EFLG_RXWAR) {
>                                       frame->can_id |= CAN_ERR_CRTL;
>                                       frame->data[1] |=
>                                         CAN_ERR_CRTL_RX_WARNING;
>                               }
>                       }
> 
>                       /* update net stats */
>                       if (eflag & (EFLG_RX0OVR | EFLG_RX1OVR)) {
>                               if (eflag & EFLG_RX0OVR)
>                                       net->stats.rx_over_errors++;
>                               if (eflag & EFLG_RX1OVR)
>                                       net->stats.rx_over_errors++;
>                               if (frame) {
>                                       frame->can_id |= CAN_ERR_CRTL;
>                                       frame->data[1] =
>                                         CAN_ERR_CRTL_RX_OVERFLOW;
>                               }
>                       }
> 
>                       /* update can state */
>                       if (eflag & EFLG_TXBO) {
>                               new_state = CAN_STATE_BUS_OFF;
>                               can_bus_off(net);
>                       } else if (eflag & EFLG_TXEP)
>                               new_state = CAN_STATE_ERROR_PASSIVE;
>                       else if (eflag & EFLG_RXEP)
>                               new_state = CAN_STATE_ERROR_PASSIVE;
>                       else if (eflag & EFLG_TXWAR)
>                               new_state = CAN_STATE_ERROR_WARNING;
>                       else if (eflag & EFLG_RXWAR)
>                               new_state = CAN_STATE_ERROR_WARNING;
>                       else
>                               new_state = CAN_STATE_ERROR_ACTIVE;

Any effort to make the error code handling more compact would be nice.
E.g., this if block could be combined with the above one using a temp.
variable data1. Then: if (skb && data1) {frame->data[1] = data1, ...}

>                       mcp251x_write_reg(spi, EFLG, 0x00);
> 
>                       if (skb)
>                               netif_rx(skb);
>               } else
>                       new_state = CAN_STATE_ERROR_ACTIVE;
> 
>               /* update can state statistics */
>               switch (priv->can.state) {
>               case CAN_STATE_ERROR_ACTIVE:
>                       if (new_state >= CAN_STATE_ERROR_WARNING &&
>                           new_state <= CAN_STATE_BUS_OFF)
>                               priv->can.can_stats.error_warning++;
>               case CAN_STATE_ERROR_WARNING:   /* fallthrough */
>                       if (new_state >= CAN_STATE_ERROR_PASSIVE &&
>                           new_state <= CAN_STATE_BUS_OFF)
>                               priv->can.can_stats.error_passive++;
>                       break;
>               case CAN_STATE_BUS_OFF:
>                       if (new_state <= CAN_STATE_ERROR_PASSIVE)
>                               netif_carrier_on(net);

In case of automatice bus-off recovery, a RESTARTED error message should
be created (frame->can_id |= CAN_ERR_RESTARTED).

>                       break;
>               default:
>                       break;
>               }

>               priv->can.state = new_state;
> 
>               if (intf & (CANINTF_TX2IF | CANINTF_TX1IF | CANINTF_TX0IF)) {
>                       net->stats.tx_packets++;
>                       net->stats.tx_bytes += priv->tx_len - 1;
>                       WARN_ON(priv->tx_skb);
>                       WARN_ON(!priv->tx_len);
>                       if (priv->tx_len) {
>                               can_get_echo_skb(net, 0);
>                               priv->tx_len = 0;
>                       }
>                       mcp251x_clean(priv);
>                       netif_wake_queue(net);
>               }
> 
>               if (intf & CANINTF_RX0IF)
>                       mcp251x_hw_rx(spi, 0);
> 
>               if (intf & CANINTF_RX1IF)
>                       mcp251x_hw_rx(spi, 1);
> 
>       }
> 
>       mcp251x_read_reg(spi, CANSTAT);
> }
> 
> static irqreturn_t mcp251x_can_isr(int irq, void *dev_id)
> {
>       struct net_device *net = (struct net_device *)dev_id;
>       struct mcp251x_priv *priv = netdev_priv(net);
> 
>       /* Schedule bottom half */
>       if (!work_pending(&priv->irq_work))
>               queue_work(priv->wq, &priv->irq_work);
> 
>       return IRQ_HANDLED;
> }
> 
> #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,28)
> static const struct net_device_ops mcp251x_netdev_ops = {
>       .ndo_open       = mcp251x_open,
>       .ndo_stop       = mcp251x_stop,
>       .ndo_start_xmit = mcp251x_hard_start_xmit,
> };
> #endif
> 
> static struct net_device *alloc_mcp251x_netdev(int sizeof_priv,
>                               struct mcp251x_platform_data *pdata)
> {
>       struct net_device *net;
>       struct mcp251x_priv *priv;
> 
>       net = alloc_candev(sizeof_priv, TX_ECHO_SKB_MAX);
>       if (!net)
>               return NULL;
> 
>       priv = netdev_priv(net);
> 
> #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,28)
>       net->netdev_ops         = &mcp251x_netdev_ops;
> #else
>       net->open               = mcp251x_open;
>       net->stop               = mcp251x_stop;
>       net->hard_start_xmit    = mcp251x_hard_start_xmit;
> #endif
>       net->flags              |= IFF_ECHO;
> 
>       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.do_set_bittiming      = mcp251x_do_set_bittiming;
> 
>       priv->net = net;
> 
>       return net;
> }
> 
> static int __devinit mcp251x_can_probe(struct spi_device *spi)
> {
>       struct net_device *net;
>       struct mcp251x_priv *priv;
>       struct mcp251x_platform_data *pdata = spi->dev.platform_data;
>       int ret = -ENODEV;
> 
>       if (!pdata) {
>               /* Platform data is required for osc freq */
>               goto error_out;
>       }
> 
>       /* Allocate can/net device */
>       net = alloc_mcp251x_netdev(sizeof(struct mcp251x_priv), pdata);
>       if (!net) {
>               ret = -ENOMEM;
>               goto error_alloc;
>       }
> 
>       priv = netdev_priv(net);
>       dev_set_drvdata(&spi->dev, priv);
> 
>       priv->spi = spi;
>       mutex_init(&priv->spi_lock);
> 
>       /* If requested, allocate DMA buffers */
>       if (mcp251x_enable_dma) {
>               spi->dev.coherent_dma_mask = DMA_32BIT_MASK;
> 
>               /* Minimum coherent DMA allocation is PAGE_SIZE, so allocate
>                  that much and share it between Tx and Rx DMA buffers. */
>               priv->spi_tx_buf = dma_alloc_coherent(&spi->dev,
>                       PAGE_SIZE, &priv->spi_tx_dma, GFP_DMA);
> 
>               if (priv->spi_tx_buf) {
>                       priv->spi_rx_buf = (u8 *)(priv->spi_tx_buf +
>                               (PAGE_SIZE / 2));
>                       priv->spi_rx_dma = (dma_addr_t)(priv->spi_tx_dma +
>                               (PAGE_SIZE / 2));
>               } else {
>                       /* Fall back to non-DMA */
>                       mcp251x_enable_dma = 0;
>               }
>       }
> 
>       /* Allocate non-DMA buffers */
>       if (!mcp251x_enable_dma) {
>               priv->spi_tx_buf = kmalloc(SPI_TRANSFER_BUF_LEN, GFP_KERNEL);
>               if (!priv->spi_tx_buf) {
>                       ret = -ENOMEM;
>                       goto error_tx_buf;
>               }
>               priv->spi_rx_buf = kmalloc(SPI_TRANSFER_BUF_LEN, GFP_KERNEL);
>               if (!priv->spi_tx_buf) {
>                       ret = -ENOMEM;
>                       goto error_rx_buf;
>               }
>       }
> 
>       if (pdata->power_enable)
>               pdata->power_enable(1);
> 
>       /* Call out to platform specific setup */
>       if (pdata->board_specific_setup)
>               pdata->board_specific_setup(spi);
> 
>       SET_NETDEV_DEV(net, &spi->dev);
> 
>       priv->wq = create_freezeable_workqueue("mcp251x_wq");
> 
>       INIT_WORK(&priv->tx_work, mcp251x_tx_work_handler);
>       INIT_WORK(&priv->irq_work, mcp251x_irq_work_handler);
> 
>       init_completion(&priv->awake);
> 
>       /* Configure the SPI bus */
>       spi->mode = SPI_MODE_0;
>       spi->bits_per_word = 8;
>       spi_setup(spi);
> 
>       /* Register IRQ */
>       if (request_irq(spi->irq, mcp251x_can_isr,
>                       IRQF_TRIGGER_FALLING, DEVICE_NAME, net) < 0) {
>               dev_err(&spi->dev, "failed to acquire irq %d\n", spi->irq);
>               goto error_irq;
>       }

Please return the error code of request_irq() in case of error. Also,
consider requesting the irq in the open function (and free it in the
stop function.

Wolfgang.
_______________________________________________
Socketcan-core mailing list
[email protected]
https://lists.berlios.de/mailman/listinfo/socketcan-core

Reply via email to