2007-05-21 22:23:20 +04:00
/*
* linux / drivers / mmc / sdio_ops . c
*
* Copyright 2006 - 2007 Pierre Ossman
*
* 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
* the Free Software Foundation ; either version 2 of the License , or ( at
* your option ) any later version .
*/
# ifndef _MMC_SDIO_OPS_H
# define _MMC_SDIO_OPS_H
2017-01-13 16:14:07 +03:00
# include <linux/types.h>
2015-09-22 18:30:24 +03:00
# include <linux/mmc/sdio.h>
2017-01-13 16:14:07 +03:00
struct mmc_host ;
struct mmc_card ;
mmc: sdio: Add API to manage SDIO IRQs from a workqueue
For hosts not supporting MMC_CAP2_SDIO_IRQ_NOTHREAD but MMC_CAP_SDIO_IRQ,
the SDIO IRQs are processed from a dedicated kernel thread. For these
cases, the host calls mmc_signal_sdio_irq() from its ISR to signal a new
SDIO IRQ.
Signaling an SDIO IRQ makes the host's ->enable_sdio_irq() callback to be
invoked to temporary disable the IRQs, before the kernel thread is woken up
to process it. When processing of the IRQs are completed, they are
re-enabled by the kernel thread, again via invoking the host's
->enable_sdio_irq().
The observation from this, is that the execution path is being unnecessary
complex, as the host driver already knows that it needs to temporary
disable the IRQs before signaling a new one. Moreover, replacing the kernel
thread with a work/workqueue would not only greatly simplify the code, but
also make it more robust.
To address the above problems, let's continue to build upon the support for
MMC_CAP2_SDIO_IRQ_NOTHREAD, as it already implements SDIO IRQs to be
processed without using the clumsy kernel thread and without the ping-pong
calls of the host's ->enable_sdio_irq() callback for each processed IRQ.
Therefore, let's add new API sdio_signal_irq(), which enables hosts to
signal/process SDIO IRQs by using a work/workqueue, rather than using the
kernel thread.
Add also a new host callback ->ack_sdio_irq(), which the work invokes when
the SDIO IRQs have been processed. This informs the host about when it
shall re-enable the SDIO IRQs. Potentially, we could re-use the existing
->enable_sdio_irq() callback instead of adding a new one, however it has
turned out that it's more convenient for hosts to get this information via
a separate callback.
Hosts that wants to use this new method to signal/process SDIO IRQs, must
enable MMC_CAP2_SDIO_IRQ_NOTHREAD and implement the ->ack_sdio_irq()
callback.
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
Tested-by: Douglas Anderson <dianders@chromium.org>
Reviewed-by: Douglas Anderson <dianders@chromium.org>
2017-04-13 17:48:11 +03:00
struct work_struct ;
2017-01-13 16:14:07 +03:00
2007-05-21 22:23:20 +04:00
int mmc_send_io_op_cond ( struct mmc_host * host , u32 ocr , u32 * rocr ) ;
2007-05-22 22:25:21 +04:00
int mmc_io_rw_direct ( struct mmc_card * card , int write , unsigned fn ,
unsigned addr , u8 in , u8 * out ) ;
2007-07-06 15:35:01 +04:00
int mmc_io_rw_extended ( struct mmc_card * card , int write , unsigned fn ,
2007-08-08 17:24:21 +04:00
unsigned addr , int incr_addr , u8 * buf , unsigned blocks , unsigned blksz ) ;
2010-03-11 02:20:37 +03:00
int sdio_reset ( struct mmc_host * host ) ;
mmc: sdio: Add API to manage SDIO IRQs from a workqueue
For hosts not supporting MMC_CAP2_SDIO_IRQ_NOTHREAD but MMC_CAP_SDIO_IRQ,
the SDIO IRQs are processed from a dedicated kernel thread. For these
cases, the host calls mmc_signal_sdio_irq() from its ISR to signal a new
SDIO IRQ.
Signaling an SDIO IRQ makes the host's ->enable_sdio_irq() callback to be
invoked to temporary disable the IRQs, before the kernel thread is woken up
to process it. When processing of the IRQs are completed, they are
re-enabled by the kernel thread, again via invoking the host's
->enable_sdio_irq().
The observation from this, is that the execution path is being unnecessary
complex, as the host driver already knows that it needs to temporary
disable the IRQs before signaling a new one. Moreover, replacing the kernel
thread with a work/workqueue would not only greatly simplify the code, but
also make it more robust.
To address the above problems, let's continue to build upon the support for
MMC_CAP2_SDIO_IRQ_NOTHREAD, as it already implements SDIO IRQs to be
processed without using the clumsy kernel thread and without the ping-pong
calls of the host's ->enable_sdio_irq() callback for each processed IRQ.
Therefore, let's add new API sdio_signal_irq(), which enables hosts to
signal/process SDIO IRQs by using a work/workqueue, rather than using the
kernel thread.
Add also a new host callback ->ack_sdio_irq(), which the work invokes when
the SDIO IRQs have been processed. This informs the host about when it
shall re-enable the SDIO IRQs. Potentially, we could re-use the existing
->enable_sdio_irq() callback instead of adding a new one, however it has
turned out that it's more convenient for hosts to get this information via
a separate callback.
Hosts that wants to use this new method to signal/process SDIO IRQs, must
enable MMC_CAP2_SDIO_IRQ_NOTHREAD and implement the ->ack_sdio_irq()
callback.
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
Tested-by: Douglas Anderson <dianders@chromium.org>
Reviewed-by: Douglas Anderson <dianders@chromium.org>
2017-04-13 17:48:11 +03:00
void sdio_irq_work ( struct work_struct * work ) ;
2007-05-21 22:23:20 +04:00
2017-04-23 12:38:27 +03:00
static inline bool sdio_is_io_busy ( u32 opcode , u32 arg )
2015-09-22 18:30:24 +03:00
{
2017-04-23 12:38:27 +03:00
u32 addr ;
addr = ( arg > > 9 ) & 0x1FFFF ;
return ( opcode = = SD_IO_RW_EXTENDED | |
( opcode = = SD_IO_RW_DIRECT & &
! ( addr = = SDIO_CCCR_ABORT | | addr = = SDIO_CCCR_SUSPEND ) ) ) ;
2015-09-22 18:30:24 +03:00
}
2007-05-21 22:23:20 +04:00
# endif