static void gs_destroy_candev(struct gs_can *dev) { unregister_candev(dev->netdev); free_candev(dev->netdev); usb_kill_anchored_urbs(&dev->tx_submitted); kfree(dev); }
void free_c_can_dev(struct net_device *dev) { struct c_can_priv *priv = netdev_priv(dev); netif_napi_del(&priv->napi); free_candev(dev); }
/* remove a CAN-FD channel by releasing all of its resources */ static void pciefd_can_remove(struct pciefd_can *priv) { /* unregister (close) the can device to go back to RST mode first */ unregister_candev(priv->ucan.ndev); /* finally, free the candev object */ free_candev(priv->ucan.ndev); }
/* * called by the usb core when the device is removed from the system */ static void sam4e_usb_disconnect(struct usb_interface *intf) { struct sam4e_usb *dev; dev = usb_get_intfdata(intf); usb_set_intfdata(intf, NULL); if (dev) { LOGNI("Disconnect sam4e\n"); if (dev->netdev1) { unregister_netdev(dev->netdev1); free_candev(dev->netdev1); } if (dev->netdev2) { unregister_netdev(dev->netdev2); free_candev(dev->netdev2); } kfree(dev->assembly_buffer); unlink_all_urbs(dev); kfree(dev); } }
static int ti_hecc_remove(struct platform_device *pdev) { struct resource *res; struct net_device *ndev = platform_get_drvdata(pdev); struct ti_hecc_priv *priv = netdev_priv(ndev); unregister_candev(ndev); clk_disable(priv->clk); clk_put(priv->clk); res = platform_get_resource(pdev, IORESOURCE_MEM, 0); iounmap(priv->base); release_mem_region(res->start, resource_size(res)); free_candev(ndev); return 0; }
/* * called by the usb core when the device is removed from the system */ static void ems_usb_disconnect(struct usb_interface *intf) { struct ems_usb *dev = usb_get_intfdata(intf); usb_set_intfdata(intf, NULL); if (dev) { unregister_netdev(dev->netdev); free_candev(dev->netdev); unlink_all_urbs(dev); usb_free_urb(dev->intr_urb); kfree(dev->intr_in_buffer); } }
static int __devexit omapl_pru_can_remove(struct platform_device *pdev) { struct resource *res; struct net_device *ndev = platform_get_drvdata(pdev); struct omapl_pru_can_priv *priv = netdev_priv(ndev); omapl_pru_can_stop(ndev); pru_can_emulation_exit(); release_firmware(priv->fw_tx); release_firmware(priv->fw_rx); clk_put(priv->clk); flush_workqueue(priv->pru_can_wQ); destroy_workqueue(priv->pru_can_wQ); res = platform_get_resource(pdev, IORESOURCE_MEM, 0); iounmap(priv->pru_arm_iomap.pru_io_addr); release_mem_region(res->start, resource_size(res)); unregister_candev(ndev); free_candev(ndev); platform_set_drvdata(pdev, NULL); return 0; }
/* 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_probe(struct platform_device *pdev) { struct net_device *ndev = (struct net_device *)0; struct ti_hecc_priv *priv; struct ti_hecc_platform_data *pdata; struct resource *mem, *irq; void __iomem *addr; int err = -ENODEV; pdata = pdev->dev.platform_data; if (!pdata) { dev_err(&pdev->dev, "No platform data\n"); goto probe_exit; } mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!mem) { dev_err(&pdev->dev, "No mem resources\n"); goto probe_exit; } irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); if (!irq) { dev_err(&pdev->dev, "No irq resource\n"); goto probe_exit; } if (!request_mem_region(mem->start, resource_size(mem), pdev->name)) { dev_err(&pdev->dev, "HECC region already claimed\n"); err = -EBUSY; goto probe_exit; } addr = ioremap(mem->start, resource_size(mem)); if (!addr) { dev_err(&pdev->dev, "ioremap failed\n"); err = -ENOMEM; goto probe_exit_free_region; } ndev = alloc_candev(sizeof(struct ti_hecc_priv), HECC_MAX_TX_MBOX); if (!ndev) { dev_err(&pdev->dev, "alloc_candev failed\n"); err = -ENOMEM; goto probe_exit_iounmap; } priv = netdev_priv(ndev); priv->ndev = ndev; priv->base = addr; priv->scc_ram_offset = pdata->scc_ram_offset; priv->hecc_ram_offset = pdata->hecc_ram_offset; priv->mbx_offset = pdata->mbx_offset; priv->int_line = pdata->int_line; priv->transceiver_switch = pdata->transceiver_switch; 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.do_get_berr_counter = ti_hecc_get_berr_counter; priv->can.ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES; spin_lock_init(&priv->mbx_lock); ndev->irq = irq->start; ndev->flags |= IFF_ECHO; platform_set_drvdata(pdev, ndev); SET_NETDEV_DEV(ndev, &pdev->dev); ndev->netdev_ops = &ti_hecc_netdev_ops; priv->clk = clk_get(&pdev->dev, "hecc_ck"); if (IS_ERR(priv->clk)) { dev_err(&pdev->dev, "No clock available\n"); err = PTR_ERR(priv->clk); priv->clk = NULL; goto probe_exit_candev; } priv->can.clock.freq = clk_get_rate(priv->clk); netif_napi_add(ndev, &priv->napi, ti_hecc_rx_poll, HECC_DEF_NAPI_WEIGHT); clk_enable(priv->clk); err = register_candev(ndev); if (err) { dev_err(&pdev->dev, "register_candev() failed\n"); goto probe_exit_clk; } dev_info(&pdev->dev, "device registered (reg_base=%p, irq=%u)\n", priv->base, (u32) ndev->irq); return 0; probe_exit_clk: clk_put(priv->clk); probe_exit_candev: free_candev(ndev); probe_exit_iounmap: iounmap(addr); probe_exit_free_region: release_mem_region(mem->start, resource_size(mem)); probe_exit: return err; }
void free_c_can_dev(struct net_device *dev) { free_candev(dev); }
static struct gs_can *gs_make_candev(unsigned int channel, struct usb_interface *intf, struct gs_device_config *dconf) { struct gs_can *dev; struct net_device *netdev; int rc; struct gs_device_bt_const *bt_const; bt_const = kmalloc(sizeof(*bt_const), GFP_KERNEL); if (!bt_const) return ERR_PTR(-ENOMEM); /* fetch bit timing constants */ rc = usb_control_msg(interface_to_usbdev(intf), usb_rcvctrlpipe(interface_to_usbdev(intf), 0), GS_USB_BREQ_BT_CONST, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE, channel, 0, bt_const, sizeof(*bt_const), 1000); if (rc < 0) { dev_err(&intf->dev, "Couldn't get bit timing const for channel (err=%d)\n", rc); kfree(bt_const); return ERR_PTR(rc); } /* create netdev */ netdev = alloc_candev(sizeof(struct gs_can), GS_MAX_TX_URBS); if (!netdev) { dev_err(&intf->dev, "Couldn't allocate candev\n"); kfree(bt_const); return ERR_PTR(-ENOMEM); } dev = netdev_priv(netdev); netdev->netdev_ops = &gs_usb_netdev_ops; netdev->flags |= IFF_ECHO; /* we support full roundtrip echo */ /* dev settup */ strcpy(dev->bt_const.name, "gs_usb"); dev->bt_const.tseg1_min = bt_const->tseg1_min; dev->bt_const.tseg1_max = bt_const->tseg1_max; dev->bt_const.tseg2_min = bt_const->tseg2_min; dev->bt_const.tseg2_max = bt_const->tseg2_max; dev->bt_const.sjw_max = bt_const->sjw_max; dev->bt_const.brp_min = bt_const->brp_min; dev->bt_const.brp_max = bt_const->brp_max; dev->bt_const.brp_inc = bt_const->brp_inc; dev->udev = interface_to_usbdev(intf); dev->iface = intf; dev->netdev = netdev; dev->channel = channel; init_usb_anchor(&dev->tx_submitted); atomic_set(&dev->active_tx_urbs, 0); spin_lock_init(&dev->tx_ctx_lock); for (rc = 0; rc < GS_MAX_TX_URBS; rc++) { dev->tx_context[rc].dev = dev; dev->tx_context[rc].echo_id = GS_MAX_TX_URBS; } /* can settup */ dev->can.state = CAN_STATE_STOPPED; dev->can.clock.freq = bt_const->fclk_can; dev->can.bittiming_const = &dev->bt_const; dev->can.do_set_bittiming = gs_usb_set_bittiming; dev->can.ctrlmode_supported = 0; if (bt_const->feature & GS_CAN_FEATURE_LISTEN_ONLY) dev->can.ctrlmode_supported |= CAN_CTRLMODE_LISTENONLY; if (bt_const->feature & GS_CAN_FEATURE_LOOP_BACK) dev->can.ctrlmode_supported |= CAN_CTRLMODE_LOOPBACK; if (bt_const->feature & GS_CAN_FEATURE_TRIPLE_SAMPLE) dev->can.ctrlmode_supported |= CAN_CTRLMODE_3_SAMPLES; if (bt_const->feature & GS_CAN_FEATURE_ONE_SHOT) dev->can.ctrlmode_supported |= CAN_CTRLMODE_ONE_SHOT; SET_NETDEV_DEV(netdev, &intf->dev); if (dconf->sw_version > 1) if (bt_const->feature & GS_CAN_FEATURE_IDENTIFY) netdev->ethtool_ops = &gs_usb_ethtool_ops; kfree(bt_const); rc = register_candev(dev->netdev); if (rc) { free_candev(dev->netdev); dev_err(&intf->dev, "Couldn't register candev (err=%d)\n", rc); return ERR_PTR(rc); } return dev; }
/* * probe function for new CPC-USB devices */ static int ems_usb_probe(struct usb_interface *intf, const struct usb_device_id *id) { struct net_device *netdev; struct ems_usb *dev; int i, err = -ENOMEM; netdev = alloc_candev(sizeof(struct ems_usb), MAX_TX_URBS); if (!netdev) { dev_err(&intf->dev, "ems_usb: Couldn't alloc candev\n"); return -ENOMEM; } dev = netdev_priv(netdev); dev->udev = interface_to_usbdev(intf); dev->netdev = netdev; dev->can.state = CAN_STATE_STOPPED; dev->can.clock.freq = EMS_USB_ARM7_CLOCK; 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->netdev_ops = &ems_usb_netdev_ops; netdev->flags |= IFF_ECHO; /* we support local echo */ init_usb_anchor(&dev->rx_submitted); init_usb_anchor(&dev->tx_submitted); atomic_set(&dev->active_tx_urbs, 0); for (i = 0; i < MAX_TX_URBS; i++) dev->tx_contexts[i].echo_index = MAX_TX_URBS; dev->intr_urb = usb_alloc_urb(0, GFP_KERNEL); if (!dev->intr_urb) { dev_err(&intf->dev, "Couldn't alloc intr URB\n"); goto cleanup_candev; } dev->intr_in_buffer = kzalloc(INTR_IN_BUFFER_SIZE, GFP_KERNEL); if (!dev->intr_in_buffer) goto cleanup_intr_urb; dev->tx_msg_buffer = kzalloc(CPC_HEADER_SIZE + sizeof(struct ems_cpc_msg), GFP_KERNEL); if (!dev->tx_msg_buffer) goto cleanup_intr_in_buffer; usb_set_intfdata(intf, dev); SET_NETDEV_DEV(netdev, &intf->dev); init_params_sja1000(&dev->active_params); err = ems_usb_command_msg(dev, &dev->active_params); if (err) { netdev_err(netdev, "couldn't initialize controller: %d\n", err); goto cleanup_tx_msg_buffer; } err = register_candev(netdev); if (err) { netdev_err(netdev, "couldn't register CAN device: %d\n", err); goto cleanup_tx_msg_buffer; } return 0; cleanup_tx_msg_buffer: kfree(dev->tx_msg_buffer); cleanup_intr_in_buffer: kfree(dev->intr_in_buffer); cleanup_intr_urb: usb_free_urb(dev->intr_urb); cleanup_candev: free_candev(netdev); return err; }
static int __devinit omapl_pru_can_probe(struct platform_device *pdev) { struct net_device *ndev = NULL; struct omapl_pru_can_priv *priv = NULL; struct ti_pru_can_platform_data *pdata; struct resource *res_mem, *trx_irq; pru_can_firmware_structure fw_pru; u32 err, retries = 0; pdata = pdev->dev.platform_data; if (!pdata) { dev_err(&pdev->dev, "no platform data provided for pru!\n"); return -ENODEV; } res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res_mem) { dev_err(&pdev->dev, "unable to get pru memory resources!\n"); err = -ENODEV; goto probe_exit; } trx_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); if (!trx_irq) { dev_err(&pdev->dev, "unable to get pru interrupt resources!\n"); err = -ENODEV; goto probe_exit; } if (!request_mem_region(res_mem->start, resource_size(res_mem), dev_name(&pdev->dev))) { dev_err(&pdev->dev, "pru memory region already claimed!\n"); err = -EBUSY; goto probe_exit; } ndev = alloc_candev(sizeof(struct omapl_pru_can_priv), MB_MAX + 1); if (!ndev) { dev_err(&pdev->dev, "alloc_candev failed\n"); err = -ENOMEM; goto probe_exit_free_region; } priv = netdev_priv(ndev); priv->pru_arm_iomap.pru_io_addr = ioremap(res_mem->start, resource_size(res_mem)); if (!priv->pru_arm_iomap.pru_io_addr) { dev_err(&pdev->dev, "ioremap failed\n"); err = -ENOMEM; goto probe_exit_free_region; } priv->pru_arm_iomap.psc0_io_addr = IO_ADDRESS(DA8XX_PSC0_BASE); if (!priv->pru_arm_iomap.psc0_io_addr) { dev_err(&pdev->dev, "ioremap failed\n"); err = -ENOMEM; goto probe_exit_iounmap; } priv->pru_arm_iomap.psc1_io_addr = IO_ADDRESS(DA8XX_PSC1_BASE); if (!priv->pru_arm_iomap.psc1_io_addr) { dev_err(&pdev->dev, "ioremap failed\n"); err = -ENOMEM; goto probe_exit_iounmap; } priv->pru_arm_iomap.syscfg_io_addr = IO_ADDRESS(DA8XX_SYSCFG0_BASE); if (!priv->pru_arm_iomap.syscfg_io_addr) { dev_err(&pdev->dev, "ioremap failed\n"); err = -ENOMEM; goto probe_exit_iounmap; } priv->ndev = ndev; priv->trx_irq = trx_irq->start; priv->can.bittiming_const = NULL; priv->can.do_set_bittiming = omapl_pru_can_set_bittiming; priv->can.do_set_mode = omapl_pru_can_set_mode; priv->can.do_get_state = omapl_pru_can_get_state; priv->can_tx_hndl.u8prunumber = CAN_TX_PRU_1; priv->can_rx_hndl.u8prunumber = CAN_RX_PRU_0; ndev->flags |= (IFF_ECHO | IFF_NOARP); /* we support local echo, no arp */ platform_set_drvdata(pdev, ndev); SET_NETDEV_DEV(ndev, &pdev->dev); ndev->netdev_ops = &omapl_pru_can_netdev_ops; priv->clk = clk_get(&pdev->dev, "pru_ck"); if (IS_ERR(priv->clk)) { dev_err(&pdev->dev, "no clock available\n"); err = PTR_ERR(priv->clk); priv->clk = NULL; goto probe_exit_candev; } priv->can.clock.freq = clk_get_rate(priv->clk); priv->clk_timer = clk_get(&pdev->dev, "pll1_sysclk2"); if (IS_ERR(priv->clk_timer)) { dev_err(&pdev->dev, "no timer clock available\n"); err = PTR_ERR(priv->clk_timer); priv->clk_timer = NULL; goto probe_exit_candev; } priv->timer_freq = clk_get_rate(priv->clk_timer); err = register_candev(ndev); if (err) { dev_err(&pdev->dev, "register_candev() failed\n"); err = -ENODEV; goto probe_exit_clk; } err = request_firmware(&priv->fw_tx, "PRU_CAN_Emulation_Tx.bin", &pdev->dev); if (err) { dev_err(&pdev->dev, "can't load firmware\n"); err = -ENODEV; goto probe_exit_clk; } dev_info(&pdev->dev, "fw_tx size %d. downloading...\n", priv->fw_tx->size); err = request_firmware(&priv->fw_rx, "PRU_CAN_Emulation_Rx.bin", &pdev->dev); if (err) { dev_err(&pdev->dev, "can't load firmware\n"); err = -ENODEV; goto probe_release_fw; } dev_info(&pdev->dev, "fw_rx size %d. downloading...\n", priv->fw_rx->size); fw_pru.ptr_pru1 = kmalloc(priv->fw_tx->size, GFP_KERNEL); memcpy((void *)fw_pru.ptr_pru1, (const void *)priv->fw_tx->data, priv->fw_tx->size); fw_pru.u32_pru1_code_size = priv->fw_tx->size; fw_pru.ptr_pru0 = kmalloc(priv->fw_rx->size, GFP_KERNEL); memcpy((void *)fw_pru.ptr_pru0, (const void *)priv->fw_rx->data, priv->fw_rx->size); fw_pru.u32_pru0_code_size = priv->fw_rx->size; /* init the pru */ pru_can_emulation_init(&priv->pru_arm_iomap, priv->can.clock.freq); while ((pru_can_check_init_status()) && (retries++ < MAX_INIT_RETRIES)) udelay(retries); if (MAX_INIT_RETRIES <= retries) { dev_err(&pdev->dev, "failed to initialize the pru\n"); err = -ENODEV; goto probe_release_fw_1; } pru_can_enable(); /* download firmware into pru */ err = pru_can_download_firmware(&fw_pru, 0); if (err) { dev_err(&pdev->dev, "firmware download error\n"); err = -ENODEV; goto probe_release_fw_1; } err = pru_can_download_firmware(&fw_pru, 1); if (err) { dev_err(&pdev->dev, "firmware download error\n"); err = -ENODEV; goto probe_release_fw_1; } if (pru_can_calculatetiming (DFLT_PRU_FREQ, DFLT_PRU_BITRATE) != 0) { return -EINVAL; } pru_can_run(0); pru_can_run(1); kfree((const void *)fw_pru.ptr_pru0); kfree((const void *)fw_pru.ptr_pru1); /*Create The Work Queue */ if ((priv->pru_can_wQ = create_freezeable_workqueue("omapl_pru_wQ")) == NULL) dev_err(&pdev->dev, "failed to create work queue\n"); INIT_WORK(&priv->rx_work, omapl_pru_can_rx_wQ); dev_info(&pdev->dev, "%s device registered" "(®_base=0x%p, trx_irq = %d, clk = %d)\n", DRV_NAME, priv->pru_arm_iomap.pru_io_addr, priv->trx_irq, priv->can.clock.freq); return 0; probe_release_fw_1: kfree((const void *)fw_pru.ptr_pru0); kfree((const void *)fw_pru.ptr_pru1); release_firmware(priv->fw_rx); probe_release_fw: release_firmware(priv->fw_tx); probe_exit_clk: clk_put(priv->clk); probe_exit_candev: if (NULL != ndev) free_candev(ndev); probe_exit_iounmap: iounmap(priv->pru_arm_iomap.pru_io_addr); probe_exit_free_region: release_mem_region(res_mem->start, resource_size(res_mem)); probe_exit: return err; }
/* probe for CAN-FD channel #pciefd_board->can_count */ static int pciefd_can_probe(struct pciefd_board *pciefd) { struct net_device *ndev; struct pciefd_can *priv; u32 clk; int err; /* allocate the candev object with default isize of echo skbs ring */ ndev = alloc_peak_canfd_dev(sizeof(*priv), pciefd->can_count, PCIEFD_ECHO_SKB_MAX); if (!ndev) { dev_err(&pciefd->pci_dev->dev, "failed to alloc candev object\n"); goto failure; } priv = netdev_priv(ndev); /* fill-in candev private object: */ /* setup PCIe-FD own callbacks */ priv->ucan.pre_cmd = pciefd_pre_cmd; priv->ucan.write_cmd = pciefd_write_cmd; priv->ucan.post_cmd = pciefd_post_cmd; priv->ucan.enable_tx_path = pciefd_enable_tx_path; priv->ucan.alloc_tx_msg = pciefd_alloc_tx_msg; priv->ucan.write_tx_msg = pciefd_write_tx_msg; /* setup PCIe-FD own command buffer */ priv->ucan.cmd_buffer = &priv->pucan_cmd; priv->ucan.cmd_maxlen = sizeof(priv->pucan_cmd); priv->board = pciefd; /* CAN config regs block address */ priv->reg_base = pciefd->reg_base + PCIEFD_CANX_OFF(priv->ucan.index); /* allocate non-cacheable DMA'able 4KB memory area for Rx */ priv->rx_dma_vaddr = dmam_alloc_coherent(&pciefd->pci_dev->dev, PCIEFD_RX_DMA_SIZE, &priv->rx_dma_laddr, GFP_KERNEL); if (!priv->rx_dma_vaddr) { dev_err(&pciefd->pci_dev->dev, "Rx dmam_alloc_coherent(%u) failure\n", PCIEFD_RX_DMA_SIZE); goto err_free_candev; } /* allocate non-cacheable DMA'able 4KB memory area for Tx */ priv->tx_dma_vaddr = dmam_alloc_coherent(&pciefd->pci_dev->dev, PCIEFD_TX_DMA_SIZE, &priv->tx_dma_laddr, GFP_KERNEL); if (!priv->tx_dma_vaddr) { dev_err(&pciefd->pci_dev->dev, "Tx dmaim_alloc_coherent(%u) failure\n", PCIEFD_TX_DMA_SIZE); goto err_free_candev; } /* CAN clock in RST mode */ pciefd_can_writereg(priv, CANFD_MISC_TS_RST, PCIEFD_REG_CAN_MISC); /* read current clock value */ clk = pciefd_can_readreg(priv, PCIEFD_REG_CAN_CLK_SEL); switch (clk) { case CANFD_CLK_SEL_20MHZ: priv->ucan.can.clock.freq = 20 * 1000 * 1000; break; case CANFD_CLK_SEL_24MHZ: priv->ucan.can.clock.freq = 24 * 1000 * 1000; break; case CANFD_CLK_SEL_30MHZ: priv->ucan.can.clock.freq = 30 * 1000 * 1000; break; case CANFD_CLK_SEL_40MHZ: priv->ucan.can.clock.freq = 40 * 1000 * 1000; break; case CANFD_CLK_SEL_60MHZ: priv->ucan.can.clock.freq = 60 * 1000 * 1000; break; default: pciefd_can_writereg(priv, CANFD_CLK_SEL_80MHZ, PCIEFD_REG_CAN_CLK_SEL); /* fallthough */ case CANFD_CLK_SEL_80MHZ: priv->ucan.can.clock.freq = 80 * 1000 * 1000; break; } ndev->irq = pciefd->pci_dev->irq; SET_NETDEV_DEV(ndev, &pciefd->pci_dev->dev); err = register_candev(ndev); if (err) { dev_err(&pciefd->pci_dev->dev, "couldn't register CAN device: %d\n", err); goto err_free_candev; } spin_lock_init(&priv->tx_lock); /* save the object address in the board structure */ pciefd->can[pciefd->can_count] = priv; dev_info(&pciefd->pci_dev->dev, "%s at reg_base=0x%p irq=%d\n", ndev->name, priv->reg_base, pciefd->pci_dev->irq); return 0; err_free_candev: free_candev(ndev); failure: return -ENOMEM; }
/* * probe function for usb devices */ static int sam4e_usb_probe(struct usb_interface *intf, const struct usb_device_id *id) { struct usb_host_interface *usb_hi; struct usb_interface_descriptor *usb_if_desc; struct usb_device *udev; int err = 0; u8 if_num; struct net_device *netdev; struct sam4e_usb *dev; struct sam4e_usb_handle *sam4e_usb_hnd; int cnt = 0; usb_hi = intf->cur_altsetting; usb_if_desc = &usb_hi->desc; if_num = usb_if_desc->bInterfaceNumber; if (DEBUG_SAM4E) { dev_info(&intf->dev, "probe %p %p if_num %d id if_num %d\n", intf, id, if_num, id->bInterfaceNumber); } if (if_num != 1) return -ENODEV; dev = kzalloc(sizeof(struct sam4e_usb), GFP_KERNEL); if (!dev) { dev_err(&intf->dev, "Couldn't alloc sam4e_usb\n"); err = -ENOMEM; goto cleanup_candev; } atomic_set(&dev->netif_queue_stop, 0); while (cnt < MAX_CAN_INTF) { netdev = alloc_candev(sizeof(struct sam4e_usb_handle), MAX_TX_URBS); if (!netdev) { dev_err(&intf->dev, "Couldn't alloc candev\n"); err = -ENOMEM; goto cleanup_candev; } sam4e_usb_hnd = netdev_priv(netdev); sam4e_usb_hnd->sam4e_dev = dev; sam4e_usb_hnd->owner_netdev_index = cnt; dev->udev = interface_to_usbdev(intf); if (cnt == 0) dev->netdev1 = netdev; else dev->netdev2 = netdev; dev->assembly_buffer = kzalloc(RX_ASSEMBLY_BUFFER_SIZE, GFP_KERNEL); netdev->netdev_ops = &sam4e_usb_netdev_ops; init_usb_anchor(&dev->rx_submitted); init_usb_anchor(&dev->tx_submitted); atomic_set(&dev->active_tx_urbs, 0); atomic_set(&dev->msg_seq, 0); usb_set_intfdata(intf, dev); SET_NETDEV_DEV(netdev, &intf->dev); err = register_candev(netdev); if (err) { pr_err("fail reg.CAN device: %d", err); goto cleanup_candev; } udev = interface_to_usbdev(intf); if (cnt == 0) { /*use mail box 7 and 6 for e/s frames on can0*/ setup_mailbox(7, 0, CAN_EFF_FLAG, CAN_EFF_FLAG, intf, udev, dev); setup_mailbox(6, 0, CAN_EFF_FLAG, 0, intf, udev, dev); } else { /*use mail box 5 and 4 for e/s frames on can1*/ setup_mailbox(5, 1, CAN_EFF_FLAG, CAN_EFF_FLAG, intf, udev, dev); setup_mailbox(4, 1, CAN_EFF_FLAG, 0, intf, udev, dev); } cnt++; } sam4e_read_fw_version(dev); err = sam4e_init_urbs(dev); if (err) { if (err == -ENODEV) { netif_device_detach(dev->netdev1); netif_device_detach(dev->netdev2); } pr_err("couldn't start device: %d\n", err); close_candev(dev->netdev1); close_candev(dev->netdev2); goto cleanup_candev; } return 0; /*ok. it's ours */ cleanup_candev: if (dev) { kfree(dev->assembly_buffer); if (dev->netdev1) free_candev(dev->netdev1); if (dev->netdev2) free_candev(dev->netdev2); kfree(dev); } return err; }