cregit-Linux how code gets into the kernel

Release 4.7 drivers/net/usb/kaweth.c

Directory: drivers/net/usb
/****************************************************************
 *
 *     kaweth.c - driver for KL5KUSB101 based USB->Ethernet
 *
 *     (c) 2000 Interlan Communications
 *     (c) 2000 Stephane Alnet
 *     (C) 2001 Brad Hards
 *     (C) 2002 Oliver Neukum
 *
 *     Original author: The Zapman <zapman@interlan.net>
 *     Inspired by, and much credit goes to Michael Rothwell
 *     <rothwell@interlan.net> for the test equipment, help, and patience
 *     Based off of (and with thanks to) Petko Manolov's pegaus.c driver.
 *     Also many thanks to Joel Silverman and Ed Surprenant at Kawasaki
 *     for providing the firmware and driver resources.
 *
 *     This program is free software; you can redistribute it and/or
 *     modify it under the terms of the GNU General Public License as
 *     published by the Free Software Foundation; either version 2, or
 *     (at your option) any later version.
 *
 *     This program is distributed in the hope that it will be useful,
 *     but WITHOUT ANY WARRANTY; without even the implied warranty of
 *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *     GNU General Public License for more details.
 *
 *     You should have received a copy of the GNU General Public License
 *     along with this program; if not, see <http://www.gnu.org/licenses/>.
 *
 ****************************************************************/

/* TODO:
 * Develop test procedures for USB net interfaces
 * Run test procedures
 * Fix bugs from previous two steps
 * Snoop other OSs for any tricks we're not doing
 * Reduce arbitrary timeouts
 * Smart multicast support
 * Temporary MAC change support
 * Tunable SOFs parameter - ioctl()?
 * Ethernet stats collection
 * Code formatting improvements
 */

#include <linux/module.h>
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/delay.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/usb.h>
#include <linux/types.h>
#include <linux/ethtool.h>
#include <linux/dma-mapping.h>
#include <linux/wait.h>
#include <linux/firmware.h>
#include <asm/uaccess.h>
#include <asm/byteorder.h>


#undef DEBUG


#define KAWETH_MTU			1514

#define KAWETH_BUF_SIZE			1664

#define KAWETH_TX_TIMEOUT		(5 * HZ)

#define KAWETH_SCRATCH_SIZE		32

#define KAWETH_FIRMWARE_BUF_SIZE	4096

#define KAWETH_CONTROL_TIMEOUT		(30000)


#define KAWETH_STATUS_BROKEN		0x0000001

#define KAWETH_STATUS_CLOSING		0x0000002

#define KAWETH_STATUS_SUSPENDING	0x0000004


#define KAWETH_STATUS_BLOCKED (KAWETH_STATUS_CLOSING | KAWETH_STATUS_SUSPENDING)


#define KAWETH_PACKET_FILTER_PROMISCUOUS	0x01

#define KAWETH_PACKET_FILTER_ALL_MULTICAST	0x02

#define KAWETH_PACKET_FILTER_DIRECTED		0x04

#define KAWETH_PACKET_FILTER_BROADCAST		0x08

#define KAWETH_PACKET_FILTER_MULTICAST		0x10

/* Table 7 */

#define KAWETH_COMMAND_GET_ETHERNET_DESC	0x00

#define KAWETH_COMMAND_MULTICAST_FILTERS        0x01

#define KAWETH_COMMAND_SET_PACKET_FILTER	0x02

#define KAWETH_COMMAND_STATISTICS               0x03

#define KAWETH_COMMAND_SET_TEMP_MAC     	0x06

#define KAWETH_COMMAND_GET_TEMP_MAC             0x07

#define KAWETH_COMMAND_SET_URB_SIZE		0x08

#define KAWETH_COMMAND_SET_SOFS_WAIT		0x09

#define KAWETH_COMMAND_SCAN			0xFF


#define KAWETH_SOFS_TO_WAIT			0x05


#define INTBUFFERSIZE				4


#define STATE_OFFSET				0

#define STATE_MASK				0x40

#define	STATE_SHIFT				5


#define IS_BLOCKED(s) (s & KAWETH_STATUS_BLOCKED)


MODULE_AUTHOR("Michael Zappe <zapman@interlan.net>, Stephane Alnet <stephane@u-picardie.fr>, Brad Hards <bhards@bigpond.net.au> and Oliver Neukum <oliver@neukum.org>");
MODULE_DESCRIPTION("KL5USB101 USB Ethernet driver");
MODULE_LICENSE("GPL");
MODULE_FIRMWARE("kaweth/new_code.bin");
MODULE_FIRMWARE("kaweth/new_code_fix.bin");
MODULE_FIRMWARE("kaweth/trigger_code.bin");
MODULE_FIRMWARE("kaweth/trigger_code_fix.bin");


static const char driver_name[] = "kaweth";

static int kaweth_probe(
		struct usb_interface *intf,
		const struct usb_device_id *id	/* from id_table */
	);
static void kaweth_disconnect(struct usb_interface *intf);
static int kaweth_internal_control_msg(struct usb_device *usb_dev,
				       unsigned int pipe,
				       struct usb_ctrlrequest *cmd, void *data,
				       int len, int timeout);
static int kaweth_suspend(struct usb_interface *intf, pm_message_t message);
static int kaweth_resume(struct usb_interface *intf);

/****************************************************************
 *     usb_device_id
 ****************************************************************/

