|
@@ -175,6 +175,8 @@ static inline struct sk_buff *pull_skb(rtl8150_t *);
|
|
|
static void rtl8150_disconnect(struct usb_interface *intf);
|
|
|
static int rtl8150_probe(struct usb_interface *intf,
|
|
|
const struct usb_device_id *id);
|
|
|
+static int rtl8150_suspend(struct usb_interface *intf, pm_message_t message);
|
|
|
+static int rtl8150_resume(struct usb_interface *intf);
|
|
|
|
|
|
static const char driver_name [] = "rtl8150";
|
|
|
|
|
@@ -183,6 +185,8 @@ static struct usb_driver rtl8150_driver = {
|
|
|
.probe = rtl8150_probe,
|
|
|
.disconnect = rtl8150_disconnect,
|
|
|
.id_table = rtl8150_table,
|
|
|
+ .suspend = rtl8150_suspend,
|
|
|
+ .resume = rtl8150_resume
|
|
|
};
|
|
|
|
|
|
/*
|
|
@@ -238,9 +242,11 @@ static int async_set_registers(rtl8150_t * dev, u16 indx, u16 size)
|
|
|
usb_fill_control_urb(dev->ctrl_urb, dev->udev,
|
|
|
usb_sndctrlpipe(dev->udev, 0), (char *) &dev->dr,
|
|
|
&dev->rx_creg, size, ctrl_callback, dev);
|
|
|
- if ((ret = usb_submit_urb(dev->ctrl_urb, GFP_ATOMIC)))
|
|
|
+ if ((ret = usb_submit_urb(dev->ctrl_urb, GFP_ATOMIC))) {
|
|
|
+ if (ret == -ENODEV)
|
|
|
+ netif_device_detach(dev->netdev);
|
|
|
err("control request submission failed: %d", ret);
|
|
|
- else
|
|
|
+ } else
|
|
|
set_bit(RX_REG_SET, &dev->flags);
|
|
|
|
|
|
return ret;
|
|
@@ -416,6 +422,7 @@ static void read_bulk_callback(struct urb *urb, struct pt_regs *regs)
|
|
|
struct sk_buff *skb;
|
|
|
struct net_device *netdev;
|
|
|
u16 rx_stat;
|
|
|
+ int status;
|
|
|
|
|
|
dev = urb->context;
|
|
|
if (!dev)
|
|
@@ -465,7 +472,10 @@ static void read_bulk_callback(struct urb *urb, struct pt_regs *regs)
|
|
|
goon:
|
|
|
usb_fill_bulk_urb(dev->rx_urb, dev->udev, usb_rcvbulkpipe(dev->udev, 1),
|
|
|
dev->rx_skb->data, RTL8150_MTU, read_bulk_callback, dev);
|
|
|
- if (usb_submit_urb(dev->rx_urb, GFP_ATOMIC)) {
|
|
|
+ status = usb_submit_urb(dev->rx_urb, GFP_ATOMIC);
|
|
|
+ if (status == -ENODEV)
|
|
|
+ netif_device_detach(dev->netdev);
|
|
|
+ else if (status) {
|
|
|
set_bit(RX_URB_FAIL, &dev->flags);
|
|
|
goto resched;
|
|
|
} else {
|
|
@@ -481,6 +491,7 @@ static void rx_fixup(unsigned long data)
|
|
|
{
|
|
|
rtl8150_t *dev;
|
|
|
struct sk_buff *skb;
|
|
|
+ int status;
|
|
|
|
|
|
dev = (rtl8150_t *)data;
|
|
|
|
|
@@ -499,10 +510,13 @@ static void rx_fixup(unsigned long data)
|
|
|
usb_fill_bulk_urb(dev->rx_urb, dev->udev, usb_rcvbulkpipe(dev->udev, 1),
|
|
|
dev->rx_skb->data, RTL8150_MTU, read_bulk_callback, dev);
|
|
|
try_again:
|
|
|
- if (usb_submit_urb(dev->rx_urb, GFP_ATOMIC)) {
|
|
|
+ status = usb_submit_urb(dev->rx_urb, GFP_ATOMIC);
|
|
|
+ if (status == -ENODEV) {
|
|
|
+ netif_device_detach(dev->netdev);
|
|
|
+ } else if (status) {
|
|
|
set_bit(RX_URB_FAIL, &dev->flags);
|
|
|
goto tlsched;
|
|
|
- } else {
|
|
|
+ } else {
|
|
|
clear_bit(RX_URB_FAIL, &dev->flags);
|
|
|
}
|
|
|
|
|
@@ -574,12 +588,43 @@ static void intr_callback(struct urb *urb, struct pt_regs *regs)
|
|
|
|
|
|
resubmit:
|
|
|
status = usb_submit_urb (urb, SLAB_ATOMIC);
|
|
|
- if (status)
|
|
|
+ if (status == -ENODEV)
|
|
|
+ netif_device_detach(dev->netdev);
|
|
|
+ else if (status)
|
|
|
err ("can't resubmit intr, %s-%s/input0, status %d",
|
|
|
dev->udev->bus->bus_name,
|
|
|
dev->udev->devpath, status);
|
|
|
}
|
|
|
|
|
|
+static int rtl8150_suspend(struct usb_interface *intf, pm_message_t message)
|
|
|
+{
|
|
|
+ rtl8150_t *dev = usb_get_intfdata(intf);
|
|
|
+
|
|
|
+ netif_device_detach(dev->netdev);
|
|
|
+
|
|
|
+ if (netif_running(dev->netdev)) {
|
|
|
+ usb_kill_urb(dev->rx_urb);
|
|
|
+ usb_kill_urb(dev->intr_urb);
|
|
|
+ }
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static int rtl8150_resume(struct usb_interface *intf)
|
|
|
+{
|
|
|
+ rtl8150_t *dev = usb_get_intfdata(intf);
|
|
|
+
|
|
|
+ netif_device_attach(dev->netdev);
|
|
|
+ if (netif_running(dev->netdev)) {
|
|
|
+ dev->rx_urb->status = 0;
|
|
|
+ dev->rx_urb->actual_length = 0;
|
|
|
+ read_bulk_callback(dev->rx_urb, NULL);
|
|
|
+
|
|
|
+ dev->intr_urb->status = 0;
|
|
|
+ dev->intr_urb->actual_length = 0;
|
|
|
+ intr_callback(dev->intr_urb, NULL);
|
|
|
+ }
|
|
|
+ return 0;
|
|
|
+}
|
|
|
|
|
|
/*
|
|
|
**
|
|
@@ -690,9 +735,14 @@ static int rtl8150_start_xmit(struct sk_buff *skb, struct net_device *netdev)
|
|
|
usb_fill_bulk_urb(dev->tx_urb, dev->udev, usb_sndbulkpipe(dev->udev, 2),
|
|
|
skb->data, count, write_bulk_callback, dev);
|
|
|
if ((res = usb_submit_urb(dev->tx_urb, GFP_ATOMIC))) {
|
|
|
- warn("failed tx_urb %d\n", res);
|
|
|
- dev->stats.tx_errors++;
|
|
|
- netif_start_queue(netdev);
|
|
|
+ /* Can we get/handle EPIPE here? */
|
|
|
+ if (res == -ENODEV)
|
|
|
+ netif_device_detach(dev->netdev);
|
|
|
+ else {
|
|
|
+ warn("failed tx_urb %d\n", res);
|
|
|
+ dev->stats.tx_errors++;
|
|
|
+ netif_start_queue(netdev);
|
|
|
+ }
|
|
|
} else {
|
|
|
dev->stats.tx_packets++;
|
|
|
dev->stats.tx_bytes += skb->len;
|
|
@@ -729,16 +779,25 @@ static int rtl8150_open(struct net_device *netdev)
|
|
|
|
|
|
usb_fill_bulk_urb(dev->rx_urb, dev->udev, usb_rcvbulkpipe(dev->udev, 1),
|
|
|
dev->rx_skb->data, RTL8150_MTU, read_bulk_callback, dev);
|
|
|
- if ((res = usb_submit_urb(dev->rx_urb, GFP_KERNEL)))
|
|
|
+ if ((res = usb_submit_urb(dev->rx_urb, GFP_KERNEL))) {
|
|
|
+ if (res == -ENODEV)
|
|
|
+ netif_device_detach(dev->netdev);
|
|
|
warn("%s: rx_urb submit failed: %d", __FUNCTION__, res);
|
|
|
+ return res;
|
|
|
+ }
|
|
|
usb_fill_int_urb(dev->intr_urb, dev->udev, usb_rcvintpipe(dev->udev, 3),
|
|
|
dev->intr_buff, INTBUFSIZE, intr_callback,
|
|
|
dev, dev->intr_interval);
|
|
|
- if ((res = usb_submit_urb(dev->intr_urb, GFP_KERNEL)))
|
|
|
+ if ((res = usb_submit_urb(dev->intr_urb, GFP_KERNEL))) {
|
|
|
+ if (res == -ENODEV)
|
|
|
+ netif_device_detach(dev->netdev);
|
|
|
warn("%s: intr_urb submit failed: %d", __FUNCTION__, res);
|
|
|
- netif_start_queue(netdev);
|
|
|
+ usb_kill_urb(dev->rx_urb);
|
|
|
+ return res;
|
|
|
+ }
|
|
|
enable_net_traffic(dev);
|
|
|
set_carrier(netdev);
|
|
|
+ netif_start_queue(netdev);
|
|
|
|
|
|
return res;
|
|
|
}
|