mmc: fix integer assignments to pointer
[pandora-kernel.git] / drivers / mmc / core / core.c
index 91a0a74..557856b 100644 (file)
@@ -24,6 +24,8 @@
 #include <linux/regulator/consumer.h>
 #include <linux/pm_runtime.h>
 #include <linux/suspend.h>
+#include <linux/fault-inject.h>
+#include <linux/random.h>
 
 #include <linux/mmc/card.h>
 #include <linux/mmc/host.h>
@@ -83,6 +85,43 @@ static void mmc_flush_scheduled_work(void)
        flush_workqueue(workqueue);
 }
 
+#ifdef CONFIG_FAIL_MMC_REQUEST
+
+/*
+ * Internal function. Inject random data errors.
+ * If mmc_data is NULL no errors are injected.
+ */
+static void mmc_should_fail_request(struct mmc_host *host,
+                                   struct mmc_request *mrq)
+{
+       struct mmc_command *cmd = mrq->cmd;
+       struct mmc_data *data = mrq->data;
+       static const int data_errors[] = {
+               -ETIMEDOUT,
+               -EILSEQ,
+               -EIO,
+       };
+
+       if (!data)
+               return;
+
+       if (cmd->error || data->error ||
+           !should_fail(&host->fail_mmc_request, data->blksz * data->blocks))
+               return;
+
+       data->error = data_errors[random32() % ARRAY_SIZE(data_errors)];
+       data->bytes_xfered = (random32() % (data->bytes_xfered >> 9)) << 9;
+}
+
+#else /* CONFIG_FAIL_MMC_REQUEST */
+
+static inline void mmc_should_fail_request(struct mmc_host *host,
+                                          struct mmc_request *mrq)
+{
+}
+
+#endif /* CONFIG_FAIL_MMC_REQUEST */
+
 /**
  *     mmc_request_done - finish processing an MMC request
  *     @host: MMC host which completed request
@@ -109,6 +148,8 @@ void mmc_request_done(struct mmc_host *host, struct mmc_request *mrq)
                cmd->error = 0;
                host->ops->request(host, mrq);
        } else {
+               mmc_should_fail_request(host, mrq);
+
                led_trigger_event(host->led, LED_OFF);
 
                pr_debug("%s: req done (CMD%u): %d: %08x %08x %08x %08x\n",
@@ -133,7 +174,7 @@ void mmc_request_done(struct mmc_host *host, struct mmc_request *mrq)
                if (mrq->done)
                        mrq->done(mrq);
 
-               mmc_host_clk_gate(host);
+               mmc_host_clk_release(host);
        }
 }
 
@@ -192,7 +233,7 @@ mmc_start_request(struct mmc_host *host, struct mmc_request *mrq)
                        mrq->stop->mrq = mrq;
                }
        }
-       mmc_host_clk_ungate(host);
+       mmc_host_clk_hold(host);
        led_trigger_event(host->led, LED_FULL);
        host->ops->request(host, mrq);
 }
@@ -330,7 +371,7 @@ EXPORT_SYMBOL(mmc_wait_for_req);
  */
 int mmc_wait_for_cmd(struct mmc_host *host, struct mmc_command *cmd, int retries)
 {
-       struct mmc_request mrq = {0};
+       struct mmc_request mrq = {NULL};
 
        WARN_ON(!host->claimed);
 
@@ -728,15 +769,17 @@ static inline void mmc_set_ios(struct mmc_host *host)
  */
 void mmc_set_chip_select(struct mmc_host *host, int mode)
 {
+       mmc_host_clk_hold(host);
        host->ios.chip_select = mode;
        mmc_set_ios(host);
+       mmc_host_clk_release(host);
 }
 
 /*
  * Sets the host clock to the highest possible frequency that
  * is below "hz".
  */
-void mmc_set_clock(struct mmc_host *host, unsigned int hz)
+static void __mmc_set_clock(struct mmc_host *host, unsigned int hz)
 {
        WARN_ON(hz < host->f_min);
 
@@ -747,6 +790,13 @@ void mmc_set_clock(struct mmc_host *host, unsigned int hz)
        mmc_set_ios(host);
 }
 
+void mmc_set_clock(struct mmc_host *host, unsigned int hz)
+{
+       mmc_host_clk_hold(host);
+       __mmc_set_clock(host, hz);
+       mmc_host_clk_release(host);
+}
+
 #ifdef CONFIG_MMC_CLKGATE
 /*
  * This gates the clock by setting it to 0 Hz.
@@ -779,7 +829,7 @@ void mmc_ungate_clock(struct mmc_host *host)
        if (host->clk_old) {
                BUG_ON(host->ios.clock);
                /* This call will also set host->clk_gated to false */
-               mmc_set_clock(host, host->clk_old);
+               __mmc_set_clock(host, host->clk_old);
        }
 }
 