static struct usb_device_id usb_klsi_table[] = {
	{ USB_DEVICE(0x03e8, 0x0008) }, /* AOX Endpoints USB Ethernet */
	{ USB_DEVICE(0x04bb, 0x0901) }, /* I-O DATA USB-ET/T */
	{ USB_DEVICE(0x0506, 0x03e8) }, /* 3Com 3C19250 */
	{ USB_DEVICE(0x0506, 0x11f8) }, /* 3Com 3C460 */
	{ USB_DEVICE(0x0557, 0x2002) }, /* ATEN USB Ethernet */
	{ USB_DEVICE(0x0557, 0x4000) }, /* D-Link DSB-650C */
	{ USB_DEVICE(0x0565, 0x0002) }, /* Peracom Enet */
	{ USB_DEVICE(0x0565, 0x0003) }, /* Optus@Home UEP1045A */
	{ USB_DEVICE(0x0565, 0x0005) }, /* Peracom Enet2 */
	{ USB_DEVICE(0x05e9, 0x0008) }, /* KLSI KL5KUSB101B */
	{ USB_DEVICE(0x05e9, 0x0009) }, /* KLSI KL5KUSB101B (Board change) */
	{ USB_DEVICE(0x066b, 0x2202) }, /* Linksys USB10T */
	{ USB_DEVICE(0x06e1, 0x0008) }, /* ADS USB-10BT */
	{ USB_DEVICE(0x06e1, 0x0009) }, /* ADS USB-10BT */
	{ USB_DEVICE(0x0707, 0x0100) }, /* SMC 2202USB */
	{ USB_DEVICE(0x07aa, 0x0001) }, /* Correga K.K. */
	{ USB_DEVICE(0x07b8, 0x4000) }, /* D-Link DU-E10 */
	{ USB_DEVICE(0x07c9, 0xb010) }, /* Allied Telesyn AT-USB10 USB Ethernet Adapter */
	{ USB_DEVICE(0x0846, 0x1001) }, /* NetGear EA-101 */
	{ USB_DEVICE(0x0846, 0x1002) }, /* NetGear EA-101 */
	{ USB_DEVICE(0x085a, 0x0008) }, /* PortGear Ethernet Adapter */
	{ USB_DEVICE(0x085a, 0x0009) }, /* PortGear Ethernet Adapter */
	{ USB_DEVICE(0x087d, 0x5704) }, /* Jaton USB Ethernet Device Adapter */
	{ USB_DEVICE(0x0951, 0x0008) }, /* Kingston Technology USB Ethernet Adapter */
	{ USB_DEVICE(0x095a, 0x3003) }, /* Portsmith Express Ethernet Adapter */
	{ USB_DEVICE(0x10bd, 0x1427) }, /* ASANTE USB To Ethernet Adapter */
	{ USB_DEVICE(0x1342, 0x0204) }, /* Mobility USB-Ethernet Adapter */
	{ USB_DEVICE(0x13d2, 0x0400) }, /* Shark Pocket Adapter */
	{ USB_DEVICE(0x1485, 0x0001) },	/* Silicom U2E */
	{ USB_DEVICE(0x1485, 0x0002) }, /* Psion Dacom Gold Port Ethernet */
	{ USB_DEVICE(0x1645, 0x0005) }, /* Entrega E45 */
	{ USB_DEVICE(0x1645, 0x0008) }, /* Entrega USB Ethernet Adapter */
	{ USB_DEVICE(0x1645, 0x8005) }, /* PortGear Ethernet Adapter */
	{ USB_DEVICE(0x1668, 0x0323) }, /* Actiontec USB Ethernet */
	{ USB_DEVICE(0x2001, 0x4000) }, /* D-link DSB-650C */
	{} /* Null terminator */
};

MODULE_DEVICE_TABLE (usb, usb_klsi_table);

/****************************************************************
 *     kaweth_driver
 ****************************************************************/

static struct usb_driver kaweth_driver = {
	.name =		driver_name,
	.probe =	kaweth_probe,
	.disconnect =	kaweth_disconnect,
	.suspend =	kaweth_suspend,
	.resume =	kaweth_resume,
	.id_table =     usb_klsi_table,
	.supports_autosuspend =	1,
	.disable_hub_initiated_lpm = 1,
};


typedef __u8 eth_addr_t[6];

/****************************************************************
 *     usb_eth_dev
 ****************************************************************/

struct usb_eth_dev {
	
char *name;
	
__u16 vendor;
	
__u16 device;
	
void *pdata;
};

/****************************************************************
 *     kaweth_ethernet_configuration
 *     Refer Table 8
 ****************************************************************/

struct kaweth_ethernet_configuration
{
	
__u8 size;
	
__u8 reserved1;
	
__u8 reserved2;
	
eth_addr_t hw_addr;
	
__u32 statistics_mask;
	
__le16 segment_size;
	
__u16 max_multicast_filters;
	
__u8 reserved3;
} 
__packed;

/****************************************************************
 *     kaweth_device
 ****************************************************************/

struct kaweth_device
{
	
spinlock_t device_lock;

	
__u32 status;
	
int end;
	
int suspend_lowmem_rx;
	
int suspend_lowmem_ctrl;
	
int linkstate;
	
int opened;
	
struct delayed_work lowmem_work;

	
struct usb_device *dev;
	
struct usb_interface *intf;
	
struct net_device *net;
	
wait_queue_head_t term_wait;

	
struct urb *rx_urb;
	
struct urb *tx_urb;
	
struct urb *irq_urb;

	
dma_addr_t intbufferhandle;
	
__u8 *intbuffer;
	
dma_addr_t rxbufferhandle;
	
__u8 *rx_buf;

	
	
struct sk_buff *tx_skb;

	
__u8 *firmware_buf;
	
__u8 scratch[KAWETH_SCRATCH_SIZE];
	
__u16 packet_filter_bitmap;

	
struct kaweth_ethernet_configuration configuration;

	
struct net_device_stats stats;
};

/****************************************************************
 *     kaweth_control
 ****************************************************************/

static int kaweth_control(struct kaweth_device *kaweth, unsigned int pipe, __u8 request, __u8 requesttype, __u16 value, __u16 index, void *data, __u16 size, int timeout) { struct usb_ctrlrequest *dr; int retval; netdev_dbg(kaweth->net, "kaweth_control()\n"); if(in_interrupt()) { netdev_dbg(kaweth->net, "in_interrupt()\n"); return -EBUSY; } dr = kmalloc(sizeof(struct usb_ctrlrequest), GFP_ATOMIC); if (!dr) return -ENOMEM; dr->bRequestType = requesttype; dr->bRequest = request; dr->wValue = cpu_to_le16(value); dr->wIndex = cpu_to_le16(index); dr->wLength = cpu_to_le16(size); retval = kaweth_internal_control_msg(kaweth->dev, pipe, dr, data, size, timeout); kfree(dr); return retval; }

Contributors

PersonTokensPropCommitsCommitProp
linus torvaldslinus torvalds13482.72%350.00%
kevin cernekeekevin cernekee138.02%116.67%
greg kroah-hartmangreg kroah-hartman127.41%116.67%
harvey harrisonharvey harrison31.85%116.67%
Total162100.00%6100.00%

/**************************************************************** * kaweth_read_configuration ****************************************************************/
static int kaweth_read_configuration(struct kaweth_device *kaweth) { int retval; netdev_dbg(kaweth->net, "Reading kaweth configuration\n"); retval = kaweth_control(kaweth, usb_rcvctrlpipe(kaweth->dev, 0), KAWETH_COMMAND_GET_ETHERNET_DESC, USB_TYPE_VENDOR | USB_DIR_IN | USB_RECIP_DEVICE, 0, 0, (void *)&kaweth->configuration, sizeof(kaweth->configuration), KAWETH_CONTROL_TIMEOUT); return retval; }

Contributors

PersonTokensPropCommitsCommitProp
linus torvaldslinus torvalds6691.67%150.00%
greg kroah-hartmangreg kroah-hartman68.33%150.00%
Total72100.00%2100.00%

