[IRDA]: nsc-ircc: PM update
authorDmitry Torokhov <dtor@mail.ru>
Tue, 21 Mar 2006 02:59:05 +0000 (18:59 -0800)
committerDavid S. Miller <davem@davemloft.net>
Tue, 21 Mar 2006 02:59:05 +0000 (18:59 -0800)
This patch brings the nsc-ircc code to a more up to date power
management scheme, following the current device model.

Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
Signed-off-by: Rudolf Marek <r.marek@sh.cvut.cz>
Signed-off-by: Samuel Ortiz <samuel.ortiz@nokia.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/irda/nsc-ircc.c
drivers/net/irda/nsc-ircc.h

index 282414ba22f03784cd70deaba9378bf5ba4cdc85..81a4ccf54c574d450322a1d45f2b4d6450746891 100644 (file)
 #include <linux/rtnetlink.h>
 #include <linux/dma-mapping.h>
 #include <linux/pnp.h>
+#include <linux/platform_device.h>
 
 #include <asm/io.h>
 #include <asm/dma.h>
 #include <asm/byteorder.h>
 
-#include <linux/pm.h>
-#include <linux/pm_legacy.h>
-
 #include <net/irda/wrapper.h>
 #include <net/irda/irda.h>
 #include <net/irda/irda_device.h>
 
 static char *driver_name = "nsc-ircc";
 
+/* Power Management */
+#define NSC_IRCC_DRIVER_NAME                  "nsc-ircc"
+static int nsc_ircc_suspend(struct platform_device *dev, pm_message_t state);
+static int nsc_ircc_resume(struct platform_device *dev);
+
+static struct platform_driver nsc_ircc_driver = {
+       .suspend        = nsc_ircc_suspend,
+       .resume         = nsc_ircc_resume,
+       .driver         = {
+               .name   = NSC_IRCC_DRIVER_NAME,
+       },
+};
+
 /* Module parameters */
 static int qos_mtt_bits = 0x07;  /* 1 ms or more */
 static int dongle_id;
@@ -164,7 +175,6 @@ static int  nsc_ircc_net_open(struct net_device *dev);
 static int  nsc_ircc_net_close(struct net_device *dev);
 static int  nsc_ircc_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
 static struct net_device_stats *nsc_ircc_net_get_stats(struct net_device *dev);
-static int nsc_ircc_pmproc(struct pm_dev *dev, pm_request_t rqst, void *data);
 
 /* Globals */
 static int pnp_registered;
@@ -186,6 +196,12 @@ static int __init nsc_ircc_init(void)
        int reg;
        int i = 0;
 
+       ret = platform_driver_register(&nsc_ircc_driver);
+        if (ret) {
+                IRDA_ERROR("%s, Can't register driver!\n", driver_name);
+                return ret;
+        }
+
        /* Register with PnP subsystem to detect disable ports */
        ret = pnp_register_driver(&nsc_ircc_pnp_driver);
 
@@ -274,6 +290,7 @@ static int __init nsc_ircc_init(void)
        }
 
        if (ret) {
+               platform_driver_unregister(&nsc_ircc_driver);
                pnp_unregister_driver(&nsc_ircc_pnp_driver);
                pnp_registered = 0;
        }
