* Receive routines.
*/
-static void catc_rx_done(struct urb *urb, struct pt_regs *regs)
+static void catc_rx_done(struct urb *urb)
{
struct catc *catc = urb->context;
u8 *pkt_start = urb->transfer_buffer;
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);
}
}
-static void catc_irq_done(struct urb *urb, struct pt_regs *regs)
+static void catc_irq_done(struct urb *urb)
{
struct catc *catc = urb->context;
u8 *data = urb->transfer_buffer;
}
}
resubmit:
- status = usb_submit_urb (urb, SLAB_ATOMIC);
+ status = usb_submit_urb (urb, GFP_ATOMIC);
if (status)
err ("can't resubmit intr, %s-%s, status %d",
catc->usbdev->bus->bus_name,
* Transmit routines.
*/
-static void catc_tx_run(struct catc *catc)
+static int catc_tx_run(struct catc *catc)
{
int status;
catc->tx_ptr = 0;
catc->netdev->trans_start = jiffies;
+ return status;
}
-static void catc_tx_done(struct urb *urb, struct pt_regs *regs)
+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.");
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);
{
struct catc *catc = netdev_priv(netdev);
unsigned long flags;
+ int r = 0;
char *tx_buf;
spin_lock_irqsave(&catc->tx_lock, flags);
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))))
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);
err("submit(ctrl_urb) status %d", status);
}
-static void catc_ctrl_done(struct urb *urb, struct pt_regs *regs)
+static void catc_ctrl_done(struct urb *urb)
{
struct catc *catc = urb->context;
struct ctrl_queue *q;
if ((!catc->ctrl_urb) || (!catc->tx_urb) ||
(!catc->rx_urb) || (!catc->irq_urb)) {
err("No free urbs available.");
- if (catc->ctrl_urb)
- usb_free_urb(catc->ctrl_urb);
- if (catc->tx_urb)
- usb_free_urb(catc->tx_urb);
- if (catc->rx_urb)
- usb_free_urb(catc->rx_urb);
- if (catc->irq_urb)
- usb_free_urb(catc->irq_urb);
+ usb_free_urb(catc->ctrl_urb);
+ usb_free_urb(catc->tx_urb);
+ usb_free_urb(catc->rx_urb);
+ usb_free_urb(catc->irq_urb);
free_netdev(netdev);
return -ENOMEM;
}