/**************************************************************** * kaweth_set_urb_size ****************************************************************/
static int kaweth_set_urb_size(struct kaweth_device *kaweth, __u16 urb_size) { int retval; netdev_dbg(kaweth->net, "Setting URB size to %d\n", (unsigned)urb_size); retval = kaweth_control(kaweth, usb_sndctrlpipe(kaweth->dev, 0), KAWETH_COMMAND_SET_URB_SIZE, USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_DEVICE, urb_size, 0, (void *)&kaweth->scratch, 0, KAWETH_CONTROL_TIMEOUT); return retval; }

Contributors

PersonTokensPropCommitsCommitProp
linus torvaldslinus torvalds6890.67%133.33%
greg kroah-hartmangreg kroah-hartman68.00%133.33%
oliver neukumoliver neukum11.33%133.33%
Total75100.00%3100.00%

/**************************************************************** * kaweth_set_sofs_wait ****************************************************************/
static int kaweth_set_sofs_wait(struct kaweth_device *kaweth, __u16 sofs_wait) { int retval; netdev_dbg(kaweth->net, "Set SOFS wait to %d\n", (unsigned)sofs_wait); retval = kaweth_control(kaweth, usb_sndctrlpipe(kaweth->dev, 0), KAWETH_COMMAND_SET_SOFS_WAIT, USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_DEVICE, sofs_wait, 0, (void *)&kaweth->scratch, 0, KAWETH_CONTROL_TIMEOUT); return retval; }

Contributors

PersonTokensPropCommitsCommitProp
linus torvaldslinus torvalds6890.67%133.33%
greg kroah-hartmangreg kroah-hartman68.00%133.33%
oliver neukumoliver neukum11.33%133.33%
Total75100.00%3100.00%

/**************************************************************** * kaweth_set_receive_filter ****************************************************************/
static int kaweth_set_receive_filter(struct kaweth_device *kaweth, __u16 receive_filter) { int retval; netdev_dbg(kaweth->net, "Set receive filter to %d\n", (unsigned)receive_filter); retval = kaweth_control(kaweth, usb_sndctrlpipe(kaweth->dev, 0), KAWETH_COMMAND_SET_PACKET_FILTER, USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_DEVICE, receive_filter, 0, (void *)&kaweth->scratch, 0, KAWETH_CONTROL_TIMEOUT); return retval; }

Contributors

PersonTokensPropCommitsCommitProp
linus torvaldslinus torvalds6890.67%133.33%
greg kroah-hartmangreg kroah-hartman68.00%133.33%
oliver neukumoliver neukum11.33%133.33%
Total75100.00%3100.00%

/**************************************************************** * kaweth_download_firmware ****************************************************************/
static int kaweth_download_firmware(struct kaweth_device *kaweth, const char *fwname, __u8 interrupt, __u8 type) { const struct firmware *fw; int data_len; int ret; ret = request_firmware(&fw, fwname, &kaweth->dev->dev); if (ret) { dev_err(&kaweth->intf->dev, "Firmware request failed\n"); return ret; } if (fw->size > KAWETH_FIRMWARE_BUF_SIZE) { dev_err(&kaweth->intf->dev, "Firmware too big: %zu\n", fw->size); release_firmware(fw); return -ENOSPC; } data_len = fw->size; memcpy(kaweth->firmware_buf, fw->data, fw->size); release_firmware(fw); kaweth->firmware_buf[2] = (data_len & 0xFF) - 7; kaweth->firmware_buf[3] = data_len >> 8; kaweth->firmware_buf[4] = type; kaweth->firmware_buf[5] = interrupt; netdev_dbg(kaweth->net, "High: %i, Low:%i\n", kaweth->firmware_buf[3], kaweth->firmware_buf[2]); netdev_dbg(kaweth->net, "Downloading firmware at %p to kaweth device at %p\n", kaweth->firmware_buf, kaweth); netdev_dbg(kaweth->net, "Firmware length: %d\n", data_len); return kaweth_control(kaweth, usb_sndctrlpipe(kaweth->dev, 0), KAWETH_COMMAND_SCAN, USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_DEVICE, 0, 0, (void *)kaweth->firmware_buf, data_len, KAWETH_CONTROL_TIMEOUT); }

Contributors

PersonTokensPropCommitsCommitProp
linus torvaldslinus torvalds15558.49%228.57%
david woodhousedavid woodhouse6825.66%114.29%
greg kroah-hartmangreg kroah-hartman3513.21%228.57%
jesper juhljesper juhl51.89%114.29%
alan coxalan cox20.75%114.29%
Total265100.00%7100.00%

/**************************************************************** * kaweth_trigger_firmware ****************************************************************/
static int kaweth_trigger_firmware(struct kaweth_device *kaweth, __u8 interrupt) { kaweth->firmware_buf[0] = 0xB6; kaweth->firmware_buf[1] = 0xC3; kaweth->firmware_buf[2] = 0x01; kaweth->firmware_buf[3] = 0x00; kaweth->firmware_buf[4] = 0x06; kaweth->firmware_buf[5] = interrupt; kaweth->firmware_buf[6] = 0x00; kaweth->firmware_buf[7] = 0x00; netdev_dbg(kaweth->net, "Triggering firmware\n"); return kaweth_control(kaweth, usb_sndctrlpipe(kaweth->dev, 0), KAWETH_COMMAND_SCAN, USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_DEVICE, 0, 0, (void *)kaweth->firmware_buf, 8, KAWETH_CONTROL_TIMEOUT); }

Contributors

PersonTokensPropCommitsCommitProp
linus torvaldslinus torvalds12895.52%150.00%
greg kroah-hartmangreg kroah-hartman64.48%150.00%
Total134100.00%2100.00%

/**************************************************************** * kaweth_reset ****************************************************************/
static int kaweth_reset(struct kaweth_device *kaweth) { int result; netdev_dbg(kaweth->net, "kaweth_reset(%p)\n", kaweth); result = usb_reset_configuration(kaweth->dev); mdelay(10); netdev_dbg(kaweth->net, "kaweth_reset() returns %d.\n", result); return result; }

Contributors

PersonTokensPropCommitsCommitProp
linus torvaldslinus torvalds3871.70%125.00%
greg kroah-hartmangreg kroah-hartman1222.64%125.00%
guillaume gouratguillaume gourat23.77%125.00%
oliver neukumoliver neukum11.89%125.00%
Total53100.00%4100.00%

static void kaweth_usb_receive(struct urb *); static int kaweth_resubmit_rx_urb(struct kaweth_device *, gfp_t); /**************************************************************** int_callback *****************************************************************/
static void kaweth_resubmit_int_urb(struct kaweth_device *kaweth, gfp_t mf) { int status; status = usb_submit_urb (kaweth->irq_urb, mf); if (unlikely(status == -ENOMEM)) { kaweth->suspend_lowmem_ctrl = 1; schedule_delayed_work(&kaweth->lowmem_work, HZ/4); } else { kaweth->suspend_lowmem_ctrl = 0; } if (status) dev_err(&kaweth->intf->dev, "can't resubmit intr, %s-%s, status %d\n", kaweth->dev->bus->bus_name, kaweth->dev->devpath, status); }