@@ -291,13 +308,13 @@ static void __exit nsc_ircc_cleanup(void)
 {
        int i;
 
-       pm_unregister_all(nsc_ircc_pmproc);
-
        for (i = 0; i < ARRAY_SIZE(dev_self); i++) {
                if (dev_self[i])
                        nsc_ircc_close(dev_self[i]);
        }
 
+       platform_driver_unregister(&nsc_ircc_driver);
+
        if (pnp_registered)
                pnp_unregister_driver(&nsc_ircc_pnp_driver);
 
@@ -314,7 +331,6 @@ static int __init nsc_ircc_open(chipio_t *info)
 {
        struct net_device *dev;
        struct nsc_ircc_cb *self;
-       struct pm_dev *pmdev;
        void *ret;
        int err, chip_index;
 
@@ -444,11 +460,18 @@ static int __init nsc_ircc_open(chipio_t *info)
        self->io.dongle_id = dongle_id;
        nsc_ircc_init_dongle_interface(self->io.fir_base, dongle_id);
 
-        pmdev = pm_register(PM_SYS_DEV, PM_SYS_IRDA, nsc_ircc_pmproc);
-        if (pmdev)
-                pmdev->data = self;
+       self->pldev = platform_device_register_simple(NSC_IRCC_DRIVER_NAME,
+                                                     self->index, NULL, 0);
+       if (IS_ERR(self->pldev)) {
+               err = PTR_ERR(self->pldev);
+               goto out5;
+       }
+       platform_set_drvdata(self->pldev, self);
 
        return chip_index;
+
+ out5:
+       unregister_netdev(dev);
  out4:
        dma_free_coherent(NULL, self->tx_buff.truesize,
                          self->tx_buff.head, self->tx_buff_dma);
@@ -479,6 +502,8 @@ static int __exit nsc_ircc_close(struct nsc_ircc_cb *self)
 
         iobase = self->io.fir_base;
 
+       platform_device_unregister(self->pldev);
+
        /* Remove netdevice */
        unregister_netdev(self->netdev);
 
@@ -2278,45 +2303,83 @@ static struct net_device_stats *nsc_ircc_net_get_stats(struct net_device *dev)
        return &self->stats;
 }
 
-static void nsc_ircc_suspend(struct nsc_ircc_cb *self)
+static int nsc_ircc_suspend(struct platform_device *dev, pm_message_t state)
 {
-       IRDA_MESSAGE("%s, Suspending\n", driver_name);
+       struct nsc_ircc_cb *self = platform_get_drvdata(dev);
+       int bank;
+       unsigned long flags;
+       int iobase = self->io.fir_base;
 
        if (self->io.suspended)
-               return;
+               return 0;
 
-       nsc_ircc_net_close(self->netdev);
+       IRDA_DEBUG(1, "%s, Suspending\n", driver_name);
 
+       rtnl_lock();
+       if (netif_running(self->netdev)) {
+               netif_device_detach(self->netdev);
+               spin_lock_irqsave(&self->lock, flags);
+               /* Save current bank */
+               bank = inb(iobase+BSR);
+
+               /* Disable interrupts */
+               switch_bank(iobase, BANK0);
+               outb(0, iobase+IER);
+
+               /* Restore bank register */
+               outb(bank, iobase+BSR);
+
+               spin_unlock_irqrestore(&self->lock, flags);
+               free_irq(self->io.irq, self->netdev);
+               disable_dma(self->io.dma);
+       }
        self->io.suspended = 1;
+       rtnl_unlock();
+
+       return 0;
 }
 
-static void nsc_ircc_wakeup(struct nsc_ircc_cb *self)
+static int nsc_ircc_resume(struct platform_device *dev)
 {
+       struct nsc_ircc_cb *self = platform_get_drvdata(dev);
+       unsigned long flags;
+
        if (!self->io.suspended)
-               return;
+               return 0;
 
+       IRDA_DEBUG(1, "%s, Waking up\n", driver_name);
+
+       rtnl_lock();
        nsc_ircc_setup(&self->io);
-       nsc_ircc_net_open(self->netdev);
-       
-       IRDA_MESSAGE("%s, Waking up\n", driver_name);
+       nsc_ircc_init_dongle_interface(self->io.fir_base, self->io.dongle_id);
 
+       if (netif_running(self->netdev)) {
+               if (request_irq(self->io.irq, nsc_ircc_interrupt, 0,
+                               self->netdev->name, self->netdev)) {
+                       IRDA_WARNING("%s, unable to allocate irq=%d\n",
+                                    driver_name, self->io.irq);
+
+                       /*
+                        * Don't fail resume process, just kill this
+                        * network interface
+                        */
+                       unregister_netdevice(self->netdev);
+               } else {
+                       spin_lock_irqsave(&self->lock, flags);
+                       nsc_ircc_change_speed(self, self->io.speed);
+                       spin_unlock_irqrestore(&self->lock, flags);
+                       netif_device_attach(self->netdev);
+               }
+
+       } else {
+               spin_lock_irqsave(&self->lock, flags);
+               nsc_ircc_change_speed(self, 9600);
+               spin_unlock_irqrestore(&self->lock, flags);
+       }
        self->io.suspended = 0;
-}
+       rtnl_unlock();
 
-static int nsc_ircc_pmproc(struct pm_dev *dev, pm_request_t rqst, void *data)
-{
-        struct nsc_ircc_cb *self = (struct nsc_ircc_cb*) dev->data;
-        if (self) {
-                switch (rqst) {
-                case PM_SUSPEND:
-                        nsc_ircc_suspend(self);
-                        break;
-                case PM_RESUME:
-                        nsc_ircc_wakeup(self);
-                        break;
-                }
-        }
-       return 0;
+       return 0;
 }
 
 MODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no>");
index 6edf7e514624f4575e9fd27fa4adfed25e014bc4..dacf671abcd6c01d49aa12a4585cb9ba9dc19a3a 100644 (file)
@@ -269,7 +269,7 @@ struct nsc_ircc_cb {
        __u32 new_speed;
        int index;                 /* Instance index */
 
-        struct pm_dev *dev;
+       struct platform_device *pldev;
 };
 
 static inline void switch_bank(int iobase, int bank)