On Fri, 16 Dec 2011 02:03:51 +0200 Grazvydas Ignotas <notasas@xxxxxxxxx> wrote: > Hi, > > I'm running 3.2-rc5 on pandora with Neil's twl patches on top, and > omap_hsmmc driver fails to probe: > [ 3.491394] omap_hsmmc omap_hsmmc.0: context was not lost > [ 3.497161] omap_hsmmc omap_hsmmc.0: enabled > [ 3.715270] omap_hsmmc omap_hsmmc.0: Unable to grab MMC CD IRQ > > Pandora is using twl4030 GPIOs for card detect. From what I tried to > debug, omap_hsmmc is failing after call to request_irq() on card > detect irq with -EINVAL, irq number is 384 which is in range of other > twl4030 irqs. It looks like request_irq() is calling > request_threaded_irq() on ARM with NULL thread_fn, which in turn calls > __setup_irq() that calls irq_settings_is_nested_thread() that results > with true. As this nested flag is set it checks thread_fn, but that is > NULL causing -EINVAL final result. > > Could someone who knows irq code better look at this? I think this > should reproduce on beagle too. > > Try this. I wrote it for a slightly different reason, but I think it applies here. NeilBrown From f7f05b87364d0316f1f6ddad0d7387b25f5d21b9 Mon Sep 17 00:00:00 2001 From: NeilBrown <neilb@xxxxxxx> Date: Fri, 2 Dec 2011 15:35:16 +1100 Subject: [PATCH] omap_hsmmc - use threaded irq handler for card-detect. The the card-detect irq handler just schedules work to be done by a thread, we can use request_threaded_irq to do much of the work for us. Signed-off-by: NeilBrown <neilb@xxxxxxx> diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index 101cd31..d72c181 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -24,7 +24,6 @@ #include <linux/delay.h> #include <linux/dma-mapping.h> #include <linux/platform_device.h> -#include <linux/workqueue.h> #include <linux/timer.h> #include <linux/clk.h> #include <linux/mmc/host.h> @@ -163,7 +162,6 @@ struct omap_hsmmc_host { */ struct regulator *vcc; struct regulator *vcc_aux; - struct work_struct mmc_carddetect_work; void __iomem *base; resource_size_t mapbase; spinlock_t irq_lock; /* Prevent races with irq handler */ @@ -1279,17 +1277,16 @@ static void omap_hsmmc_protect_card(struct omap_hsmmc_host *host) } /* - * Work Item to notify the core about card insertion/removal + * irq handler to notify the core about card insertion/removal */ -static void omap_hsmmc_detect(struct work_struct *work) +static irqreturn_t omap_hsmmc_detect(int irq, void *dev_id) { - struct omap_hsmmc_host *host = - container_of(work, struct omap_hsmmc_host, mmc_carddetect_work); + struct omap_hsmmc_host *host = dev_id; struct omap_mmc_slot_data *slot = &mmc_slot(host); int carddetect; if (host->suspended) - return; + return IRQ_HANDLED; sysfs_notify(&host->mmc->class_dev.kobj, NULL, "cover_switch"); @@ -1304,19 +1301,6 @@ static void omap_hsmmc_detect(struct work_struct *work) mmc_detect_change(host->mmc, (HZ * 200) / 1000); else mmc_detect_change(host->mmc, (HZ * 50) / 1000); -} - -/* - * ISR for handling card insertion and removal - */ -static irqreturn_t omap_hsmmc_cd_handler(int irq, void *dev_id) -{ - struct omap_hsmmc_host *host = (struct omap_hsmmc_host *)dev_id; - - if (host->suspended) - return IRQ_HANDLED; - schedule_work(&host->mmc_carddetect_work); - return IRQ_HANDLED; } @@ -1916,7 +1900,6 @@ static int __init omap_hsmmc_probe(struct platform_device *pdev) host->next_data.cookie = 1; platform_set_drvdata(pdev, host); - INIT_WORK(&host->mmc_carddetect_work, omap_hsmmc_detect); mmc->ops = &omap_hsmmc_ops; @@ -2044,10 +2027,11 @@ static int __init omap_hsmmc_probe(struct platform_device *pdev) /* Request IRQ for card detect */ if ((mmc_slot(host).card_detect_irq)) { - ret = request_irq(mmc_slot(host).card_detect_irq, - omap_hsmmc_cd_handler, - IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, - mmc_hostname(mmc), host); + ret = request_threaded_irq(mmc_slot(host).card_detect_irq, + NULL, + omap_hsmmc_detect, + IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, + mmc_hostname(mmc), host); if (ret) { dev_dbg(mmc_dev(host->mmc), "Unable to grab MMC CD IRQ\n"); @@ -2126,7 +2110,6 @@ static int omap_hsmmc_remove(struct platform_device *pdev) free_irq(host->irq, host); if (mmc_slot(host).card_detect_irq) free_irq(mmc_slot(host).card_detect_irq, host); - flush_work_sync(&host->mmc_carddetect_work); pm_runtime_put_sync(host->dev); pm_runtime_disable(host->dev); @@ -2173,7 +2156,6 @@ static int omap_hsmmc_suspend(struct device *dev) return ret; } } - cancel_work_sync(&host->mmc_carddetect_work); ret = mmc_suspend_host(host->mmc); if (ret == 0) {
Attachment:
signature.asc
Description: PGP signature