[patch 2/2] IRDA: nsc-ircc - switch to new power management scheme

From: Dmitry Torokhov
Date: Tue Sep 13 2005 - 00:31:04 EST


IRDA: nsc-ircc - switch to new power management scheme

Signed-off-by: Dmitry Torokhov <dtor@xxxxxxx>
---

drivers/net/irda/nsc-ircc.c | 153 ++++++++++++++++++++++++++++++--------------
drivers/net/irda/nsc-ircc.h | 2
2 files changed, 108 insertions(+), 47 deletions(-)

Index: work/drivers/net/irda/nsc-ircc.c
===================================================================
--- work.orig/drivers/net/irda/nsc-ircc.c
+++ work/drivers/net/irda/nsc-ircc.c
@@ -53,13 +53,12 @@
#include <linux/init.h>
#include <linux/rtnetlink.h>
#include <linux/dma-mapping.h>
+#include <linux/device.h>

#include <asm/io.h>
#include <asm/dma.h>
#include <asm/byteorder.h>

-#include <linux/pm.h>
-
#include <net/irda/wrapper.h>
#include <net/irda/irda.h>
#include <net/irda/irda_device.h>
@@ -69,7 +68,9 @@
#define CHIP_IO_EXTENT 8
#define BROKEN_DONGLE_ID

-static char *driver_name = "nsc-ircc";
+#define NSC_IRCC_DRIVER_NAME "nsc-ircc"
+
+static char *driver_name = NSC_IRCC_DRIVER_NAME;

/* Module parameters */
static int qos_mtt_bits = 0x07; /* 1 ms or more */
@@ -145,7 +146,15 @@ static int nsc_ircc_net_open(struct net
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);
+static int nsc_ircc_suspend(struct device *dev, pm_message_t state, u32 level);
+static int nsc_ircc_resume(struct device *dev, u32 level);
+
+static struct device_driver nsc_ircc_driver = {
+ .name = NSC_IRCC_DRIVER_NAME,
+ .bus = &platform_bus_type,
+ .suspend = nsc_ircc_suspend,
+ .resume = nsc_ircc_resume,
+};

