static int net1080_rx_fixup(struct usbnet *dev, struct sk_buff *skb) { struct nc_header *header; struct nc_trailer *trailer; u16 hdr_len, packet_len; /* This check is no longer done by usbnet */ if (skb->len < dev->net->hard_header_len) return 0; if (!(skb->len & 0x01)) { netdev_dbg(dev->net, "rx framesize %d range %d..%d mtu %d\n", skb->len, dev->net->hard_header_len, dev->hard_mtu, dev->net->mtu); dev->net->stats.rx_frame_errors++; nc_ensure_sync(dev); return 0; } header = (struct nc_header *) skb->data; hdr_len = le16_to_cpup(&header->hdr_len); packet_len = le16_to_cpup(&header->packet_len); if (FRAMED_SIZE(packet_len) > NC_MAX_PACKET) { dev->net->stats.rx_frame_errors++; netdev_dbg(dev->net, "packet too big, %d\n", packet_len); nc_ensure_sync(dev); return 0; } else if (hdr_len < MIN_HEADER) { dev->net->stats.rx_frame_errors++; netdev_dbg(dev->net, "header too short, %d\n", hdr_len); nc_ensure_sync(dev); return 0; } else if (hdr_len > MIN_HEADER) { // out of band data for us? netdev_dbg(dev->net, "header OOB, %d bytes\n", hdr_len - MIN_HEADER); nc_ensure_sync(dev); // switch (vendor/product ids) { ... } } skb_pull(skb, hdr_len); trailer = (struct nc_trailer *) (skb->data + skb->len - sizeof *trailer); skb_trim(skb, skb->len - sizeof *trailer); if ((packet_len & 0x01) == 0) { if (skb->data [packet_len] != PAD_BYTE) { dev->net->stats.rx_frame_errors++; netdev_dbg(dev->net, "bad pad\n"); return 0; } skb_trim(skb, skb->len - 1); } if (skb->len != packet_len) { dev->net->stats.rx_frame_errors++; netdev_dbg(dev->net, "bad packet len %d (expected %d)\n", skb->len, packet_len); nc_ensure_sync(dev); return 0; } if (header->packet_id != get_unaligned(&trailer->packet_id)) { dev->net->stats.rx_fifo_errors++; netdev_dbg(dev->net, "(2+ dropped) rx packet_id mismatch 0x%x 0x%x\n", le16_to_cpu(header->packet_id), le16_to_cpu(trailer->packet_id)); return 0; } #if 0 netdev_dbg(dev->net, "frame <rx h %d p %d id %d\n", header->hdr_len, header->packet_len, header->packet_id); #endif dev->frame_errors = 0; return 1; }
static void rx_submit (struct usbnet *dev, struct urb *urb, int flags) { struct sk_buff *skb; struct skb_data *entry; int retval = 0; unsigned long lockflags; size_t size; #ifdef CONFIG_USB_NET1080 if (dev->driver_info->flags & FLAG_FRAMING_NC) size = FRAMED_SIZE (dev->net.mtu); else #endif #ifdef CONFIG_USB_GENESYS if (dev->driver_info->flags & FLAG_FRAMING_GL) size = GL_RCV_BUF_SIZE; else #endif size = (sizeof (struct ethhdr) + dev->net.mtu); if ((skb = alloc_skb (size, flags)) == 0) { dbg ("no rx skb"); tasklet_schedule (&dev->bh); usb_free_urb (urb); return; } entry = (struct skb_data *) skb->cb; entry->urb = urb; entry->dev = dev; entry->state = rx_start; entry->length = 0; FILL_BULK_URB (urb, dev->udev, usb_rcvbulkpipe (dev->udev, dev->driver_info->in), skb->data, size, rx_complete, skb); urb->transfer_flags |= USB_ASYNC_UNLINK; #ifdef REALLY_QUEUE urb->transfer_flags |= USB_QUEUE_BULK; #endif #if 0 // Idle-but-posted reads with UHCI really chew up // PCI bandwidth unless FSBR is disabled urb->transfer_flags |= USB_NO_FSBR; #endif spin_lock_irqsave (&dev->rxq.lock, lockflags); if (netif_running (&dev->net)) { if ((retval = usb_submit_urb (urb)) != 0) { dbg ("%s rx submit, %d", dev->net.name, retval); tasklet_schedule (&dev->bh); } else { __skb_queue_tail (&dev->rxq, skb); } } else { dbg ("rx: stopped"); retval = -ENOLINK; } spin_unlock_irqrestore (&dev->rxq.lock, lockflags); if (retval) { dev_kfree_skb_any (skb); usb_free_urb (urb); } }