--- d/ar6000/hif/hif2.c 2009-03-30 01:11:04.000000000 +0400 +++ e/ar6000//hif/hif2.c 2009-03-30 01:33:03.000000000 +0400 @@ -98,6 +98,13 @@ struct sdio_func *func; /* + * SDIO irq process handle, for prevent claim/relese in irq call. + * we must try not permit send any, not IRQ process necessary data, + * while IRQ not completed. + */ + struct task_struct *irq_task; + + /* * @@@ our sweet little bit of bogosity - the mechanism that lets us * use the SDIO stack from softirqs. This really wants to use skbs. */ @@ -202,7 +209,9 @@ hif = sdio_get_drvdata(func); - sdio_claim_host(func); + /* prevent claim in irq */ + if (hif->irq_task != current) + sdio_claim_host(func); #ifdef _GTA02_ while (!s3c2410_gpio_getpin(S3C2410_GPE7)) { @@ -212,7 +221,9 @@ mmc_wait_for_req(host, &req.mrq); - sdio_release_host(func); + /* prevent relese in irq */ + if (hif->irq_task != current) + sdio_release_host(func); if ((req.cmd.error) || (req.data.error)) return A_ERROR; @@ -420,9 +431,10 @@ * * Solution 2) is probably the best for now. Will try it later. */ - sdio_release_host(func); + hif->irq_task = current; ar6000_do_irq(func); - sdio_claim_host(func); + hif->irq_task = NULL; + in_interrupt = 0; } @@ -515,8 +527,13 @@ mbs_cfg[i] = HIF_MBOX_START_ADDR(i); break; case HIF_DEVICE_GET_IRQ_PROC_MODE: - *ipm_cfg = HIF_DEVICE_IRQ_SYNC_ONLY; -// *ipm_cfg = HIF_DEVICE_IRQ_ASYNC_SYNC; + /* + * WARN: + * HIF_DEVICE_IRQ_ASYNC_SYNC in BUG list, but I not have it problem. + * Need additional testing on different boards. + */ +// *ipm_cfg = HIF_DEVICE_IRQ_SYNC_ONLY; + *ipm_cfg = HIF_DEVICE_IRQ_ASYNC_SYNC; break; default: return A_ERROR; @@ -574,7 +591,6 @@ return 0; } - /* ----- Device probe and removal (Linux side) ----------------------------- */