public inbox for linux-mmc@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/4] mmc: sdhci: try to avoid another division by zero
@ 2011-08-03 15:35 Andy Shevchenko
  2011-08-03 15:35 ` [PATCH 1/4] Revert "mmc: sdhci: Fix SDHCI_QUIRK_TIMEOUT_USES_SDCLK" Andy Shevchenko
                   ` (3 more replies)
  0 siblings, 4 replies; 5+ messages in thread
From: Andy Shevchenko @ 2011-08-03 15:35 UTC (permalink / raw)
  To: linux-mmc, Chris Ball; +Cc: Andy Shevchenko

The set of patches that applied for 3.0 exposes another "division by zero"
error. This set tries to remake the "Fix SDHCI_QUIRK_TIMEOUT_USES_SDCLK" patch.

Comments are very welcome!

Of course, the set needs to be tested carefully.

Andy Shevchenko (4):
  Revert "mmc: sdhci: Fix SDHCI_QUIRK_TIMEOUT_USES_SDCLK"
  mmc: sdhci: check host->clock before use it as denominator
  mmc: sdhci: move timeout_clk calculation a bit further
  mmc: sdhci: use f_max instead of host->clock for timeouts

 drivers/mmc/host/sdhci.c |   50 ++++++++++++++++++++++-----------------------
 1 files changed, 24 insertions(+), 26 deletions(-)

-- 
1.7.5.4


^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH 1/4] Revert "mmc: sdhci: Fix SDHCI_QUIRK_TIMEOUT_USES_SDCLK"
  2011-08-03 15:35 [PATCH 0/4] mmc: sdhci: try to avoid another division by zero Andy Shevchenko
@ 2011-08-03 15:35 ` Andy Shevchenko
  2011-08-03 15:35 ` [PATCH 2/4] mmc: sdhci: check host->clock before use it as denominator Andy Shevchenko
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 5+ messages in thread
From: Andy Shevchenko @ 2011-08-03 15:35 UTC (permalink / raw)
  To: linux-mmc, Chris Ball; +Cc: Andy Shevchenko

This reverts commit 4b01681c77642c62a833187066c35e71e59caaf5.
---
 drivers/mmc/host/sdhci.c |    7 +++----
 1 files changed, 3 insertions(+), 4 deletions(-)

diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 51c3b3f..aef7982 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -633,9 +633,6 @@ static u8 sdhci_calc_timeout(struct sdhci_host *host, struct mmc_command *cmd)
 		target_timeout = data->timeout_ns / 1000 +
 			data->timeout_clks / host->clock;
 
-	if (host->quirks & SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK)
-		host->timeout_clk = host->clock / 1000;
-
 	/*
 	 * Figure out needed cycles.
 	 * We do this in steps in order to fit inside a 32 bit int.
@@ -646,7 +643,6 @@ static u8 sdhci_calc_timeout(struct sdhci_host *host, struct mmc_command *cmd)
 	 *     =>
 	 *     (1) / (2) > 2^6
 	 */