/*
* Function nsc_ircc_init ()
@@ -163,6 +172,12 @@ static int __init nsc_ircc_init(void)
int reg;
int i = 0;

+ ret = driver_register(&nsc_ircc_driver);
+ if (ret) {
+ IRDA_ERROR("%s, Can't register driver!\n", driver_name);
+ return ret;
+ }
+
/* Probe for all the NSC chipsets we know about */
for (chip=chips; chip->name ; chip++) {
IRDA_DEBUG(2, "%s(), Probing for %s ...\n", __FUNCTION__,
@@ -226,12 +241,11 @@ static void __exit nsc_ircc_cleanup(void
{
int i;

- pm_unregister_all(nsc_ircc_pmproc);
-
- for (i=0; i < 4; i++) {
+ for (i=0; i < 4; i++)
if (dev_self[i])
nsc_ircc_close(dev_self[i]);
- }
+
+ driver_unregister(&nsc_ircc_driver);
}

/*
@@ -244,7 +258,6 @@ static int __init nsc_ircc_open(int i, c
{
struct net_device *dev;
struct nsc_ircc_cb *self;
- struct pm_dev *pmdev;
void *ret;
int err;

@@ -363,11 +376,19 @@ static int __init nsc_ircc_open(int i, c
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(driver_name, self->index, NULL, 0);
+ if (IS_ERR(self->pldev)) {
+ IRDA_ERROR("%s(), platform_device_register_simple() failed!\n",
+ __FUNCTION__);
+ err = PTR_ERR(self->pldev);
+ goto out5;
+ }
+ dev_set_drvdata(&self->pldev->dev, self);

return 0;
+
+ out5:
+ unregister_netdev(self->netdev);
out4:
dma_free_coherent(NULL, self->tx_buff.truesize,
self->tx_buff.head, self->tx_buff_dma);
@@ -398,6 +419,8 @@ static int __exit nsc_ircc_close(struct

iobase = self->io.fir_base;

+ platform_device_unregister(self->pldev);
+
/* Remove netdevice */
unregister_netdev(self->netdev);

@@ -1995,6 +2018,20 @@ static int nsc_ircc_is_receiving(struct
return status;
}

+static int nsc_ircc_request_irq(struct nsc_ircc_cb *self)
+{
+ int error;
+
+ error = request_irq(self->io.irq, nsc_ircc_interrupt, 0,
+ self->netdev->name, self->netdev);
+ if (error)
+ IRDA_WARNING("%s, unable to allocate irq=%d, err=%d\n",
+ driver_name, self->io.irq, error);
+
+ return error;
+}
+
+
/*
* Function nsc_ircc_net_open (dev)
*
@@ -2005,6 +2042,7 @@ static int nsc_ircc_net_open(struct net_
{
struct nsc_ircc_cb *self;
int iobase;
+ int error;
char hwname[32];
__u8 bank;

@@ -2017,11 +2055,10 @@ static int nsc_ircc_net_open(struct net_

iobase = self->io.fir_base;

- if (request_irq(self->io.irq, nsc_ircc_interrupt, 0, dev->name, dev)) {
- IRDA_WARNING("%s, unable to allocate irq=%d\n",
- driver_name, self->io.irq);
- return -EAGAIN;
- }
+ error = nsc_ircc_request_irq(self);
+ if (error)
+ return error;
+
/*
* Always allocate the DMA channel after the IRQ, and clean up on
* failure.
@@ -2096,7 +2133,8 @@ static int nsc_ircc_net_close(struct net
switch_bank(iobase, BANK0);
outb(0, iobase+IER);

- free_irq(self->io.irq, dev);
+ if (!self->io.suspended)
+ free_irq(self->io.irq, dev);
free_dma(self->io.dma);

/* Restore bank register */
@@ -2160,44 +2198,67 @@ static struct net_device_stats *nsc_ircc
return &self->stats;
}

-static void nsc_ircc_suspend(struct nsc_ircc_cb *self)
+static int nsc_ircc_suspend(struct device *dev, pm_message_t state, u32 level)
{
- IRDA_MESSAGE("%s, Suspending\n", driver_name);
+ struct nsc_ircc_cb *self = dev_get_drvdata(dev);
+ __u8 bank;

- if (self->io.suspended)
- return;
+ if (level == SUSPEND_DISABLE && !self->io.suspended) {

- nsc_ircc_net_close(self->netdev);
+ IRDA_MESSAGE("%s, Suspending\n", driver_name);

- self->io.suspended = 1;
+ rtnl_lock();
+ if (netif_running(self->netdev)) {
+ netif_device_detach(self->netdev);
+
+ /* Disable interrupts */
+ bank = inb(self->io.fir_base + BSR);
+ switch_bank(self->io.fir_base, BANK0);
+ outb(0, self->io.fir_base + IER);
+ outb(bank, self->io.fir_base + BSR);
+
+ 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 device *dev, u32 level)
{
- if (!self->io.suspended)
- return;
-
- nsc_ircc_setup(&self->io);
- nsc_ircc_net_open(self->netdev);
+ struct nsc_ircc_cb *self = dev_get_drvdata(dev);
+ __u8 bank;

- IRDA_MESSAGE("%s, Waking up\n", driver_name);
+ if (level == RESUME_ENABLE && self->io.suspended) {
+ IRDA_DEBUG(1, "%s, Waking up\n", driver_name);

- self->io.suspended = 0;
-}
+ rtnl_lock();
+ if (nsc_ircc_setup(&self->io) < 0) {
+ /*
+ * Don't fail resume process, just kill this
+ * network interface
+ */
+ unregister_netdevice(self->netdev);
+ } else if (netif_running(self->netdev)) {
+ if (nsc_ircc_request_irq(self)) {
+ unregister_netdevice(self->netdev);
+ } else {
+ enable_dma(self->io.dma);
+ /* Start interrupts */
+ bank = inb(self->io.fir_base + BSR);
+ switch_bank(self->io.fir_base, BANK0);
+ outb(IER_LS_IE | IER_RXHDL_IE,
+ self->io.fir_base + IER);
+ outb(bank, self->io.fir_base + BSR);
+ netif_device_attach(self->netdev);
+ }
+ }
+ 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;
}

Index: work/drivers/net/irda/nsc-ircc.h
===================================================================
--- work.orig/drivers/net/irda/nsc-ircc.h
+++ work/drivers/net/irda/nsc-ircc.h
@@ -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)

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/