Contributors

PersonTokensPropCommitsCommitProp
oliver neukumoliver neukum8989.90%133.33%
greg kroah-hartmangreg kroah-hartman99.09%133.33%
al viroal viro11.01%133.33%
Total99100.00%3100.00%


static void int_callback(struct urb *u) { struct kaweth_device *kaweth = u->context; int act_state; int status = u->status; switch (status) { case 0: /* success */ break; case -ECONNRESET: /* unlink */ case -ENOENT: case -ESHUTDOWN: return; /* -EPIPE: should clear the halt */ default: /* error */ goto resubmit; } /* we check the link state to report changes */ if (kaweth->linkstate != (act_state = ( kaweth->intbuffer[STATE_OFFSET] | STATE_MASK) >> STATE_SHIFT)) { if (act_state) netif_carrier_on(kaweth->net); else netif_carrier_off(kaweth->net); kaweth->linkstate = act_state; } resubmit: kaweth_resubmit_int_urb(kaweth, GFP_ATOMIC); }

Contributors

PersonTokensPropCommitsCommitProp
oliver neukumoliver neukum7461.16%360.00%
david brownelldavid brownell3730.58%120.00%
linus torvaldslinus torvalds108.26%120.00%
Total121100.00%5100.00%


static void kaweth_resubmit_tl(struct work_struct *work) { struct kaweth_device *kaweth = container_of(work, struct kaweth_device, lowmem_work.work); if (IS_BLOCKED(kaweth->status)) return; if (kaweth->suspend_lowmem_rx) kaweth_resubmit_rx_urb(kaweth, GFP_NOIO); if (kaweth->suspend_lowmem_ctrl) kaweth_resubmit_int_urb(kaweth, GFP_NOIO); }

Contributors

PersonTokensPropCommitsCommitProp
oliver neukumoliver neukum4062.50%360.00%
david howellsdavid howells1218.75%120.00%
david brownelldavid brownell1218.75%120.00%
Total64100.00%5100.00%

/**************************************************************** * kaweth_resubmit_rx_urb ****************************************************************/
static int kaweth_resubmit_rx_urb(struct kaweth_device *kaweth, gfp_t mem_flags) { int result; usb_fill_bulk_urb(kaweth->rx_urb, kaweth->dev, usb_rcvbulkpipe(kaweth->dev, 1), kaweth->rx_buf, KAWETH_BUF_SIZE, kaweth_usb_receive, kaweth); kaweth->rx_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; kaweth->rx_urb->transfer_dma = kaweth->rxbufferhandle; if((result = usb_submit_urb(kaweth->rx_urb, mem_flags))) { if (result == -ENOMEM) { kaweth->suspend_lowmem_rx = 1; schedule_delayed_work(&kaweth->lowmem_work, HZ/4); } dev_err(&kaweth->intf->dev, "resubmitting rx_urb %d failed\n", result); } else { kaweth->suspend_lowmem_rx = 0; } return result; }

Contributors

PersonTokensPropCommitsCommitProp
oliver neukumoliver neukum7253.33%444.44%
linus torvaldslinus torvalds5037.04%111.11%
greg kroah-hartmangreg kroah-hartman118.15%222.22%
josh myerjosh myer10.74%111.11%
al viroal viro10.74%111.11%
Total135100.00%9100.00%

static void kaweth_async_set_rx_mode(struct kaweth_device *kaweth); /**************************************************************** * kaweth_usb_receive ****************************************************************/
static void kaweth_usb_receive(struct urb *urb) { struct device *dev = &urb->dev->dev; struct kaweth_device *kaweth = urb->context; struct net_device *net = kaweth->net; int status = urb->status; int count = urb->actual_length; int count2 = urb->transfer_buffer_length; __u16 pkt_len = le16_to_cpup((__le16 *)kaweth->rx_buf); struct sk_buff *skb; if (unlikely(status == -EPIPE)) { kaweth->stats.rx_errors++; kaweth->end = 1; wake_up(&kaweth->term_wait); dev_dbg(dev, "Status was -EPIPE.\n"); return; } if (unlikely(status == -ECONNRESET || status == -ESHUTDOWN)) { /* we are killed - set a flag and wake the disconnect handler */ kaweth->end = 1; wake_up(&kaweth->term_wait); dev_dbg(dev, "Status was -ECONNRESET or -ESHUTDOWN.\n"); return; } if (unlikely(status == -EPROTO || status == -ETIME || status == -EILSEQ)) { kaweth->stats.rx_errors++; dev_dbg(dev, "Status was -EPROTO, -ETIME, or -EILSEQ.\n"); return; } if (unlikely(status == -EOVERFLOW)) { kaweth->stats.rx_errors++; dev_dbg(dev, "Status was -EOVERFLOW.\n"); } spin_lock(&kaweth->device_lock); if (IS_BLOCKED(kaweth->status)) { spin_unlock(&kaweth->device_lock); return; } spin_unlock(&kaweth->device_lock); if(status && status != -EREMOTEIO && count != 1) { dev_err(&kaweth->intf->dev, "%s RX status: %d count: %d packet_len: %d\n", net->name, status, count, (int)pkt_len); kaweth_resubmit_rx_urb(kaweth, GFP_ATOMIC); return; } if(kaweth->net && (count > 2)) { if(pkt_len > (count - 2)) { dev_err(&kaweth->intf->dev, "Packet length too long for USB frame (pkt_len: %x, count: %x)\n", pkt_len, count); dev_err(&kaweth->intf->dev, "Packet len & 2047: %x\n", pkt_len & 2047); dev_err(&kaweth->intf->dev, "Count 2: %x\n", count2); kaweth_resubmit_rx_urb(kaweth, GFP_ATOMIC); return; } if(!(skb = dev_alloc_skb(pkt_len+2))) { kaweth_resubmit_rx_urb(kaweth, GFP_ATOMIC); return; } skb_reserve(skb, 2); /* Align IP on 16 byte boundaries */ skb_copy_to_linear_data(skb, kaweth->rx_buf + 2, pkt_len); skb_put(skb, pkt_len); skb->protocol = eth_type_trans(skb, net); netif_rx(skb); kaweth->stats.rx_packets++; kaweth->stats.rx_bytes += pkt_len; } kaweth_resubmit_rx_urb(kaweth, GFP_ATOMIC); }

Contributors

PersonTokensPropCommitsCommitProp
linus torvaldslinus torvalds22647.18%320.00%
larry fingerlarry finger9620.04%16.67%
oliver neukumoliver neukum8317.33%640.00%
greg kroah-hartmangreg kroah-hartman7215.03%320.00%
david s. millerdavid s. miller10.21%16.67%
al viroal viro10.21%16.67%
Total479100.00%15100.00%

