/* handle uCAN overrun message */ static int pcan_usb_fd_decode_overrun(struct pcan_usb_fd_if *usb_if, struct pucan_msg *rx_msg) { struct pcan_ufd_ovr_msg *ov = (struct pcan_ufd_ovr_msg *)rx_msg; struct peak_usb_device *dev = usb_if->dev[pufd_omsg_get_channel(ov)]; struct net_device *netdev = dev->netdev; struct can_frame *cf; struct sk_buff *skb; /* allocate an skb to store the error frame */ skb = alloc_can_err_skb(netdev, &cf); if (!skb) return -ENOMEM; cf->can_id |= CAN_ERR_CRTL; cf->data[1] |= CAN_ERR_CRTL_RX_OVERFLOW; peak_usb_netif_rx(skb, &usb_if->time_ref, le32_to_cpu(ov->ts_low), le32_to_cpu(ov->ts_high)); netdev->stats.rx_over_errors++; netdev->stats.rx_errors++; return 0; }
static void c_can_handle_lost_msg_obj(struct net_device *dev, int iface, int objno) { struct c_can_priv *priv = netdev_priv(dev); struct net_device_stats *stats = &dev->stats; struct sk_buff *skb; struct can_frame *frame; netdev_err(dev, "msg lost in buffer %d\n", objno); c_can_object_get(dev, iface, objno, IF_COMM_ALL & ~IF_COMM_TXRQST); priv->write_reg(priv, C_CAN_IFACE(MSGCTRL_REG, iface), IF_MCONT_CLR_MSGLST); c_can_object_put(dev, 0, objno, IF_COMM_CONTROL); /* create an error msg */ skb = alloc_can_err_skb(dev, &frame); if (unlikely(!skb)) return; frame->can_id |= CAN_ERR_CRTL; frame->data[1] = CAN_ERR_CRTL_RX_OVERFLOW; stats->rx_errors++; stats->rx_over_errors++; netif_receive_skb(skb); }
static int c_can_handle_lost_msg_obj(struct net_device *dev, int iface, int objno, u32 ctrl) { struct net_device_stats *stats = &dev->stats; struct c_can_priv *priv = netdev_priv(dev); struct can_frame *frame; struct sk_buff *skb; ctrl &= ~(IF_MCONT_MSGLST | IF_MCONT_INTPND | IF_MCONT_NEWDAT); priv->write_reg(priv, C_CAN_IFACE(MSGCTRL_REG, iface), ctrl); c_can_object_put(dev, iface, objno, IF_COMM_CONTROL); stats->rx_errors++; stats->rx_over_errors++; /* create an error msg */ skb = alloc_can_err_skb(dev, &frame); if (unlikely(!skb)) return 0; frame->can_id |= CAN_ERR_CRTL; frame->data[1] = CAN_ERR_CRTL_RX_OVERFLOW; netif_receive_skb(skb); return 1; }
/* handle uCAN status message */ static int pcan_usb_fd_decode_status(struct pcan_usb_fd_if *usb_if, struct pucan_msg *rx_msg) { struct pucan_status_msg *sm = (struct pucan_status_msg *)rx_msg; struct peak_usb_device *dev = usb_if->dev[pucan_stmsg_get_channel(sm)]; struct pcan_usb_fd_device *pdev = container_of(dev, struct pcan_usb_fd_device, dev); enum can_state new_state = CAN_STATE_ERROR_ACTIVE; enum can_state rx_state, tx_state; struct net_device *netdev = dev->netdev; struct can_frame *cf; struct sk_buff *skb; /* nothing should be sent while in BUS_OFF state */ if (dev->can.state == CAN_STATE_BUS_OFF) return 0; if (sm->channel_p_w_b & PUCAN_BUS_BUSOFF) { new_state = CAN_STATE_BUS_OFF; } else if (sm->channel_p_w_b & PUCAN_BUS_PASSIVE) { new_state = CAN_STATE_ERROR_PASSIVE; } else if (sm->channel_p_w_b & PUCAN_BUS_WARNING) { new_state = CAN_STATE_ERROR_WARNING; } else { /* no error bit (so, no error skb, back to active state) */ dev->can.state = CAN_STATE_ERROR_ACTIVE; pdev->bec.txerr = 0; pdev->bec.rxerr = 0; return 0; } /* state hasn't changed */ if (new_state == dev->can.state) return 0; /* handle bus state change */ tx_state = (pdev->bec.txerr >= pdev->bec.rxerr) ? new_state : 0; rx_state = (pdev->bec.txerr <= pdev->bec.rxerr) ? new_state : 0; /* allocate an skb to store the error frame */ skb = alloc_can_err_skb(netdev, &cf); if (skb) can_change_state(netdev, cf, tx_state, rx_state); /* things must be done even in case of OOM */ if (new_state == CAN_STATE_BUS_OFF) can_bus_off(netdev); if (!skb) return -ENOMEM; peak_usb_netif_rx(skb, &usb_if->time_ref, le32_to_cpu(sm->ts_low), le32_to_cpu(sm->ts_high)); netdev->stats.rx_packets++; netdev->stats.rx_bytes += cf->can_dlc; return 0; }
static int omapl_pru_can_err(struct net_device *ndev, int int_status, int err_status) { struct omapl_pru_can_priv *priv = netdev_priv(ndev); struct net_device_stats *stats = &ndev->stats; struct can_frame *cf; struct sk_buff *skb; int tx_err_cnt, rx_err_cnt; /* propogate the error condition to the can stack */ skb = alloc_can_err_skb(ndev, &cf); if (!skb) { if (printk_ratelimit()) dev_err(priv->ndev->dev.parent, "omapl_pru_can_err: alloc_can_err_skb() failed\n"); return -ENOMEM; } if (err_status & PRU_CAN_GSR_BIT_EPM) { /* error passive int */ priv->can.state = CAN_STATE_ERROR_PASSIVE; ++priv->can.can_stats.error_passive; cf->can_id |= CAN_ERR_CRTL; tx_err_cnt = pru_can_get_error_cnt(CAN_TX_PRU_1); rx_err_cnt = pru_can_get_error_cnt(CAN_RX_PRU_0); if (tx_err_cnt > 127) cf->data[1] |= CAN_ERR_CRTL_TX_PASSIVE; if (rx_err_cnt > 127) cf->data[1] |= CAN_ERR_CRTL_RX_PASSIVE; dev_dbg(priv->ndev->dev.parent, "Error passive interrupt\n"); } if (err_status & PRU_CAN_GSR_BIT_BFM) { priv->can.state = CAN_STATE_BUS_OFF; cf->can_id |= CAN_ERR_BUSOFF; /* * Disable all interrupts in bus-off to avoid int hog * this should be handled by the pru */ pru_can_mask_ints(0xFFFF); can_bus_off(ndev); dev_dbg(priv->ndev->dev.parent, "Bus off mode\n"); } netif_rx(skb); stats->rx_packets++; stats->rx_bytes += cf->can_dlc; return 0; }
/* * CAN device restart for bus-off recovery */ void can_restart(unsigned long data) { struct net_device *dev = (struct net_device *)data; struct can_priv *priv = netdev_priv(dev); struct net_device_stats *stats = &dev->stats; struct sk_buff *skb; struct can_frame *cf; int err; BUG_ON(netif_carrier_ok(dev)); /* * No synchronization needed because the device is bus-off and * no messages can come in or go out. */ can_flush_echo_skb(dev); /* send restart message upstream */ skb = alloc_can_err_skb(dev, &cf); if (skb == NULL) { err = -ENOMEM; goto restart; } cf->can_id |= CAN_ERR_RESTARTED; netif_rx(skb); stats->rx_packets++; stats->rx_bytes += cf->can_dlc; restart: dev_dbg(dev->dev.parent, "restarted\n"); priv->can_stats.restarts++; /* Now restart the device */ err = priv->do_set_mode(dev, CAN_MODE_START); netif_carrier_on(dev); if (err) dev_err(dev->dev.parent, "Error %d during restart", err); }
void can_restart(unsigned long data) { struct net_device *dev = (struct net_device *)data; struct can_priv *priv = netdev_priv(dev); struct net_device_stats *stats = &dev->stats; struct sk_buff *skb; struct can_frame *cf; int err; BUG_ON(netif_carrier_ok(dev)); can_flush_echo_skb(dev); skb = alloc_can_err_skb(dev, &cf); if (skb == NULL) { err = -ENOMEM; goto restart; } cf->can_id |= CAN_ERR_RESTARTED; netif_rx(skb); stats->rx_packets++; stats->rx_bytes += cf->can_dlc; restart: netdev_dbg(dev, "restarted\n"); priv->can_stats.restarts++; err = priv->do_set_mode(dev, CAN_MODE_START); netif_carrier_on(dev); if (err) netdev_err(dev, "Error %d during restart", err); }
/* Send close command to device */ static int usb_8dev_cmd_close(struct usb_8dev_priv *priv) { struct usb_8dev_cmd_msg inmsg; struct usb_8dev_cmd_msg outmsg = { .channel = 0, .command = USB_8DEV_CLOSE, .opt1 = 0, .opt2 = 0 }; return usb_8dev_send_cmd(priv, &outmsg, &inmsg); } /* Get firmware and hardware version */ static int usb_8dev_cmd_version(struct usb_8dev_priv *priv, u32 *res) { struct usb_8dev_cmd_msg inmsg; struct usb_8dev_cmd_msg outmsg = { .channel = 0, .command = USB_8DEV_GET_SOFTW_HARDW_VER, .opt1 = 0, .opt2 = 0 }; int err = usb_8dev_send_cmd(priv, &outmsg, &inmsg); if (err) return err; *res = be32_to_cpup((__be32 *)inmsg.data); return err; } /* Set network device mode * * Maybe we should leave this function empty, because the device * set mode variable with open command. */ static int usb_8dev_set_mode(struct net_device *netdev, enum can_mode mode) { struct usb_8dev_priv *priv = netdev_priv(netdev); int err = 0; switch (mode) { case CAN_MODE_START: err = usb_8dev_cmd_open(priv); if (err) netdev_warn(netdev, "couldn't start device"); break; default: return -EOPNOTSUPP; } return err; } /* Read error/status frames */ static void usb_8dev_rx_err_msg(struct usb_8dev_priv *priv, struct usb_8dev_rx_msg *msg) { struct can_frame *cf; struct sk_buff *skb; struct net_device_stats *stats = &priv->netdev->stats; /* Error message: * byte 0: Status * byte 1: bit 7: Receive Passive * byte 1: bit 0-6: Receive Error Counter * byte 2: Transmit Error Counter * byte 3: Always 0 (maybe reserved for future use) */ u8 state = msg->data[0]; u8 rxerr = msg->data[1] & USB_8DEV_RP_MASK; u8 txerr = msg->data[2]; int rx_errors = 0; int tx_errors = 0; skb = alloc_can_err_skb(priv->netdev, &cf); if (!skb) return; switch (state) { case USB_8DEV_STATUSMSG_OK: priv->can.state = CAN_STATE_ERROR_ACTIVE; cf->can_id |= CAN_ERR_PROT; cf->data[2] = CAN_ERR_PROT_ACTIVE; break; case USB_8DEV_STATUSMSG_BUSOFF: priv->can.state = CAN_STATE_BUS_OFF; cf->can_id |= CAN_ERR_BUSOFF; can_bus_off(priv->netdev); break; case USB_8DEV_STATUSMSG_OVERRUN: case USB_8DEV_STATUSMSG_BUSLIGHT: case USB_8DEV_STATUSMSG_BUSHEAVY: cf->can_id |= CAN_ERR_CRTL; break; default: priv->can.state = CAN_STATE_ERROR_WARNING; cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR; priv->can.can_stats.bus_error++; break; } switch (state) { case USB_8DEV_STATUSMSG_OK: case USB_8DEV_STATUSMSG_BUSOFF: break; case USB_8DEV_STATUSMSG_ACK: cf->can_id |= CAN_ERR_ACK; tx_errors = 1; break; case USB_8DEV_STATUSMSG_CRC: cf->data[2] |= CAN_ERR_PROT_UNSPEC; cf->data[3] |= CAN_ERR_PROT_LOC_CRC_SEQ | CAN_ERR_PROT_LOC_CRC_DEL; rx_errors = 1; break; case USB_8DEV_STATUSMSG_BIT0: cf->data[2] |= CAN_ERR_PROT_BIT0; tx_errors = 1; break; case USB_8DEV_STATUSMSG_BIT1: cf->data[2] |= CAN_ERR_PROT_BIT1; tx_errors = 1; break; case USB_8DEV_STATUSMSG_FORM: cf->data[2] |= CAN_ERR_PROT_FORM; rx_errors = 1; break; case USB_8DEV_STATUSMSG_STUFF: cf->data[2] |= CAN_ERR_PROT_STUFF; rx_errors = 1; break; case USB_8DEV_STATUSMSG_OVERRUN: cf->data[1] = CAN_ERR_CRTL_RX_OVERFLOW; stats->rx_over_errors++; rx_errors = 1; break; case USB_8DEV_STATUSMSG_BUSLIGHT: priv->can.state = CAN_STATE_ERROR_WARNING; cf->data[1] = (txerr > rxerr) ? CAN_ERR_CRTL_TX_WARNING : CAN_ERR_CRTL_RX_WARNING; priv->can.can_stats.error_warning++; break; case USB_8DEV_STATUSMSG_BUSHEAVY: priv->can.state = CAN_STATE_ERROR_PASSIVE; cf->data[1] = (txerr > rxerr) ? CAN_ERR_CRTL_TX_PASSIVE : CAN_ERR_CRTL_RX_PASSIVE; priv->can.can_stats.error_passive++; break; default: netdev_warn(priv->netdev, "Unknown status/error message (%d)\n", state); break; } if (tx_errors) { cf->data[2] |= CAN_ERR_PROT_TX; stats->tx_errors++; } if (rx_errors) stats->rx_errors++; cf->data[6] = txerr; cf->data[7] = rxerr; priv->bec.txerr = txerr; priv->bec.rxerr = rxerr; netif_rx(skb); stats->rx_packets++; stats->rx_bytes += cf->can_dlc; } /* Read data and status frames */ static void usb_8dev_rx_can_msg(struct usb_8dev_priv *priv, struct usb_8dev_rx_msg *msg) { struct can_frame *cf; struct sk_buff *skb; struct net_device_stats *stats = &priv->netdev->stats; if (msg->type == USB_8DEV_TYPE_ERROR_FRAME && msg->flags == USB_8DEV_ERR_FLAG) { usb_8dev_rx_err_msg(priv, msg); } else if (msg->type == USB_8DEV_TYPE_CAN_FRAME) { skb = alloc_can_skb(priv->netdev, &cf); if (!skb) return; cf->can_id = be32_to_cpu(msg->id); cf->can_dlc = get_can_dlc(msg->dlc & 0xF); if (msg->flags & USB_8DEV_EXTID) cf->can_id |= CAN_EFF_FLAG; if (msg->flags & USB_8DEV_RTR) cf->can_id |= CAN_RTR_FLAG; else memcpy(cf->data, msg->data, cf->can_dlc); netif_rx(skb); stats->rx_packets++; stats->rx_bytes += cf->can_dlc; can_led_event(priv->netdev, CAN_LED_EVENT_RX); } else { netdev_warn(priv->netdev, "frame type %d unknown", msg->type); } } /* Callback for reading data from device * * Check urb status, call read function and resubmit urb read operation. */ static void usb_8dev_read_bulk_callback(struct urb *urb) { struct usb_8dev_priv *priv = urb->context; struct net_device *netdev; int retval; int pos = 0; netdev = priv->netdev; if (!netif_device_present(netdev)) return; switch (urb->status) { case 0: /* success */ break; case -ENOENT: case -ESHUTDOWN: return; default: netdev_info(netdev, "Rx URB aborted (%d)\n", urb->status); goto resubmit_urb; } while (pos < urb->actual_length) { struct usb_8dev_rx_msg *msg; if (pos + sizeof(struct usb_8dev_rx_msg) > urb->actual_length) { netdev_err(priv->netdev, "format error\n"); break; } msg = (struct usb_8dev_rx_msg *)(urb->transfer_buffer + pos); usb_8dev_rx_can_msg(priv, msg); pos += sizeof(struct usb_8dev_rx_msg); } resubmit_urb: usb_fill_bulk_urb(urb, priv->udev, usb_rcvbulkpipe(priv->udev, USB_8DEV_ENDP_DATA_RX), urb->transfer_buffer, RX_BUFFER_SIZE, usb_8dev_read_bulk_callback, priv); retval = usb_submit_urb(urb, GFP_ATOMIC); if (retval == -ENODEV) netif_device_detach(netdev); else if (retval) netdev_err(netdev, "failed resubmitting read bulk urb: %d\n", retval); } /* Callback handler for write operations * * Free allocated buffers, check transmit status and * calculate statistic. */ static void usb_8dev_write_bulk_callback(struct urb *urb) { struct usb_8dev_tx_urb_context *context = urb->context; struct usb_8dev_priv *priv; struct net_device *netdev; BUG_ON(!context); priv = context->priv; netdev = priv->netdev; /* free up our allocated buffer */ usb_free_coherent(urb->dev, urb->transfer_buffer_length, urb->transfer_buffer, urb->transfer_dma); atomic_dec(&priv->active_tx_urbs); if (!netif_device_present(netdev)) return; if (urb->status) netdev_info(netdev, "Tx URB aborted (%d)\n", urb->status); netdev->stats.tx_packets++; netdev->stats.tx_bytes += context->dlc; can_get_echo_skb(netdev, context->echo_index); can_led_event(netdev, CAN_LED_EVENT_TX); /* Release context */ context->echo_index = MAX_TX_URBS; netif_wake_queue(netdev); } /* Send data to device */ static netdev_tx_t usb_8dev_start_xmit(struct sk_buff *skb, struct net_device *netdev) { struct usb_8dev_priv *priv = netdev_priv(netdev); struct net_device_stats *stats = &netdev->stats; struct can_frame *cf = (struct can_frame *) skb->data; struct usb_8dev_tx_msg *msg; struct urb *urb; struct usb_8dev_tx_urb_context *context = NULL; u8 *buf; int i, err; size_t size = sizeof(struct usb_8dev_tx_msg); if (can_dropped_invalid_skb(netdev, skb)) return NETDEV_TX_OK; /* create a URB, and a buffer for it, and copy the data to the URB */ urb = usb_alloc_urb(0, GFP_ATOMIC); if (!urb) { netdev_err(netdev, "No memory left for URBs\n"); goto nomem; } buf = usb_alloc_coherent(priv->udev, size, GFP_ATOMIC, &urb->transfer_dma); if (!buf) { netdev_err(netdev, "No memory left for USB buffer\n"); goto nomembuf; } memset(buf, 0, size); msg = (struct usb_8dev_tx_msg *)buf; msg->begin = USB_8DEV_DATA_START; msg->flags = 0x00; if (cf->can_id & CAN_RTR_FLAG) msg->flags |= USB_8DEV_RTR; if (cf->can_id & CAN_EFF_FLAG) msg->flags |= USB_8DEV_EXTID; msg->id = cpu_to_be32(cf->can_id & CAN_ERR_MASK); msg->dlc = cf->can_dlc; memcpy(msg->data, cf->data, cf->can_dlc); msg->end = USB_8DEV_DATA_END; for (i = 0; i < MAX_TX_URBS; i++) { if (priv->tx_contexts[i].echo_index == MAX_TX_URBS) { context = &priv->tx_contexts[i]; break; } } /* May never happen! When this happens we'd more URBs in flight as * allowed (MAX_TX_URBS). */ if (!context) goto nofreecontext; context->priv = priv; context->echo_index = i; context->dlc = cf->can_dlc; usb_fill_bulk_urb(urb, priv->udev, usb_sndbulkpipe(priv->udev, USB_8DEV_ENDP_DATA_TX), buf, size, usb_8dev_write_bulk_callback, context); urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; usb_anchor_urb(urb, &priv->tx_submitted); can_put_echo_skb(skb, netdev, context->echo_index); atomic_inc(&priv->active_tx_urbs); err = usb_submit_urb(urb, GFP_ATOMIC); if (unlikely(err)) goto failed; else if (atomic_read(&priv->active_tx_urbs) >= MAX_TX_URBS) /* Slow down tx path */ netif_stop_queue(netdev); /* Release our reference to this URB, the USB core will eventually free * it entirely. */ usb_free_urb(urb); return NETDEV_TX_OK; nofreecontext: usb_free_coherent(priv->udev, size, buf, urb->transfer_dma); usb_free_urb(urb); netdev_warn(netdev, "couldn't find free context"); return NETDEV_TX_BUSY; failed: can_free_echo_skb(netdev, context->echo_index); usb_unanchor_urb(urb); usb_free_coherent(priv->udev, size, buf, urb->transfer_dma); atomic_dec(&priv->active_tx_urbs); if (err == -ENODEV) netif_device_detach(netdev); else netdev_warn(netdev, "failed tx_urb %d\n", err); nomembuf: usb_free_urb(urb); nomem: dev_kfree_skb(skb); stats->tx_dropped++; return NETDEV_TX_OK; } static int usb_8dev_get_berr_counter(const struct net_device *netdev, struct can_berr_counter *bec) { struct usb_8dev_priv *priv = netdev_priv(netdev); bec->txerr = priv->bec.txerr; bec->rxerr = priv->bec.rxerr; return 0; } /* Start USB device */ static int usb_8dev_start(struct usb_8dev_priv *priv) { struct net_device *netdev = priv->netdev; int err, i; for (i = 0; i < MAX_RX_URBS; i++) { struct urb *urb = NULL; u8 *buf; /* create a URB, and a buffer for it */ urb = usb_alloc_urb(0, GFP_KERNEL); if (!urb) { netdev_err(netdev, "No memory left for URBs\n"); err = -ENOMEM; break; } buf = usb_alloc_coherent(priv->udev, RX_BUFFER_SIZE, GFP_KERNEL, &urb->transfer_dma); if (!buf) { netdev_err(netdev, "No memory left for USB buffer\n"); usb_free_urb(urb); err = -ENOMEM; break; } usb_fill_bulk_urb(urb, priv->udev, usb_rcvbulkpipe(priv->udev, USB_8DEV_ENDP_DATA_RX), buf, RX_BUFFER_SIZE, usb_8dev_read_bulk_callback, priv); urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; usb_anchor_urb(urb, &priv->rx_submitted); err = usb_submit_urb(urb, GFP_KERNEL); if (err) { usb_unanchor_urb(urb); usb_free_coherent(priv->udev, RX_BUFFER_SIZE, buf, urb->transfer_dma); usb_free_urb(urb); break; } /* Drop reference, USB core will take care of freeing it */ usb_free_urb(urb); } /* Did we submit any URBs */ if (i == 0) { netdev_warn(netdev, "couldn't setup read URBs\n"); return err; } /* Warn if we've couldn't transmit all the URBs */ if (i < MAX_RX_URBS) netdev_warn(netdev, "rx performance may be slow\n"); err = usb_8dev_cmd_open(priv); if (err) goto failed; priv->can.state = CAN_STATE_ERROR_ACTIVE; return 0; failed: if (err == -ENODEV) netif_device_detach(priv->netdev); netdev_warn(netdev, "couldn't submit control: %d\n", err); return err; } /* Open USB device */ static int usb_8dev_open(struct net_device *netdev) { struct usb_8dev_priv *priv = netdev_priv(netdev); int err; /* common open */ err = open_candev(netdev); if (err) return err; can_led_event(netdev, CAN_LED_EVENT_OPEN); /* finally start device */ err = usb_8dev_start(priv); if (err) { if (err == -ENODEV) netif_device_detach(priv->netdev); netdev_warn(netdev, "couldn't start device: %d\n", err); close_candev(netdev); return err; } netif_start_queue(netdev); return 0; } static void unlink_all_urbs(struct usb_8dev_priv *priv) { int i; usb_kill_anchored_urbs(&priv->rx_submitted); usb_kill_anchored_urbs(&priv->tx_submitted); atomic_set(&priv->active_tx_urbs, 0); for (i = 0; i < MAX_TX_URBS; i++) priv->tx_contexts[i].echo_index = MAX_TX_URBS; } /* Close USB device */ static int usb_8dev_close(struct net_device *netdev) { struct usb_8dev_priv *priv = netdev_priv(netdev); int err = 0; /* Send CLOSE command to CAN controller */ err = usb_8dev_cmd_close(priv); if (err) netdev_warn(netdev, "couldn't stop device"); priv->can.state = CAN_STATE_STOPPED; netif_stop_queue(netdev); /* Stop polling */ unlink_all_urbs(priv); close_candev(netdev); can_led_event(netdev, CAN_LED_EVENT_STOP); return err; } static const struct net_device_ops usb_8dev_netdev_ops = { .ndo_open = usb_8dev_open, .ndo_stop = usb_8dev_close, .ndo_start_xmit = usb_8dev_start_xmit, .ndo_change_mtu = can_change_mtu, }; static const struct can_bittiming_const usb_8dev_bittiming_const = { .name = "usb_8dev", .tseg1_min = 1, .tseg1_max = 16, .tseg2_min = 1, .tseg2_max = 8, .sjw_max = 4, .brp_min = 1, .brp_max = 1024, .brp_inc = 1, }; /* Probe USB device * * Check device and firmware. * Set supported modes and bittiming constants. * Allocate some memory. */ static int usb_8dev_probe(struct usb_interface *intf, const struct usb_device_id *id) { struct net_device *netdev; struct usb_8dev_priv *priv; int i, err = -ENOMEM; u32 version; char buf[18]; struct usb_device *usbdev = interface_to_usbdev(intf); /* product id looks strange, better we also check iProduct string */ if (usb_string(usbdev, usbdev->descriptor.iProduct, buf, sizeof(buf)) > 0 && strcmp(buf, "USB2CAN converter")) { dev_info(&usbdev->dev, "ignoring: not an USB2CAN converter\n"); return -ENODEV; } netdev = alloc_candev(sizeof(struct usb_8dev_priv), MAX_TX_URBS); if (!netdev) { dev_err(&intf->dev, "Couldn't alloc candev\n"); return -ENOMEM; } priv = netdev_priv(netdev); priv->udev = usbdev; priv->netdev = netdev; priv->can.state = CAN_STATE_STOPPED; priv->can.clock.freq = USB_8DEV_ABP_CLOCK; priv->can.bittiming_const = &usb_8dev_bittiming_const; priv->can.do_set_mode = usb_8dev_set_mode; priv->can.do_get_berr_counter = usb_8dev_get_berr_counter; priv->can.ctrlmode_supported = CAN_CTRLMODE_LOOPBACK | CAN_CTRLMODE_LISTENONLY | CAN_CTRLMODE_ONE_SHOT; netdev->netdev_ops = &usb_8dev_netdev_ops; netdev->flags |= IFF_ECHO; /* we support local echo */ init_usb_anchor(&priv->rx_submitted); init_usb_anchor(&priv->tx_submitted); atomic_set(&priv->active_tx_urbs, 0); for (i = 0; i < MAX_TX_URBS; i++) priv->tx_contexts[i].echo_index = MAX_TX_URBS; priv->cmd_msg_buffer = kzalloc(sizeof(struct usb_8dev_cmd_msg), GFP_KERNEL); if (!priv->cmd_msg_buffer) goto cleanup_candev; usb_set_intfdata(intf, priv); SET_NETDEV_DEV(netdev, &intf->dev); mutex_init(&priv->usb_8dev_cmd_lock); err = register_candev(netdev); if (err) { netdev_err(netdev, "couldn't register CAN device: %d\n", err); goto cleanup_cmd_msg_buffer; } err = usb_8dev_cmd_version(priv, &version); if (err) { netdev_err(netdev, "can't get firmware version\n"); goto cleanup_unregister_candev; } else { netdev_info(netdev, "firmware: %d.%d, hardware: %d.%d\n", (version>>24) & 0xff, (version>>16) & 0xff, (version>>8) & 0xff, version & 0xff); } devm_can_led_init(netdev); return 0; cleanup_unregister_candev: unregister_netdev(priv->netdev); cleanup_cmd_msg_buffer: kfree(priv->cmd_msg_buffer); cleanup_candev: free_candev(netdev); return err; } /* Called by the usb core when driver is unloaded or device is removed */ static void usb_8dev_disconnect(struct usb_interface *intf) { struct usb_8dev_priv *priv = usb_get_intfdata(intf); usb_set_intfdata(intf, NULL); if (priv) { netdev_info(priv->netdev, "device disconnected\n"); unregister_netdev(priv->netdev); free_candev(priv->netdev); unlink_all_urbs(priv); } } static struct usb_driver usb_8dev_driver = { .name = "usb_8dev", .probe = usb_8dev_probe, .disconnect = usb_8dev_disconnect, .id_table = usb_8dev_table, }; module_usb_driver(usb_8dev_driver); MODULE_AUTHOR("Bernd Krumboeck <*****@*****.**>"); MODULE_DESCRIPTION("CAN driver for 8 devices USB2CAN interfaces"); MODULE_LICENSE("GPL v2");
static int ti_hecc_error(struct net_device *ndev, int int_status, int err_status) { struct ti_hecc_priv *priv = netdev_priv(ndev); struct net_device_stats *stats = &ndev->stats; struct can_frame *cf; struct sk_buff *skb; /* propagate the error condition to the can stack */ skb = alloc_can_err_skb(ndev, &cf); if (!skb) { if (printk_ratelimit()) netdev_err(priv->ndev, "ti_hecc_error: alloc_can_err_skb() failed\n"); return -ENOMEM; } if (int_status & HECC_CANGIF_WLIF) { /* warning level int */ if ((int_status & HECC_CANGIF_BOIF) == 0) { priv->can.state = CAN_STATE_ERROR_WARNING; ++priv->can.can_stats.error_warning; cf->can_id |= CAN_ERR_CRTL; if (hecc_read(priv, HECC_CANTEC) > 96) cf->data[1] |= CAN_ERR_CRTL_TX_WARNING; if (hecc_read(priv, HECC_CANREC) > 96) cf->data[1] |= CAN_ERR_CRTL_RX_WARNING; } hecc_set_bit(priv, HECC_CANES, HECC_CANES_EW); netdev_dbg(priv->ndev, "Error Warning interrupt\n"); hecc_clear_bit(priv, HECC_CANMC, HECC_CANMC_CCR); } if (int_status & HECC_CANGIF_EPIF) { /* error passive int */ if ((int_status & HECC_CANGIF_BOIF) == 0) { priv->can.state = CAN_STATE_ERROR_PASSIVE; ++priv->can.can_stats.error_passive; cf->can_id |= CAN_ERR_CRTL; if (hecc_read(priv, HECC_CANTEC) > 127) cf->data[1] |= CAN_ERR_CRTL_TX_PASSIVE; if (hecc_read(priv, HECC_CANREC) > 127) cf->data[1] |= CAN_ERR_CRTL_RX_PASSIVE; } hecc_set_bit(priv, HECC_CANES, HECC_CANES_EP); netdev_dbg(priv->ndev, "Error passive interrupt\n"); hecc_clear_bit(priv, HECC_CANMC, HECC_CANMC_CCR); } /* * Need to check busoff condition in error status register too to * ensure warning interrupts don't hog the system */ if ((int_status & HECC_CANGIF_BOIF) || (err_status & HECC_CANES_BO)) { priv->can.state = CAN_STATE_BUS_OFF; cf->can_id |= CAN_ERR_BUSOFF; hecc_set_bit(priv, HECC_CANES, HECC_CANES_BO); hecc_clear_bit(priv, HECC_CANMC, HECC_CANMC_CCR); /* Disable all interrupts in bus-off to avoid int hog */ hecc_write(priv, HECC_CANGIM, 0); can_bus_off(ndev); } if (err_status & HECC_BUS_ERROR) { ++priv->can.can_stats.bus_error; cf->can_id |= CAN_ERR_BUSERROR | CAN_ERR_PROT; cf->data[2] |= CAN_ERR_PROT_UNSPEC; if (err_status & HECC_CANES_FE) { hecc_set_bit(priv, HECC_CANES, HECC_CANES_FE); cf->data[2] |= CAN_ERR_PROT_FORM; } if (err_status & HECC_CANES_BE) { hecc_set_bit(priv, HECC_CANES, HECC_CANES_BE); cf->data[2] |= CAN_ERR_PROT_BIT; } if (err_status & HECC_CANES_SE) { hecc_set_bit(priv, HECC_CANES, HECC_CANES_SE); cf->data[2] |= CAN_ERR_PROT_STUFF; } if (err_status & HECC_CANES_CRCE) { hecc_set_bit(priv, HECC_CANES, HECC_CANES_CRCE); cf->data[3] |= CAN_ERR_PROT_LOC_CRC_SEQ | CAN_ERR_PROT_LOC_CRC_DEL; } if (err_status & HECC_CANES_ACKE) { hecc_set_bit(priv, HECC_CANES, HECC_CANES_ACKE); cf->data[3] |= CAN_ERR_PROT_LOC_ACK | CAN_ERR_PROT_LOC_ACK_DEL; } } netif_rx(skb); stats->rx_packets++; stats->rx_bytes += cf->can_dlc; return 0; }
static int c_can_handle_bus_err(struct net_device *dev, enum c_can_lec_type lec_type) { struct c_can_priv *priv = netdev_priv(dev); struct net_device_stats *stats = &dev->stats; struct can_frame *cf; struct sk_buff *skb; /* * early exit if no lec update or no error. * no lec update means that no CAN bus event has been detected * since CPU wrote 0x7 value to status reg. */ if (lec_type == LEC_UNUSED || lec_type == LEC_NO_ERROR) return 0; /* propagate the error condition to the CAN stack */ skb = alloc_can_err_skb(dev, &cf); if (unlikely(!skb)) return 0; /* * check for 'last error code' which tells us the * type of the last error to occur on the CAN bus */ /* common for all type of bus errors */ priv->can.can_stats.bus_error++; stats->rx_errors++; cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR; cf->data[2] |= CAN_ERR_PROT_UNSPEC; switch (lec_type) { case LEC_STUFF_ERROR: netdev_dbg(dev, "stuff error\n"); cf->data[2] |= CAN_ERR_PROT_STUFF; break; case LEC_FORM_ERROR: netdev_dbg(dev, "form error\n"); cf->data[2] |= CAN_ERR_PROT_FORM; break; case LEC_ACK_ERROR: netdev_dbg(dev, "ack error\n"); cf->data[3] |= (CAN_ERR_PROT_LOC_ACK | CAN_ERR_PROT_LOC_ACK_DEL); break; case LEC_BIT1_ERROR: netdev_dbg(dev, "bit1 error\n"); cf->data[2] |= CAN_ERR_PROT_BIT1; break; case LEC_BIT0_ERROR: netdev_dbg(dev, "bit0 error\n"); cf->data[2] |= CAN_ERR_PROT_BIT0; break; case LEC_CRC_ERROR: netdev_dbg(dev, "CRC error\n"); cf->data[3] |= (CAN_ERR_PROT_LOC_CRC_SEQ | CAN_ERR_PROT_LOC_CRC_DEL); break; default: break; } /* set a `lec` value so that we can check for updates later */ priv->write_reg(priv, C_CAN_STS_REG, LEC_UNUSED); netif_receive_skb(skb); stats->rx_packets++; stats->rx_bytes += cf->can_dlc; return 1; }
static int c_can_handle_state_change(struct net_device *dev, enum c_can_bus_error_types error_type) { unsigned int reg_err_counter; unsigned int rx_err_passive; struct c_can_priv *priv = netdev_priv(dev); struct net_device_stats *stats = &dev->stats; struct can_frame *cf; struct sk_buff *skb; struct can_berr_counter bec; /* propagate the error condition to the CAN stack */ skb = alloc_can_err_skb(dev, &cf); if (unlikely(!skb)) return 0; c_can_get_berr_counter(dev, &bec); reg_err_counter = priv->read_reg(priv, C_CAN_ERR_CNT_REG); rx_err_passive = (reg_err_counter & ERR_CNT_RP_MASK) >> ERR_CNT_RP_SHIFT; switch (error_type) { case C_CAN_ERROR_WARNING: /* error warning state */ priv->can.can_stats.error_warning++; priv->can.state = CAN_STATE_ERROR_WARNING; cf->can_id |= CAN_ERR_CRTL; cf->data[1] = (bec.txerr > bec.rxerr) ? CAN_ERR_CRTL_TX_WARNING : CAN_ERR_CRTL_RX_WARNING; cf->data[6] = bec.txerr; cf->data[7] = bec.rxerr; break; case C_CAN_ERROR_PASSIVE: /* error passive state */ priv->can.can_stats.error_passive++; priv->can.state = CAN_STATE_ERROR_PASSIVE; cf->can_id |= CAN_ERR_CRTL; if (rx_err_passive) cf->data[1] |= CAN_ERR_CRTL_RX_PASSIVE; if (bec.txerr > 127) cf->data[1] |= CAN_ERR_CRTL_TX_PASSIVE; cf->data[6] = bec.txerr; cf->data[7] = bec.rxerr; break; case C_CAN_BUS_OFF: /* bus-off state */ priv->can.state = CAN_STATE_BUS_OFF; cf->can_id |= CAN_ERR_BUSOFF; /* * disable all interrupts in bus-off mode to ensure that * the CPU is not hogged down */ c_can_enable_all_interrupts(priv, DISABLE_ALL_INTERRUPTS); can_bus_off(dev); break; default: break; } netif_receive_skb(skb); stats->rx_packets++; stats->rx_bytes += cf->can_dlc; return 1; }
static void gs_usb_receive_bulk_callback(struct urb *urb) { struct gs_usb *usbcan = urb->context; struct gs_can *dev; struct net_device *netdev; int rc; struct net_device_stats *stats; struct gs_host_frame *hf = urb->transfer_buffer; struct gs_tx_context *txc; struct can_frame *cf; struct sk_buff *skb; BUG_ON(!usbcan); switch (urb->status) { case 0: /* success */ break; case -ENOENT: case -ESHUTDOWN: return; default: /* do not resubmit aborted urbs. eg: when device goes down */ return; } /* device reports out of range channel id */ if (hf->channel >= GS_MAX_INTF) goto resubmit_urb; dev = usbcan->canch[hf->channel]; netdev = dev->netdev; stats = &netdev->stats; if (!netif_device_present(netdev)) return; if (hf->echo_id == -1) { /* normal rx */ skb = alloc_can_skb(dev->netdev, &cf); if (!skb) return; cf->can_id = hf->can_id; cf->can_dlc = get_can_dlc(hf->can_dlc); memcpy(cf->data, hf->data, 8); /* ERROR frames tell us information about the controller */ if (hf->can_id & CAN_ERR_FLAG) gs_update_state(dev, cf); netdev->stats.rx_packets++; netdev->stats.rx_bytes += hf->can_dlc; netif_rx(skb); } else { /* echo_id == hf->echo_id */ if (hf->echo_id >= GS_MAX_TX_URBS) { netdev_err(netdev, "Unexpected out of range echo id %d\n", hf->echo_id); goto resubmit_urb; } netdev->stats.tx_packets++; netdev->stats.tx_bytes += hf->can_dlc; txc = gs_get_tx_context(dev, hf->echo_id); /* bad devices send bad echo_ids. */ if (!txc) { netdev_err(netdev, "Unexpected unused echo id %d\n", hf->echo_id); goto resubmit_urb; } can_get_echo_skb(netdev, hf->echo_id); gs_free_tx_context(txc); netif_wake_queue(netdev); } if (hf->flags & GS_CAN_FLAG_OVERFLOW) { skb = alloc_can_err_skb(netdev, &cf); if (!skb) goto resubmit_urb; cf->can_id |= CAN_ERR_CRTL; cf->can_dlc = CAN_ERR_DLC; cf->data[1] = CAN_ERR_CRTL_RX_OVERFLOW; stats->rx_over_errors++; stats->rx_errors++; netif_rx(skb); } resubmit_urb: usb_fill_bulk_urb(urb, usbcan->udev, usb_rcvbulkpipe(usbcan->udev, GSUSB_ENDPOINT_IN), hf, sizeof(struct gs_host_frame), gs_usb_receive_bulk_callback, usbcan ); rc = usb_submit_urb(urb, GFP_ATOMIC); /* USB failure take down all interfaces */ if (rc == -ENODEV) { for (rc = 0; rc < GS_MAX_INTF; rc++) { if (usbcan->canch[rc]) netif_device_detach(usbcan->canch[rc]->netdev); } } }
static void ems_usb_rx_err(struct ems_usb *dev, struct ems_cpc_msg *msg) { struct can_frame *cf; struct sk_buff *skb; struct net_device_stats *stats = &dev->netdev->stats; skb = alloc_can_err_skb(dev->netdev, &cf); if (skb == NULL) return; if (msg->type == CPC_MSG_TYPE_CAN_STATE) { u8 state = msg->msg.can_state; if (state & SJA1000_SR_BS) { dev->can.state = CAN_STATE_BUS_OFF; cf->can_id |= CAN_ERR_BUSOFF; can_bus_off(dev->netdev); } else if (state & SJA1000_SR_ES) { dev->can.state = CAN_STATE_ERROR_WARNING; dev->can.can_stats.error_warning++; } else { dev->can.state = CAN_STATE_ERROR_ACTIVE; dev->can.can_stats.error_passive++; } } else if (msg->type == CPC_MSG_TYPE_CAN_FRAME_ERROR) { u8 ecc = msg->msg.error.cc.regs.sja1000.ecc; u8 txerr = msg->msg.error.cc.regs.sja1000.txerr; u8 rxerr = msg->msg.error.cc.regs.sja1000.rxerr; /* bus error interrupt */ dev->can.can_stats.bus_error++; stats->rx_errors++; cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR; switch (ecc & SJA1000_ECC_MASK) { case SJA1000_ECC_BIT: cf->data[2] |= CAN_ERR_PROT_BIT; break; case SJA1000_ECC_FORM: cf->data[2] |= CAN_ERR_PROT_FORM; break; case SJA1000_ECC_STUFF: cf->data[2] |= CAN_ERR_PROT_STUFF; break; default: cf->data[2] |= CAN_ERR_PROT_UNSPEC; cf->data[3] = ecc & SJA1000_ECC_SEG; break; } /* Error occurred during transmission? */ if ((ecc & SJA1000_ECC_DIR) == 0) cf->data[2] |= CAN_ERR_PROT_TX; if (dev->can.state == CAN_STATE_ERROR_WARNING || dev->can.state == CAN_STATE_ERROR_PASSIVE) { cf->data[1] = (txerr > rxerr) ? CAN_ERR_CRTL_TX_PASSIVE : CAN_ERR_CRTL_RX_PASSIVE; } } else if (msg->type == CPC_MSG_TYPE_OVERRUN) { cf->can_id |= CAN_ERR_CRTL; cf->data[1] = CAN_ERR_CRTL_RX_OVERFLOW; stats->rx_over_errors++; stats->rx_errors++; } netif_rx(skb); stats->rx_packets++; stats->rx_bytes += cf->can_dlc; }
static void grcan_err(struct net_device *dev, u32 sources, u32 status) { struct grcan_priv *priv = netdev_priv(dev); struct grcan_registers __iomem *regs = priv->regs; struct grcan_dma *dma = &priv->dma; struct net_device_stats *stats = &dev->stats; struct can_frame cf; /* Zero potential error_frame */ memset(&cf, 0, sizeof(cf)); /* Message lost interrupt. This might be due to arbitration error, but * is also triggered when there is no one else on the can bus or when * there is a problem with the hardware interface or the bus itself. As * arbitration errors can not be singled out, no error frames are * generated reporting this event as an arbitration error. */ if (sources & GRCAN_IRQ_TXLOSS) { /* Take care of failed one-shot transmit */ if (priv->can.ctrlmode & CAN_CTRLMODE_ONE_SHOT) grcan_lost_one_shot_frame(dev); /* Stop printing as soon as error passive or bus off is in * effect to limit the amount of txloss debug printouts. */ if (!(status & GRCAN_STAT_ERRCTR_RELATED)) { netdev_dbg(dev, "tx message lost\n"); stats->tx_errors++; } } /* Conditions dealing with the error counters. There is no interrupt for * error warning, but there are interrupts for increases of the error * counters. */ if ((sources & GRCAN_IRQ_ERRCTR_RELATED) || (status & GRCAN_STAT_ERRCTR_RELATED)) { enum can_state state = priv->can.state; enum can_state oldstate = state; u32 txerr = (status & GRCAN_STAT_TXERRCNT) >> GRCAN_STAT_TXERRCNT_BIT; u32 rxerr = (status & GRCAN_STAT_RXERRCNT) >> GRCAN_STAT_RXERRCNT_BIT; /* Figure out current state */ if (status & GRCAN_STAT_OFF) { state = CAN_STATE_BUS_OFF; } else if (status & GRCAN_STAT_PASS) { state = CAN_STATE_ERROR_PASSIVE; } else if (txerr >= GRCAN_STAT_ERRCNT_WARNING_LIMIT || rxerr >= GRCAN_STAT_ERRCNT_WARNING_LIMIT) { state = CAN_STATE_ERROR_WARNING; } else { state = CAN_STATE_ERROR_ACTIVE; } /* Handle and report state changes */ if (state != oldstate) { switch (state) { case CAN_STATE_BUS_OFF: netdev_dbg(dev, "bus-off\n"); netif_carrier_off(dev); priv->can.can_stats.bus_off++; /* Prevent the hardware from recovering from bus * off on its own if restart is disabled. */ if (!priv->can.restart_ms) grcan_stop_hardware(dev); cf.can_id |= CAN_ERR_BUSOFF; break; case CAN_STATE_ERROR_PASSIVE: netdev_dbg(dev, "Error passive condition\n"); priv->can.can_stats.error_passive++; cf.can_id |= CAN_ERR_CRTL; if (txerr >= GRCAN_STAT_ERRCNT_PASSIVE_LIMIT) cf.data[1] |= CAN_ERR_CRTL_TX_PASSIVE; if (rxerr >= GRCAN_STAT_ERRCNT_PASSIVE_LIMIT) cf.data[1] |= CAN_ERR_CRTL_RX_PASSIVE; break; case CAN_STATE_ERROR_WARNING: netdev_dbg(dev, "Error warning condition\n"); priv->can.can_stats.error_warning++; cf.can_id |= CAN_ERR_CRTL; if (txerr >= GRCAN_STAT_ERRCNT_WARNING_LIMIT) cf.data[1] |= CAN_ERR_CRTL_TX_WARNING; if (rxerr >= GRCAN_STAT_ERRCNT_WARNING_LIMIT) cf.data[1] |= CAN_ERR_CRTL_RX_WARNING; break; case CAN_STATE_ERROR_ACTIVE: netdev_dbg(dev, "Error active condition\n"); cf.can_id |= CAN_ERR_CRTL; break; default: /* There are no others at this point */ break; } cf.data[6] = txerr; cf.data[7] = rxerr; priv->can.state = state; } /* Report automatic restarts */ if (priv->can.restart_ms && oldstate == CAN_STATE_BUS_OFF) { unsigned long flags; cf.can_id |= CAN_ERR_RESTARTED; netdev_dbg(dev, "restarted\n"); priv->can.can_stats.restarts++; netif_carrier_on(dev); spin_lock_irqsave(&priv->lock, flags); if (!priv->resetting && !priv->closing) { u32 txwr = grcan_read_reg(®s->txwr); if (grcan_txspace(dma->tx.size, txwr, priv->eskbp)) netif_wake_queue(dev); } spin_unlock_irqrestore(&priv->lock, flags); } } /* Data overrun interrupt */ if ((sources & GRCAN_IRQ_OR) || (status & GRCAN_STAT_OR)) { netdev_dbg(dev, "got data overrun interrupt\n"); stats->rx_over_errors++; stats->rx_errors++; cf.can_id |= CAN_ERR_CRTL; cf.data[1] |= CAN_ERR_CRTL_RX_OVERFLOW; } /* AHB bus error interrupts (not CAN bus errors) - shut down the * device. */ if (sources & (GRCAN_IRQ_TXAHBERR | GRCAN_IRQ_RXAHBERR) || (status & GRCAN_STAT_AHBERR)) { char *txrx = ""; unsigned long flags; if (sources & GRCAN_IRQ_TXAHBERR) { txrx = "on tx "; stats->tx_errors++; } else if (sources & GRCAN_IRQ_RXAHBERR) { txrx = "on rx "; stats->rx_errors++; } netdev_err(dev, "Fatal AHB buss error %s- halting device\n", txrx); spin_lock_irqsave(&priv->lock, flags); /* Prevent anything to be enabled again and halt device */ priv->closing = true; netif_stop_queue(dev); grcan_stop_hardware(dev); priv->can.state = CAN_STATE_STOPPED; spin_unlock_irqrestore(&priv->lock, flags); } /* Pass on error frame if something to report, * i.e. id contains some information */ if (cf.can_id) { struct can_frame *skb_cf; struct sk_buff *skb = alloc_can_err_skb(dev, &skb_cf); if (skb == NULL) { netdev_dbg(dev, "could not allocate error frame\n"); return; } skb_cf->can_id |= cf.can_id; memcpy(skb_cf->data, cf.data, sizeof(cf.data)); netif_rx(skb); } }