|
@@ -266,6 +266,9 @@ static struct mmc_blk_ioc_data *mmc_blk_ioctl_copy_from_user(
|
|
|
goto idata_err;
|
|
|
}
|
|
|
|
|
|
+ if (!idata->buf_bytes)
|
|
|
+ return idata;
|
|
|
+
|
|
|
idata->buf = kzalloc(idata->buf_bytes, GFP_KERNEL);
|
|
|
if (!idata->buf) {
|
|
|
err = -ENOMEM;
|
|
@@ -312,25 +315,6 @@ static int mmc_blk_ioctl_cmd(struct block_device *bdev,
|
|
|
if (IS_ERR(idata))
|
|
|
return PTR_ERR(idata);
|
|
|
|
|
|
- cmd.opcode = idata->ic.opcode;
|
|
|
- cmd.arg = idata->ic.arg;
|
|
|
- cmd.flags = idata->ic.flags;
|
|
|
-
|
|
|
- data.sg = &sg;
|
|
|
- data.sg_len = 1;
|
|
|
- data.blksz = idata->ic.blksz;
|
|
|
- data.blocks = idata->ic.blocks;
|
|
|
-
|
|
|
- sg_init_one(data.sg, idata->buf, idata->buf_bytes);
|
|
|
-
|
|
|
- if (idata->ic.write_flag)
|
|
|
- data.flags = MMC_DATA_WRITE;
|
|
|
- else
|
|
|
- data.flags = MMC_DATA_READ;
|
|
|
-
|
|
|
- mrq.cmd = &cmd;
|
|
|
- mrq.data = &data;
|
|
|
-
|
|
|
md = mmc_blk_get(bdev->bd_disk);
|
|
|
if (!md) {
|
|
|
err = -EINVAL;
|
|
@@ -343,6 +327,48 @@ static int mmc_blk_ioctl_cmd(struct block_device *bdev,
|
|
|
goto cmd_done;
|
|
|
}
|
|
|
|
|
|
+ cmd.opcode = idata->ic.opcode;
|
|
|
+ cmd.arg = idata->ic.arg;
|
|
|
+ cmd.flags = idata->ic.flags;
|
|
|
+
|
|
|
+ if (idata->buf_bytes) {
|
|
|
+ data.sg = &sg;
|
|
|
+ data.sg_len = 1;
|
|
|
+ data.blksz = idata->ic.blksz;
|
|
|
+ data.blocks = idata->ic.blocks;
|
|
|
+
|
|
|
+ sg_init_one(data.sg, idata->buf, idata->buf_bytes);
|
|
|
+
|
|
|
+ if (idata->ic.write_flag)
|
|
|
+ data.flags = MMC_DATA_WRITE;
|
|
|
+ else
|
|
|
+ data.flags = MMC_DATA_READ;
|
|
|
+
|
|
|
+ /* data.flags must already be set before doing this. */
|
|
|
+ mmc_set_data_timeout(&data, card);
|
|
|
+
|
|
|
+ /* Allow overriding the timeout_ns for empirical tuning. */
|
|
|
+ if (idata->ic.data_timeout_ns)
|
|
|
+ data.timeout_ns = idata->ic.data_timeout_ns;
|
|
|
+
|
|
|
+ if ((cmd.flags & MMC_RSP_R1B) == MMC_RSP_R1B) {
|
|
|
+ /*
|
|
|
+ * Pretend this is a data transfer and rely on the
|
|
|
+ * host driver to compute timeout. When all host
|
|
|
+ * drivers support cmd.cmd_timeout for R1B, this
|
|
|
+ * can be changed to:
|
|
|
+ *
|
|
|
+ * mrq.data = NULL;
|
|
|
+ * cmd.cmd_timeout = idata->ic.cmd_timeout_ms;
|
|
|
+ */
|
|
|
+ data.timeout_ns = idata->ic.cmd_timeout_ms * 1000000;
|
|
|
+ }
|
|
|
+
|
|
|
+ mrq.data = &data;
|
|
|
+ }
|
|
|
+
|
|
|
+ mrq.cmd = &cmd;
|
|
|
+
|
|
|
mmc_claim_host(card->host);
|
|
|
|
|
|
if (idata->ic.is_acmd) {
|
|
@@ -351,24 +377,6 @@ static int mmc_blk_ioctl_cmd(struct block_device *bdev,
|
|
|
goto cmd_rel_host;
|
|
|
}
|
|
|
|
|
|
- /* data.flags must already be set before doing this. */
|
|
|
- mmc_set_data_timeout(&data, card);
|
|
|
- /* Allow overriding the timeout_ns for empirical tuning. */
|
|
|
- if (idata->ic.data_timeout_ns)
|
|
|
- data.timeout_ns = idata->ic.data_timeout_ns;
|
|
|
-
|
|
|
- if ((cmd.flags & MMC_RSP_R1B) == MMC_RSP_R1B) {
|
|
|
- /*
|
|
|
- * Pretend this is a data transfer and rely on the host driver
|
|
|
- * to compute timeout. When all host drivers support
|
|
|
- * cmd.cmd_timeout for R1B, this can be changed to:
|
|
|
- *
|
|
|
- * mrq.data = NULL;
|
|
|
- * cmd.cmd_timeout = idata->ic.cmd_timeout_ms;
|
|
|
- */
|
|
|
- data.timeout_ns = idata->ic.cmd_timeout_ms * 1000000;
|
|
|
- }
|
|
|
-
|
|
|
mmc_wait_for_req(card->host, &mrq);
|
|
|
|
|
|
if (cmd.error) {
|