-	BUG_ON(!host->timeout_clk);
 	count = 0;
 	current_timeout = (1 << 13) * 1000 / host->timeout_clk;
 	while (current_timeout < target_timeout) {
@@ -2475,6 +2471,9 @@ int sdhci_add_host(struct sdhci_host *host)
 	if (caps[0] & SDHCI_TIMEOUT_CLK_UNIT)
 		host->timeout_clk *= 1000;
 
+	if (host->quirks & SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK)
+		host->timeout_clk = host->clock / 1000;
+
 	/*
 	 * In case of Host Controller v3.00, find out whether clock
 	 * multiplier is supported.
-- 
1.7.5.4


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH 2/4] mmc: sdhci: check host->clock before use it as denominator
  2011-08-03 15:35 [PATCH 0/4] mmc: sdhci: try to avoid another division by zero Andy Shevchenko
  2011-08-03 15:35 ` [PATCH 1/4] Revert "mmc: sdhci: Fix SDHCI_QUIRK_TIMEOUT_USES_SDCLK" Andy Shevchenko
@ 2011-08-03 15:35 ` Andy Shevchenko
  2011-08-03 15:36 ` [PATCH 3/4] mmc: sdhci: move timeout_clk calculation a bit further Andy Shevchenko
  2011-08-03 15:36 ` [PATCH 4/4] mmc: sdhci: use f_max instead of host->clock for timeouts Andy Shevchenko
  3 siblings, 0 replies; 5+ messages in thread
From: Andy Shevchenko @ 2011-08-03 15:35 UTC (permalink / raw)
  To: linux-mmc, Chris Ball; +Cc: Andy Shevchenko

Sometimes host->clock could be zero which is legal situation. This patch checks
host->clock before usage as denominator when timeout is calculated. The similar
patch is applied for mmc core (see commit e9b8684).

Without this patch the execution of the sdhci_calc_timeout could end up with
traceback like following:

<0>[    4.014319] divide error: 0000 [#1] PREEMPT SMP
<4>[    4.014352] Modules linked in: g_ether
<4>[    4.014376]
<4>[    4.014393] Pid: 33, comm: kworker/u:2 Not tainted 3.0.0+ #646
<4>[    4.014421] EIP: 0060:[<c12fa38e>] EFLAGS: 00010046 CPU: 1
<4>[    4.014449] EIP is at sdhci_calc_timeout+0x2e/0x100
<4>[    4.014468] EAX: 00000000 EBX: f5930fc8 ECX: 00000000 EDX: 00000000
<4>[    4.014488] ESI: f5291de8 EDI: f5291db8 EBP: f5291c6c ESP: f5291c50
<4>[    4.014508]  DS: 007b ES: 007b FS: 00d8 GS: 0000 SS: 0068
<0>[    4.014529] Process kworker/u:2 (pid: 33, ti=f5290000 task=f53065a0 task.ti=f5290000)
<0>[    4.014546] Stack:
<4>[    4.014557]  00000082 c1054fdd f5291c78 04000000 f5930fc8 f5291de8 f5291db8 f5291cac
<4>[    4.014611]  c12fab7c c107a98b f5291c88 c13b6d3f f593109c f5882000 f5291cac c1054fdd
<4>[    4.014663]  00000000 00000000 f5882000 00000082 f5930fc8 f5291db8 0000000a f5291ccc
<0>[    4.014716] Call Trace:
<4>[    4.014743]  [<c1054fdd>] ? mod_timer+0x11d/0x380
<4>[    4.014770]  [<c12fab7c>] sdhci_prepare_data+0x2c/0x3a0
<4>[    4.014798]  [<c107a98b>] ? trace_hardirqs_off+0xb/0x10
<4>[    4.014827]  [<c13b6d3f>] ? _raw_spin_unlock_irqrestore+0x2f/0x60
<4>[    4.014854]  [<c1054fdd>] ? mod_timer+0x11d/0x380
<4>[    4.014880]  [<c12fc7db>] sdhci_send_command+0xdb/0x210
<4>[    4.014906]  [<c12fd5f3>] sdhci_request+0xc3/0x150
<4>[    4.014932]  [<c12ec56a>] mmc_start_request+0xda/0x200
<4>[    4.014960]  [<c120d7c2>] ? __raw_spin_lock_init+0x32/0x60
<4>[    4.014989]  [<c1066a85>] ? __init_waitqueue_head+0x35/0x50
<4>[    4.015015]  [<c12ec70b>] mmc_wait_for_req+0x7b/0x90
<4>[    4.015045]  [<c12f0c67>] mmc_send_cxd_data+0xf7/0x130
<4>[    4.015076]  [<c12ecbc0>] ? mmc_erase+0x140/0x140
<4>[    4.015102]  [<c12f139d>] mmc_send_ext_csd+0x1d/0x20
<4>[    4.015125]  [<c12efef0>] mmc_get_ext_csd+0x70/0x140
<4>[    4.015151]  [<c12effe8>] mmc_compare_ext_csds+0x28/0x190
<4>[    4.015176]  [<c12f039f>] mmc_init_card+0x24f/0x650
<4>[    4.015201]  [<c13b6d5d>] ? _raw_spin_unlock_irqrestore+0x4d/0x60
<4>[    4.015226]  [<c107fd9c>] ? trace_hardirqs_on_caller+0x11c/0x160
<4>[    4.015255]  [<c12f09a4>] mmc_attach_mmc+0xa4/0x190
<4>[    4.015282]  [<c12ee3f0>] mmc_rescan+0x210/0x240
<4>[    4.015311]  [<c105f9b6>] process_one_work+0x176/0x550
<4>[    4.015336]  [<c105f93a>] ? process_one_work+0xfa/0x550
<4>[    4.015360]  [<c12ee1e0>] ? mmc_init_erase+0x140/0x140
<4>[    4.015385]  [<c1061c2a>] worker_thread+0x12a/0x2c0
<4>[    4.015410]  [<c1061b00>] ? manage_workers.clone.18+0x100/0x100
<4>[    4.015437]  [<c1066244>] kthread+0x74/0x80
<4>[    4.015463]  [<c10661d0>] ? __init_kthread_worker+0x60/0x60
<4>[    4.015490]  [<c13b7dfa>] kernel_thread_helper+0x6/0xd
<0>[    4.015507] Code: 57 89 d7 56 53 89 c3 83 ec 10 8b 40 04 8b 72 28 f6 c4 10 89 45 f0 0f 85 91 00 00 00 85 f6 0f 84 c1 00 00 00 8b 4e 04 31 d2 89 c8 <f7> 73 58 ba d3 4d 62 10 89 c1 8b 06 f7 e2 c1 ea 06 01 d1 f7 45
<0>[    4.015829] EIP: [<c12fa38e>] sdhci_calc_timeout+0x2e/0x100 SS:ESP 0068:f5291c50

Reported-by: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
---
 drivers/mmc/host/sdhci.c |    8 +++++---
 1 files changed, 5 insertions(+), 3 deletions(-)

diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index aef7982..58bb15c 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -629,9 +629,11 @@ static u8 sdhci_calc_timeout(struct sdhci_host *host, struct mmc_command *cmd)
 	/* timeout in us */
 	if (!data)
 		target_timeout = cmd->cmd_timeout_ms * 1000;
-	else
-		target_timeout = data->timeout_ns / 1000 +
-			data->timeout_clks / host->clock;
+	else {
+		target_timeout = data->timeout_ns / 1000;
+		if (host->clock)
+			target_timeout += data->timeout_clks / host->clock;
+	}
 
 	/*
 	 * Figure out needed cycles.
-- 
1.7.5.4


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH 3/4] mmc: sdhci: move timeout_clk calculation a bit further
  2011-08-03 15:35 [PATCH 0/4] mmc: sdhci: try to avoid another division by zero Andy Shevchenko
  2011-08-03 15:35 ` [PATCH 1/4] Revert "mmc: sdhci: Fix SDHCI_QUIRK_TIMEOUT_USES_SDCLK" Andy Shevchenko
  2011-08-03 15:35 ` [PATCH 2/4] mmc: sdhci: check host->clock before use it as denominator Andy Shevchenko
@ 2011-08-03 15:36 ` Andy Shevchenko
  2011-08-03 15:36 ` [PATCH 4/4] mmc: sdhci: use f_max instead of host->clock for timeouts Andy Shevchenko
  3 siblings, 0 replies; 5+ messages in thread
From: Andy Shevchenko @ 2011-08-03 15:36 UTC (permalink / raw)
  To: linux-mmc, Chris Ball; +Cc: Andy Shevchenko

We will need the f_max for our calculations in the next patch in the series.

Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
---
 drivers/mmc/host/sdhci.c |   38 +++++++++++++++++++-------------------
 1 files changed, 19 insertions(+), 19 deletions(-)

diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 58bb15c..4a7dd06 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -2457,25 +2457,6 @@ int sdhci_add_host(struct sdhci_host *host)
 		host->max_clk = host->ops->get_max_clock(host);
 	}
 
-	host->timeout_clk =
-		(caps[0] & SDHCI_TIMEOUT_CLK_MASK) >> SDHCI_TIMEOUT_CLK_SHIFT;
-	if (host->timeout_clk == 0) {
-		if (host->ops->get_timeout_clock) {
-			host->timeout_clk = host->ops->get_timeout_clock(host);
-		} else if (!(host->quirks &
-				SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK)) {
-			printk(KERN_ERR
-			       "%s: Hardware doesn't specify timeout clock "
-			       "frequency.\n", mmc_hostname(mmc));
-			return -ENODEV;
-		}
-	}
-	if (caps[0] & SDHCI_TIMEOUT_CLK_UNIT)
-		host->timeout_clk *= 1000;
-
-	if (host->quirks & SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK)
-		host->timeout_clk = host->clock / 1000;
-
 	/*
 	 * In case of Host Controller v3.00, find out whether clock
 	 * multiplier is supported.
@@ -2508,6 +2489,25 @@ int sdhci_add_host(struct sdhci_host *host)
 	} else
 		mmc->f_min = host->max_clk / SDHCI_MAX_DIV_SPEC_200;
 
+	host->timeout_clk =
+		(caps[0] & SDHCI_TIMEOUT_CLK_MASK) >> SDHCI_TIMEOUT_CLK_SHIFT;
+	if (host->timeout_clk == 0) {
+		if (host->ops->get_timeout_clock) {
+			host->timeout_clk = host->ops->get_timeout_clock(host);
+		} else if (!(host->quirks &
+				SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK)) {
+			printk(KERN_ERR
+			       "%s: Hardware doesn't specify timeout clock "
+			       "frequency.\n", mmc_hostname(mmc));
+			return -ENODEV;
+		}
+	}
+	if (caps[0] & SDHCI_TIMEOUT_CLK_UNIT)
+		host->timeout_clk *= 1000;
+
+	if (host->quirks & SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK)
+		host->timeout_clk = host->clock / 1000;
+
 	if (host->quirks & SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK)
 		mmc->max_discard_to = (1 << 27) / (mmc->f_max / 1000);
 	else
-- 
1.7.5.4


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH 4/4] mmc: sdhci: use f_max instead of host->clock for timeouts
  2011-08-03 15:35 [PATCH 0/4] mmc: sdhci: try to avoid another division by zero Andy Shevchenko
                   ` (2 preceding siblings ...)
  2011-08-03 15:36 ` [PATCH 3/4] mmc: sdhci: move timeout_clk calculation a bit further Andy Shevchenko
@ 2011-08-03 15:36 ` Andy Shevchenko
  3 siblings, 0 replies; 5+ messages in thread
From: Andy Shevchenko @ 2011-08-03 15:36 UTC (permalink / raw)
  To: linux-mmc, Chris Ball; +Cc: Andy Shevchenko, Mark Brown

When timeout_clk is calculated the host->clock could be zero. So, instead of
host->clock the calculation uses mmc->f_max.

Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Cc: Mark Brown <broonie@opensource.wolfsonmicro.com>
---
 drivers/mmc/host/sdhci.c |    7 ++-----
 1 files changed, 2 insertions(+), 5 deletions(-)

diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 4a7dd06..56619f4 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -2506,12 +2506,9 @@ int sdhci_add_host(struct sdhci_host *host)
 		host->timeout_clk *= 1000;
 
 	if (host->quirks & SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK)
-		host->timeout_clk = host->clock / 1000;
+		host->timeout_clk = mmc->f_max / 1000;
 
-	if (host->quirks & SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK)
-		mmc->max_discard_to = (1 << 27) / (mmc->f_max / 1000);
-	else
-		mmc->max_discard_to = (1 << 27) / host->timeout_clk;
+	mmc->max_discard_to = (1 << 27) / host->timeout_clk;
 
 	mmc->caps |= MMC_CAP_SDIO_IRQ | MMC_CAP_ERASE | MMC_CAP_CMD23;
 
-- 
1.7.5.4


^ permalink raw reply related	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2011-08-03 15:37 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-08-03 15:35 [PATCH 0/4] mmc: sdhci: try to avoid another division by zero Andy Shevchenko
2011-08-03 15:35 ` [PATCH 1/4] Revert "mmc: sdhci: Fix SDHCI_QUIRK_TIMEOUT_USES_SDCLK" Andy Shevchenko
2011-08-03 15:35 ` [PATCH 2/4] mmc: sdhci: check host->clock before use it as denominator Andy Shevchenko
2011-08-03 15:36 ` [PATCH 3/4] mmc: sdhci: move timeout_clk calculation a bit further Andy Shevchenko
2011-08-03 15:36 ` [PATCH 4/4] mmc: sdhci: use f_max instead of host->clock for timeouts Andy Shevchenko

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox