From: Mike K. <mk...@vx...> - 2007-01-18 17:16:26
|
Do you believe this to affect most other running lircd instances (like lirc_mceusb)...that they affect suspend/hibernate? I am having problems with this area in Ubuntu and am running lirc...and prob' another 30 daemons which could (I guess) be affecting this area. mike Andrei Tanas wrote: > Hi, > > This patch has been tested with kernels 2.6.19 and higher only. The basic idea > is to provide support for suspend/resume. Without it, the driver has to be > unloaded before going to standby and reloaded after resume, lircd and any > applications that depend on it need to be restarted etc - it's just a mess. The > patch solves all this. > My HTPC box (running 2.6.19-rc6-mm2 kernel), can be suspended by simple "echo > mem > /sys/power/state", and works 100% fine after resume. > > ------------------------------------------------------------------------ > > --- lirc-0.8.1/drivers/lirc_serial/lirc_serial.c 2006-12-27 15:59:25.000000000 -0500 > +++ /home/htpc/lirc-0.8.1/drivers/lirc_serial/lirc_serial.c 2007-01-17 20:00:27.067020640 -0500 > @@ -11,6 +11,7 @@ > * Copyright (C) 1998 Trent Piepho <xyzzy@u.washington.edu> > * Copyright (C) 1998 Ben Pfaff <bl...@gn...> > * Copyright (C) 1999 Christoph Bartelmus <li...@ba...> > + * Copyright (C) 2007 Andrei Tanas <an...@ta...> (suspend/resume support) > * > * This program is free software; you can redistribute it and/or modify > * it under the terms of the GNU General Public License as published by > @@ -89,6 +90,7 @@ > #include <linux/mm.h> > #include <linux/delay.h> > #include <linux/poll.h> > +#include <linux/platform_device.h> > > #include <asm/system.h> > #include <asm/uaccess.h> > @@ -843,36 +845,10 @@ > return IRQ_RETVAL(IRQ_HANDLED); > } > > -static int init_port(void) > +static void hardware_init_port(void) > { > unsigned long flags; > > - > - /* Reserve io region. */ > -#if defined(LIRC_ALLOW_MMAPPED_IO) > - /* Future MMAP-Developers: Attention! > - For memory mapped I/O you *might* need to use ioremap() first, > - for the NSLU2 it's done in boot code. */ > - if(((iommap != 0) > - && (request_mem_region(iommap, 8<<ioshift, > - LIRC_DRIVER_NAME) == NULL)) > - || ((iommap == 0) > - && (request_region(io, 8, LIRC_DRIVER_NAME) == NULL))) > -#else > - if(request_region(io, 8, LIRC_DRIVER_NAME)==NULL) > -#endif > - { > - printk(KERN_ERR LIRC_DRIVER_NAME > - ": port %04x already in use\n", io); > - printk(KERN_WARNING LIRC_DRIVER_NAME > - ": use 'setserial /dev/ttySX uart none'\n"); > - printk(KERN_WARNING LIRC_DRIVER_NAME > - ": or compile the serial port driver as module and\n"); > - printk(KERN_WARNING LIRC_DRIVER_NAME > - ": make sure this module is loaded first\n"); > - return(-EBUSY); > - } > - > local_irq_save(flags); > > /* Set DLAB 0. */ > @@ -931,7 +907,37 @@ > } > > local_irq_restore(flags); > - > +} > + > +static int init_port(void) > +{ > + /* Reserve io region. */ > +#if defined(LIRC_ALLOW_MMAPPED_IO) > + /* Future MMAP-Developers: Attention! > + For memory mapped I/O you *might* need to use ioremap() first, > + for the NSLU2 it's done in boot code. */ > + if(((iommap != 0) > + && (request_mem_region(iommap, 8<<ioshift, > + LIRC_DRIVER_NAME) == NULL)) > + || ((iommap == 0) > + && (request_region(io, 8, LIRC_DRIVER_NAME) == NULL))) > +#else > + if(request_region(io, 8, LIRC_DRIVER_NAME)==NULL) > +#endif > + { > + printk(KERN_ERR LIRC_DRIVER_NAME > + ": port %04x already in use\n", io); > + printk(KERN_WARNING LIRC_DRIVER_NAME > + ": use 'setserial /dev/ttySX uart none'\n"); > + printk(KERN_WARNING LIRC_DRIVER_NAME > + ": or compile the serial port driver as module and\n"); > + printk(KERN_WARNING LIRC_DRIVER_NAME > + ": make sure this module is loaded first\n"); > + return(-EBUSY); > + } > + > + hardware_init_port(); > + > /* Initialize pulse/space widths */ > init_timing_params(duty_cycle, freq); > > @@ -1146,10 +1152,84 @@ > > #ifdef MODULE > > -int init_module(void) > +static struct platform_device *lirc_serial_dev; > + > +static int __devinit lirc_serial_probe(struct platform_device *dev) { > + return 0; > +} > + > +static int __devexit lirc_serial_remove(struct platform_device * dev) { > + return 0; > +} > + > +static int lirc_serial_suspend(struct platform_device *dev, pm_message_t state) { > + /* Set DLAB 0. */ > + soutp(UART_LCR, sinp(UART_LCR) & (~UART_LCR_DLAB)); > + > + /* Disable all interrupts */ > + soutp(UART_IER, sinp(UART_IER)& > + (~(UART_IER_MSI|UART_IER_RLSI|UART_IER_THRI|UART_IER_RDI))); > + > + /* Clear registers. */ > + sinp(UART_LSR); > + sinp(UART_RX); > + sinp(UART_IIR); > + sinp(UART_MSR); > + > + return 0; > +} > + > +static int lirc_serial_resume(struct platform_device *dev) { > + unsigned long flags; > + unsigned long f; > + > + hardware_init_port(); > + > + local_irq_save(flags); > + /* Enable Interrupt */ > + soutp(UART_IER, sinp(UART_IER)|UART_IER_MSI); > + off(); > + > + lirc_buffer_lock(&rbuf, &f); > + rbuf.head = rbuf.tail = rbuf.fill = 0; > + lirc_buffer_unlock(&rbuf, &f); > + > + local_irq_restore(flags); > + > + return 0; > +} > + > +static struct platform_driver lirc_serial_driver = { > + .probe = lirc_serial_probe, > + .remove = __devexit_p(lirc_serial_remove), > + .suspend = lirc_serial_suspend, > + .resume = lirc_serial_resume, > + .driver = { > + .name = "lirc_serial", > + .owner = THIS_MODULE, > + }, > +}; > + > +static int __init lirc_serial_init(void) > { > int result; > - > + > + lirc_serial_dev = platform_device_alloc("lirc_serial", 0); > + if (!lirc_serial_dev) > + return -ENOMEM; > + result = platform_device_add(lirc_serial_dev); > + if (result) { > + platform_device_put(lirc_serial_dev); > + return result; > + } > + result = platform_driver_register(&lirc_serial_driver); > + if (result) { > + printk("lirc register returned %d\n", result); > + platform_device_del(lirc_serial_dev); > + platform_device_put(lirc_serial_dev); > + return result; > + } > + > switch(type) > { > case LIRC_HOMEBREW: > @@ -1191,8 +1271,13 @@ > return 0; > } > > -void cleanup_module(void) > +static void __exit lirc_serial_exit(void) > { > + struct platform_device *pdev = lirc_serial_dev; > + lirc_serial_dev = NULL; > + platform_driver_unregister(&lirc_serial_driver); > + platform_device_unregister(pdev); > + > #if defined(LIRC_ALLOW_MMAPPED_IO) > if(iommap != 0) > { > @@ -1209,6 +1294,9 @@ > dprintk("cleaned up module\n"); > } > > +module_init(lirc_serial_init); > +module_exit(lirc_serial_exit); > + > MODULE_DESCRIPTION("Infra-red receiver driver for serial ports."); > MODULE_AUTHOR("Ralph Metzler, Trent Piepho, Ben Pfaff, Christoph Bartelmus"); > MODULE_LICENSE("GPL"); > > ------------------------------------------------------------------------ > > ------------------------------------------------------------------------- > 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 |