/**************************************************************** * kaweth_open ****************************************************************/
static int kaweth_open(struct net_device *net) { struct kaweth_device *kaweth = netdev_priv(net); int res; netdev_dbg(kaweth->net, "Opening network device.\n"); res = usb_autopm_get_interface(kaweth->intf); if (res) { dev_err(&kaweth->intf->dev, "Interface cannot be resumed.\n"); return -EIO; } res = kaweth_resubmit_rx_urb(kaweth, GFP_KERNEL); if (res) goto err_out; usb_fill_int_urb( kaweth->irq_urb, kaweth->dev, usb_rcvintpipe(kaweth->dev, 3), kaweth->intbuffer, INTBUFFERSIZE, int_callback, kaweth, 250); /* overriding the descriptor */ kaweth->irq_urb->transfer_dma = kaweth->intbufferhandle; kaweth->irq_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; res = usb_submit_urb(kaweth->irq_urb, GFP_KERNEL); if (res) { usb_kill_urb(kaweth->rx_urb); goto err_out; } kaweth->opened = 1; netif_start_queue(net); kaweth_async_set_rx_mode(kaweth); return 0; err_out: usb_autopm_put_interface(kaweth->intf); return -EIO; }

Contributors

PersonTokensPropCommitsCommitProp
oliver neukumoliver neukum13269.47%753.85%
linus torvaldslinus torvalds3820.00%17.69%
greg kroah-hartmangreg kroah-hartman157.89%215.38%
stephen hemmingerstephen hemminger31.58%17.69%
borislav petkovborislav petkov10.53%17.69%
josh myerjosh myer10.53%17.69%
Total190100.00%13100.00%

/**************************************************************** * kaweth_kill_urbs ****************************************************************/
static void kaweth_kill_urbs(struct kaweth_device *kaweth) { usb_kill_urb(kaweth->irq_urb); usb_kill_urb(kaweth->rx_urb); usb_kill_urb(kaweth->tx_urb); cancel_delayed_work_sync(&kaweth->lowmem_work); /* a scheduled work may have resubmitted, we hit them again */ usb_kill_urb(kaweth->irq_urb); usb_kill_urb(kaweth->rx_urb); }

Contributors

PersonTokensPropCommitsCommitProp
oliver neukumoliver neukum2545.45%342.86%
linus torvaldslinus torvalds1221.82%114.29%
herbert xuherbert xu712.73%114.29%
david s. millerdavid s. miller712.73%114.29%
borislav petkovborislav petkov47.27%114.29%
Total55100.00%7100.00%

