diff options
Diffstat (limited to 'drivers/net/can/usb/esd_usb2.c')
| -rw-r--r-- | drivers/net/can/usb/esd_usb2.c | 241 | 
1 files changed, 133 insertions, 108 deletions
diff --git a/drivers/net/can/usb/esd_usb2.c b/drivers/net/can/usb/esd_usb2.c index 05a52754f48..b7c9e8b1146 100644 --- a/drivers/net/can/usb/esd_usb2.c +++ b/drivers/net/can/usb/esd_usb2.c @@ -1,7 +1,7 @@  /* - * CAN driver for esd CAN-USB/2 + * CAN driver for esd CAN-USB/2 and CAN-USB/Micro   * - * Copyright (C) 2010 Matthias Fuchs <matthias.fuchs@esd.eu>, esd gmbh + * Copyright (C) 2010-2012 Matthias Fuchs <matthias.fuchs@esd.eu>, esd gmbh   *   * This program is free software; you can redistribute it and/or modify it   * under the terms of the GNU General Public License as published @@ -16,7 +16,6 @@   * with this program; if not, write to the Free Software Foundation, Inc.,   * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.   */ -#include <linux/init.h>  #include <linux/signal.h>  #include <linux/slab.h>  #include <linux/module.h> @@ -28,14 +27,16 @@  #include <linux/can/error.h>  MODULE_AUTHOR("Matthias Fuchs <matthias.fuchs@esd.eu>"); -MODULE_DESCRIPTION("CAN driver for esd CAN-USB/2 interfaces"); +MODULE_DESCRIPTION("CAN driver for esd CAN-USB/2 and CAN-USB/Micro interfaces");  MODULE_LICENSE("GPL v2");  /* Define these values to match your devices */  #define USB_ESDGMBH_VENDOR_ID	0x0ab4  #define USB_CANUSB2_PRODUCT_ID	0x0010 +#define USB_CANUSBM_PRODUCT_ID	0x0011  #define ESD_USB2_CAN_CLOCK	60000000 +#define ESD_USBM_CAN_CLOCK	36000000  #define ESD_USB2_MAX_NETS	2  /* USB2 commands */ @@ -69,6 +70,7 @@ MODULE_LICENSE("GPL v2");  #define ESD_USB2_TSEG2_SHIFT	20  #define ESD_USB2_SJW_MAX	4  #define ESD_USB2_SJW_SHIFT	14 +#define ESD_USBM_SJW_SHIFT	24  #define ESD_USB2_BRP_MIN	1  #define ESD_USB2_BRP_MAX	1024  #define ESD_USB2_BRP_INC	1 @@ -183,6 +185,7 @@ struct __attribute__ ((packed)) esd_usb2_msg {  static struct usb_device_id esd_usb2_table[] = {  	{USB_DEVICE(USB_ESDGMBH_VENDOR_ID, USB_CANUSB2_PRODUCT_ID)}, +	{USB_DEVICE(USB_ESDGMBH_VENDOR_ID, USB_CANUSBM_PRODUCT_ID)},  	{}  };  MODULE_DEVICE_TABLE(usb, esd_usb2_table); @@ -213,7 +216,6 @@ struct esd_usb2_net_priv {  	struct usb_anchor tx_submitted;  	struct esd_tx_urb_context tx_contexts[MAX_TX_URBS]; -	int open_time;  	struct esd_usb2 *usb2;  	struct net_device *netdev;  	int index; @@ -284,7 +286,7 @@ static void esd_usb2_rx_event(struct esd_usb2_net_priv *priv,  				break;  			} -			/* Error occured during transmission? */ +			/* Error occurred during transmission? */  			if (!(ecc & SJA1000_ECC_DIR))  				cf->data[2] |= CAN_ERR_PROT_TX; @@ -409,10 +411,20 @@ static void esd_usb2_read_bulk_callback(struct urb *urb)  		switch (msg->msg.hdr.cmd) {  		case CMD_CAN_RX: +			if (msg->msg.rx.net >= dev->net_count) { +				dev_err(dev->udev->dev.parent, "format error\n"); +				break; +			} +  			esd_usb2_rx_can_msg(dev->nets[msg->msg.rx.net], msg);  			break;  		case CMD_CAN_TX: +			if (msg->msg.txdone.net >= dev->net_count) { +				dev_err(dev->udev->dev.parent, "format error\n"); +				break; +			} +  			esd_usb2_tx_done_msg(dev->nets[msg->msg.txdone.net],  					     msg);  			break; @@ -470,8 +482,7 @@ static void esd_usb2_write_bulk_callback(struct urb *urb)  		return;  	if (urb->status) -		dev_info(netdev->dev.parent, "Tx URB aborted (%d)\n", -			 urb->status); +		netdev_info(netdev, "Tx URB aborted (%d)\n", urb->status);  	netdev->trans_start = jiffies;  } @@ -610,9 +621,15 @@ static int esd_usb2_start(struct esd_usb2_net_priv *priv)  {  	struct esd_usb2 *dev = priv->usb2;  	struct net_device *netdev = priv->netdev; -	struct esd_usb2_msg msg; +	struct esd_usb2_msg *msg;  	int err, i; +	msg = kmalloc(sizeof(*msg), GFP_KERNEL); +	if (!msg) { +		err = -ENOMEM; +		goto out; +	} +  	/*  	 * Enable all IDs  	 * The IDADD message takes up to 64 32 bit bitmasks (2048 bits). @@ -626,40 +643,39 @@ static int esd_usb2_start(struct esd_usb2_net_priv *priv)  	 * the number of the starting bitmask (0..64) to the filter.option  	 * field followed by only some bitmasks.  	 */ -	msg.msg.hdr.cmd = CMD_IDADD; -	msg.msg.hdr.len = 2 + ESD_MAX_ID_SEGMENT; -	msg.msg.filter.net = priv->index; -	msg.msg.filter.option = ESD_ID_ENABLE; /* start with segment 0 */ +	msg->msg.hdr.cmd = CMD_IDADD; +	msg->msg.hdr.len = 2 + ESD_MAX_ID_SEGMENT; +	msg->msg.filter.net = priv->index; +	msg->msg.filter.option = ESD_ID_ENABLE; /* start with segment 0 */  	for (i = 0; i < ESD_MAX_ID_SEGMENT; i++) -		msg.msg.filter.mask[i] = cpu_to_le32(0xffffffff); +		msg->msg.filter.mask[i] = cpu_to_le32(0xffffffff);  	/* enable 29bit extended IDs */ -	msg.msg.filter.mask[ESD_MAX_ID_SEGMENT] = cpu_to_le32(0x00000001); +	msg->msg.filter.mask[ESD_MAX_ID_SEGMENT] = cpu_to_le32(0x00000001); -	err = esd_usb2_send_msg(dev, &msg); +	err = esd_usb2_send_msg(dev, msg);  	if (err) -		goto failed; +		goto out;  	err = esd_usb2_setup_rx_urbs(dev);  	if (err) -		goto failed; +		goto out;  	priv->can.state = CAN_STATE_ERROR_ACTIVE; -	return 0; - -failed: +out:  	if (err == -ENODEV)  		netif_device_detach(netdev); +	if (err) +		netdev_err(netdev, "couldn't start device: %d\n", err); -	dev_err(netdev->dev.parent, "couldn't start device: %d\n", err); - +	kfree(msg);  	return err;  }  static void unlink_all_urbs(struct esd_usb2 *dev)  {  	struct esd_usb2_net_priv *priv; -	int i; +	int i, j;  	usb_kill_anchored_urbs(&dev->rx_submitted);  	for (i = 0; i < dev->net_count; i++) { @@ -668,8 +684,8 @@ static void unlink_all_urbs(struct esd_usb2 *dev)  			usb_kill_anchored_urbs(&priv->tx_submitted);  			atomic_set(&priv->active_tx_jobs, 0); -			for (i = 0; i < MAX_TX_URBS; i++) -				priv->tx_contexts[i].echo_index = MAX_TX_URBS; +			for (j = 0; j < MAX_TX_URBS; j++) +				priv->tx_contexts[j].echo_index = MAX_TX_URBS;  		}  	}  } @@ -687,14 +703,11 @@ static int esd_usb2_open(struct net_device *netdev)  	/* finally start device */  	err = esd_usb2_start(priv);  	if (err) { -		dev_warn(netdev->dev.parent, -			 "couldn't start device: %d\n", err); +		netdev_warn(netdev, "couldn't start device: %d\n", err);  		close_candev(netdev);  		return err;  	} -	priv->open_time = jiffies; -  	netif_start_queue(netdev);  	return 0; @@ -721,7 +734,7 @@ static netdev_tx_t esd_usb2_start_xmit(struct sk_buff *skb,  	/* create a URB, and a buffer for it, and copy the data to the URB */  	urb = usb_alloc_urb(0, GFP_ATOMIC);  	if (!urb) { -		dev_err(netdev->dev.parent, "No memory left for URBs\n"); +		netdev_err(netdev, "No memory left for URBs\n");  		stats->tx_dropped++;  		dev_kfree_skb(skb);  		goto nourbmem; @@ -730,7 +743,7 @@ static netdev_tx_t esd_usb2_start_xmit(struct sk_buff *skb,  	buf = usb_alloc_coherent(dev->udev, size, GFP_ATOMIC,  				 &urb->transfer_dma);  	if (!buf) { -		dev_err(netdev->dev.parent, "No memory left for USB buffer\n"); +		netdev_err(netdev, "No memory left for USB buffer\n");  		stats->tx_dropped++;  		dev_kfree_skb(skb);  		goto nobufmem; @@ -766,7 +779,7 @@ static netdev_tx_t esd_usb2_start_xmit(struct sk_buff *skb,  	 * This may never happen.  	 */  	if (!context) { -		dev_warn(netdev->dev.parent, "couldn't find free context\n"); +		netdev_warn(netdev, "couldn't find free context\n");  		ret = NETDEV_TX_BUSY;  		goto releasebuf;  	} @@ -806,7 +819,7 @@ static netdev_tx_t esd_usb2_start_xmit(struct sk_buff *skb,  		if (err == -ENODEV)  			netif_device_detach(netdev);  		else -			dev_warn(netdev->dev.parent, "failed tx_urb %d\n", err); +			netdev_warn(netdev, "failed tx_urb %d\n", err);  		goto releasebuf;  	} @@ -834,27 +847,31 @@ nourbmem:  static int esd_usb2_close(struct net_device *netdev)  {  	struct esd_usb2_net_priv *priv = netdev_priv(netdev); -	struct esd_usb2_msg msg; +	struct esd_usb2_msg *msg;  	int i; +	msg = kmalloc(sizeof(*msg), GFP_KERNEL); +	if (!msg) +		return -ENOMEM; +  	/* Disable all IDs (see esd_usb2_start()) */ -	msg.msg.hdr.cmd = CMD_IDADD; -	msg.msg.hdr.len = 2 + ESD_MAX_ID_SEGMENT; -	msg.msg.filter.net = priv->index; -	msg.msg.filter.option = ESD_ID_ENABLE; /* start with segment 0 */ +	msg->msg.hdr.cmd = CMD_IDADD; +	msg->msg.hdr.len = 2 + ESD_MAX_ID_SEGMENT; +	msg->msg.filter.net = priv->index; +	msg->msg.filter.option = ESD_ID_ENABLE; /* start with segment 0 */  	for (i = 0; i <= ESD_MAX_ID_SEGMENT; i++) -		msg.msg.filter.mask[i] = 0; -	if (esd_usb2_send_msg(priv->usb2, &msg) < 0) -		dev_err(netdev->dev.parent, "sending idadd message failed\n"); +		msg->msg.filter.mask[i] = 0; +	if (esd_usb2_send_msg(priv->usb2, msg) < 0) +		netdev_err(netdev, "sending idadd message failed\n");  	/* set CAN controller to reset mode */ -	msg.msg.hdr.len = 2; -	msg.msg.hdr.cmd = CMD_SETBAUD; -	msg.msg.setbaud.net = priv->index; -	msg.msg.setbaud.rsvd = 0; -	msg.msg.setbaud.baud = cpu_to_le32(ESD_USB2_NO_BAUDRATE); -	if (esd_usb2_send_msg(priv->usb2, &msg) < 0) -		dev_err(netdev->dev.parent, "sending setbaud message failed\n"); +	msg->msg.hdr.len = 2; +	msg->msg.hdr.cmd = CMD_SETBAUD; +	msg->msg.setbaud.net = priv->index; +	msg->msg.setbaud.rsvd = 0; +	msg->msg.setbaud.baud = cpu_to_le32(ESD_USB2_NO_BAUDRATE); +	if (esd_usb2_send_msg(priv->usb2, msg) < 0) +		netdev_err(netdev, "sending setbaud message failed\n");  	priv->can.state = CAN_STATE_STOPPED; @@ -862,7 +879,7 @@ static int esd_usb2_close(struct net_device *netdev)  	close_candev(netdev); -	priv->open_time = 0; +	kfree(msg);  	return 0;  } @@ -871,9 +888,10 @@ static const struct net_device_ops esd_usb2_netdev_ops = {  	.ndo_open = esd_usb2_open,  	.ndo_stop = esd_usb2_close,  	.ndo_start_xmit = esd_usb2_start_xmit, +	.ndo_change_mtu = can_change_mtu,  }; -static struct can_bittiming_const esd_usb2_bittiming_const = { +static const struct can_bittiming_const esd_usb2_bittiming_const = {  	.name = "esd_usb2",  	.tseg1_min = ESD_USB2_TSEG1_MIN,  	.tseg1_max = ESD_USB2_TSEG1_MAX, @@ -889,13 +907,25 @@ static int esd_usb2_set_bittiming(struct net_device *netdev)  {  	struct esd_usb2_net_priv *priv = netdev_priv(netdev);  	struct can_bittiming *bt = &priv->can.bittiming; -	struct esd_usb2_msg msg; +	struct esd_usb2_msg *msg; +	int err;  	u32 canbtr; +	int sjw_shift;  	canbtr = ESD_USB2_UBR; +	if (priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY) +		canbtr |= ESD_USB2_LOM; +  	canbtr |= (bt->brp - 1) & (ESD_USB2_BRP_MAX - 1); + +	if (le16_to_cpu(priv->usb2->udev->descriptor.idProduct) == +	    USB_CANUSBM_PRODUCT_ID) +		sjw_shift = ESD_USBM_SJW_SHIFT; +	else +		sjw_shift = ESD_USB2_SJW_SHIFT; +  	canbtr |= ((bt->sjw - 1) & (ESD_USB2_SJW_MAX - 1)) -		<< ESD_USB2_SJW_SHIFT; +		<< sjw_shift;  	canbtr |= ((bt->prop_seg + bt->phase_seg1 - 1)  		   & (ESD_USB2_TSEG1_MAX - 1))  		<< ESD_USB2_TSEG1_SHIFT; @@ -904,15 +934,22 @@ static int esd_usb2_set_bittiming(struct net_device *netdev)  	if (priv->can.ctrlmode & CAN_CTRLMODE_3_SAMPLES)  		canbtr |= ESD_USB2_3_SAMPLES; -	msg.msg.hdr.len = 2; -	msg.msg.hdr.cmd = CMD_SETBAUD; -	msg.msg.setbaud.net = priv->index; -	msg.msg.setbaud.rsvd = 0; -	msg.msg.setbaud.baud = cpu_to_le32(canbtr); +	msg = kmalloc(sizeof(*msg), GFP_KERNEL); +	if (!msg) +		return -ENOMEM; -	dev_info(netdev->dev.parent, "setting BTR=%#x\n", canbtr); +	msg->msg.hdr.len = 2; +	msg->msg.hdr.cmd = CMD_SETBAUD; +	msg->msg.setbaud.net = priv->index; +	msg->msg.setbaud.rsvd = 0; +	msg->msg.setbaud.baud = cpu_to_le32(canbtr); -	return esd_usb2_send_msg(priv->usb2, &msg); +	netdev_info(netdev, "setting BTR=%#x\n", canbtr); + +	err = esd_usb2_send_msg(priv->usb2, msg); + +	kfree(msg); +	return err;  }  static int esd_usb2_get_berr_counter(const struct net_device *netdev, @@ -928,11 +965,6 @@ static int esd_usb2_get_berr_counter(const struct net_device *netdev,  static int esd_usb2_set_mode(struct net_device *netdev, enum can_mode mode)  { -	struct esd_usb2_net_priv *priv = netdev_priv(netdev); - -	if (!priv->open_time) -		return -EINVAL; -  	switch (mode) {  	case CAN_MODE_START:  		netif_wake_queue(netdev); @@ -973,30 +1005,38 @@ static int esd_usb2_probe_one_net(struct usb_interface *intf, int index)  	priv->index = index;  	priv->can.state = CAN_STATE_STOPPED; -	priv->can.clock.freq = ESD_USB2_CAN_CLOCK; +	priv->can.ctrlmode_supported = CAN_CTRLMODE_LISTENONLY; + +	if (le16_to_cpu(dev->udev->descriptor.idProduct) == +	    USB_CANUSBM_PRODUCT_ID) +		priv->can.clock.freq = ESD_USBM_CAN_CLOCK; +	else { +		priv->can.clock.freq = ESD_USB2_CAN_CLOCK; +		priv->can.ctrlmode_supported |= CAN_CTRLMODE_3_SAMPLES; +	} +  	priv->can.bittiming_const = &esd_usb2_bittiming_const;  	priv->can.do_set_bittiming = esd_usb2_set_bittiming;  	priv->can.do_set_mode = esd_usb2_set_mode;  	priv->can.do_get_berr_counter = esd_usb2_get_berr_counter; -	priv->can.ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES;  	netdev->flags |= IFF_ECHO; /* we support local echo */  	netdev->netdev_ops = &esd_usb2_netdev_ops;  	SET_NETDEV_DEV(netdev, &intf->dev); +	netdev->dev_id = index;  	err = register_candev(netdev);  	if (err) { -		dev_err(&intf->dev, -			"couldn't register CAN device: %d\n", err); +		dev_err(&intf->dev, "couldn't register CAN device: %d\n", err);  		free_candev(netdev);  		err = -ENOMEM;  		goto done;  	}  	dev->nets[index] = priv; -	dev_info(netdev->dev.parent, "device %s registered\n", netdev->name); +	netdev_info(netdev, "device %s registered\n", netdev->name);  done:  	return err; @@ -1012,7 +1052,7 @@ static int esd_usb2_probe(struct usb_interface *intf,  			 const struct usb_device_id *id)  {  	struct esd_usb2 *dev; -	struct esd_usb2_msg msg; +	struct esd_usb2_msg *msg;  	int i, err;  	dev = kzalloc(sizeof(*dev), GFP_KERNEL); @@ -1027,27 +1067,33 @@ static int esd_usb2_probe(struct usb_interface *intf,  	usb_set_intfdata(intf, dev); +	msg = kmalloc(sizeof(*msg), GFP_KERNEL); +	if (!msg) { +		err = -ENOMEM; +		goto free_msg; +	} +  	/* query number of CAN interfaces (nets) */ -	msg.msg.hdr.cmd = CMD_VERSION; -	msg.msg.hdr.len = 2; -	msg.msg.version.rsvd = 0; -	msg.msg.version.flags = 0; -	msg.msg.version.drv_version = 0; +	msg->msg.hdr.cmd = CMD_VERSION; +	msg->msg.hdr.len = 2; +	msg->msg.version.rsvd = 0; +	msg->msg.version.flags = 0; +	msg->msg.version.drv_version = 0; -	err = esd_usb2_send_msg(dev, &msg); +	err = esd_usb2_send_msg(dev, msg);  	if (err < 0) {  		dev_err(&intf->dev, "sending version message failed\n"); -		goto free_dev; +		goto free_msg;  	} -	err = esd_usb2_wait_msg(dev, &msg); +	err = esd_usb2_wait_msg(dev, msg);  	if (err < 0) {  		dev_err(&intf->dev, "no version message answer\n"); -		goto free_dev; +		goto free_msg;  	} -	dev->net_count = (int)msg.msg.version_reply.nets; -	dev->version = le32_to_cpu(msg.msg.version_reply.version); +	dev->net_count = (int)msg->msg.version_reply.nets; +	dev->version = le32_to_cpu(msg->msg.version_reply.version);  	if (device_create_file(&intf->dev, &dev_attr_firmware))  		dev_err(&intf->dev, @@ -1065,10 +1111,10 @@ static int esd_usb2_probe(struct usb_interface *intf,  	for (i = 0; i < dev->net_count; i++)  		esd_usb2_probe_one_net(intf, i); -	return 0; - -free_dev: -	kfree(dev); +free_msg: +	kfree(msg); +	if (err) +		kfree(dev);  done:  	return err;  } @@ -1108,25 +1154,4 @@ static struct usb_driver esd_usb2_driver = {  	.id_table = esd_usb2_table,  }; -static int __init esd_usb2_init(void) -{ -	int err; - -	/* register this driver with the USB subsystem */ -	err = usb_register(&esd_usb2_driver); - -	if (err) { -		err("usb_register failed. Error number %d\n", err); -		return err; -	} - -	return 0; -} -module_init(esd_usb2_init); - -static void __exit esd_usb2_exit(void) -{ -	/* deregister this driver with the USB subsystem */ -	usb_deregister(&esd_usb2_driver); -} -module_exit(esd_usb2_exit); +module_usb_driver(esd_usb2_driver);  | 
