aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorMika Westerberg <mika.westerberg@linux.intel.com>2011-08-18 08:23:48 -0400
committerChris Ball <cjb@laptop.org>2011-08-31 16:25:49 -0400
commit778e277cb82411c9002ca28ccbd216c4d9eb9158 (patch)
tree4bc74d9c9c982863efeae95c604be99eb23d73a3 /drivers
parent08c14071fda4e69abb9d5b1566651cd092b158d3 (diff)
mmc: core: prevent aggressive clock gating racing with ios updates
We have seen at least two different races when clock gating kicks in in a middle of ios structure update. First one happens when ios->clock is changed outside of aggressive clock gating framework, for example via mmc_set_clock(). The race might happen when we run following code: mmc_set_ios(): ... if (ios->clock > 0) mmc_set_ungated(host); Now if gating kicks in right after the condition check we end up setting host->clk_gated to false even though we have just gated the clock. Next time a request is started we try to ungate and restore the clock in mmc_host_clk_hold(). However since we have host->clk_gated set to false the original clock is not restored. This eventually will cause the host controller to hang since its clock is disabled while we are trying to issue a request. For example on Intel Medfield platform we see: [ 13.818610] mmc2: Timeout waiting for hardware interrupt. [ 13.818698] sdhci: =========== REGISTER DUMP (mmc2)=========== [ 13.818753] sdhci: Sys addr: 0x00000000 | Version: 0x00008901 [ 13.818804] sdhci: Blk size: 0x00000000 | Blk cnt: 0x00000000 [ 13.818853] sdhci: Argument: 0x00000000 | Trn mode: 0x00000000 [ 13.818903] sdhci: Present: 0x1fff0000 | Host ctl: 0x00000001 [ 13.818951] sdhci: Power: 0x0000000d | Blk gap: 0x00000000 [ 13.819000] sdhci: Wake-up: 0x00000000 | Clock: 0x00000000 [ 13.819049] sdhci: Timeout: 0x00000000 | Int stat: 0x00000000 [ 13.819098] sdhci: Int enab: 0x00ff00c3 | Sig enab: 0x00ff00c3 [ 13.819147] sdhci: AC12 err: 0x00000000 | Slot int: 0x00000000 [ 13.819196] sdhci: Caps: 0x6bee32b2 | Caps_1: 0x00000000 [ 13.819245] sdhci: Cmd: 0x00000000 | Max curr: 0x00000000 [ 13.819292] sdhci: Host ctl2: 0x00000000 [ 13.819331] sdhci: ADMA Err: 0x00000000 | ADMA Ptr: 0x00000000 [ 13.819377] sdhci: =========================================== [ 13.919605] mmc2: Reset 0x2 never completed. and it never recovers. Second race might happen while running mmc_power_off(): static void mmc_power_off(struct mmc_host *host) { host->ios.clock = 0; host->ios.vdd = 0; [ clock gating kicks in here ] /* * Reset ocr mask to be the highest possible voltage supported for * this mmc host. This value will be used at next power up. */ host->ocr = 1 << (fls(host->ocr_avail) - 1); if (!mmc_host_is_spi(host)) { host->ios.bus_mode = MMC_BUSMODE_OPENDRAIN; host->ios.chip_select = MMC_CS_DONTCARE; } host->ios.power_mode = MMC_POWER_OFF; host->ios.bus_width = MMC_BUS_WIDTH_1; host->ios.timing = MMC_TIMING_LEGACY; mmc_set_ios(host); } If the clock gating worker kicks in while we are only partially updated the ios structure the host controller gets incomplete ios and might not work as supposed. Again on Intel Medfield platform we get: [ 4.185349] kernel BUG at drivers/mmc/host/sdhci.c:1155! [ 4.185422] invalid opcode: 0000 [#1] PREEMPT SMP [ 4.185509] Modules linked in: [ 4.185565] [ 4.185608] Pid: 4, comm: kworker/0:0 Not tainted 3.0.0+ #240 Intel Corporation Medfield/iCDKA [ 4.185742] EIP: 0060:[<c136364e>] EFLAGS: 00010083 CPU: 0 [ 4.185827] EIP is at sdhci_set_power+0x3e/0xd0 [ 4.185891] EAX: f5ff98e0 EBX: f5ff98e0 ECX: 00000000 EDX: 00000001 [ 4.185970] ESI: f5ff977c EDI: f5ff9904 EBP: f644fe98 ESP: f644fe94 [ 4.186049] DS: 007b ES: 007b FS: 00d8 GS: 0000 SS: 0068 [ 4.186125] Process kworker/0:0 (pid: 4, ti=f644e000 task=f644c0e0 task.ti=f644e000) [ 4.186219] Stack: [ 4.186257] f5ff98e0 f644feb0 c1365173 00000282 f5ff9460 f5ff96e0 f5ff96e0 f644feec [ 4.186418] c1355bd8 f644c0e0 c1499c3d f5ff96e0 f644fed4 00000006 f5ff96e0 00000286 [ 4.186579] f644fedc c107922b f644feec 00000286 f5ff9460 f5ff9700 f644ff10 c135839e [ 4.186739] Call Trace: [ 4.186802] [<c1365173>] sdhci_set_ios+0x1c3/0x340 [ 4.186883] [<c1355bd8>] mmc_gate_clock+0x68/0x120 [ 4.186963] [<c1499c3d>] ? _raw_spin_unlock_irqrestore+0x4d/0x60 [ 4.187052] [<c107922b>] ? trace_hardirqs_on+0xb/0x10 [ 4.187134] [<c135839e>] mmc_host_clk_gate_delayed+0xbe/0x130 [ 4.187219] [<c105ec09>] ? process_one_work+0xf9/0x5b0 [ 4.187300] [<c135841d>] mmc_host_clk_gate_work+0xd/0x10 [ 4.187379] [<c105ec82>] process_one_work+0x172/0x5b0 [ 4.187457] [<c105ec09>] ? process_one_work+0xf9/0x5b0 [ 4.187538] [<c1358410>] ? mmc_host_clk_gate_delayed+0x130/0x130 [ 4.187625] [<c105f3c8>] worker_thread+0x118/0x330 [ 4.187700] [<c1496cee>] ? preempt_schedule+0x2e/0x50 [ 4.187779] [<c105f2b0>] ? rescuer_thread+0x1f0/0x1f0 [ 4.187857] [<c1062cf4>] kthread+0x74/0x80 [ 4.187931] [<c1062c80>] ? __init_kthread_worker+0x60/0x60 [ 4.188015] [<c149acfa>] kernel_thread_helper+0x6/0xd [ 4.188079] Code: 81 fa 00 00 04 00 0f 84 a7 00 00 00 7f 21 81 fa 80 00 00 00 0f 84 92 00 00 00 81 fa 00 00 0 [ 4.188780] EIP: [<c136364e>] sdhci_set_power+0x3e/0xd0 SS:ESP 0068:f644fe94 [ 4.188898] ---[ end trace a7b23eecc71777e4 ]--- This BUG() comes from the fact that ios.power_mode was still in previous value (MMC_POWER_ON) and ios.vdd was set to zero. We prevent these by inhibiting the clock gating while we update the ios structure. Both problems can be reproduced by simply running the device in a reboot loop. Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com> Reviewed-by: Linus Walleij <linus.walleij@linaro.org> Tested-by: Chris Ball <cjb@laptop.org> Cc: <stable@kernel.org> Signed-off-by: Chris Ball <cjb@laptop.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/mmc/core/core.c31
1 files changed, 29 insertions, 2 deletions
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index 63ffc65f84af..b27b94078c21 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -728,15 +728,17 @@ static inline void mmc_set_ios(struct mmc_host *host)
728 */ 728 */
729void mmc_set_chip_select(struct mmc_host *host, int mode) 729void mmc_set_chip_select(struct mmc_host *host, int mode)
730{ 730{
731 mmc_host_clk_hold(host);
731 host->ios.chip_select = mode; 732 host->ios.chip_select = mode;
732 mmc_set_ios(host); 733 mmc_set_ios(host);
734 mmc_host_clk_release(host);
733} 735}
734 736
735/* 737/*
736 * Sets the host clock to the highest possible frequency that 738 * Sets the host clock to the highest possible frequency that
737 * is below "hz". 739 * is below "hz".
738 */ 740 */
739void mmc_set_clock(struct mmc_host *host, unsigned int hz) 741static void __mmc_set_clock(struct mmc_host *host, unsigned int hz)
740{ 742{
741 WARN_ON(hz < host->f_min); 743 WARN_ON(hz < host->f_min);
742 744
@@ -747,6 +749,13 @@ void mmc_set_clock(struct mmc_host *host, unsigned int hz)
747 mmc_set_ios(host); 749 mmc_set_ios(host);
748} 750}
749 751
752void mmc_set_clock(struct mmc_host *host, unsigned int hz)
753{
754 mmc_host_clk_hold(host);
755 __mmc_set_clock(host, hz);
756 mmc_host_clk_release(host);
757}
758
750#ifdef CONFIG_MMC_CLKGATE 759#ifdef CONFIG_MMC_CLKGATE
751/* 760/*
752 * This gates the clock by setting it to 0 Hz. 761 * This gates the clock by setting it to 0 Hz.
@@ -779,7 +788,7 @@ void mmc_ungate_clock(struct mmc_host *host)
779 if (host->clk_old) { 788 if (host->clk_old) {
780 BUG_ON(host->ios.clock); 789 BUG_ON(host->ios.clock);
781 /* This call will also set host->clk_gated to false */ 790 /* This call will also set host->clk_gated to false */
782 mmc_set_clock(host, host->clk_old); 791 __mmc_set_clock(host, host->clk_old);
783 } 792 }
784} 793}
785 794
@@ -807,8 +816,10 @@ void mmc_set_ungated(struct mmc_host *host)
807 */ 816 */
808void mmc_set_bus_mode(struct mmc_host *host, unsigned int mode) 817void mmc_set_bus_mode(struct mmc_host *host, unsigned int mode)
809{ 818{
819 mmc_host_clk_hold(host);
810 host->ios.bus_mode = mode; 820 host->ios.bus_mode = mode;
811 mmc_set_ios(host); 821 mmc_set_ios(host);
822 mmc_host_clk_release(host);
812} 823}
813 824
814/* 825/*
@@ -816,8 +827,10 @@ void mmc_set_bus_mode(struct mmc_host *host, unsigned int mode)
816 */ 827 */
817void mmc_set_bus_width(struct mmc_host *host, unsigned int width) 828void mmc_set_bus_width(struct mmc_host *host, unsigned int width)
818{ 829{
830 mmc_host_clk_hold(host);
819 host->ios.bus_width = width; 831 host->ios.bus_width = width;
820 mmc_set_ios(host); 832 mmc_set_ios(host);
833 mmc_host_clk_release(host);
821} 834}
822 835
823/** 836/**
@@ -1015,8 +1028,10 @@ u32 mmc_select_voltage(struct mmc_host *host, u32 ocr)
1015 1028
1016 ocr &= 3 << bit; 1029 ocr &= 3 << bit;
1017 1030
1031 mmc_host_clk_hold(host);
1018 host->ios.vdd = bit; 1032 host->ios.vdd = bit;
1019 mmc_set_ios(host); 1033 mmc_set_ios(host);
1034 mmc_host_clk_release(host);
1020 } else { 1035 } else {
1021 pr_warning("%s: host doesn't support card's voltages\n", 1036 pr_warning("%s: host doesn't support card's voltages\n",
1022 mmc_hostname(host)); 1037 mmc_hostname(host));
@@ -1063,8 +1078,10 @@ int mmc_set_signal_voltage(struct mmc_host *host, int signal_voltage, bool cmd11
1063 */ 1078 */
1064void mmc_set_timing(struct mmc_host *host, unsigned int timing) 1079void mmc_set_timing(struct mmc_host *host, unsigned int timing)
1065{ 1080{
1081 mmc_host_clk_hold(host);
1066 host->ios.timing = timing; 1082 host->ios.timing = timing;
1067 mmc_set_ios(host); 1083 mmc_set_ios(host);
1084 mmc_host_clk_release(host);
1068} 1085}
1069 1086
1070/* 1087/*
@@ -1072,8 +1089,10 @@ void mmc_set_timing(struct mmc_host *host, unsigned int timing)
1072 */ 1089 */
1073void mmc_set_driver_type(struct mmc_host *host, unsigned int drv_type) 1090void mmc_set_driver_type(struct mmc_host *host, unsigned int drv_type)
1074{ 1091{
1092 mmc_host_clk_hold(host);
1075 host->ios.drv_type = drv_type; 1093 host->ios.drv_type = drv_type;
1076 mmc_set_ios(host); 1094 mmc_set_ios(host);
1095 mmc_host_clk_release(host);
1077} 1096}
1078 1097
1079/* 1098/*
@@ -1091,6 +1110,8 @@ static void mmc_power_up(struct mmc_host *host)
1091{ 1110{
1092 int bit; 1111 int bit;
1093 1112
1113 mmc_host_clk_hold(host);
1114
1094 /* If ocr is set, we use it */ 1115 /* If ocr is set, we use it */
1095 if (host->ocr) 1116 if (host->ocr)
1096 bit = ffs(host->ocr) - 1; 1117 bit = ffs(host->ocr) - 1;
@@ -1126,10 +1147,14 @@ static void mmc_power_up(struct mmc_host *host)
1126 * time required to reach a stable voltage. 1147 * time required to reach a stable voltage.
1127 */ 1148 */
1128 mmc_delay(10); 1149 mmc_delay(10);
1150
1151 mmc_host_clk_release(host);
1129} 1152}
1130 1153
1131static void mmc_power_off(struct mmc_host *host) 1154static void mmc_power_off(struct mmc_host *host)
1132{ 1155{
1156 mmc_host_clk_hold(host);
1157
1133 host->ios.clock = 0; 1158 host->ios.clock = 0;
1134 host->ios.vdd = 0; 1159 host->ios.vdd = 0;
1135 1160
@@ -1147,6 +1172,8 @@ static void mmc_power_off(struct mmc_host *host)
1147 host->ios.bus_width = MMC_BUS_WIDTH_1; 1172 host->ios.bus_width = MMC_BUS_WIDTH_1;
1148 host->ios.timing = MMC_TIMING_LEGACY; 1173 host->ios.timing = MMC_TIMING_LEGACY;
1149 mmc_set_ios(host); 1174 mmc_set_ios(host);
1175
1176 mmc_host_clk_release(host);
1150} 1177}
1151 1178
1152/* 1179/*