/**************************************************************** * kaweth_close ****************************************************************/
static int kaweth_close(struct net_device *net) { struct kaweth_device *kaweth = netdev_priv(net); netif_stop_queue(net); kaweth->opened = 0; kaweth->status |= KAWETH_STATUS_CLOSING; kaweth_kill_urbs(kaweth); kaweth->status &= ~KAWETH_STATUS_CLOSING; usb_autopm_put_interface(kaweth->intf); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
oliver neukumoliver neukum4981.67%375.00%
linus torvaldslinus torvalds1118.33%125.00%
Total60100.00%4100.00%


static u32 kaweth_get_link(struct net_device *dev) { struct kaweth_device *kaweth = netdev_priv(dev); return kaweth->linkstate; }

Contributors

PersonTokensPropCommitsCommitProp
oliver neukumoliver neukum2596.15%150.00%
christoph hellwigchristoph hellwig13.85%150.00%
Total26100.00%2100.00%

static const struct ethtool_ops ops = { .get_link = kaweth_get_link }; /**************************************************************** * kaweth_usb_transmit_complete ****************************************************************/
static void kaweth_usb_transmit_complete(struct urb *urb) { struct kaweth_device *kaweth = urb->context; struct sk_buff *skb = kaweth->tx_skb; int status = urb->status; if (unlikely(status != 0)) if (status != -ENOENT) dev_dbg(&urb->dev->dev, "%s: TX status %d.\n", kaweth->net->name, status); netif_wake_queue(kaweth->net); dev_kfree_skb_irq(skb); }

Contributors

PersonTokensPropCommitsCommitProp
linus torvaldslinus torvalds4250.00%114.29%
oliver neukumoliver neukum2833.33%457.14%
greg kroah-hartmangreg kroah-hartman1416.67%228.57%
Total84100.00%7100.00%

/**************************************************************** * kaweth_start_xmit ****************************************************************/
static netdev_tx_t kaweth_start_xmit(struct sk_buff *skb, struct net_device *net) { struct kaweth_device *kaweth = netdev_priv(net); __le16 *private_header; int res; spin_lock_irq(&kaweth->device_lock); kaweth_async_set_rx_mode(kaweth); netif_stop_queue(net); if (IS_BLOCKED(kaweth->status)) { goto skip; } /* We now decide whether we can put our special header into the sk_buff */ if (skb_cloned(skb) || skb_headroom(skb) < 2) { /* no such luck - we make our own */ struct sk_buff *copied_skb; copied_skb = skb_copy_expand(skb, 2, 0, GFP_ATOMIC); dev_kfree_skb_irq(skb); skb = copied_skb; if (!copied_skb) { kaweth->stats.tx_errors++; netif_start_queue(net); spin_unlock_irq(&kaweth->device_lock); return NETDEV_TX_OK; } } private_header = (__le16 *)__skb_push(skb, 2); *private_header = cpu_to_le16(skb->len-2); kaweth->tx_skb = skb; usb_fill_bulk_urb(kaweth->tx_urb, kaweth->dev, usb_sndbulkpipe(kaweth->dev, 2), private_header, skb->len, kaweth_usb_transmit_complete, kaweth); kaweth->end = 0; if((res = usb_submit_urb(kaweth->tx_urb, GFP_ATOMIC))) { dev_warn(&net->dev, "kaweth failed tx_urb %d\n", res); skip: kaweth->stats.tx_errors++; netif_start_queue(net); dev_kfree_skb_irq(skb); } else { kaweth->stats.tx_packets++; kaweth->stats.tx_bytes += skb->len; } spin_unlock_irq(&kaweth->device_lock); return NETDEV_TX_OK; }

Contributors

PersonTokensPropCommitsCommitProp
linus torvaldslinus torvalds14550.70%212.50%
oliver neukumoliver neukum11740.91%531.25%
greg kroah-hartmangreg kroah-hartman93.15%212.50%
stephen hemmingerstephen hemminger41.40%212.50%
andrew mortonandrew morton31.05%16.25%
larry fingerlarry finger31.05%16.25%
al viroal viro20.70%16.25%
patrick mchardypatrick mchardy20.70%16.25%
josh myerjosh myer10.35%16.25%
Total286100.00%16100.00%

/**************************************************************** * kaweth_set_rx_mode ****************************************************************/
static void kaweth_set_rx_mode(struct net_device *net) { struct kaweth_device *kaweth = netdev_priv(net); __u16 packet_filter_bitmap = KAWETH_PACKET_FILTER_DIRECTED | KAWETH_PACKET_FILTER_BROADCAST | KAWETH_PACKET_FILTER_MULTICAST; netdev_dbg(net, "Setting Rx mode to %d\n", packet_filter_bitmap); netif_stop_queue(net); if (net->flags & IFF_PROMISC) { packet_filter_bitmap |= KAWETH_PACKET_FILTER_PROMISCUOUS; } else if (!netdev_mc_empty(net) || (net->flags & IFF_ALLMULTI)) { packet_filter_bitmap |= KAWETH_PACKET_FILTER_ALL_MULTICAST; } kaweth->packet_filter_bitmap = packet_filter_bitmap; netif_wake_queue(net); }

Contributors

PersonTokensPropCommitsCommitProp
linus torvaldslinus torvalds8188.04%125.00%
greg kroah-hartmangreg kroah-hartman44.35%125.00%
jiri pirkojiri pirko44.35%125.00%
stephen hemmingerstephen hemminger33.26%125.00%
Total92100.00%4100.00%

/**************************************************************** * kaweth_async_set_rx_mode ****************************************************************/
static void kaweth_async_set_rx_mode(struct kaweth_device *kaweth) { int result; __u16 packet_filter_bitmap = kaweth->packet_filter_bitmap; kaweth->packet_filter_bitmap = 0; if (packet_filter_bitmap == 0) return; if (in_interrupt()) return; result = kaweth_control(kaweth, usb_sndctrlpipe(kaweth->dev, 0), KAWETH_COMMAND_SET_PACKET_FILTER, USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_DEVICE, packet_filter_bitmap, 0, (void *)&kaweth->scratch, 0, KAWETH_CONTROL_TIMEOUT); if(result < 0) { dev_err(&kaweth->intf->dev, "Failed to set Rx mode: %d\n", result); } else { netdev_dbg(kaweth->net, "Set Rx mode to %d\n", packet_filter_bitmap); } }

Contributors

PersonTokensPropCommitsCommitProp
linus torvaldslinus torvalds9278.63%120.00%
greg kroah-hartmangreg kroah-hartman1512.82%240.00%
larry fingerlarry finger97.69%120.00%
oliver neukumoliver neukum10.85%120.00%
Total117100.00%5100.00%

/**************************************************************** * kaweth_netdev_stats ****************************************************************/
static struct net_device_stats *kaweth_netdev_stats(struct net_device *dev) { struct kaweth_device *kaweth = netdev_priv(dev); return &kaweth->stats; }

Contributors

PersonTokensPropCommitsCommitProp
linus torvaldslinus torvalds1862.07%150.00%
stephen hemmingerstephen hemminger1137.93%150.00%
Total29100.00%2100.00%

/**************************************************************** * kaweth_tx_timeout ****************************************************************/
static void kaweth_tx_timeout(struct net_device *net) { struct kaweth_device *kaweth = netdev_priv(net); dev_warn(&net->dev, "%s: Tx timed out. Resetting.\n", net->name); kaweth->stats.tx_errors++; netif_trans_update(net); usb_unlink_urb(kaweth->tx_urb); }

Contributors

PersonTokensPropCommitsCommitProp
linus torvaldslinus torvalds4175.93%125.00%
greg kroah-hartmangreg kroah-hartman712.96%125.00%
stephen hemmingerstephen hemminger35.56%125.00%
florian westphalflorian westphal35.56%125.00%
Total54100.00%4100.00%

/**************************************************************** * kaweth_suspend ****************************************************************/
static int kaweth_suspend(struct usb_interface *intf, pm_message_t message) { struct kaweth_device *kaweth = usb_get_intfdata(intf); unsigned long flags; dev_dbg(&intf->dev, "Suspending device\n"); spin_lock_irqsave(&kaweth->device_lock, flags); kaweth->status |= KAWETH_STATUS_SUSPENDING; spin_unlock_irqrestore(&kaweth->device_lock, flags); kaweth_kill_urbs(kaweth); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
oliver neukumoliver neukum6590.28%266.67%
greg kroah-hartmangreg kroah-hartman79.72%133.33%
Total72100.00%3100.00%

/**************************************************************** * kaweth_resume ****************************************************************/
static int kaweth_resume(struct usb_interface *intf) { struct kaweth_device *kaweth = usb_get_intfdata(intf); unsigned long flags; dev_dbg(&intf->dev, "Resuming device\n"); spin_lock_irqsave(&kaweth->device_lock, flags); kaweth->status &= ~KAWETH_STATUS_SUSPENDING; spin_unlock_irqrestore(&kaweth->device_lock, flags); if (!kaweth->opened) return 0; kaweth_resubmit_rx_urb(kaweth, GFP_NOIO); kaweth_resubmit_int_urb(kaweth, GFP_NOIO); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
oliver neukumoliver neukum8292.13%266.67%
greg kroah-hartmangreg kroah-hartman77.87%133.33%
Total89100.00%3100.00%

/**************************************************************** * kaweth_probe ****************************************************************/ static const struct net_device_ops kaweth_netdev_ops = { .ndo_open = kaweth_open, .ndo_stop = kaweth_close, .ndo_start_xmit = kaweth_start_xmit, .ndo_tx_timeout = kaweth_tx_timeout, .ndo_set_rx_mode = kaweth_set_rx_mode, .ndo_get_stats = kaweth_netdev_stats, .ndo_change_mtu = eth_change_mtu, .ndo_set_mac_address = eth_mac_addr, .ndo_validate_addr = eth_validate_addr, };
static int kaweth_probe( struct usb_interface *intf, const struct usb_device_id *id /* from id_table */ ) { struct device *dev = &intf->dev; struct usb_device *udev = interface_to_usbdev(intf); struct kaweth_device *kaweth; struct net_device *netdev; const eth_addr_t bcast_addr = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; int result = 0; dev_dbg(dev, "Kawasaki Device Probe (Device number:%d): 0x%4.4x:0x%4.4x:0x%4.4x\n", udev->devnum, le16_to_cpu(udev->descriptor.idVendor), le16_to_cpu(udev->descriptor.idProduct), le16_to_cpu(udev->descriptor.bcdDevice)); dev_dbg(dev, "Device at %p\n", udev); dev_dbg(dev, "Descriptor length: %x type: %x\n", (int)udev->descriptor.bLength, (int)udev->descriptor.bDescriptorType); netdev = alloc_etherdev(sizeof(*kaweth)); if (!netdev) return -ENOMEM; kaweth = netdev_priv(netdev); kaweth->dev = udev; kaweth->net = netdev; spin_lock_init(&kaweth->device_lock); init_waitqueue_head(&kaweth->term_wait); dev_dbg(dev, "Resetting.\n"); kaweth_reset(kaweth); /* * If high byte of bcdDevice is nonzero, firmware is already * downloaded. Don't try to do it again, or we'll hang the device. */ if (le16_to_cpu(udev->descriptor.bcdDevice) >> 8) { dev_info(dev, "Firmware present in device.\n"); } else { /* Download the firmware */ dev_info(dev, "Downloading firmware...\n"); kaweth->firmware_buf = (__u8 *)__get_free_page(GFP_KERNEL); if ((result = kaweth_download_firmware(kaweth, "kaweth/new_code.bin", 100, 2)) < 0) { dev_err(dev, "Error downloading firmware (%d)\n", result); goto err_fw; } if ((result = kaweth_download_firmware(kaweth, "kaweth/new_code_fix.bin", 100, 3)) < 0) { dev_err(dev, "Error downloading firmware fix (%d)\n", result); goto err_fw; } if ((result = kaweth_download_firmware(kaweth, "kaweth/trigger_code.bin", 126, 2)) < 0) { dev_err(dev, "Error downloading trigger code (%d)\n", result); goto err_fw; } if ((result = kaweth_download_firmware(kaweth, "kaweth/trigger_code_fix.bin", 126, 3)) < 0) { dev_err(dev, "Error downloading trigger code fix (%d)\n", result); goto err_fw; } if ((result = kaweth_trigger_firmware(kaweth, 126)) < 0) { dev_err(dev, "Error triggering firmware (%d)\n", result); goto err_fw; } /* Device will now disappear for a moment... */ dev_info(dev, "Firmware loaded. I'll be back...\n"); err_fw: free_page((unsigned long)kaweth->firmware_buf); free_netdev(netdev); return -EIO; } result = kaweth_read_configuration(kaweth); if(result < 0) { dev_err(dev, "Error reading configuration (%d), no net device created\n", result); goto err_free_netdev; } dev_info(dev, "Statistics collection: %x\n", kaweth->configuration.statistics_mask); dev_info(dev, "Multicast filter limit: %x\n", kaweth->configuration.max_multicast_filters & ((1 << 15) - 1)); dev_info(dev, "MTU: %d\n", le16_to_cpu(kaweth->configuration.segment_size)); dev_info(dev, "Read MAC address %pM\n", kaweth->configuration.hw_addr); if(!memcmp(&kaweth->configuration.hw_addr, &bcast_addr, sizeof(bcast_addr))) { dev_err(dev, "Firmware not functioning properly, no net device created\n"); goto err_free_netdev; } if(kaweth_set_urb_size(kaweth, KAWETH_BUF_SIZE) < 0) { dev_dbg(dev, "Error setting URB size\n"); goto err_free_netdev; } if(kaweth_set_sofs_wait(kaweth, KAWETH_SOFS_TO_WAIT) < 0) { dev_err(dev, "Error setting SOFS wait\n"); goto err_free_netdev; } result = kaweth_set_receive_filter(kaweth, KAWETH_PACKET_FILTER_DIRECTED | KAWETH_PACKET_FILTER_BROADCAST | KAWETH_PACKET_FILTER_MULTICAST); if(result < 0) { dev_err(dev, "Error setting receive filter\n"); goto err_free_netdev; } dev_dbg(dev, "Initializing net device.\n"); kaweth->intf = intf; kaweth->tx_urb = usb_alloc_urb(0, GFP_KERNEL); if (!kaweth->tx_urb) goto err_free_netdev; kaweth->rx_urb = usb_alloc_urb(0, GFP_KERNEL); if (!kaweth->rx_urb) goto err_only_tx; kaweth->irq_urb = usb_alloc_urb(0, GFP_KERNEL); if (!kaweth->irq_urb) goto err_tx_and_rx; kaweth->intbuffer = usb_alloc_coherent( kaweth->dev, INTBUFFERSIZE, GFP_KERNEL, &kaweth->intbufferhandle); if (!kaweth->intbuffer) goto err_tx_and_rx_and_irq; kaweth->rx_buf = usb_alloc_coherent( kaweth->dev, KAWETH_BUF_SIZE, GFP_KERNEL, &kaweth->rxbufferhandle); if (!kaweth->rx_buf) goto err_all_but_rxbuf; memcpy(netdev->broadcast, &bcast_addr, sizeof(bcast_addr)); memcpy(netdev->dev_addr, &kaweth->configuration.hw_addr, sizeof(kaweth->configuration.hw_addr)); netdev->netdev_ops = &kaweth_netdev_ops; netdev->watchdog_timeo = KAWETH_TX_TIMEOUT; netdev->mtu = le16_to_cpu(kaweth->configuration.segment_size); netdev->ethtool_ops = &ops; /* kaweth is zeroed as part of alloc_netdev */ INIT_DELAYED_WORK(&kaweth->lowmem_work, kaweth_resubmit_tl); usb_set_intfdata(intf, kaweth); SET_NETDEV_DEV(netdev, dev); if (register_netdev(netdev) != 0) { dev_err(dev, "Error registering netdev.\n"); goto err_intfdata; } dev_info(dev, "kaweth interface created at %s\n", kaweth->net->name); dev_dbg(dev, "Kaweth probe returning.\n"); return 0; err_intfdata: usb_set_intfdata(intf, NULL); usb_free_coherent(kaweth->dev, KAWETH_BUF_SIZE, (void *)kaweth->rx_buf, kaweth->rxbufferhandle); err_all_but_rxbuf: usb_free_coherent(kaweth->dev, INTBUFFERSIZE, (void *)kaweth->intbuffer, kaweth->intbufferhandle); err_tx_and_rx_and_irq: usb_free_urb(kaweth->irq_urb); err_tx_and_rx: usb_free_urb(kaweth->rx_urb); err_only_tx: usb_free_urb(kaweth->tx_urb); err_free_netdev: free_netdev(netdev); return -EIO; }

Contributors

PersonTokensPropCommitsCommitProp
linus torvaldslinus torvalds50950.05%26.67%
oliver neukumoliver neukum23923.50%930.00%
greg kroah-hartmangreg kroah-hartman17116.81%826.67%
stephen hemmingerstephen hemminger575.60%26.67%
al viroal viro212.06%310.00%
david brownelldavid brownell70.69%13.33%
daniel mackdaniel mack40.39%13.33%
david woodhousedavid woodhouse40.39%13.33%
wilfried klaebewilfried klaebe30.29%13.33%
david howellsdavid howells10.10%13.33%
danny kukawkadanny kukawka10.10%13.33%
Total1017100.00%30100.00%

/**************************************************************** * kaweth_disconnect ****************************************************************/
static void kaweth_disconnect(struct usb_interface *intf) { struct kaweth_device *kaweth = usb_get_intfdata(intf); struct net_device *netdev; dev_info(&intf->dev, "Unregistering\n"); usb_set_intfdata(intf, NULL); if (!kaweth) { dev_warn(&intf->dev, "unregistering non-existent device\n"); return; } netdev = kaweth->net; netdev_dbg(kaweth->net, "Unregistering net device\n"); unregister_netdev(netdev); usb_free_urb(kaweth->rx_urb); usb_free_urb(kaweth->tx_urb); usb_free_urb(kaweth->irq_urb); usb_free_coherent(kaweth->dev, KAWETH_BUF_SIZE, (void *)kaweth->rx_buf, kaweth->rxbufferhandle); usb_free_coherent(kaweth->dev, INTBUFFERSIZE, (void *)kaweth->intbuffer, kaweth->intbufferhandle); free_netdev(netdev); }

Contributors

PersonTokensPropCommitsCommitProp
linus torvaldslinus torvalds5134.23%19.09%
oliver neukumoliver neukum4731.54%19.09%
greg kroah-hartmangreg kroah-hartman3221.48%545.45%
stephen hemmingerstephen hemminger149.40%19.09%
al viroal viro21.34%19.09%
daniel mackdaniel mack21.34%19.09%
lucas de marchilucas de marchi10.67%19.09%
Total149100.00%11100.00%

// FIXME this completion stuff is a modified clone of // an OLD version of some stuff in usb.c ... struct usb_api_data { wait_queue_head_t wqh; int done; }; /*-------------------------------------------------------------------* * completion handler for compatibility wrappers (sync control/bulk) * *-------------------------------------------------------------------*/
static void usb_api_blocking_completion(struct urb *urb) { struct usb_api_data *awd = (struct usb_api_data *)urb->context; awd->done=1; wake_up(&awd->wqh); }

Contributors

PersonTokensPropCommitsCommitProp
linus torvaldslinus torvalds39100.00%3100.00%
Total39100.00%3100.00%

/*-------------------------------------------------------------------* * COMPATIBILITY STUFF * *-------------------------------------------------------------------*/ // Starts urb and waits for completion or timeout
static int usb_start_wait_urb(struct urb *urb, int timeout, int* actual_length) { struct usb_api_data awd; int status; init_waitqueue_head(&awd.wqh); awd.done = 0; urb->context = &awd; status = usb_submit_urb(urb, GFP_ATOMIC); if (status) { // something went wrong usb_free_urb(urb); return status; } if (!wait_event_timeout(awd.wqh, awd.done, timeout)) { // timeout dev_warn(&urb->dev->dev, "usb_control/bulk_msg: timeout\n"); usb_kill_urb(urb); // remove urb safely status = -ETIMEDOUT; } else { status = urb->status; } if (actual_length) { *actual_length = urb->actual_length; } usb_free_urb(urb); return status; }

Contributors

PersonTokensPropCommitsCommitProp
linus torvaldslinus torvalds12386.62%337.50%
greg kroah-hartmangreg kroah-hartman107.04%225.00%
nishanth aravamudannishanth aravamudan74.93%112.50%
alexey khoroshilovalexey khoroshilov10.70%112.50%
borislav petkovborislav petkov10.70%112.50%
Total142100.00%8100.00%

/*-------------------------------------------------------------------*/ // returns status (negative) or length (positive)
static int kaweth_internal_control_msg(struct usb_device *usb_dev, unsigned int pipe, struct usb_ctrlrequest *cmd, void *data, int len, int timeout) { struct urb *urb; int retv; int length = 0; /* shut up GCC */ urb = usb_alloc_urb(0, GFP_ATOMIC); if (!urb) return -ENOMEM; usb_fill_control_urb(urb, usb_dev, pipe, (unsigned char*)cmd, data, len, usb_api_blocking_completion, NULL); retv = usb_start_wait_urb(urb, timeout, &length); if (retv < 0) { return retv; } else { return length; } }

Contributors

PersonTokensPropCommitsCommitProp
linus torvaldslinus torvalds10793.04%333.33%
oliver neukumoliver neukum32.61%111.11%
greg kroah-hartmangreg kroah-hartman21.74%222.22%
al viroal viro10.87%111.11%
josh myerjosh myer10.87%111.11%
dan carpenterdan carpenter10.87%111.11%
Total115100.00%9100.00%

module_usb_driver(kaweth_driver);

Overall Contributors

PersonTokensPropCommitsCommitProp
linus torvaldslinus torvalds300055.15%88.08%
oliver neukumoliver neukum139025.55%2626.26%
greg kroah-hartmangreg kroah-hartman4949.08%1414.14%
larry fingerlarry finger1092.00%22.02%
stephen hemmingerstephen hemminger961.76%44.04%
david woodhousedavid woodhouse951.75%11.01%
david brownelldavid brownell561.03%22.02%
al viroal viro360.66%66.06%
ben hutchingsben hutchings150.28%22.02%
david howellsdavid howells140.26%11.01%
kevin cernekeekevin cernekee130.24%11.01%
david s. millerdavid s. miller110.20%33.03%
nishanth aravamudannishanth aravamudan100.18%11.01%
andreas hartmannandreas hartmann100.18%11.01%
olaf heringolaf hering90.17%11.01%
rusty russellrusty russell80.15%11.01%
herbert xuherbert xu70.13%11.01%
christoph hellwigchristoph hellwig70.13%11.01%
borislav petkovborislav petkov60.11%11.01%
daniel mackdaniel mack60.11%11.01%
jiri pirkojiri pirko50.09%22.02%
jesper juhljesper juhl50.09%11.01%
sarah sharpsarah sharp50.09%11.01%
josh myerjosh myer40.07%11.01%
florian westphalflorian westphal30.06%11.01%
harvey harrisonharvey harrison30.06%11.01%
wilfried klaebewilfried klaebe30.06%11.01%
andrew mortonandrew morton30.06%11.01%
guillaume gouratguillaume gourat20.04%11.01%
alan coxalan cox20.04%11.01%
patrick mchardypatrick mchardy20.04%11.01%
dave jonesdave jones20.04%11.01%
harm verhagenharm verhagen20.04%11.01%
dan carpenterdan carpenter10.02%11.01%
russ dillruss dill10.02%11.01%
eric dumazeteric dumazet10.02%11.01%
alexey khoroshilovalexey khoroshilov10.02%11.01%
jeff kirsherjeff kirsher10.02%11.01%
lucas de marchilucas de marchi10.02%11.01%
danny kukawkadanny kukawka10.02%11.01%
Total5440100.00%99100.00%
Directory: drivers/net/usb
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
{% endraw %}