@@ -807,8 +857,10 @@ void mmc_set_ungated(struct mmc_host *host)
  */
 void mmc_set_bus_mode(struct mmc_host *host, unsigned int mode)
 {
+       mmc_host_clk_hold(host);
        host->ios.bus_mode = mode;
        mmc_set_ios(host);
+       mmc_host_clk_release(host);
 }
 
 /*
@@ -816,8 +868,10 @@ void mmc_set_bus_mode(struct mmc_host *host, unsigned int mode)
  */
 void mmc_set_bus_width(struct mmc_host *host, unsigned int width)
 {
+       mmc_host_clk_hold(host);
        host->ios.bus_width = width;
        mmc_set_ios(host);
+       mmc_host_clk_release(host);
 }
 
 /**
@@ -1015,8 +1069,10 @@ u32 mmc_select_voltage(struct mmc_host *host, u32 ocr)
 
                ocr &= 3 << bit;
 
+               mmc_host_clk_hold(host);
                host->ios.vdd = bit;
                mmc_set_ios(host);
+               mmc_host_clk_release(host);
        } else {
                pr_warning("%s: host doesn't support card's voltages\n",
                                mmc_hostname(host));
@@ -1063,8 +1119,10 @@ int mmc_set_signal_voltage(struct mmc_host *host, int signal_voltage, bool cmd11
  */
 void mmc_set_timing(struct mmc_host *host, unsigned int timing)
 {
+       mmc_host_clk_hold(host);
        host->ios.timing = timing;
        mmc_set_ios(host);
+       mmc_host_clk_release(host);
 }
 
 /*
@@ -1072,8 +1130,10 @@ void mmc_set_timing(struct mmc_host *host, unsigned int timing)
  */
 void mmc_set_driver_type(struct mmc_host *host, unsigned int drv_type)
 {
+       mmc_host_clk_hold(host);
        host->ios.drv_type = drv_type;
        mmc_set_ios(host);
+       mmc_host_clk_release(host);
 }
 
 /*
@@ -1091,6 +1151,8 @@ static void mmc_power_up(struct mmc_host *host)
 {
        int bit;
 
+       mmc_host_clk_hold(host);
+
        /* If ocr is set, we use it */
        if (host->ocr)
                bit = ffs(host->ocr) - 1;
@@ -1126,10 +1188,14 @@ static void mmc_power_up(struct mmc_host *host)
         * time required to reach a stable voltage.
         */
        mmc_delay(10);
+
+       mmc_host_clk_release(host);
 }
 
 static void mmc_power_off(struct mmc_host *host)
 {
+       mmc_host_clk_hold(host);
+
        host->ios.clock = 0;
        host->ios.vdd = 0;
 
@@ -1147,6 +1213,8 @@ static void mmc_power_off(struct mmc_host *host)
        host->ios.bus_width = MMC_BUS_WIDTH_1;
        host->ios.timing = MMC_TIMING_LEGACY;
        mmc_set_ios(host);
+
+       mmc_host_clk_release(host);
 }
 
 /*