diff options
Diffstat (limited to 'drivers/pcmcia')
-rw-r--r-- | drivers/pcmcia/at91_cf.c | 79 | ||||
-rw-r--r-- | drivers/pcmcia/au1000_db1x00.c | 3 | ||||
-rw-r--r-- | drivers/pcmcia/au1000_generic.c | 1 | ||||
-rw-r--r-- | drivers/pcmcia/au1000_generic.h | 1 | ||||
-rw-r--r-- | drivers/pcmcia/au1000_pb1x00.c | 1 | ||||
-rw-r--r-- | drivers/pcmcia/cs.c | 29 | ||||
-rw-r--r-- | drivers/pcmcia/hd64465_ss.c | 2 | ||||
-rw-r--r-- | drivers/pcmcia/i82092.c | 2 | ||||
-rw-r--r-- | drivers/pcmcia/i82365.c | 6 | ||||
-rw-r--r-- | drivers/pcmcia/m32r_cfc.c | 1 | ||||
-rw-r--r-- | drivers/pcmcia/m32r_pcc.c | 1 | ||||
-rw-r--r-- | drivers/pcmcia/omap_cf.c | 2 | ||||
-rw-r--r-- | drivers/pcmcia/pcmcia_resource.c | 27 | ||||
-rw-r--r-- | drivers/pcmcia/pd6729.c | 2 | ||||
-rw-r--r-- | drivers/pcmcia/pxa2xx_base.c | 1 | ||||
-rw-r--r-- | drivers/pcmcia/sa1100_generic.c | 1 | ||||
-rw-r--r-- | drivers/pcmcia/sa1111_generic.c | 1 | ||||
-rw-r--r-- | drivers/pcmcia/sa11xx_base.c | 1 | ||||
-rw-r--r-- | drivers/pcmcia/soc_common.c | 5 | ||||
-rw-r--r-- | drivers/pcmcia/ti113x.h | 1 | ||||
-rw-r--r-- | drivers/pcmcia/vrc4171_card.c | 2 | ||||
-rw-r--r-- | drivers/pcmcia/vrc4173_cardu.c | 2 | ||||
-rw-r--r-- | drivers/pcmcia/yenta_socket.c | 87 |
23 files changed, 192 insertions, 66 deletions
diff --git a/drivers/pcmcia/at91_cf.c b/drivers/pcmcia/at91_cf.c index a4d50940ebeb..40569f40e90e 100644 --- a/drivers/pcmcia/at91_cf.c +++ b/drivers/pcmcia/at91_cf.c @@ -214,11 +214,10 @@ static struct pccard_operations at91_cf_ops = { /*--------------------------------------------------------------------------*/ -static int __init at91_cf_probe(struct device *dev) +static int __init at91_cf_probe(struct platform_device *pdev) { struct at91_cf_socket *cf; - struct at91_cf_data *board = dev->platform_data; - struct platform_device *pdev = to_platform_device(dev); + struct at91_cf_data *board = pdev->dev.platform_data; struct resource *io; unsigned int csa; int status; @@ -236,7 +235,7 @@ static int __init at91_cf_probe(struct device *dev) cf->board = board; cf->pdev = pdev; - dev_set_drvdata(dev, cf); + platform_set_drvdata(pdev, cf); /* CF takes over CS4, CS5, CS6 */ csa = at91_sys_read(AT91_EBI_CSA); @@ -268,9 +267,10 @@ static int __init at91_cf_probe(struct device *dev) /* must be a GPIO; ergo must trigger on both edges */ status = request_irq(board->det_pin, at91_cf_irq, - SA_SAMPLE_RANDOM, driver_name, cf); + IRQF_SAMPLE_RANDOM, driver_name, cf); if (status < 0) goto fail0; + device_init_wakeup(&pdev->dev, 1); /* * The card driver will request this irq later as needed. @@ -280,7 +280,7 @@ static int __init at91_cf_probe(struct device *dev) */ if (board->irq_pin) { status = request_irq(board->irq_pin, at91_cf_irq, - SA_SHIRQ, driver_name, cf); + IRQF_SHARED, driver_name, cf); if (status < 0) goto fail0a; cf->socket.pci_irq = board->irq_pin; @@ -301,7 +301,7 @@ static int __init at91_cf_probe(struct device *dev) board->det_pin, board->irq_pin); cf->socket.owner = THIS_MODULE; - cf->socket.dev.dev = dev; + cf->socket.dev.dev = &pdev->dev; cf->socket.ops = &at91_cf_ops; cf->socket.resource_ops = &pccard_static_ops; cf->socket.features = SS_CAP_PCCARD | SS_CAP_STATIC_MAP @@ -323,21 +323,25 @@ fail1: free_irq(board->irq_pin, cf); fail0a: free_irq(board->det_pin, cf); + device_init_wakeup(&pdev->dev, 0); fail0: at91_sys_write(AT91_EBI_CSA, csa); kfree(cf); return status; } -static int __exit at91_cf_remove(struct device *dev) +static int __exit at91_cf_remove(struct platform_device *pdev) { - struct at91_cf_socket *cf = dev_get_drvdata(dev); + struct at91_cf_socket *cf = platform_get_drvdata(pdev); + struct at91_cf_data *board = cf->board; struct resource *io = cf->socket.io[0].res; unsigned int csa; pcmcia_unregister_socket(&cf->socket); - free_irq(cf->board->irq_pin, cf); - free_irq(cf->board->det_pin, cf); + if (board->irq_pin) + free_irq(board->irq_pin, cf); + free_irq(board->det_pin, cf); + device_init_wakeup(&pdev->dev, 0); iounmap((void __iomem *) cf->socket.io_offset); release_mem_region(io->start, io->end + 1 - io->start); @@ -348,26 +352,65 @@ static int __exit at91_cf_remove(struct device *dev) return 0; } -static struct device_driver at91_cf_driver = { - .name = (char *) driver_name, - .bus = &platform_bus_type, +#ifdef CONFIG_PM + +static int at91_cf_suspend(struct platform_device *pdev, pm_message_t mesg) +{ + struct at91_cf_socket *cf = platform_get_drvdata(pdev); + struct at91_cf_data *board = cf->board; + + pcmcia_socket_dev_suspend(&pdev->dev, mesg); + if (device_may_wakeup(&pdev->dev)) + enable_irq_wake(board->det_pin); + else { + disable_irq_wake(board->det_pin); + disable_irq(board->det_pin); + } + if (board->irq_pin) + disable_irq(board->irq_pin); + return 0; +} + +static int at91_cf_resume(struct platform_device *pdev) +{ + struct at91_cf_socket *cf = platform_get_drvdata(pdev); + struct at91_cf_data *board = cf->board; + + if (board->irq_pin) + enable_irq(board->irq_pin); + if (!device_may_wakeup(&pdev->dev)) + enable_irq(board->det_pin); + pcmcia_socket_dev_resume(&pdev->dev); + return 0; +} + +#else +#define at91_cf_suspend NULL +#define at91_cf_resume NULL +#endif + +static struct platform_driver at91_cf_driver = { + .driver = { + .name = (char *) driver_name, + .owner = THIS_MODULE, + }, .probe = at91_cf_probe, .remove = __exit_p(at91_cf_remove), - .suspend = pcmcia_socket_dev_suspend, - .resume = pcmcia_socket_dev_resume, + .suspend = at91_cf_suspend, + .resume = at91_cf_resume, }; /*--------------------------------------------------------------------------*/ static int __init at91_cf_init(void) { - return driver_register(&at91_cf_driver); + return platform_driver_register(&at91_cf_driver); } module_init(at91_cf_init); static void __exit at91_cf_exit(void) { - driver_unregister(&at91_cf_driver); + platform_driver_unregister(&at91_cf_driver); } module_exit(at91_cf_exit); diff --git a/drivers/pcmcia/au1000_db1x00.c b/drivers/pcmcia/au1000_db1x00.c index abc13f28ba3f..74e051535d6c 100644 --- a/drivers/pcmcia/au1000_db1x00.c +++ b/drivers/pcmcia/au1000_db1x00.c @@ -30,7 +30,6 @@ * */ -#include <linux/config.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/errno.h> @@ -296,7 +295,7 @@ struct pcmcia_low_level db1x00_pcmcia_ops = { .socket_suspend = db1x00_socket_suspend }; -int __init au1x_board_init(struct device *dev) +int au1x_board_init(struct device *dev) { int ret = -ENODEV; bcsr->pcmcia = 0; /* turn off power, if it's not already off */ diff --git a/drivers/pcmcia/au1000_generic.c b/drivers/pcmcia/au1000_generic.c index 971a35281649..d5dd0ce65536 100644 --- a/drivers/pcmcia/au1000_generic.c +++ b/drivers/pcmcia/au1000_generic.c @@ -33,7 +33,6 @@ #include <linux/module.h> #include <linux/moduleparam.h> #include <linux/init.h> -#include <linux/config.h> #include <linux/cpufreq.h> #include <linux/ioport.h> #include <linux/kernel.h> diff --git a/drivers/pcmcia/au1000_generic.h b/drivers/pcmcia/au1000_generic.h index f2c970b5f4ff..1e467bb54077 100644 --- a/drivers/pcmcia/au1000_generic.h +++ b/drivers/pcmcia/au1000_generic.h @@ -22,7 +22,6 @@ #define __ASM_AU1000_PCMCIA_H /* include the world */ -#include <linux/config.h> #include <pcmcia/cs_types.h> #include <pcmcia/cs.h> diff --git a/drivers/pcmcia/au1000_pb1x00.c b/drivers/pcmcia/au1000_pb1x00.c index fd5522ede867..86c0808d6a05 100644 --- a/drivers/pcmcia/au1000_pb1x00.c +++ b/drivers/pcmcia/au1000_pb1x00.c @@ -21,7 +21,6 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. */ -#include <linux/config.h> #include <linux/module.h> #include <linux/init.h> #include <linux/delay.h> diff --git a/drivers/pcmcia/cs.c b/drivers/pcmcia/cs.c index 3162998579c1..f9cd831a3f31 100644 --- a/drivers/pcmcia/cs.c +++ b/drivers/pcmcia/cs.c @@ -28,6 +28,7 @@ #include <linux/pm.h> #include <linux/pci.h> #include <linux/device.h> +#include <linux/kthread.h> #include <asm/system.h> #include <asm/irq.h> @@ -176,6 +177,7 @@ static int pccardd(void *__skt); */ int pcmcia_register_socket(struct pcmcia_socket *socket) { + struct task_struct *tsk; int ret; if (!socket || !socket->ops || !socket->dev.dev || !socket->resource_ops) @@ -239,15 +241,18 @@ int pcmcia_register_socket(struct pcmcia_socket *socket) mutex_init(&socket->skt_mutex); spin_lock_init(&socket->thread_lock); - ret = kernel_thread(pccardd, socket, CLONE_KERNEL); - if (ret < 0) + tsk = kthread_run(pccardd, socket, "pccardd"); + if (IS_ERR(tsk)) { + ret = PTR_ERR(tsk); goto err; + } wait_for_completion(&socket->thread_done); - if(!socket->thread) { + if (!socket->thread) { printk(KERN_WARNING "PCMCIA: warning: socket thread for socket %p did not start\n", socket); return -EIO; } + pcmcia_parse_events(socket, SS_DETECT); return 0; @@ -272,10 +277,8 @@ void pcmcia_unregister_socket(struct pcmcia_socket *socket) cs_dbg(socket, 0, "pcmcia_unregister_socket(0x%p)\n", socket->ops); if (socket->thread) { - init_completion(&socket->thread_done); - socket->thread = NULL; wake_up(&socket->thread_wait); - wait_for_completion(&socket->thread_done); + kthread_stop(socket->thread); } release_cis_mem(socket); @@ -630,8 +633,6 @@ static int pccardd(void *__skt) DECLARE_WAITQUEUE(wait, current); int ret; - daemonize("pccardd"); - skt->thread = current; skt->socket = dead_socket; skt->ops->init(skt); @@ -643,7 +644,8 @@ static int pccardd(void *__skt) printk(KERN_WARNING "PCMCIA: unable to register socket 0x%p\n", skt); skt->thread = NULL; - complete_and_exit(&skt->thread_done, 0); + complete(&skt->thread_done); + return 0; } add_wait_queue(&skt->thread_wait, &wait); @@ -674,7 +676,7 @@ static int pccardd(void *__skt) continue; } - if (!skt->thread) + if (kthread_should_stop()) break; schedule(); @@ -688,7 +690,7 @@ static int pccardd(void *__skt) /* remove from the device core */ class_device_unregister(&skt->dev); - complete_and_exit(&skt->thread_done, 0); + return 0; } /* @@ -697,11 +699,12 @@ static int pccardd(void *__skt) */ void pcmcia_parse_events(struct pcmcia_socket *s, u_int events) { + unsigned long flags; cs_dbg(s, 4, "parse_events: events %08x\n", events); if (s->thread) { - spin_lock(&s->thread_lock); + spin_lock_irqsave(&s->thread_lock, flags); s->thread_events |= events; - spin_unlock(&s->thread_lock); + spin_unlock_irqrestore(&s->thread_lock, flags); wake_up(&s->thread_wait); } diff --git a/drivers/pcmcia/hd64465_ss.c b/drivers/pcmcia/hd64465_ss.c index c662e4f89d46..ad02629c8be2 100644 --- a/drivers/pcmcia/hd64465_ss.c +++ b/drivers/pcmcia/hd64465_ss.c @@ -761,7 +761,7 @@ static int hs_init_socket(hs_socket_t *sp, int irq, unsigned long mem_base, hd64465_register_irq_demux(sp->irq, hs_irq_demux, sp); - if ((err = request_irq(sp->irq, hs_interrupt, SA_INTERRUPT, MODNAME, sp)) < 0) + if ((err = request_irq(sp->irq, hs_interrupt, IRQF_DISABLED, MODNAME, sp)) < 0) return err; if (request_mem_region(sp->mem_base, sp->mem_length, MODNAME) == 0) { sp->mem_base = 0; diff --git a/drivers/pcmcia/i82092.c b/drivers/pcmcia/i82092.c index d5f03a338c6c..2163aa75a257 100644 --- a/drivers/pcmcia/i82092.c +++ b/drivers/pcmcia/i82092.c @@ -149,7 +149,7 @@ static int __devinit i82092aa_pci_probe(struct pci_dev *dev, const struct pci_de /* Register the interrupt handler */ dprintk(KERN_DEBUG "Requesting interrupt %i \n",dev->irq); - if ((ret = request_irq(dev->irq, i82092aa_interrupt, SA_SHIRQ, "i82092aa", i82092aa_interrupt))) { + if ((ret = request_irq(dev->irq, i82092aa_interrupt, IRQF_SHARED, "i82092aa", i82092aa_interrupt))) { printk(KERN_ERR "i82092aa: Failed to register IRQ %d, aborting\n", dev->irq); goto err_out_free_res; } diff --git a/drivers/pcmcia/i82365.c b/drivers/pcmcia/i82365.c index ff51a65d9433..1cc2682394b1 100644 --- a/drivers/pcmcia/i82365.c +++ b/drivers/pcmcia/i82365.c @@ -509,7 +509,7 @@ static irqreturn_t i365_count_irq(int irq, void *dev, struct pt_regs *regs) static u_int __init test_irq(u_short sock, int irq) { debug(2, " testing ISA irq %d\n", irq); - if (request_irq(irq, i365_count_irq, SA_PROBEIRQ, "scan", + if (request_irq(irq, i365_count_irq, IRQF_PROBE_SHARED, "scan", i365_count_irq) != 0) return 1; irq_hits = 0; irq_sock = sock; @@ -562,7 +562,7 @@ static u_int __init isa_scan(u_short sock, u_int mask0) } else { /* Fallback: just find interrupts that aren't in use */ for (i = 0; i < 16; i++) - if ((mask0 & (1 << i)) && (_check_irq(i, SA_PROBEIRQ) == 0)) + if ((mask0 & (1 << i)) && (_check_irq(i, IRQF_PROBE_SHARED) == 0)) mask1 |= (1 << i); printk("default"); /* If scan failed, default to polled status */ @@ -726,7 +726,7 @@ static void __init add_pcic(int ns, int type) u_int cs_mask = mask & ((cs_irq) ? (1<<cs_irq) : ~(1<<12)); for (cs_irq = 15; cs_irq > 0; cs_irq--) if ((cs_mask & (1 << cs_irq)) && - (_check_irq(cs_irq, SA_PROBEIRQ) == 0)) + (_check_irq(cs_irq, IRQF_PROBE_SHARED) == 0)) break; if (cs_irq) { grab_irq = 1; diff --git a/drivers/pcmcia/m32r_cfc.c b/drivers/pcmcia/m32r_cfc.c index 071cf485e1a3..9e768eaef17a 100644 --- a/drivers/pcmcia/m32r_cfc.c +++ b/drivers/pcmcia/m32r_cfc.c @@ -10,7 +10,6 @@ #include <linux/module.h> #include <linux/moduleparam.h> #include <linux/init.h> -#include <linux/config.h> #include <linux/types.h> #include <linux/fcntl.h> #include <linux/string.h> diff --git a/drivers/pcmcia/m32r_pcc.c b/drivers/pcmcia/m32r_pcc.c index 70d5f0748d55..61d50b5620dd 100644 --- a/drivers/pcmcia/m32r_pcc.c +++ b/drivers/pcmcia/m32r_pcc.c @@ -10,7 +10,6 @@ #include <linux/module.h> #include <linux/moduleparam.h> #include <linux/init.h> -#include <linux/config.h> #include <linux/types.h> #include <linux/fcntl.h> #include <linux/string.h> diff --git a/drivers/pcmcia/omap_cf.c b/drivers/pcmcia/omap_cf.c index 2c23d7584399..420e10aec0ae 100644 --- a/drivers/pcmcia/omap_cf.c +++ b/drivers/pcmcia/omap_cf.c @@ -232,7 +232,7 @@ static int __init omap_cf_probe(struct device *dev) dev_set_drvdata(dev, cf); /* this primarily just shuts up irq handling noise */ - status = request_irq(irq, omap_cf_irq, SA_SHIRQ, + status = request_irq(irq, omap_cf_irq, IRQF_SHARED, driver_name, cf); if (status < 0) goto fail0; diff --git a/drivers/pcmcia/pcmcia_resource.c b/drivers/pcmcia/pcmcia_resource.c index 3131bb0a0095..7bf25b88ea31 100644 --- a/drivers/pcmcia/pcmcia_resource.c +++ b/drivers/pcmcia/pcmcia_resource.c @@ -788,6 +788,7 @@ int pcmcia_request_irq(struct pcmcia_device *p_dev, irq_req_t *req) struct pcmcia_socket *s = p_dev->socket; config_t *c; int ret = CS_IN_USE, irq = 0; + int type; if (!(s->state & SOCKET_PRESENT)) return CS_NO_CARD; @@ -797,6 +798,13 @@ int pcmcia_request_irq(struct pcmcia_device *p_dev, irq_req_t *req) if (c->state & CONFIG_IRQ_REQ) return CS_IN_USE; + /* Decide what type of interrupt we are registering */ + type = 0; + if (s->functions > 1) /* All of this ought to be handled higher up */ + type = IRQF_SHARED; + if (req->Attributes & IRQ_TYPE_DYNAMIC_SHARING) + type = IRQF_SHARED; + #ifdef CONFIG_PCMCIA_PROBE if (s->irq.AssignedIRQ != 0) { /* If the interrupt is already assigned, it must be the same */ @@ -822,9 +830,7 @@ int pcmcia_request_irq(struct pcmcia_device *p_dev, irq_req_t *req) * marked as used by the kernel resource management core */ ret = request_irq(irq, (req->Attributes & IRQ_HANDLE_PRESENT) ? req->Handler : test_action, - ((req->Attributes & IRQ_TYPE_DYNAMIC_SHARING) || - (s->functions > 1) || - (irq == s->pci_irq)) ? SA_SHIRQ : 0, + type, p_dev->devname, (req->Attributes & IRQ_HANDLE_PRESENT) ? req->Instance : data); if (!ret) { @@ -839,18 +845,21 @@ int pcmcia_request_irq(struct pcmcia_device *p_dev, irq_req_t *req) if (ret && !s->irq.AssignedIRQ) { if (!s->pci_irq) return ret; + type = IRQF_SHARED; irq = s->pci_irq; } - if (ret && req->Attributes & IRQ_HANDLE_PRESENT) { - if (request_irq(irq, req->Handler, - ((req->Attributes & IRQ_TYPE_DYNAMIC_SHARING) || - (s->functions > 1) || - (irq == s->pci_irq)) ? SA_SHIRQ : 0, - p_dev->devname, req->Instance)) + if (ret && (req->Attributes & IRQ_HANDLE_PRESENT)) { + if (request_irq(irq, req->Handler, type, p_dev->devname, req->Instance)) return CS_IN_USE; } + /* Make sure the fact the request type was overridden is passed back */ + if (type == IRQF_SHARED && !(req->Attributes & IRQ_TYPE_DYNAMIC_SHARING)) { + req->Attributes |= IRQ_TYPE_DYNAMIC_SHARING; + printk(KERN_WARNING "pcmcia: request for exclusive IRQ could not be fulfilled.\n"); + printk(KERN_WARNING "pcmcia: the driver needs updating to supported shared IRQ lines.\n"); + } c->irq.Attributes = req->Attributes; s->irq.AssignedIRQ = req->AssignedIRQ = irq; s->irq.Config++; diff --git a/drivers/pcmcia/pd6729.c b/drivers/pcmcia/pd6729.c index 9ee26c1b8635..22c5e7427ddd 100644 --- a/drivers/pcmcia/pd6729.c +++ b/drivers/pcmcia/pd6729.c @@ -689,7 +689,7 @@ static int __devinit pd6729_pci_probe(struct pci_dev *dev, pci_set_drvdata(dev, socket); if (irq_mode == 1) { /* Register the interrupt handler */ - if ((ret = request_irq(dev->irq, pd6729_interrupt, SA_SHIRQ, + if ((ret = request_irq(dev->irq, pd6729_interrupt, IRQF_SHARED, "pd6729", socket))) { printk(KERN_ERR "pd6729: Failed to register irq %d, " "aborting\n", dev->irq); diff --git a/drivers/pcmcia/pxa2xx_base.c b/drivers/pcmcia/pxa2xx_base.c index 7fa18fb814bc..b3518131ea0d 100644 --- a/drivers/pcmcia/pxa2xx_base.c +++ b/drivers/pcmcia/pxa2xx_base.c @@ -18,7 +18,6 @@ #include <linux/module.h> #include <linux/init.h> -#include <linux/config.h> #include <linux/cpufreq.h> #include <linux/ioport.h> #include <linux/kernel.h> diff --git a/drivers/pcmcia/sa1100_generic.c b/drivers/pcmcia/sa1100_generic.c index 6d441ec75c6a..c5b2a44b4c37 100644 --- a/drivers/pcmcia/sa1100_generic.c +++ b/drivers/pcmcia/sa1100_generic.c @@ -32,7 +32,6 @@ #include <linux/module.h> #include <linux/init.h> -#include <linux/config.h> #include <linux/platform_device.h> #include <pcmcia/cs_types.h> diff --git a/drivers/pcmcia/sa1111_generic.c b/drivers/pcmcia/sa1111_generic.c index 81ded52c8959..658cddfbcf29 100644 --- a/drivers/pcmcia/sa1111_generic.c +++ b/drivers/pcmcia/sa1111_generic.c @@ -5,7 +5,6 @@ * basically means we handle everything except controlling the * power. Power is machine specific... */ -#include <linux/config.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/ioport.h> diff --git a/drivers/pcmcia/sa11xx_base.c b/drivers/pcmcia/sa11xx_base.c index 59c5d968e9f6..31a7abc55b23 100644 --- a/drivers/pcmcia/sa11xx_base.c +++ b/drivers/pcmcia/sa11xx_base.c @@ -32,7 +32,6 @@ #include <linux/module.h> #include <linux/init.h> -#include <linux/config.h> #include <linux/cpufreq.h> #include <linux/ioport.h> #include <linux/kernel.h> diff --git a/drivers/pcmcia/soc_common.c b/drivers/pcmcia/soc_common.c index ea7d9ca160b2..ecaa132fa592 100644 --- a/drivers/pcmcia/soc_common.c +++ b/drivers/pcmcia/soc_common.c @@ -31,7 +31,6 @@ ======================================================================*/ -#include <linux/config.h> #include <linux/module.h> #include <linux/moduleparam.h> #include <linux/init.h> @@ -39,12 +38,12 @@ #include <linux/timer.h> #include <linux/mm.h> #include <linux/interrupt.h> +#include <linux/irq.h> #include <linux/spinlock.h> #include <linux/cpufreq.h> #include <asm/hardware.h> #include <asm/io.h> -#include <asm/irq.h> #include <asm/system.h> #include "soc_common.h" @@ -524,7 +523,7 @@ int soc_pcmcia_request_irqs(struct soc_pcmcia_socket *skt, if (irqs[i].sock != skt->nr) continue; res = request_irq(irqs[i].irq, soc_common_pcmcia_interrupt, - SA_INTERRUPT, irqs[i].str, skt); + IRQF_DISABLED, irqs[i].str, skt); if (res) break; set_irq_type(irqs[i].irq, IRQT_NOEDGE); diff --git a/drivers/pcmcia/ti113x.h b/drivers/pcmcia/ti113x.h index 7a3d1b8e16b9..62e9ebf967f9 100644 --- a/drivers/pcmcia/ti113x.h +++ b/drivers/pcmcia/ti113x.h @@ -647,6 +647,7 @@ static int ti12xx_2nd_slot_empty(struct yenta_socket *socket) */ break; + case PCI_DEVICE_ID_TI_XX12: case PCI_DEVICE_ID_TI_X515: case PCI_DEVICE_ID_TI_X420: case PCI_DEVICE_ID_TI_X620: diff --git a/drivers/pcmcia/vrc4171_card.c b/drivers/pcmcia/vrc4171_card.c index 459e6e1946fd..e076a13db555 100644 --- a/drivers/pcmcia/vrc4171_card.c +++ b/drivers/pcmcia/vrc4171_card.c @@ -730,7 +730,7 @@ static int __devinit vrc4171_card_init(void) retval = vrc4171_add_sockets(); if (retval == 0) - retval = request_irq(vrc4171_irq, pccard_interrupt, SA_SHIRQ, + retval = request_irq(vrc4171_irq, pccard_interrupt, IRQF_SHARED, vrc4171_card_name, vrc4171_sockets); if (retval < 0) { diff --git a/drivers/pcmcia/vrc4173_cardu.c b/drivers/pcmcia/vrc4173_cardu.c index 6004196f7cc1..d19a9138135f 100644 --- a/drivers/pcmcia/vrc4173_cardu.c +++ b/drivers/pcmcia/vrc4173_cardu.c @@ -500,7 +500,7 @@ static int __devinit vrc4173_cardu_probe(struct pci_dev *dev, return -ENOMEM; } - if (request_irq(dev->irq, cardu_interrupt, SA_SHIRQ, socket->name, socket) < 0) { + if (request_irq(dev->irq, cardu_interrupt, IRQF_SHARED, socket->name, socket) < 0) { pcmcia_unregister_socket(socket->pcmcia_socket); socket->pcmcia_socket = NULL; iounmap(socket->base); diff --git a/drivers/pcmcia/yenta_socket.c b/drivers/pcmcia/yenta_socket.c index 4145eb83b9b6..1344746381e8 100644 --- a/drivers/pcmcia/yenta_socket.c +++ b/drivers/pcmcia/yenta_socket.c @@ -287,7 +287,10 @@ static int yenta_set_socket(struct pcmcia_socket *sock, socket_state_t *state) struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket); u16 bridge; - yenta_set_power(socket, state); + /* if powering down: do it immediately */ + if (state->Vcc == 0) + yenta_set_power(socket, state); + socket->io_irq = state->io_irq; bridge = config_readw(socket, CB_BRIDGE_CONTROL) & ~(CB_BRIDGE_CRST | CB_BRIDGE_INTR); if (cb_readl(socket, CB_SOCKET_STATE) & CB_CBCARD) { @@ -339,6 +342,10 @@ static int yenta_set_socket(struct pcmcia_socket *sock, socket_state_t *state) /* Socket event mask: get card insert/remove events.. */ cb_writel(socket, CB_SOCKET_EVENT, -1); cb_writel(socket, CB_SOCKET_MASK, CB_CDMASK); + + /* if powering up: do it as the last step when the socket is configured */ + if (state->Vcc != 0) + yenta_set_power(socket, state); return 0; } @@ -916,7 +923,7 @@ static int yenta_probe_cb_irq(struct yenta_socket *socket) socket->probe_status = 0; - if (request_irq(socket->cb_irq, yenta_probe_handler, SA_SHIRQ, "yenta", socket)) { + if (request_irq(socket->cb_irq, yenta_probe_handler, IRQF_SHARED, "yenta", socket)) { printk(KERN_WARNING "Yenta: request_irq() in yenta_probe_cb_irq() failed!\n"); return -1; } @@ -998,6 +1005,77 @@ static void yenta_config_init(struct yenta_socket *socket) config_writew(socket, CB_BRIDGE_CONTROL, bridge); } +/** + * yenta_fixup_parent_bridge - Fix subordinate bus# of the parent bridge + * @cardbus_bridge: The PCI bus which the CardBus bridge bridges to + * + * Checks if devices on the bus which the CardBus bridge bridges to would be + * invisible during PCI scans because of a misconfigured subordinate number + * of the parent brige - some BIOSes seem to be too lazy to set it right. + * Does the fixup carefully by checking how far it can go without conflicts. + * See http://bugzilla.kernel.org/show_bug.cgi?id=2944 for more information. + */ +static void yenta_fixup_parent_bridge(struct pci_bus *cardbus_bridge) +{ + struct list_head *tmp; + unsigned char upper_limit; + /* + * We only check and fix the parent bridge: All systems which need + * this fixup that have been reviewed are laptops and the only bridge + * which needed fixing was the parent bridge of the CardBus bridge: + */ + struct pci_bus *bridge_to_fix = cardbus_bridge->parent; + + /* Check bus numbers are already set up correctly: */ + if (bridge_to_fix->subordinate >= cardbus_bridge->subordinate) + return; /* The subordinate number is ok, nothing to do */ + + if (!bridge_to_fix->parent) + return; /* Root bridges are ok */ + + /* stay within the limits of the bus range of the parent: */ + upper_limit = bridge_to_fix->parent->subordinate; + + /* check the bus ranges of all silbling bridges to prevent overlap */ + list_for_each(tmp, &bridge_to_fix->parent->children) { + struct pci_bus * silbling = pci_bus_b(tmp); + /* + * If the silbling has a higher secondary bus number + * and it's secondary is equal or smaller than our + * current upper limit, set the new upper limit to + * the bus number below the silbling's range: + */ + if (silbling->secondary > bridge_to_fix->subordinate + && silbling->secondary <= upper_limit) + upper_limit = silbling->secondary - 1; + } + + /* Show that the wanted subordinate number is not possible: */ + if (cardbus_bridge->subordinate > upper_limit) + printk(KERN_WARNING "Yenta: Upper limit for fixing this " + "bridge's parent bridge: #%02x\n", upper_limit); + + /* If we have room to increase the bridge's subordinate number, */ + if (bridge_to_fix->subordinate < upper_limit) { + + /* use the highest number of the hidden bus, within limits */ + unsigned char subordinate_to_assign = + min(cardbus_bridge->subordinate, upper_limit); + + printk(KERN_INFO "Yenta: Raising subordinate bus# of parent " + "bus (#%02x) from #%02x to #%02x\n", + bridge_to_fix->number, + bridge_to_fix->subordinate, subordinate_to_assign); + + /* Save the new subordinate in the bus struct of the bridge */ + bridge_to_fix->subordinate = subordinate_to_assign; + + /* and update the PCI config space with the new subordinate */ + pci_write_config_byte(bridge_to_fix->self, + PCI_SUBORDINATE_BUS, bridge_to_fix->subordinate); + } +} + /* * Initialize a cardbus controller. Make sure we have a usable * interrupt, and that we can map the cardbus area. Fill in the @@ -1094,7 +1172,7 @@ static int __devinit yenta_probe (struct pci_dev *dev, const struct pci_device_i /* We must finish initialization here */ - if (!socket->cb_irq || request_irq(socket->cb_irq, yenta_interrupt, SA_SHIRQ, "yenta", socket)) { + if (!socket->cb_irq || request_irq(socket->cb_irq, yenta_interrupt, IRQF_SHARED, "yenta", socket)) { /* No IRQ or request_irq failed. Poll */ socket->cb_irq = 0; /* But zero is a valid IRQ number. */ init_timer(&socket->poll_timer); @@ -1113,6 +1191,8 @@ static int __devinit yenta_probe (struct pci_dev *dev, const struct pci_device_i yenta_get_socket_capabilities(socket, isa_interrupts); printk(KERN_INFO "Socket status: %08x\n", cb_readl(socket, CB_SOCKET_STATE)); + yenta_fixup_parent_bridge(dev->subordinate); + /* Register it with the pcmcia layer.. */ ret = pcmcia_register_socket(&socket->socket); if (ret == 0) { @@ -1232,6 +1312,7 @@ static struct pci_device_id yenta_table [] = { CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_XX21_XX11, TI12XX), CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_X515, TI12XX), + CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_XX12, TI12XX), CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_X420, TI12XX), CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_X620, TI12XX), CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_7410, TI12XX), |