Hi,

On Fri, Dec 16, 2011 at 11:50:32AM +1100, NeilBrown wrote:
> On Fri, 16 Dec 2011 02:03:51 +0200 Grazvydas Ignotas <[email protected]>
> 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 <[email protected]>
> 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 <[email protected]>

Didn't test myself, but looks like the right approach:

Reviewed-by: Felipe Balbi <[email protected]>

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



-- 
balbi

Attachment: signature.asc
Description: Digital signature

Reply via email to