[IRDA]: nsc-ircc: PM update

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>
This commit is contained in:
Dmitry Torokhov 2006-03-20 18:59:05 -08:00 committed by David S. Miller
parent ec4f32d550
commit 3b99b93bab
2 changed files with 105 additions and 42 deletions

View file

@ -55,14 +55,12 @@
#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>
@ -74,6 +72,19 @@
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,47 +2303,85 @@ 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();
static void nsc_ircc_wakeup(struct nsc_ircc_cb *self)
{
if (!self->io.suspended)
return;
nsc_ircc_setup(&self->io);
nsc_ircc_net_open(self->netdev);
IRDA_MESSAGE("%s, Waking up\n", driver_name);
self->io.suspended = 0;
}
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;
}
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 0;
IRDA_DEBUG(1, "%s, Waking up\n", driver_name);
rtnl_lock();
nsc_ircc_setup(&self->io);
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();
return 0;
}
MODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no>");
MODULE_DESCRIPTION("NSC IrDA Device Driver");
MODULE_LICENSE("GPL");

View 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)