aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mmc/host
diff options
context:
space:
mode:
authorWolfgang Muees <wolfgang.mues@auerswald.de>2009-04-07 10:26:30 -0400
committerPierre Ossman <pierre@ossman.eu>2009-04-08 14:38:42 -0400
commit56e303ebeec7ef43dbd9d7998f8ad1a9f75d59bc (patch)
treefb673041c46307965f45fd0af50e5c06f728deda /drivers/mmc/host
parent9d9f25c036dd584db175552a7d162403d3ab54b3 (diff)
mmc_spi: convert timeout handling to jiffies and avoid busy waiting
SD/MMC card timeouts can be very high. So avoid busy-waiting, using the scheduler. Calculate all timeouts in jiffies units, because this will give us the correct sign when to involve the scheduler. Signed-off-by: Wolfgang Muees <wolfgang.mues@auerswald.de> Signed-off-by: Pierre Ossman <pierre@ossman.eu>
Diffstat (limited to 'drivers/mmc/host')
-rw-r--r--drivers/mmc/host/mmc_spi.c38
1 files changed, 21 insertions, 17 deletions
diff --git a/drivers/mmc/host/mmc_spi.c b/drivers/mmc/host/mmc_spi.c
index 72f8bde4877a..ed02ebd899d1 100644
--- a/drivers/mmc/host/mmc_spi.c
+++ b/drivers/mmc/host/mmc_spi.c
@@ -24,7 +24,7 @@
24 * along with this program; if not, write to the Free Software 24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 25 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 */ 26 */
27#include <linux/hrtimer.h> 27#include <linux/sched.h>
28#include <linux/delay.h> 28#include <linux/delay.h>
29#include <linux/bio.h> 29#include <linux/bio.h>
30#include <linux/dma-mapping.h> 30#include <linux/dma-mapping.h>
@@ -95,7 +95,7 @@
95 * reads which takes nowhere near that long. Older cards may be able to use 95 * reads which takes nowhere near that long. Older cards may be able to use
96 * shorter timeouts ... but why bother? 96 * shorter timeouts ... but why bother?
97 */ 97 */
98#define r1b_timeout ktime_set(3, 0) 98#define r1b_timeout (HZ * 3)
99 99
100 100
101/****************************************************************************/ 101/****************************************************************************/
@@ -183,12 +183,11 @@ mmc_spi_readbytes(struct mmc_spi_host *host, unsigned len)
183 return status; 183 return status;
184} 184}
185 185
186static int 186static int mmc_spi_skip(struct mmc_spi_host *host, unsigned long timeout,
187mmc_spi_skip(struct mmc_spi_host *host, ktime_t timeout, unsigned n, u8 byte) 187 unsigned n, u8 byte)
188{ 188{
189 u8 *cp = host->data->status; 189 u8 *cp = host->data->status;
190 190 unsigned long start = jiffies;
191 timeout = ktime_add(timeout, ktime_get());
192 191
193 while (1) { 192 while (1) {
194 int status; 193 int status;
@@ -203,22 +202,26 @@ mmc_spi_skip(struct mmc_spi_host *host, ktime_t timeout, unsigned n, u8 byte)
203 return cp[i]; 202 return cp[i];
204 } 203 }
205 204
206 /* REVISIT investigate msleep() to avoid busy-wait I/O 205 if (time_is_before_jiffies(start + timeout))
207 * in at least some cases.
208 */
209 if (ktime_to_ns(ktime_sub(ktime_get(), timeout)) > 0)
210 break; 206 break;
207
208 /* If we need long timeouts, we may release the CPU.
209 * We use jiffies here because we want to have a relation
210 * between elapsed time and the blocking of the scheduler.
211 */
212 if (time_is_before_jiffies(start+1))
213 schedule();
211 } 214 }
212 return -ETIMEDOUT; 215 return -ETIMEDOUT;
213} 216}
214 217
215static inline int 218static inline int
216mmc_spi_wait_unbusy(struct mmc_spi_host *host, ktime_t timeout) 219mmc_spi_wait_unbusy(struct mmc_spi_host *host, unsigned long timeout)
217{ 220{
218 return mmc_spi_skip(host, timeout, sizeof(host->data->status), 0); 221 return mmc_spi_skip(host, timeout, sizeof(host->data->status), 0);
219} 222}
220 223
221static int mmc_spi_readtoken(struct mmc_spi_host *host, ktime_t timeout) 224static int mmc_spi_readtoken(struct mmc_spi_host *host, unsigned long timeout)
222{ 225{
223 return mmc_spi_skip(host, timeout, 1, 0xff); 226 return mmc_spi_skip(host, timeout, 1, 0xff);
224} 227}
@@ -607,7 +610,7 @@ mmc_spi_setup_data_message(
607 */ 610 */
608static int 611static int
609mmc_spi_writeblock(struct mmc_spi_host *host, struct spi_transfer *t, 612mmc_spi_writeblock(struct mmc_spi_host *host, struct spi_transfer *t,
610 ktime_t timeout) 613 unsigned long timeout)
611{ 614{
612 struct spi_device *spi = host->spi; 615 struct spi_device *spi = host->spi;
613 int status, i; 616 int status, i;
@@ -717,7 +720,7 @@ mmc_spi_writeblock(struct mmc_spi_host *host, struct spi_transfer *t,
717 */ 720 */
718static int 721static int
719mmc_spi_readblock(struct mmc_spi_host *host, struct spi_transfer *t, 722mmc_spi_readblock(struct mmc_spi_host *host, struct spi_transfer *t,
720 ktime_t timeout) 723 unsigned long timeout)
721{ 724{
722 struct spi_device *spi = host->spi; 725 struct spi_device *spi = host->spi;
723 int status; 726 int status;
@@ -803,7 +806,7 @@ mmc_spi_data_do(struct mmc_spi_host *host, struct mmc_command *cmd,
803 unsigned n_sg; 806 unsigned n_sg;
804 int multiple = (data->blocks > 1); 807 int multiple = (data->blocks > 1);
805 u32 clock_rate; 808 u32 clock_rate;
806 ktime_t timeout; 809 unsigned long timeout;
807 810
808 if (data->flags & MMC_DATA_READ) 811 if (data->flags & MMC_DATA_READ)
809 direction = DMA_FROM_DEVICE; 812 direction = DMA_FROM_DEVICE;
@@ -817,8 +820,9 @@ mmc_spi_data_do(struct mmc_spi_host *host, struct mmc_command *cmd,
817 else 820 else
818 clock_rate = spi->max_speed_hz; 821 clock_rate = spi->max_speed_hz;
819 822
820 timeout = ktime_add_ns(ktime_set(0, 0), data->timeout_ns + 823 timeout = data->timeout_ns +
821 data->timeout_clks * 1000000 / clock_rate); 824 data->timeout_clks * 1000000 / clock_rate;
825 timeout = usecs_to_jiffies((unsigned int)(timeout / 1000)) + 1;
822 826
823 /* Handle scatterlist segments one at a time, with synch for 827 /* Handle scatterlist segments one at a time, with synch for
824 * each 512-byte block 828 * each 512-byte block