X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fusb%2Fnet%2Fkaweth.c;h=fa78326d0bf0c695f1771929d4e90b12e13ef4ff;hb=refs%2Fheads%2Fvserver;hp=09c6bbe66b39b3a0c800c5ff41722b41ae9042bb;hpb=5273a3df6485dc2ad6aa7ddd441b9a21970f003b;p=linux-2.6.git diff --git a/drivers/usb/net/kaweth.c b/drivers/usb/net/kaweth.c index 09c6bbe66..fa78326d0 100644 --- a/drivers/usb/net/kaweth.c +++ b/drivers/usb/net/kaweth.c @@ -58,21 +58,12 @@ #include #include #include +#include #include #include #include -#define DEBUG - -#ifdef DEBUG -#define kaweth_dbg(format, arg...) printk(KERN_DEBUG __FILE__ ": " format "\n" ,##arg) -#else -#define kaweth_dbg(format, arg...) do {} while (0) -#endif -#define kaweth_err(format, arg...) printk(KERN_ERR __FILE__ ": " format "\n" ,##arg) -#define kaweth_info(format, arg...) printk(KERN_INFO __FILE__ ": " format "\n" , ##arg) -#define kaweth_warn(format, arg...) printk(KERN_WARNING __FILE__ ": " format "\n" , ##arg) - +#undef DEBUG #include "kawethfw.h" @@ -85,6 +76,9 @@ #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 @@ -111,6 +105,8 @@ #define STATE_MASK 0x40 #define STATE_SHIFT 5 +#define IS_BLOCKED(s) (s & KAWETH_STATUS_BLOCKED) + MODULE_AUTHOR("Michael Zappe , Stephane Alnet , Brad Hards and Oliver Neukum "); MODULE_DESCRIPTION("KL5USB101 USB Ethernet driver"); @@ -123,9 +119,12 @@ static int kaweth_probe( const struct usb_device_id *id /* from id_table */ ); static void kaweth_disconnect(struct usb_interface *intf); -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_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 @@ -159,9 +158,11 @@ static struct usb_device_id usb_klsi_table[] = { { 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 */ }; @@ -172,10 +173,11 @@ MODULE_DEVICE_TABLE (usb, usb_klsi_table); * kaweth_driver ****************************************************************/ static struct usb_driver kaweth_driver = { - .owner = THIS_MODULE, .name = driver_name, .probe = kaweth_probe, .disconnect = kaweth_disconnect, + .suspend = kaweth_suspend, + .resume = kaweth_resume, .id_table = usb_klsi_table, }; @@ -202,7 +204,7 @@ struct kaweth_ethernet_configuration __u8 reserved2; eth_addr_t hw_addr; __u32 statistics_mask; - __u16 segment_size; + __le16 segment_size; __u16 max_multicast_filters; __u8 reserved3; } __attribute__ ((packed)); @@ -216,11 +218,11 @@ struct kaweth_device __u32 status; int end; - int removed; int suspend_lowmem_rx; int suspend_lowmem_ctrl; int linkstate; - struct work_struct lowmem_work; + int opened; + struct delayed_work lowmem_work; struct usb_device *dev; struct net_device *net; @@ -245,7 +247,7 @@ struct kaweth_device struct kaweth_ethernet_configuration configuration; struct net_device_stats stats; -} __attribute__ ((packed)); +}; /**************************************************************** @@ -263,17 +265,17 @@ static int kaweth_control(struct kaweth_device *kaweth, { struct usb_ctrlrequest *dr; - kaweth_dbg("kaweth_control()"); + dbg("kaweth_control()"); if(in_interrupt()) { - kaweth_dbg("in_interrupt()"); + dbg("in_interrupt()"); return -EBUSY; } dr = kmalloc(sizeof(struct usb_ctrlrequest), GFP_ATOMIC); if (!dr) { - kaweth_dbg("kmalloc() failed"); + dbg("kmalloc() failed"); return -ENOMEM; } @@ -298,7 +300,7 @@ static int kaweth_read_configuration(struct kaweth_device *kaweth) { int retval; - kaweth_dbg("Reading kaweth configuration"); + dbg("Reading kaweth configuration"); retval = kaweth_control(kaweth, usb_rcvctrlpipe(kaweth->dev, 0), @@ -320,7 +322,7 @@ static int kaweth_set_urb_size(struct kaweth_device *kaweth, __u16 urb_size) { int retval; - kaweth_dbg("Setting URB size to %d", (unsigned)urb_size); + dbg("Setting URB size to %d", (unsigned)urb_size); retval = kaweth_control(kaweth, usb_sndctrlpipe(kaweth->dev, 0), @@ -342,7 +344,7 @@ static int kaweth_set_sofs_wait(struct kaweth_device *kaweth, __u16 sofs_wait) { int retval; - kaweth_dbg("Set SOFS wait to %d", (unsigned)sofs_wait); + dbg("Set SOFS wait to %d", (unsigned)sofs_wait); retval = kaweth_control(kaweth, usb_sndctrlpipe(kaweth->dev, 0), @@ -365,7 +367,7 @@ static int kaweth_set_receive_filter(struct kaweth_device *kaweth, { int retval; - kaweth_dbg("Set receive filter to %d", (unsigned)receive_filter); + dbg("Set receive filter to %d", (unsigned)receive_filter); retval = kaweth_control(kaweth, usb_sndctrlpipe(kaweth->dev, 0), @@ -390,7 +392,7 @@ static int kaweth_download_firmware(struct kaweth_device *kaweth, __u8 type) { if(data_len > KAWETH_FIRMWARE_BUF_SIZE) { - kaweth_err("Firmware too big: %d", data_len); + err("Firmware too big: %d", data_len); return -ENOSPC; } @@ -401,13 +403,13 @@ static int kaweth_download_firmware(struct kaweth_device *kaweth, kaweth->firmware_buf[4] = type; kaweth->firmware_buf[5] = interrupt; - kaweth_dbg("High: %i, Low:%i", kaweth->firmware_buf[3], + dbg("High: %i, Low:%i", kaweth->firmware_buf[3], kaweth->firmware_buf[2]); - kaweth_dbg("Downloading firmware at %p to kaweth device at %p", + dbg("Downloading firmware at %p to kaweth device at %p", data, kaweth); - kaweth_dbg("Firmware length: %d", data_len); + dbg("Firmware length: %d", data_len); return kaweth_control(kaweth, usb_sndctrlpipe(kaweth->dev, 0), @@ -435,7 +437,7 @@ static int kaweth_trigger_firmware(struct kaweth_device *kaweth, kaweth->firmware_buf[6] = 0x00; kaweth->firmware_buf[7] = 0x00; - kaweth_dbg("Triggering firmware"); + dbg("Triggering firmware"); return kaweth_control(kaweth, usb_sndctrlpipe(kaweth->dev, 0), @@ -455,7 +457,7 @@ static int kaweth_reset(struct kaweth_device *kaweth) { int result; - kaweth_dbg("kaweth_reset(%p)", kaweth); + dbg("kaweth_reset(%p)", kaweth); result = kaweth_control(kaweth, usb_sndctrlpipe(kaweth->dev, 0), USB_REQ_SET_CONFIGURATION, @@ -466,21 +468,21 @@ static int kaweth_reset(struct kaweth_device *kaweth) 0, KAWETH_CONTROL_TIMEOUT); - udelay(10000); + mdelay(10); - kaweth_dbg("kaweth_reset() returns %d.",result); + dbg("kaweth_reset() returns %d.",result); return result; } -static void kaweth_usb_receive(struct urb *, struct pt_regs *regs); -static int kaweth_resubmit_rx_urb(struct kaweth_device *, int); +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, int mf) +static void kaweth_resubmit_int_urb(struct kaweth_device *kaweth, gfp_t mf) { int status; @@ -498,7 +500,7 @@ static void kaweth_resubmit_int_urb(struct kaweth_device *kaweth, int mf) kaweth->dev->devpath, status); } -static void int_callback(struct urb *u, struct pt_regs *regs) +static void int_callback(struct urb *u) { struct kaweth_device *kaweth = u->context; int act_state; @@ -517,7 +519,7 @@ static void int_callback(struct urb *u, struct pt_regs *regs) /* we check the link state to report changes */ if (kaweth->linkstate != (act_state = ( kaweth->intbuffer[STATE_OFFSET] | STATE_MASK) >> STATE_SHIFT)) { - if (!act_state) + if (act_state) netif_carrier_on(kaweth->net); else netif_carrier_off(kaweth->net); @@ -528,11 +530,12 @@ resubmit: kaweth_resubmit_int_urb(kaweth, GFP_ATOMIC); } -static void kaweth_resubmit_tl(void *d) +static void kaweth_resubmit_tl(struct work_struct *work) { - struct kaweth_device *kaweth = (struct kaweth_device *)d; + struct kaweth_device *kaweth = + container_of(work, struct kaweth_device, lowmem_work.work); - if (kaweth->status | KAWETH_STATUS_CLOSING) + if (IS_BLOCKED(kaweth->status)) return; if (kaweth->suspend_lowmem_rx) @@ -547,7 +550,7 @@ static void kaweth_resubmit_tl(void *d) * kaweth_resubmit_rx_urb ****************************************************************/ static int kaweth_resubmit_rx_urb(struct kaweth_device *kaweth, - int mem_flags) + gfp_t mem_flags) { int result; @@ -566,7 +569,7 @@ static int kaweth_resubmit_rx_urb(struct kaweth_device *kaweth, kaweth->suspend_lowmem_rx = 1; schedule_delayed_work(&kaweth->lowmem_work, HZ/4); } - kaweth_err("resubmitting rx_urb %d failed", result); + err("resubmitting rx_urb %d failed", result); } else { kaweth->suspend_lowmem_rx = 0; } @@ -579,7 +582,7 @@ static void kaweth_async_set_rx_mode(struct kaweth_device *kaweth); /**************************************************************** * kaweth_usb_receive ****************************************************************/ -static void kaweth_usb_receive(struct urb *urb, struct pt_regs *regs) +static void kaweth_usb_receive(struct urb *urb) { struct kaweth_device *kaweth = urb->context; struct net_device *net = kaweth->net; @@ -587,11 +590,11 @@ static void kaweth_usb_receive(struct urb *urb, struct pt_regs *regs) int count = urb->actual_length; int count2 = urb->transfer_buffer_length; - __u16 pkt_len = le16_to_cpup((u16 *)kaweth->rx_buf); + __u16 pkt_len = le16_to_cpup((__le16 *)kaweth->rx_buf); struct sk_buff *skb; - if(unlikely(urb->status == -ECONNRESET || urb->status == -ECONNABORTED)) + if(unlikely(urb->status == -ECONNRESET || urb->status == -ESHUTDOWN)) /* we are killed - set a flag and wake the disconnect handler */ { kaweth->end = 1; @@ -599,11 +602,15 @@ static void kaweth_usb_receive(struct urb *urb, struct pt_regs *regs) return; } - if (kaweth->status & KAWETH_STATUS_CLOSING) + spin_lock(&kaweth->device_lock); + if (IS_BLOCKED(kaweth->status)) { + spin_unlock(&kaweth->device_lock); return; + } + spin_unlock(&kaweth->device_lock); if(urb->status && urb->status != -EREMOTEIO && count != 1) { - kaweth_err("%s RX status: %d count: %d packet_len: %d", + err("%s RX status: %d count: %d packet_len: %d", net->name, urb->status, count, @@ -614,9 +621,9 @@ static void kaweth_usb_receive(struct urb *urb, struct pt_regs *regs) if(kaweth->net && (count > 2)) { if(pkt_len > (count - 2)) { - kaweth_err("Packet length too long for USB frame (pkt_len: %x, count: %x)",pkt_len, count); - kaweth_err("Packet len & 2047: %x", pkt_len & 2047); - kaweth_err("Count 2: %x", count2); + err("Packet length too long for USB frame (pkt_len: %x, count: %x)",pkt_len, count); + err("Packet len & 2047: %x", pkt_len & 2047); + err("Count 2: %x", count2); kaweth_resubmit_rx_urb(kaweth, GFP_ATOMIC); return; } @@ -650,10 +657,10 @@ static void kaweth_usb_receive(struct urb *urb, struct pt_regs *regs) ****************************************************************/ static int kaweth_open(struct net_device *net) { - struct kaweth_device *kaweth = (struct kaweth_device *)net->priv; + struct kaweth_device *kaweth = netdev_priv(net); int res; - kaweth_dbg("Opening network device."); + dbg("Opening network device."); res = kaweth_resubmit_rx_urb(kaweth, GFP_KERNEL); if (res) @@ -667,15 +674,16 @@ static int kaweth_open(struct net_device *net) INTBUFFERSIZE, int_callback, kaweth, - HZ/4); + 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_unlink_urb(kaweth->rx_urb); + usb_kill_urb(kaweth->rx_urb); return -EIO; } + kaweth->opened = 1; netif_start_queue(net); @@ -683,74 +691,63 @@ static int kaweth_open(struct net_device *net) return 0; } +/**************************************************************** + * kaweth_close + ****************************************************************/ +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); + + flush_scheduled_work(); + + /* a scheduled work may have resubmitted, + we hit them again */ + usb_kill_urb(kaweth->irq_urb); + usb_kill_urb(kaweth->rx_urb); +} + /**************************************************************** * kaweth_close ****************************************************************/ static int kaweth_close(struct net_device *net) { - struct kaweth_device *kaweth = net->priv; + struct kaweth_device *kaweth = netdev_priv(net); netif_stop_queue(net); + kaweth->opened = 0; kaweth->status |= KAWETH_STATUS_CLOSING; - usb_unlink_urb(kaweth->irq_urb); - usb_unlink_urb(kaweth->rx_urb); - - flush_scheduled_work(); - - /* a scheduled work may have resubmitted, - we hit them again */ - usb_unlink_urb(kaweth->irq_urb); - usb_unlink_urb(kaweth->rx_urb); + kaweth_kill_urbs(kaweth); kaweth->status &= ~KAWETH_STATUS_CLOSING; return 0; } -static int netdev_ethtool_ioctl(struct net_device *dev, void __user *useraddr) +static void kaweth_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) { - u32 ethcmd; - - if (copy_from_user(ðcmd, useraddr, sizeof(ethcmd))) - return -EFAULT; - - switch (ethcmd) { - case ETHTOOL_GDRVINFO: { - struct ethtool_drvinfo info = {ETHTOOL_GDRVINFO}; - strlcpy(info.driver, driver_name, sizeof(info.driver)); - if (copy_to_user(useraddr, &info, sizeof(info))) - return -EFAULT; - return 0; - } - } - return -EOPNOTSUPP; + strlcpy(info->driver, driver_name, sizeof(info->driver)); } -/**************************************************************** - * kaweth_ioctl - ****************************************************************/ -static int kaweth_ioctl(struct net_device *net, struct ifreq *rq, int cmd) -{ - switch (cmd) { - case SIOCETHTOOL: - return netdev_ethtool_ioctl(net, (void __user *)rq->ifr_data); - } - return -EOPNOTSUPP; -} +static struct ethtool_ops ops = { + .get_drvinfo = kaweth_get_drvinfo +}; /**************************************************************** * kaweth_usb_transmit_complete ****************************************************************/ -static void kaweth_usb_transmit_complete(struct urb *urb, struct pt_regs *regs) +static void kaweth_usb_transmit_complete(struct urb *urb) { struct kaweth_device *kaweth = urb->context; struct sk_buff *skb = kaweth->tx_skb; if (unlikely(urb->status != 0)) - kaweth_dbg("%s: TX status %d.", kaweth->net->name, urb->status); + if (urb->status != -ENOENT) + dbg("%s: TX status %d.", kaweth->net->name, urb->status); netif_wake_queue(kaweth->net); dev_kfree_skb_irq(skb); @@ -761,22 +758,18 @@ static void kaweth_usb_transmit_complete(struct urb *urb, struct pt_regs *regs) ****************************************************************/ static int kaweth_start_xmit(struct sk_buff *skb, struct net_device *net) { - struct kaweth_device *kaweth = net->priv; - u16 *private_header; + struct kaweth_device *kaweth = netdev_priv(net); + __le16 *private_header; int res; spin_lock(&kaweth->device_lock); - if (kaweth->removed) { - /* our device is undergoing disconnection - we bail out */ - spin_unlock(&kaweth->device_lock); - dev_kfree_skb_irq(skb); - return 0; - } - 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) { @@ -793,7 +786,7 @@ static int kaweth_start_xmit(struct sk_buff *skb, struct net_device *net) } } - private_header = (u16 *)__skb_push(skb, 2); + private_header = (__le16 *)__skb_push(skb, 2); *private_header = cpu_to_le16(skb->len-2); kaweth->tx_skb = skb; @@ -805,11 +798,11 @@ static int kaweth_start_xmit(struct sk_buff *skb, struct net_device *net) kaweth_usb_transmit_complete, kaweth); kaweth->end = 0; - kaweth->tx_urb->transfer_flags |= URB_ASYNC_UNLINK; if((res = usb_submit_urb(kaweth->tx_urb, GFP_ATOMIC))) { - kaweth_warn("kaweth failed tx_urb %d", res); + warn("kaweth failed tx_urb %d", res); +skip: kaweth->stats.tx_errors++; netif_start_queue(net); @@ -832,13 +825,13 @@ static int kaweth_start_xmit(struct sk_buff *skb, struct net_device *net) ****************************************************************/ static void kaweth_set_rx_mode(struct net_device *net) { - struct kaweth_device *kaweth = net->priv; + struct kaweth_device *kaweth = netdev_priv(net); __u16 packet_filter_bitmap = KAWETH_PACKET_FILTER_DIRECTED | KAWETH_PACKET_FILTER_BROADCAST | KAWETH_PACKET_FILTER_MULTICAST; - kaweth_dbg("Setting Rx mode to %d", packet_filter_bitmap); + dbg("Setting Rx mode to %d", packet_filter_bitmap); netif_stop_queue(net); @@ -876,10 +869,10 @@ static void kaweth_async_set_rx_mode(struct kaweth_device *kaweth) KAWETH_CONTROL_TIMEOUT); if(result < 0) { - kaweth_err("Failed to set Rx mode: %d", result); + err("Failed to set Rx mode: %d", result); } else { - kaweth_dbg("Set Rx mode to %d", packet_filter_bitmap); + dbg("Set Rx mode to %d", packet_filter_bitmap); } } } @@ -889,7 +882,8 @@ static void kaweth_async_set_rx_mode(struct kaweth_device *kaweth) ****************************************************************/ static struct net_device_stats *kaweth_netdev_stats(struct net_device *dev) { - return &((struct kaweth_device *)dev->priv)->stats; + struct kaweth_device *kaweth = netdev_priv(dev); + return &kaweth->stats; } /**************************************************************** @@ -897,15 +891,51 @@ static struct net_device_stats *kaweth_netdev_stats(struct net_device *dev) ****************************************************************/ static void kaweth_tx_timeout(struct net_device *net) { - struct kaweth_device *kaweth = net->priv; + struct kaweth_device *kaweth = netdev_priv(net); - kaweth_warn("%s: Tx timed out. Resetting.", net->name); + warn("%s: Tx timed out. Resetting.", net->name); kaweth->stats.tx_errors++; net->trans_start = jiffies; usb_unlink_urb(kaweth->tx_urb); } +/**************************************************************** + * 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; + + 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; +} + +/**************************************************************** + * kaweth_resume + ****************************************************************/ +static int kaweth_resume(struct usb_interface *intf) +{ + struct kaweth_device *kaweth = usb_get_intfdata(intf); + unsigned long flags; + + 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; +} + /**************************************************************** * kaweth_probe ****************************************************************/ @@ -920,28 +950,30 @@ static int kaweth_probe( const eth_addr_t bcast_addr = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; int result = 0; - kaweth_dbg("Kawasaki Device Probe (Device number:%d): 0x%4.4x:0x%4.4x:0x%4.4x", + dbg("Kawasaki Device Probe (Device number:%d): 0x%4.4x:0x%4.4x:0x%4.4x", dev->devnum, - (int)dev->descriptor.idVendor, - (int)dev->descriptor.idProduct, - (int)dev->descriptor.bcdDevice); + le16_to_cpu(dev->descriptor.idVendor), + le16_to_cpu(dev->descriptor.idProduct), + le16_to_cpu(dev->descriptor.bcdDevice)); - kaweth_dbg("Device at %p", dev); + dbg("Device at %p", dev); - kaweth_dbg("Descriptor length: %x type: %x", + dbg("Descriptor length: %x type: %x", (int)dev->descriptor.bLength, (int)dev->descriptor.bDescriptorType); - if(!(kaweth = kmalloc(sizeof(struct kaweth_device), GFP_KERNEL))) + netdev = alloc_etherdev(sizeof(*kaweth)); + if (!netdev) return -ENOMEM; - memset(kaweth, 0, sizeof(struct kaweth_device)); - + kaweth = netdev_priv(netdev); kaweth->dev = dev; + kaweth->net = netdev; + spin_lock_init(&kaweth->device_lock); init_waitqueue_head(&kaweth->term_wait); - kaweth_dbg("Resetting."); + dbg("Resetting."); kaweth_reset(kaweth); @@ -950,21 +982,19 @@ static int kaweth_probe( * downloaded. Don't try to do it again, or we'll hang the device. */ - if (dev->descriptor.bcdDevice >> 8) { - kaweth_info("Firmware present in device."); + if (le16_to_cpu(dev->descriptor.bcdDevice) >> 8) { + info("Firmware present in device."); } else { /* Download the firmware */ - kaweth_info("Downloading firmware..."); + info("Downloading firmware..."); kaweth->firmware_buf = (__u8 *)__get_free_page(GFP_KERNEL); if ((result = kaweth_download_firmware(kaweth, kaweth_new_code, len_kaweth_new_code, 100, 2)) < 0) { - kaweth_err("Error downloading firmware (%d)", result); - free_page((unsigned long)kaweth->firmware_buf); - kfree(kaweth); - return -EIO; + err("Error downloading firmware (%d)", result); + goto err_fw; } if ((result = kaweth_download_firmware(kaweth, @@ -972,10 +1002,8 @@ static int kaweth_probe( len_kaweth_new_code_fix, 100, 3)) < 0) { - kaweth_err("Error downloading firmware fix (%d)", result); - free_page((unsigned long)kaweth->firmware_buf); - kfree(kaweth); - return -EIO; + err("Error downloading firmware fix (%d)", result); + goto err_fw; } if ((result = kaweth_download_firmware(kaweth, @@ -983,10 +1011,9 @@ static int kaweth_probe( len_kaweth_trigger_code, 126, 2)) < 0) { - kaweth_err("Error downloading trigger code (%d)", result); - free_page((unsigned long)kaweth->firmware_buf); - kfree(kaweth); - return -EIO; + err("Error downloading trigger code (%d)", result); + goto err_fw; + } if ((result = kaweth_download_firmware(kaweth, @@ -994,39 +1021,35 @@ static int kaweth_probe( len_kaweth_trigger_code_fix, 126, 3)) < 0) { - kaweth_err("Error downloading trigger code fix (%d)", result); - free_page((unsigned long)kaweth->firmware_buf); - kfree(kaweth); - return -EIO; + err("Error downloading trigger code fix (%d)", result); + goto err_fw; } if ((result = kaweth_trigger_firmware(kaweth, 126)) < 0) { - kaweth_err("Error triggering firmware (%d)", result); - free_page((unsigned long)kaweth->firmware_buf); - kfree(kaweth); - return -EIO; + err("Error triggering firmware (%d)", result); + goto err_fw; } /* Device will now disappear for a moment... */ - kaweth_info("Firmware loaded. I'll be back..."); + info("Firmware loaded. I'll be back..."); +err_fw: free_page((unsigned long)kaweth->firmware_buf); - kfree(kaweth); + free_netdev(netdev); return -EIO; } result = kaweth_read_configuration(kaweth); if(result < 0) { - kaweth_err("Error reading configuration (%d), no net device created", result); - kfree(kaweth); - return -EIO; + err("Error reading configuration (%d), no net device created", result); + goto err_free_netdev; } - kaweth_info("Statistics collection: %x", kaweth->configuration.statistics_mask); - kaweth_info("Multicast filter limit: %x", kaweth->configuration.max_multicast_filters & ((1 << 15) - 1)); - kaweth_info("MTU: %d", le16_to_cpu(kaweth->configuration.segment_size)); - kaweth_info("Read MAC address %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x", + info("Statistics collection: %x", kaweth->configuration.statistics_mask); + info("Multicast filter limit: %x", kaweth->configuration.max_multicast_filters & ((1 << 15) - 1)); + info("MTU: %d", le16_to_cpu(kaweth->configuration.segment_size)); + info("Read MAC address %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x", (int)kaweth->configuration.hw_addr[0], (int)kaweth->configuration.hw_addr[1], (int)kaweth->configuration.hw_addr[2], @@ -1037,19 +1060,18 @@ static int kaweth_probe( if(!memcmp(&kaweth->configuration.hw_addr, &bcast_addr, sizeof(bcast_addr))) { - kaweth_err("Firmware not functioning properly, no net device created"); - kfree(kaweth); - return -EIO; + err("Firmware not functioning properly, no net device created"); + goto err_free_netdev; } if(kaweth_set_urb_size(kaweth, KAWETH_BUF_SIZE) < 0) { - kaweth_dbg("Error setting URB size"); - goto err_no_netdev; + dbg("Error setting URB size"); + goto err_free_netdev; } if(kaweth_set_sofs_wait(kaweth, KAWETH_SOFS_TO_WAIT) < 0) { - kaweth_err("Error setting SOFS wait"); - goto err_no_netdev; + err("Error setting SOFS wait"); + goto err_free_netdev; } result = kaweth_set_receive_filter(kaweth, @@ -1058,21 +1080,15 @@ static int kaweth_probe( KAWETH_PACKET_FILTER_MULTICAST); if(result < 0) { - kaweth_err("Error setting receive filter"); - kfree(kaweth); - return -EIO; + err("Error setting receive filter"); + goto err_free_netdev; } - kaweth_dbg("Initializing net device."); - - if (!(netdev = alloc_etherdev(0))) { - kfree(kaweth); - return -ENOMEM; - } + dbg("Initializing net device."); kaweth->tx_urb = usb_alloc_urb(0, GFP_KERNEL); if (!kaweth->tx_urb) - goto err_no_urb; + goto err_free_netdev; kaweth->rx_urb = usb_alloc_urb(0, GFP_KERNEL); if (!kaweth->rx_urb) goto err_only_tx; @@ -1093,28 +1109,25 @@ static int kaweth_probe( if (!kaweth->rx_buf) goto err_all_but_rxbuf; - kaweth->net = netdev; - memcpy(kaweth->net->broadcast, &bcast_addr, sizeof(bcast_addr)); - memcpy(kaweth->net->dev_addr, - &kaweth->configuration.hw_addr, + memcpy(netdev->broadcast, &bcast_addr, sizeof(bcast_addr)); + memcpy(netdev->dev_addr, &kaweth->configuration.hw_addr, sizeof(kaweth->configuration.hw_addr)); - kaweth->net->priv = kaweth; - kaweth->net->open = kaweth_open; - kaweth->net->stop = kaweth_close; + netdev->open = kaweth_open; + netdev->stop = kaweth_close; - kaweth->net->watchdog_timeo = KAWETH_TX_TIMEOUT; - kaweth->net->tx_timeout = kaweth_tx_timeout; + netdev->watchdog_timeo = KAWETH_TX_TIMEOUT; + netdev->tx_timeout = kaweth_tx_timeout; - kaweth->net->do_ioctl = kaweth_ioctl; - kaweth->net->hard_start_xmit = kaweth_start_xmit; - kaweth->net->set_multicast_list = kaweth_set_rx_mode; - kaweth->net->get_stats = kaweth_netdev_stats; - kaweth->net->mtu = le16_to_cpu(kaweth->configuration.segment_size); + netdev->hard_start_xmit = kaweth_start_xmit; + netdev->set_multicast_list = kaweth_set_rx_mode; + netdev->get_stats = kaweth_netdev_stats; + netdev->mtu = le16_to_cpu(kaweth->configuration.segment_size); + SET_ETHTOOL_OPS(netdev, &ops); - memset(&kaweth->stats, 0, sizeof(kaweth->stats)); + /* kaweth is zeroed as part of alloc_netdev */ - INIT_WORK(&kaweth->lowmem_work, kaweth_resubmit_tl, (void *)kaweth); + INIT_DELAYED_WORK(&kaweth->lowmem_work, kaweth_resubmit_tl); SET_MODULE_OWNER(netdev); @@ -1128,13 +1141,13 @@ static int kaweth_probe( SET_NETDEV_DEV(netdev, &intf->dev); if (register_netdev(netdev) != 0) { - kaweth_err("Error registering netdev."); + err("Error registering netdev."); goto err_intfdata; } - kaweth_info("kaweth interface created at %s", kaweth->net->name); + info("kaweth interface created at %s", kaweth->net->name); - kaweth_dbg("Kaweth probe returning."); + dbg("Kaweth probe returning."); return 0; @@ -1149,10 +1162,9 @@ err_tx_and_rx: usb_free_urb(kaweth->rx_urb); err_only_tx: usb_free_urb(kaweth->tx_urb); -err_no_urb: +err_free_netdev: free_netdev(netdev); -err_no_netdev: - kfree(kaweth); + return -EIO; } @@ -1162,48 +1174,28 @@ err_no_netdev: static void kaweth_disconnect(struct usb_interface *intf) { struct kaweth_device *kaweth = usb_get_intfdata(intf); + struct net_device *netdev; - kaweth_info("Unregistering"); + info("Unregistering"); usb_set_intfdata(intf, NULL); if (!kaweth) { - kaweth_warn("unregistering non-existant device"); + warn("unregistering non-existant device"); return; } + netdev = kaweth->net; - kaweth->removed = 1; - usb_unlink_urb(kaweth->irq_urb); - usb_unlink_urb(kaweth->rx_urb); - - /* we need to wait for the urb to be cancelled, if it is active */ - spin_lock(&kaweth->device_lock); - if (usb_unlink_urb(kaweth->tx_urb) == -EINPROGRESS) { - spin_unlock(&kaweth->device_lock); - wait_event(kaweth->term_wait, kaweth->end); - } else { - spin_unlock(&kaweth->device_lock); - } - - if(kaweth->net) { - if(kaweth->net->flags & IFF_UP) { - kaweth_dbg("Closing net device"); - dev_close(kaweth->net); - } - - kaweth_dbg("Unregistering net device"); - unregister_netdev(kaweth->net); - free_netdev(kaweth->net); - } + dbg("Unregistering net device"); + unregister_netdev(netdev); usb_free_urb(kaweth->rx_urb); usb_free_urb(kaweth->tx_urb); usb_free_urb(kaweth->irq_urb); - usb_buffer_free(kaweth->dev, KAWETH_BUF_SIZE, (void *)kaweth->rx_buf, kaweth->rxbufferhandle); usb_buffer_free(kaweth->dev, INTBUFFERSIZE, (void *)kaweth->intbuffer, kaweth->intbufferhandle); - kfree(kaweth); + free_netdev(netdev); } @@ -1217,7 +1209,7 @@ struct usb_api_data { /*-------------------------------------------------------------------* * completion handler for compatibility wrappers (sync control/bulk) * *-------------------------------------------------------------------*/ -static void usb_api_blocking_completion(struct urb *urb, struct pt_regs *regs) +static void usb_api_blocking_completion(struct urb *urb) { struct usb_api_data *awd = (struct usb_api_data *)urb->context; @@ -1232,35 +1224,24 @@ static void usb_api_blocking_completion(struct urb *urb, struct pt_regs *regs) // Starts urb and waits for completion or timeout static int usb_start_wait_urb(struct urb *urb, int timeout, int* actual_length) { - DECLARE_WAITQUEUE(wait, current); struct usb_api_data awd; int status; init_waitqueue_head(&awd.wqh); awd.done = 0; - set_current_state(TASK_INTERRUPTIBLE); - add_wait_queue(&awd.wqh, &wait); urb->context = &awd; - status = usb_submit_urb(urb, GFP_ATOMIC); + status = usb_submit_urb(urb, GFP_NOIO); if (status) { // something went wrong usb_free_urb(urb); - set_current_state(TASK_RUNNING); - remove_wait_queue(&awd.wqh, &wait); return status; } - while (timeout && !awd.done) - timeout = schedule_timeout(timeout); - - set_current_state(TASK_RUNNING); - remove_wait_queue(&awd.wqh, &wait); - - if (!timeout) { + if (!wait_event_timeout(awd.wqh, awd.done, timeout)) { // timeout - kaweth_warn("usb_control/bulk_msg: timeout"); - usb_unlink_urb(urb); // remove urb safely + warn("usb_control/bulk_msg: timeout"); + usb_kill_urb(urb); // remove urb safely status = -ETIMEDOUT; } else { @@ -1277,9 +1258,10 @@ static int usb_start_wait_urb(struct urb *urb, int timeout, int* actual_length) /*-------------------------------------------------------------------*/ // returns status (negative) or length (positive) -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_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; @@ -1290,7 +1272,7 @@ int kaweth_internal_control_msg(struct usb_device *usb_dev, unsigned int pipe, return -ENOMEM; usb_fill_control_urb(urb, usb_dev, pipe, (unsigned char*)cmd, data, - len, usb_api_blocking_completion,0); + len, usb_api_blocking_completion, NULL); retv = usb_start_wait_urb(urb, timeout, &length); if (retv < 0) { @@ -1305,16 +1287,16 @@ int kaweth_internal_control_msg(struct usb_device *usb_dev, unsigned int pipe, /**************************************************************** * kaweth_init ****************************************************************/ -int __init kaweth_init(void) +static int __init kaweth_init(void) { - kaweth_dbg("Driver loading"); + dbg("Driver loading"); return usb_register(&kaweth_driver); } /**************************************************************** * kaweth_exit ****************************************************************/ -void __exit kaweth_exit(void) +static void __exit kaweth_exit(void) { usb_deregister(&kaweth_driver); }