Hi Niaz,
On Fri, Oct 22, 2010 at 12:27:23PM -0700, Musfiq Niaz Rahman wrote:
> Hi,
>
> I am trying to understand the linux mmc stack implementation for
> educational/research purpose and finding it very hard to track the
> inter-relation among the source files. Do you have a high-level design
> documentation of the stack or any other place where i can find the
> design or notes on the implementation?
I'm afraid we don't, that I know of. While this is no substitute for
good documentation, for what it's worth I think that ftrace is a fairly
excellent tool for understanding new areas of the kernel. For example:
# mount -t debugfs debugfs /sys/kernel/debug
# cd /sys/kernel/debug/tracing/
# echo function_graph > current_tracer
# echo "mmc*" > set_ftrace_filter
# echo "sdhci*" >> set_ftrace_filter
# echo 1 > tracing_enabled
# echo 1 > tracing_on
<insert an SD card>
# echo 0 > tracing_on
# cat trace
Produces (cleaned up a little):
0) 6.798 us | sdhci_irq();
0) | sdhci_tasklet_card() {
0) 2.825 us | mmc_detect_change();
0) 9.134 us | }
0) | mmc_rescan() {
0) 0.951 us | mmc_bus_get();
0) 0.570 us | mmc_bus_put();
0) 0.541 us | mmc_bus_get();
0) 1.368 us | mmc_bus_put();
0) 0.552 us | mmc_host_enable();
0) | mmc_power_up() {
0) | mmc_set_ios() {
0) | sdhci_set_ios() {
0) 0.571 us | sdhci_set_clock();
0) 0.583 us | sdhci_set_power();
0) 7.305 us | }
0) 8.582 us | }
0) ! 11031.80 us | mmc_delay.clone.0();
0) | mmc_set_ios() {
0) | sdhci_set_ios() {
0) 5.720 us | sdhci_set_clock();
0) 0.623 us | sdhci_set_power();
0) + 13.022 us | }
0) + 14.557 us | }
0) ! 10898.94 us | mmc_delay.clone.0();
0) ! 21959.72 us | }
0) | mmc_io_rw_direct_host() {
0) | mmc_wait_for_cmd() {
0) | mmc_wait_for_req() {
0) 5.675 us | sdhci_led_control();
0) 9.187 us | sdhci_request();
1) + 74.351 us | } /* mmc_wait_for_req */
1) + 77.657 us | } /* mmc_wait_for_cmd */
1) + 79.294 us | } /* mmc_io_rw_direct_host */
1) | mmc_io_rw_direct_host() {
1) | mmc_wait_for_cmd() {
1) | mmc_wait_for_req() {
1) 5.826 us | sdhci_led_control();
1) + 10.550 us | sdhci_request();
------------------------------------------
1) kworker-5451 => ksoftir-5404
------------------------------------------
1) | sdhci_tasklet_finish() {
1) 0.758 us | sdhci_set_clock();
1) 0.545 us | sdhci_reset();
1) 1.920 us | sdhci_reset();
1) | mmc_request_done() {
1) 5.916 us | sdhci_led_control();
1) 2.835 us | mmc_wait_done();
1) + 10.659 us | }
1) + 26.404 us | }
------------------------------------------
0) ksoftir-3 => kworker-5451
------------------------------------------
0) + 61.690 us | }
0) + 63.350 us | } /* mmc_wait_for_cmd */
0) + 65.213 us | } /* mmc_io_rw_direct_host */
0) | mmc_go_idle() {
0) | mmc_set_chip_select() {
0) | mmc_set_ios() {
0) | sdhci_set_ios() {
0) 0.702 us | sdhci_set_clock();
0) 0.815 us | sdhci_set_power();
0) 8.680 us | }
0) + 10.787 us | }
0) + 11.936 us | }
0) ! 1972.149 us | mmc_delay();
0) | mmc_wait_for_cmd() {
0) | mmc_wait_for_req() {
0) 5.648 us | sdhci_led_control();
0) 9.014 us | sdhci_request();
------------------------------------------
0) kworker-5451 => ksoftir-3
------------------------------------------
I'm going to make the hopefully-not-outrageous claim that this already
gives us a reasonable idea of how the subsystem works. We can see that
sdhci_irq() received an interrupt for the card insertion event, which
gives us an intuition that sdhci_* is responsible for actively talking
to the hardware. We then hit mmc_detect_change() and mmc_rescan(), and
that triggers are a bunch of commands to the card that are created with
mmc_wait_for_cmd() and fulfilled with sdhci_request(), and we can see
that when we hit sdhci_request() we next end up in sdhci_tasklet_finish(),
which means we got an answer to our command from the controller, and we
then go on to mmc_request_done().
This understanding (of an mmc_ layer that decides which commands to submit
and an sdhci_ layer that talks to the hardware) maps on to the directory
structure -- the mmc_ level commands are in core/, and the sdhci_ level
commands are in host/.
ftrace is also useful for attacking bugs, rather than just sprinkling
printk() everywhere -- you can compare ftrace captures across working
and failing runs, and work out where the callpath starts to differ
in the failing state.
Hope that helps,
--
Chris Ball <[email protected]> <http://printf.net/>
One Laptop Per Child
--
To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html