Hi,

this adds support for suspend and resume to the kaweth driver.
Please apply.

        Regards
                Oliver

Signed-off-by: Oliver Neukum <[EMAIL PROTECTED]>

--- current/drivers/usb/net/kaweth.c    2006-09-28 23:37:28.000000000 +0200
+++ linux-2.6.18/drivers/usb/net/kaweth.c       2006-10-03 10:14:51.000000000 
+0200
@@ -76,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
@@ -102,6 +105,8 @@
 #define STATE_MASK                             0x40
 #define        STATE_SHIFT                             5
 
+#define IS_BLOCKED(s) (s & KAWETH_STATUS_BLOCKED)
+
 
 MODULE_AUTHOR("Michael Zappe <[EMAIL PROTECTED]>, Stephane Alnet <[EMAIL 
PROTECTED]>, Brad Hards <[EMAIL PROTECTED]> and Oliver Neukum <[EMAIL 
PROTECTED]>");
 MODULE_DESCRIPTION("KL5USB101 USB Ethernet driver");
@@ -118,6 +123,8 @@
                                       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
@@ -169,6 +176,8 @@
        .name =         driver_name,
        .probe =        kaweth_probe,
        .disconnect =   kaweth_disconnect,
+       .suspend =      kaweth_suspend,
+       .resume =       kaweth_resume,
        .id_table =     usb_klsi_table,
 };
 
@@ -212,6 +221,7 @@
        int suspend_lowmem_rx;
        int suspend_lowmem_ctrl;
        int linkstate;
+       int opened;
        struct work_struct lowmem_work;
 
        struct usb_device *dev;
@@ -524,7 +534,7 @@
 {
        struct kaweth_device *kaweth = (struct kaweth_device *)d;
 
-       if (kaweth->status | KAWETH_STATUS_CLOSING)
+       if (IS_BLOCKED(kaweth->status))
                return;
 
        if (kaweth->suspend_lowmem_rx)
@@ -591,8 +601,12 @@
                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) {
                err("%s RX status: %d count: %d packet_len: %d",
@@ -668,6 +682,7 @@
                usb_kill_urb(kaweth->rx_urb);
                return -EIO;
        }
+       kaweth->opened = 1;
 
        netif_start_queue(net);
 
@@ -678,14 +693,8 @@
 /****************************************************************
  *     kaweth_close
  ****************************************************************/
-static int kaweth_close(struct net_device *net)
+static void kaweth_kill_urbs(struct kaweth_device *kaweth)
 {
-       struct kaweth_device *kaweth = netdev_priv(net);
-
-       netif_stop_queue(net);
-
-       kaweth->status |= KAWETH_STATUS_CLOSING;
-
        usb_kill_urb(kaweth->irq_urb);
        usb_kill_urb(kaweth->rx_urb);
        usb_kill_urb(kaweth->tx_urb);
@@ -696,6 +705,21 @@
           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 = netdev_priv(net);
+
+       netif_stop_queue(net);
+       kaweth->opened = 0;
+
+       kaweth->status |= KAWETH_STATUS_CLOSING;
+
+       kaweth_kill_urbs(kaweth);
 
        kaweth->status &= ~KAWETH_STATUS_CLOSING;
 
@@ -742,6 +766,9 @@
 
        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) {
@@ -774,6 +801,7 @@
        if((res = usb_submit_urb(kaweth->tx_urb, GFP_ATOMIC)))
        {
                warn("kaweth failed tx_urb %d", res);
+skip:
                kaweth->stats.tx_errors++;
 
                netif_start_queue(net);
@@ -872,6 +900,42 @@
 }
 
 /****************************************************************
+ *     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
  ****************************************************************/
 static int kaweth_probe(

-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys -- and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
_______________________________________________
linux-usb-devel@lists.sourceforge.net
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel

Reply via email to