aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDmitry Torokhov <dtor@mail.ru>2006-03-20 21:59:05 -0500
committerDavid S. Miller <davem@davemloft.net>2006-03-20 21:59:05 -0500
commit3b99b93baba4cbf4fd3d206e65e81a070b21b560 (patch)
tree7aa59a126614296b561b4d27bd92730a65fa188c
parentec4f32d550b94b4b66c9c7689bc09c6b32c8e82e (diff)
[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>
-rw-r--r--drivers/net/irda/nsc-ircc.c131
-rw-r--r--drivers/net/irda/nsc-ircc.h2
2 files changed, 98 insertions, 35 deletions
diff --git a/drivers/net/irda/nsc-ircc.c b/drivers/net/irda/nsc-ircc.c
index 282414ba22f0..81a4ccf54c57 100644
--- a/drivers/net/irda/nsc-ircc.c
+++ b/drivers/net/irda/nsc-ircc.c
@@ -55,14 +55,12 @@
55#include <linux/rtnetlink.h> 55#include <linux/rtnetlink.h>
56#include <linux/dma-mapping.h> 56#include <linux/dma-mapping.h>
57#include <linux/pnp.h> 57#include <linux/pnp.h>
58#include <linux/platform_device.h>
58 59
59#include <asm/io.h> 60#include <asm/io.h>
60#include <asm/dma.h> 61#include <asm/dma.h>
61#include <asm/byteorder.h> 62#include <asm/byteorder.h>
62 63
63#include <linux/pm.h>
64#include <linux/pm_legacy.h>
65
66#include <net/irda/wrapper.h> 64#include <net/irda/wrapper.h>
67#include <net/irda/irda.h> 65#include <net/irda/irda.h>
68#include <net/irda/irda_device.h> 66#include <net/irda/irda_device.h>
@@ -74,6 +72,19 @@
74 72
75static char *driver_name = "nsc-ircc"; 73static char *driver_name = "nsc-ircc";
76 74
75/* Power Management */
76#define NSC_IRCC_DRIVER_NAME "nsc-ircc"
77static int nsc_ircc_suspend(struct platform_device *dev, pm_message_t state);
78static int nsc_ircc_resume(struct platform_device *dev);
79
80static struct platform_driver nsc_ircc_driver = {
81 .suspend = nsc_ircc_suspend,
82 .resume = nsc_ircc_resume,
83 .driver = {
84 .name = NSC_IRCC_DRIVER_NAME,
85 },
86};
87
77/* Module parameters */ 88/* Module parameters */
78static int qos_mtt_bits = 0x07; /* 1 ms or more */ 89static int qos_mtt_bits = 0x07; /* 1 ms or more */
79static int dongle_id; 90static int dongle_id;
@@ -164,7 +175,6 @@ static int nsc_ircc_net_open(struct net_device *dev);
164static int nsc_ircc_net_close(struct net_device *dev); 175static int nsc_ircc_net_close(struct net_device *dev);
165static int nsc_ircc_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); 176static int nsc_ircc_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
166static struct net_device_stats *nsc_ircc_net_get_stats(struct net_device *dev); 177static struct net_device_stats *nsc_ircc_net_get_stats(struct net_device *dev);
167static int nsc_ircc_pmproc(struct pm_dev *dev, pm_request_t rqst, void *data);
168 178
169/* Globals */ 179/* Globals */
170static int pnp_registered; 180static int pnp_registered;
@@ -186,6 +196,12 @@ static int __init nsc_ircc_init(void)
186 int reg; 196 int reg;
187 int i = 0; 197 int i = 0;
188 198
199 ret = platform_driver_register(&nsc_ircc_driver);
200 if (ret) {
201 IRDA_ERROR("%s, Can't register driver!\n", driver_name);
202 return ret;
203 }
204
189 /* Register with PnP subsystem to detect disable ports */ 205 /* Register with PnP subsystem to detect disable ports */
190 ret = pnp_register_driver(&nsc_ircc_pnp_driver); 206 ret = pnp_register_driver(&nsc_ircc_pnp_driver);
191 207
@@ -274,6 +290,7 @@ static int __init nsc_ircc_init(void)
274 } 290 }
275 291
276 if (ret) { 292 if (ret) {
293 platform_driver_unregister(&nsc_ircc_driver);
277 pnp_unregister_driver(&nsc_ircc_pnp_driver); 294 pnp_unregister_driver(&nsc_ircc_pnp_driver);
278 pnp_registered = 0; 295 pnp_registered = 0;
279 } 296 }
@@ -291,13 +308,13 @@ static void __exit nsc_ircc_cleanup(void)
291{ 308{
292 int i; 309 int i;
293 310
294 pm_unregister_all(nsc_ircc_pmproc);
295
296 for (i = 0; i < ARRAY_SIZE(dev_self); i++) { 311 for (i = 0; i < ARRAY_SIZE(dev_self); i++) {
297 if (dev_self[i]) 312 if (dev_self[i])
298 nsc_ircc_close(dev_self[i]); 313 nsc_ircc_close(dev_self[i]);
299 } 314 }
300 315
316 platform_driver_unregister(&nsc_ircc_driver);
317
301 if (pnp_registered) 318 if (pnp_registered)
302 pnp_unregister_driver(&nsc_ircc_pnp_driver); 319 pnp_unregister_driver(&nsc_ircc_pnp_driver);
303 320
@@ -314,7 +331,6 @@ static int __init nsc_ircc_open(chipio_t *info)
314{ 331{
315 struct net_device *dev; 332 struct net_device *dev;
316 struct nsc_ircc_cb *self; 333 struct nsc_ircc_cb *self;
317 struct pm_dev *pmdev;
318 void *ret; 334 void *ret;
319 int err, chip_index; 335 int err, chip_index;
320 336
@@ -444,11 +460,18 @@ static int __init nsc_ircc_open(chipio_t *info)
444 self->io.dongle_id = dongle_id; 460 self->io.dongle_id = dongle_id;
445 nsc_ircc_init_dongle_interface(self->io.fir_base, dongle_id); 461 nsc_ircc_init_dongle_interface(self->io.fir_base, dongle_id);
446 462
447 pmdev = pm_register(PM_SYS_DEV, PM_SYS_IRDA, nsc_ircc_pmproc); 463 self->pldev = platform_device_register_simple(NSC_IRCC_DRIVER_NAME,
448 if (pmdev) 464 self->index, NULL, 0);
449 pmdev->data = self; 465 if (IS_ERR(self->pldev)) {
466 err = PTR_ERR(self->pldev);
467 goto out5;
468 }
469 platform_set_drvdata(self->pldev, self);
450 470
451 return chip_index; 471 return chip_index;
472
473 out5:
474 unregister_netdev(dev);
452 out4: 475 out4:
453 dma_free_coherent(NULL, self->tx_buff.truesize, 476 dma_free_coherent(NULL, self->tx_buff.truesize,
454 self->tx_buff.head, self->tx_buff_dma); 477 self->tx_buff.head, self->tx_buff_dma);
@@ -479,6 +502,8 @@ static int __exit nsc_ircc_close(struct nsc_ircc_cb *self)
479 502
480 iobase = self->io.fir_base; 503 iobase = self->io.fir_base;
481 504
505 platform_device_unregister(self->pldev);
506
482 /* Remove netdevice */ 507 /* Remove netdevice */
483 unregister_netdev(self->netdev); 508 unregister_netdev(self->netdev);
484 509
@@ -2278,45 +2303,83 @@ static struct net_device_stats *nsc_ircc_net_get_stats(struct net_device *dev)
2278 return &self->stats; 2303 return &self->stats;
2279} 2304}
2280 2305
2281static void nsc_ircc_suspend(struct nsc_ircc_cb *self) 2306static int nsc_ircc_suspend(struct platform_device *dev, pm_message_t state)
2282{ 2307{
2283 IRDA_MESSAGE("%s, Suspending\n", driver_name); 2308 struct nsc_ircc_cb *self = platform_get_drvdata(dev);
2309 int bank;
2310 unsigned long flags;
2311 int iobase = self->io.fir_base;
2284 2312
2285 if (self->io.suspended) 2313 if (self->io.suspended)
2286 return; 2314 return 0;
2287 2315
2288 nsc_ircc_net_close(self->netdev); 2316 IRDA_DEBUG(1, "%s, Suspending\n", driver_name);
2289 2317
2318 rtnl_lock();
2319 if (netif_running(self->netdev)) {
2320 netif_device_detach(self->netdev);
2321 spin_lock_irqsave(&self->lock, flags);
2322 /* Save current bank */
2323 bank = inb(iobase+BSR);
2324
2325 /* Disable interrupts */
2326 switch_bank(iobase, BANK0);
2327 outb(0, iobase+IER);
2328
2329 /* Restore bank register */
2330 outb(bank, iobase+BSR);
2331
2332 spin_unlock_irqrestore(&self->lock, flags);
2333 free_irq(self->io.irq, self->netdev);
2334 disable_dma(self->io.dma);
2335 }
2290 self->io.suspended = 1; 2336 self->io.suspended = 1;
2337 rtnl_unlock();
2338
2339 return 0;
2291} 2340}
2292 2341
2293static void nsc_ircc_wakeup(struct nsc_ircc_cb *self) 2342static int nsc_ircc_resume(struct platform_device *dev)
2294{ 2343{
2344 struct nsc_ircc_cb *self = platform_get_drvdata(dev);
2345 unsigned long flags;
2346
2295 if (!self->io.suspended) 2347 if (!self->io.suspended)
2296 return; 2348 return 0;
2297 2349
2350 IRDA_DEBUG(1, "%s, Waking up\n", driver_name);
2351
2352 rtnl_lock();
2298 nsc_ircc_setup(&self->io); 2353 nsc_ircc_setup(&self->io);
2299 nsc_ircc_net_open(self->netdev); 2354 nsc_ircc_init_dongle_interface(self->io.fir_base, self->io.dongle_id);
2300
2301 IRDA_MESSAGE("%s, Waking up\n", driver_name);
2302 2355
2356 if (netif_running(self->netdev)) {
2357 if (request_irq(self->io.irq, nsc_ircc_interrupt, 0,
2358 self->netdev->name, self->netdev)) {
2359 IRDA_WARNING("%s, unable to allocate irq=%d\n",
2360 driver_name, self->io.irq);
2361
2362 /*
2363 * Don't fail resume process, just kill this
2364 * network interface
2365 */
2366 unregister_netdevice(self->netdev);
2367 } else {
2368 spin_lock_irqsave(&self->lock, flags);
2369 nsc_ircc_change_speed(self, self->io.speed);
2370 spin_unlock_irqrestore(&self->lock, flags);
2371 netif_device_attach(self->netdev);
2372 }
2373
2374 } else {
2375 spin_lock_irqsave(&self->lock, flags);
2376 nsc_ircc_change_speed(self, 9600);
2377 spin_unlock_irqrestore(&self->lock, flags);
2378 }
2303 self->io.suspended = 0; 2379 self->io.suspended = 0;
2304} 2380 rtnl_unlock();
2305 2381
2306static int nsc_ircc_pmproc(struct pm_dev *dev, pm_request_t rqst, void *data) 2382 return 0;
2307{
2308 struct nsc_ircc_cb *self = (struct nsc_ircc_cb*) dev->data;
2309 if (self) {
2310 switch (rqst) {
2311 case PM_SUSPEND:
2312 nsc_ircc_suspend(self);
2313 break;
2314 case PM_RESUME:
2315 nsc_ircc_wakeup(self);
2316 break;
2317 }
2318 }
2319 return 0;
2320} 2383}
2321 2384
2322MODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no>"); 2385MODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no>");
diff --git a/drivers/net/irda/nsc-ircc.h b/drivers/net/irda/nsc-ircc.h
index 6edf7e514624..dacf671abcd6 100644
--- a/drivers/net/irda/nsc-ircc.h
+++ b/drivers/net/irda/nsc-ircc.h
@@ -269,7 +269,7 @@ struct nsc_ircc_cb {
269 __u32 new_speed; 269 __u32 new_speed;
270 int index; /* Instance index */ 270 int index; /* Instance index */
271 271
272 struct pm_dev *dev; 272 struct platform_device *pldev;
273}; 273};
274 274
275static inline void switch_bank(int iobase, int bank) 275static inline void switch_bank(int iobase, int bank)