diff options
Diffstat (limited to 'drivers/usb/net')
-rw-r--r-- | drivers/usb/net/asix.c | 8 | ||||
-rw-r--r-- | drivers/usb/net/catc.c | 30 | ||||
-rw-r--r-- | drivers/usb/net/dm9601.c | 5 | ||||
-rw-r--r-- | drivers/usb/net/gl620a.c | 2 | ||||
-rw-r--r-- | drivers/usb/net/kaweth.c | 2 | ||||
-rw-r--r-- | drivers/usb/net/net1080.c | 2 | ||||
-rw-r--r-- | drivers/usb/net/pegasus.c | 14 | ||||
-rw-r--r-- | drivers/usb/net/rndis_host.c | 114 | ||||
-rw-r--r-- | drivers/usb/net/rtl8150.c | 1 | ||||
-rw-r--r-- | drivers/usb/net/usbnet.c | 9 | ||||
-rw-r--r-- | drivers/usb/net/usbnet.h | 1 |
11 files changed, 126 insertions, 62 deletions
diff --git a/drivers/usb/net/asix.c b/drivers/usb/net/asix.c index 5808ea0..d5ef97b 100644 --- a/drivers/usb/net/asix.c +++ b/drivers/usb/net/asix.c @@ -298,7 +298,7 @@ static int asix_rx_fixup(struct usbnet *dev, struct sk_buff *skb) if (ax_skb) { ax_skb->len = size; ax_skb->data = packet; - ax_skb->tail = packet + size; + skb_set_tail_pointer(ax_skb, size); usbnet_skb_return(dev, ax_skb); } else { return 0; @@ -338,7 +338,7 @@ static struct sk_buff *asix_tx_fixup(struct usbnet *dev, struct sk_buff *skb, && ((headroom + tailroom) >= (4 + padlen))) { if ((headroom < 4) || (tailroom < padlen)) { skb->data = memmove(skb->head + 4, skb->data, skb->len); - skb->tail = skb->data + skb->len; + skb_set_tail_pointer(skb, skb->len); } } else { struct sk_buff *skb2; @@ -352,11 +352,11 @@ static struct sk_buff *asix_tx_fixup(struct usbnet *dev, struct sk_buff *skb, skb_push(skb, 4); packet_len = (((skb->len - 4) ^ 0x0000ffff) << 16) + (skb->len - 4); cpu_to_le32s(&packet_len); - memcpy(skb->data, &packet_len, sizeof(packet_len)); + skb_copy_to_linear_data(skb, &packet_len, sizeof(packet_len)); if ((skb->len % 512) == 0) { cpu_to_le32s(&padbytes); - memcpy( skb->tail, &padbytes, sizeof(padbytes)); + memcpy(skb_tail_pointer(skb), &padbytes, sizeof(padbytes)); skb_put(skb, sizeof(padbytes)); } return skb; diff --git a/drivers/usb/net/catc.c b/drivers/usb/net/catc.c index 4852012..86e90c5 100644 --- a/drivers/usb/net/catc.c +++ b/drivers/usb/net/catc.c @@ -255,7 +255,6 @@ static void catc_rx_done(struct urb *urb) if (!(skb = dev_alloc_skb(pkt_len))) return; - skb->dev = catc->netdev; eth_copy_and_sum(skb, pkt_start + pkt_offset, pkt_len, 0); skb_put(skb, pkt_len); @@ -356,7 +355,7 @@ resubmit: * Transmit routines. */ -static void catc_tx_run(struct catc *catc) +static int catc_tx_run(struct catc *catc) { int status; @@ -374,12 +373,14 @@ static void catc_tx_run(struct catc *catc) catc->tx_ptr = 0; catc->netdev->trans_start = jiffies; + return status; } static void catc_tx_done(struct urb *urb) { struct catc *catc = urb->context; unsigned long flags; + int r; if (urb->status == -ECONNRESET) { dbg("Tx Reset."); @@ -398,10 +399,13 @@ static void catc_tx_done(struct urb *urb) spin_lock_irqsave(&catc->tx_lock, flags); - if (catc->tx_ptr) - catc_tx_run(catc); - else + if (catc->tx_ptr) { + r = catc_tx_run(catc); + if (unlikely(r < 0)) + clear_bit(TX_RUNNING, &catc->flags); + } else { clear_bit(TX_RUNNING, &catc->flags); + } netif_wake_queue(catc->netdev); @@ -412,6 +416,7 @@ static int catc_hard_start_xmit(struct sk_buff *skb, struct net_device *netdev) { struct catc *catc = netdev_priv(netdev); unsigned long flags; + int r = 0; char *tx_buf; spin_lock_irqsave(&catc->tx_lock, flags); @@ -419,11 +424,14 @@ static int catc_hard_start_xmit(struct sk_buff *skb, struct net_device *netdev) catc->tx_ptr = (((catc->tx_ptr - 1) >> 6) + 1) << 6; tx_buf = catc->tx_buf[catc->tx_idx] + catc->tx_ptr; *((u16*)tx_buf) = (catc->is_f5u011) ? cpu_to_be16((u16)skb->len) : cpu_to_le16((u16)skb->len); - memcpy(tx_buf + 2, skb->data, skb->len); + skb_copy_from_linear_data(skb, tx_buf + 2, skb->len); catc->tx_ptr += skb->len + 2; - if (!test_and_set_bit(TX_RUNNING, &catc->flags)) - catc_tx_run(catc); + if (!test_and_set_bit(TX_RUNNING, &catc->flags)) { + r = catc_tx_run(catc); + if (r < 0) + clear_bit(TX_RUNNING, &catc->flags); + } if ((catc->is_f5u011 && catc->tx_ptr) || (catc->tx_ptr >= ((TX_MAX_BURST - 1) * (PKT_SZ + 2)))) @@ -431,8 +439,10 @@ static int catc_hard_start_xmit(struct sk_buff *skb, struct net_device *netdev) spin_unlock_irqrestore(&catc->tx_lock, flags); - catc->stats.tx_bytes += skb->len; - catc->stats.tx_packets++; + if (r >= 0) { + catc->stats.tx_bytes += skb->len; + catc->stats.tx_packets++; + } dev_kfree_skb(skb); diff --git a/drivers/usb/net/dm9601.c b/drivers/usb/net/dm9601.c index 5130cc7..a6763860 100644 --- a/drivers/usb/net/dm9601.c +++ b/drivers/usb/net/dm9601.c @@ -12,6 +12,7 @@ #include <linux/module.h> #include <linux/sched.h> +#include <linux/stddef.h> #include <linux/init.h> #include <linux/netdevice.h> #include <linux/etherdevice.h> @@ -85,7 +86,7 @@ static int dm_write_reg(struct usbnet *dev, u8 reg, u8 value) usb_sndctrlpipe(dev->udev, 0), DM_WRITE_REG, USB_DIR_OUT | USB_TYPE_VENDOR |USB_RECIP_DEVICE, - value, reg, 0, 0, USB_CTRL_SET_TIMEOUT); + value, reg, NULL, 0, USB_CTRL_SET_TIMEOUT); } static void dm_write_async_callback(struct urb *urb) @@ -171,7 +172,7 @@ static void dm_write_reg_async(struct usbnet *dev, u8 reg, u8 value) usb_fill_control_urb(urb, dev->udev, usb_sndctrlpipe(dev->udev, 0), - (void *)req, 0, 0, dm_write_async_callback, req); + (void *)req, NULL, 0, dm_write_async_callback, req); status = usb_submit_urb(urb, GFP_ATOMIC); if (status < 0) { diff --git a/drivers/usb/net/gl620a.c b/drivers/usb/net/gl620a.c index d257a8e..031cf5c 100644 --- a/drivers/usb/net/gl620a.c +++ b/drivers/usb/net/gl620a.c @@ -157,7 +157,7 @@ genelink_tx_fixup(struct usbnet *dev, struct sk_buff *skb, gfp_t flags) if ((headroom < (4 + 4*1)) || (tailroom < padlen)) { skb->data = memmove(skb->head + (4 + 4*1), skb->data, skb->len); - skb->tail = skb->data + skb->len; + skb_set_tail_pointer(skb, skb->len); } } else { struct sk_buff *skb2; diff --git a/drivers/usb/net/kaweth.c b/drivers/usb/net/kaweth.c index de95268..a0cc05d 100644 --- a/drivers/usb/net/kaweth.c +++ b/drivers/usb/net/kaweth.c @@ -636,8 +636,6 @@ static void kaweth_usb_receive(struct urb *urb) skb_reserve(skb, 2); /* Align IP on 16 byte boundaries */ - skb->dev = net; - eth_copy_and_sum(skb, kaweth->rx_buf + 2, pkt_len, 0); skb_put(skb, pkt_len); diff --git a/drivers/usb/net/net1080.c b/drivers/usb/net/net1080.c index ccebfde..19bf8da 100644 --- a/drivers/usb/net/net1080.c +++ b/drivers/usb/net/net1080.c @@ -520,7 +520,7 @@ net1080_tx_fixup(struct usbnet *dev, struct sk_buff *skb, gfp_t flags) skb->data = memmove(skb->head + sizeof (struct nc_header), skb->data, skb->len); - skb->tail = skb->data + len; + skb_set_tail_pointer(skb, len); goto encapsulate; } } diff --git a/drivers/usb/net/pegasus.c b/drivers/usb/net/pegasus.c index d48c024..a05fd97 100644 --- a/drivers/usb/net/pegasus.c +++ b/drivers/usb/net/pegasus.c @@ -316,6 +316,7 @@ static int update_eth_regs_async(pegasus_t * pegasus) return ret; } +/* Returns 0 on success, error on failure */ static int read_mii_word(pegasus_t * pegasus, __u8 phy, __u8 indx, __u16 * regd) { int i; @@ -574,7 +575,6 @@ static void fill_skb_pool(pegasus_t * pegasus) */ if (pegasus->rx_pool[i] == NULL) return; - pegasus->rx_pool[i]->dev = pegasus->net; skb_reserve(pegasus->rx_pool[i], 2); } } @@ -847,10 +847,6 @@ static void intr_callback(struct urb *urb) * d[0].NO_CARRIER kicks in only with failed TX. * ... so monitoring with MII may be safest. */ - if (d[0] & NO_CARRIER) - netif_carrier_off(net); - else - netif_carrier_on(net); /* bytes 3-4 == rx_lostpkt, reg 2E/2F */ pegasus->stats.rx_missed_errors += ((d[3] & 0x7f) << 8) | d[4]; @@ -883,7 +879,7 @@ static int pegasus_start_xmit(struct sk_buff *skb, struct net_device *net) netif_stop_queue(net); ((__le16 *) pegasus->tx_buff)[0] = cpu_to_le16(l16); - memcpy(pegasus->tx_buff + 2, skb->data, skb->len); + skb_copy_from_linear_data(skb, pegasus->tx_buff + 2, skb->len); usb_fill_bulk_urb(pegasus->tx_urb, pegasus->usb, usb_sndbulkpipe(pegasus->usb, 2), pegasus->tx_buff, count, @@ -950,7 +946,7 @@ static void set_carrier(struct net_device *net) pegasus_t *pegasus = netdev_priv(net); u16 tmp; - if (!read_mii_word(pegasus, pegasus->phy, MII_BMSR, &tmp)) + if (read_mii_word(pegasus, pegasus->phy, MII_BMSR, &tmp)) return; if (tmp & BMSR_LSTATUS) @@ -1408,8 +1404,10 @@ static void pegasus_disconnect(struct usb_interface *intf) unlink_all_urbs(pegasus); free_all_urbs(pegasus); free_skb_pool(pegasus); - if (pegasus->rx_skb) + if (pegasus->rx_skb != NULL) { dev_kfree_skb(pegasus->rx_skb); + pegasus->rx_skb = NULL; + } free_netdev(pegasus->net); } diff --git a/drivers/usb/net/rndis_host.c b/drivers/usb/net/rndis_host.c index 39a21c7..980e4aa 100644 --- a/drivers/usb/net/rndis_host.c +++ b/drivers/usb/net/rndis_host.c @@ -253,6 +253,7 @@ struct rndis_keepalive_c { /* IN (optionally OUT) */ * of that mess as possible. */ #define OID_802_3_PERMANENT_ADDRESS ccpu2(0x01010101) +#define OID_GEN_MAXIMUM_FRAME_SIZE ccpu2(0x00010106) #define OID_GEN_CURRENT_PACKET_FILTER ccpu2(0x0001010e) /* @@ -349,7 +350,7 @@ static int rndis_command(struct usbnet *dev, struct rndis_msg_hdr *buf) case RNDIS_MSG_INDICATE: { /* fault */ // struct rndis_indicate *msg = (void *)buf; dev_info(&info->control->dev, - "rndis fault indication\n"); + "rndis fault indication\n"); } break; case RNDIS_MSG_KEEPALIVE: { /* ping */ @@ -387,6 +388,71 @@ static int rndis_command(struct usbnet *dev, struct rndis_msg_hdr *buf) return -ETIMEDOUT; } +/* + * rndis_query: + * + * Performs a query for @oid along with 0 or more bytes of payload as + * specified by @in_len. If @reply_len is not set to -1 then the reply + * length is checked against this value, resulting in an error if it + * doesn't match. + * + * NOTE: Adding a payload exactly or greater than the size of the expected + * response payload is an evident requirement MSFT added for ActiveSync. + * + * The only exception is for OIDs that return a variably sized response, + * in which case no payload should be added. This undocumented (and + * nonsensical!) issue was found by sniffing protocol requests from the + * ActiveSync 4.1 Windows driver. + */ +static int rndis_query(struct usbnet *dev, struct usb_interface *intf, + void *buf, u32 oid, u32 in_len, + void **reply, int *reply_len) +{ + int retval; + union { + void *buf; + struct rndis_msg_hdr *header; + struct rndis_query *get; + struct rndis_query_c *get_c; + } u; + u32 off, len; + + u.buf = buf; + + memset(u.get, 0, sizeof *u.get + in_len); + u.get->msg_type = RNDIS_MSG_QUERY; + u.get->msg_len = cpu_to_le32(sizeof *u.get + in_len); + u.get->oid = oid; + u.get->len = cpu_to_le32(in_len); + u.get->offset = ccpu2(20); + + retval = rndis_command(dev, u.header); + if (unlikely(retval < 0)) { + dev_err(&intf->dev, "RNDIS_MSG_QUERY(0x%08x) failed, %d\n", + oid, retval); + return retval; + } + + off = le32_to_cpu(u.get_c->offset); + len = le32_to_cpu(u.get_c->len); + if (unlikely((8 + off + len) > CONTROL_BUFFER_SIZE)) + goto response_error; + + if (*reply_len != -1 && len != *reply_len) + goto response_error; + + *reply = (unsigned char *) &u.get_c->request_id + off; + *reply_len = len; + + return retval; + +response_error: + dev_err(&intf->dev, "RNDIS_MSG_QUERY(0x%08x) " + "invalid response - off %d len %d\n", + oid, off, len); + return -EDOM; +} + static int rndis_bind(struct usbnet *dev, struct usb_interface *intf) { int retval; @@ -403,6 +469,8 @@ static int rndis_bind(struct usbnet *dev, struct usb_interface *intf) struct rndis_set_c *set_c; } u; u32 tmp; + int reply_len; + unsigned char *bp; /* we can't rely on i/o from stack working, or stack allocation */ u.buf = kmalloc(CONTROL_BUFFER_SIZE, GFP_KERNEL); @@ -421,6 +489,12 @@ static int rndis_bind(struct usbnet *dev, struct usb_interface *intf) * TX we'll stick to one Ethernet packet plus RNDIS framing. * For RX we handle drivers that zero-pad to end-of-packet. * Don't let userspace change these settings. + * + * NOTE: there still seems to be wierdness here, as if we need + * to do some more things to make sure WinCE targets accept this. + * They default to jumbograms of 8KB or 16KB, which is absurd + * for such low data rates and which is also more than Linux + * can usually expect to allocate for SKB data... */ net->hard_header_len += sizeof (struct rndis_data_hdr); dev->hard_mtu = net->mtu + net->hard_header_len; @@ -434,7 +508,7 @@ static int rndis_bind(struct usbnet *dev, struct usb_interface *intf) if (unlikely(retval < 0)) { /* it might not even be an RNDIS device!! */ dev_err(&intf->dev, "RNDIS init failed, %d\n", retval); - goto fail_and_release; + goto fail_and_release; } tmp = le32_to_cpu(u.init_c->max_transfer_size); if (tmp < dev->hard_mtu) { @@ -450,34 +524,15 @@ static int rndis_bind(struct usbnet *dev, struct usb_interface *intf) dev->hard_mtu, tmp, dev->rx_urb_size, 1 << le32_to_cpu(u.init_c->packet_alignment)); - /* Get designated host ethernet address. - * - * Adding a payload exactly the same size as the expected response - * payload is an evident requirement MSFT added for ActiveSync. - * This undocumented (and nonsensical) issue was found by sniffing - * protocol requests from the ActiveSync 4.1 Windows driver. - */ - memset(u.get, 0, sizeof *u.get + 48); - u.get->msg_type = RNDIS_MSG_QUERY; - u.get->msg_len = ccpu2(sizeof *u.get + 48); - u.get->oid = OID_802_3_PERMANENT_ADDRESS; - u.get->len = ccpu2(48); - u.get->offset = ccpu2(20); - - retval = rndis_command(dev, u.header); - if (unlikely(retval < 0)) { + /* Get designated host ethernet address */ + reply_len = ETH_ALEN; + retval = rndis_query(dev, intf, u.buf, OID_802_3_PERMANENT_ADDRESS, + 48, (void **) &bp, &reply_len); + if (unlikely(retval< 0)) { dev_err(&intf->dev, "rndis get ethaddr, %d\n", retval); goto fail_and_release; } - tmp = le32_to_cpu(u.get_c->offset); - if (unlikely((tmp + 8) > (CONTROL_BUFFER_SIZE - ETH_ALEN) - || u.get_c->len != ccpu2(ETH_ALEN))) { - dev_err(&intf->dev, "rndis ethaddr off %d len %d ?\n", - tmp, le32_to_cpu(u.get_c->len)); - retval = -EDOM; - goto fail_and_release; - } - memcpy(net->dev_addr, tmp + (char *)&u.get_c->request_id, ETH_ALEN); + memcpy(net->dev_addr, bp, ETH_ALEN); /* set a nonzero filter to enable data transfers */ memset(u.set, 0, sizeof *u.set); @@ -502,6 +557,7 @@ static int rndis_bind(struct usbnet *dev, struct usb_interface *intf) fail_and_release: usb_set_intfdata(info->data, NULL); usb_driver_release_interface(driver_of(intf), info->data); + info->data = NULL; fail: kfree(u.buf); return retval; @@ -588,7 +644,7 @@ rndis_tx_fixup(struct usbnet *dev, struct sk_buff *skb, gfp_t flags) if (likely((sizeof *hdr) <= room)) { skb->data = memmove(skb->head + sizeof *hdr, skb->data, len); - skb->tail = skb->data + len; + skb_set_tail_pointer(skb, len); goto fill; } } @@ -618,7 +674,7 @@ fill: static const struct driver_info rndis_info = { .description = "RNDIS device", - .flags = FLAG_ETHER | FLAG_FRAMING_RN, + .flags = FLAG_ETHER | FLAG_FRAMING_RN | FLAG_NO_SETINT, .bind = rndis_bind, .unbind = rndis_unbind, .status = rndis_status, diff --git a/drivers/usb/net/rtl8150.c b/drivers/usb/net/rtl8150.c index ea153dc..fa598f0 100644 --- a/drivers/usb/net/rtl8150.c +++ b/drivers/usb/net/rtl8150.c @@ -646,7 +646,6 @@ static void fill_skb_pool(rtl8150_t *dev) if (!skb) { return; } - skb->dev = dev->netdev; skb_reserve(skb, 2); dev->rx_skb_pool[i] = skb; } diff --git a/drivers/usb/net/usbnet.c b/drivers/usb/net/usbnet.c index de69b18..f9cd42d 100644 --- a/drivers/usb/net/usbnet.c +++ b/drivers/usb/net/usbnet.c @@ -203,7 +203,6 @@ void usbnet_skb_return (struct usbnet *dev, struct sk_buff *skb) { int status; - skb->dev = dev->net; skb->protocol = eth_type_trans (skb, dev->net); dev->stats.rx_packets++; dev->stats.rx_bytes += skb->len; @@ -735,8 +734,7 @@ void usbnet_get_drvinfo (struct net_device *net, struct ethtool_drvinfo *info) { struct usbnet *dev = netdev_priv(net); - /* REVISIT don't always return "usbnet" */ - strncpy (info->driver, driver_name, sizeof info->driver); + strncpy (info->driver, dev->driver_name, sizeof info->driver); strncpy (info->version, DRIVER_VERSION, sizeof info->version); strncpy (info->fw_version, dev->driver_info->description, sizeof info->fw_version); @@ -1116,10 +1114,12 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod) struct driver_info *info; struct usb_device *xdev; int status; + const char *name; + name = udev->dev.driver->name; info = (struct driver_info *) prod->driver_info; if (!info) { - dev_dbg (&udev->dev, "blacklisted by %s\n", driver_name); + dev_dbg (&udev->dev, "blacklisted by %s\n", name); return -ENODEV; } xdev = interface_to_usbdev (udev); @@ -1139,6 +1139,7 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod) dev = netdev_priv(net); dev->udev = xdev; dev->driver_info = info; + dev->driver_name = name; dev->msg_enable = netif_msg_init (msg_level, NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_LINK); skb_queue_head_init (&dev->rxq); diff --git a/drivers/usb/net/usbnet.h b/drivers/usb/net/usbnet.h index 07c70ab..cbb53e0 100644 --- a/drivers/usb/net/usbnet.h +++ b/drivers/usb/net/usbnet.h @@ -29,6 +29,7 @@ struct usbnet { /* housekeeping */ struct usb_device *udev; struct driver_info *driver_info; + const char *driver_name; wait_queue_head_t *wait; struct mutex phy_mutex; |