can: Proper ctrlmode handling for CAN devices
[safe/jmp/linux-2.6] / drivers / net / can / ti_hecc.c
index 814e6c5..8332e24 100644 (file)
@@ -74,10 +74,6 @@ MODULE_VERSION(HECC_MODULE_VERSION);
 #define HECC_MB_TX_SHIFT       2 /* as per table above */
 #define HECC_MAX_TX_MBOX       BIT(HECC_MB_TX_SHIFT)
 
-#if (HECC_MAX_TX_MBOX > CAN_ECHO_SKB_MAX)
-#error "HECC: MAX TX mailboxes should be equal or less than CAN_ECHO_SKB_MAX"
-#endif
-
 #define HECC_TX_PRIO_SHIFT     (HECC_MB_TX_SHIFT)
 #define HECC_TX_PRIO_MASK      (MAX_TX_PRIO << HECC_MB_TX_SHIFT)
 #define HECC_TX_MB_MASK                (HECC_MAX_TX_MBOX - 1)
@@ -481,6 +477,9 @@ static netdev_tx_t ti_hecc_xmit(struct sk_buff *skb, struct net_device *ndev)
        u32 mbxno, mbx_mask, data;
        unsigned long flags;
 
+       if (can_dropped_invalid_skb(ndev, skb))
+               return NETDEV_TX_OK;
+
        mbxno = get_tx_head_mb(priv);
        mbx_mask = BIT(mbxno);
        spin_lock_irqsave(&priv->mbx_lock, flags);
@@ -495,7 +494,6 @@ static netdev_tx_t ti_hecc_xmit(struct sk_buff *skb, struct net_device *ndev)
        spin_unlock_irqrestore(&priv->mbx_lock, flags);
 
        /* Prepare mailbox for transmission */
-       data = min_t(u8, cf->can_dlc, 8);
        if (cf->can_id & CAN_RTR_FLAG) /* Remote transmission request */
                data |= HECC_CANMCF_RTR;
        data |= get_tx_head_prio(priv) << 8;
@@ -539,18 +537,15 @@ static int ti_hecc_rx_pkt(struct ti_hecc_priv *priv, int mbxno)
        u32 data, mbx_mask;
        unsigned long flags;
 
-       skb = netdev_alloc_skb(priv->ndev, sizeof(struct can_frame));
+       skb = alloc_can_skb(priv->ndev, &cf);
        if (!skb) {
                if (printk_ratelimit())
                        dev_err(priv->ndev->dev.parent,
-                               "ti_hecc_rx_pkt: netdev_alloc_skb() failed\n");
+                               "ti_hecc_rx_pkt: alloc_can_skb() failed\n");
                return -ENOMEM;
        }
-       skb->protocol = __constant_htons(ETH_P_CAN);
-       skb->ip_summed = CHECKSUM_UNNECESSARY;
 
        mbx_mask = BIT(mbxno);
-       cf = (struct can_frame *)skb_put(skb, sizeof(struct can_frame));
        data = hecc_read_mbx(priv, mbxno, HECC_CANMID);
        if (data & HECC_CANMID_IDE)
                cf->can_id = (data & CAN_EFF_MASK) | CAN_EFF_FLAG;
@@ -559,7 +554,7 @@ static int ti_hecc_rx_pkt(struct ti_hecc_priv *priv, int mbxno)
        data = hecc_read_mbx(priv, mbxno, HECC_CANMCF);
        if (data & HECC_CANMCF_RTR)
                cf->can_id |= CAN_RTR_FLAG;
-       cf->can_dlc = data & 0xF;
+       cf->can_dlc = get_can_dlc(data & 0xF);
        data = hecc_read_mbx(priv, mbxno, HECC_CANMDL);
        *(u32 *)(cf->data) = cpu_to_be32(data);
        if (cf->can_dlc > 4) {
@@ -660,19 +655,13 @@ static int ti_hecc_error(struct net_device *ndev, int int_status,
        struct sk_buff *skb;
 
        /* propogate the error condition to the can stack */
-       skb = netdev_alloc_skb(ndev, sizeof(struct can_frame));
+       skb = alloc_can_err_skb(ndev, &cf);
        if (!skb) {
                if (printk_ratelimit())
                        dev_err(priv->ndev->dev.parent,
-                               "ti_hecc_error: netdev_alloc_skb() failed\n");
+                               "ti_hecc_error: alloc_can_err_skb() failed\n");
                return -ENOMEM;
        }
-       skb->protocol = __constant_htons(ETH_P_CAN);
-       skb->ip_summed = CHECKSUM_UNNECESSARY;
-       cf = (struct can_frame *)skb_put(skb, sizeof(struct can_frame));
-       memset(cf, 0, sizeof(struct can_frame));
-       cf->can_id = CAN_ERR_FLAG;
-       cf->can_dlc = CAN_ERR_DLC;
 
        if (int_status & HECC_CANGIF_WLIF) { /* warning level int */
                if ((int_status & HECC_CANGIF_BOIF) == 0) {
@@ -902,7 +891,7 @@ static int ti_hecc_probe(struct platform_device *pdev)
                goto probe_exit_free_region;
        }
 
-       ndev = alloc_candev(sizeof(struct ti_hecc_priv));
+       ndev = alloc_candev(sizeof(struct ti_hecc_priv), HECC_MAX_TX_MBOX);
        if (!ndev) {
                dev_err(&pdev->dev, "alloc_candev failed\n");
                err = -ENOMEM;
@@ -920,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;