aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/mmc/card/block.c44
1 files changed, 37 insertions, 7 deletions
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
index 903c8aae54bb..cc9b3abf4a3f 100644
--- a/drivers/mmc/card/block.c
+++ b/drivers/mmc/card/block.c
@@ -207,6 +207,23 @@ static u32 mmc_sd_num_wr_blocks(struct mmc_card *card)
207 return ntohl(blocks); 207 return ntohl(blocks);
208} 208}
209 209
210static u32 get_card_status(struct mmc_card *card, struct request *req)
211{
212 struct mmc_command cmd;
213 int err;
214
215 memset(&cmd, 0, sizeof(struct mmc_command));
216 cmd.opcode = MMC_SEND_STATUS;
217 if (!mmc_host_is_spi(card->host))
218 cmd.arg = card->rca << 16;
219 cmd.flags = MMC_RSP_SPI_R2 | MMC_RSP_R1 | MMC_CMD_AC;
220 err = mmc_wait_for_cmd(card->host, &cmd, 0);
221 if (err)
222 printk(KERN_ERR "%s: error %d sending status comand",
223 req->rq_disk->disk_name, err);
224 return cmd.resp[0];
225}
226
210static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req) 227static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
211{ 228{
212 struct mmc_blk_data *md = mq->data; 229 struct mmc_blk_data *md = mq->data;
@@ -218,7 +235,7 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
218 235
219 do { 236 do {
220 struct mmc_command cmd; 237 struct mmc_command cmd;
221 u32 readcmd, writecmd; 238 u32 readcmd, writecmd, status = 0;
222 239
223 memset(&brq, 0, sizeof(struct mmc_blk_request)); 240 memset(&brq, 0, sizeof(struct mmc_blk_request));
224 brq.mrq.cmd = &brq.cmd; 241 brq.mrq.cmd = &brq.cmd;
@@ -273,19 +290,32 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
273 * until later as we need to wait for the card to leave 290 * until later as we need to wait for the card to leave
274 * programming mode even when things go wrong. 291 * programming mode even when things go wrong.
275 */ 292 */
293 if (brq.cmd.error || brq.data.error || brq.stop.error)
294 status = get_card_status(card, req);
295
276 if (brq.cmd.error) { 296 if (brq.cmd.error) {
277 printk(KERN_ERR "%s: error %d sending read/write command\n", 297 printk(KERN_ERR "%s: error %d sending read/write "
278 req->rq_disk->disk_name, brq.cmd.error); 298 "command, response %#x, card status %#x\n",
299 req->rq_disk->disk_name, brq.cmd.error,
300 brq.cmd.resp[0], status);
279 } 301 }
280 302
281 if (brq.data.error) { 303 if (brq.data.error) {
282 printk(KERN_ERR "%s: error %d transferring data\n", 304 if (brq.data.error == -ETIMEDOUT && brq.mrq.stop)
283 req->rq_disk->disk_name, brq.data.error); 305 /* 'Stop' response contains card status */
306 status = brq.mrq.stop->resp[0];
307 printk(KERN_ERR "%s: error %d transferring data,"
308 " sector %u, nr %u, card status %#x\n",
309 req->rq_disk->disk_name, brq.data.error,
310 (unsigned)req->sector,
311 (unsigned)req->nr_sectors, status);
284 } 312 }
285 313
286 if (brq.stop.error) { 314 if (brq.stop.error) {
287 printk(KERN_ERR "%s: error %d sending stop command\n", 315 printk(KERN_ERR "%s: error %d sending stop command, "
288 req->rq_disk->disk_name, brq.stop.error); 316 "response %#x, card status %#x\n",
317 req->rq_disk->disk_name, brq.stop.error,
318 brq.stop.resp[0], status);
289 } 319 }
290 320
291 if (!mmc_host_is_spi(card->host) && rq_data_dir(req) != READ) { 321 if (!mmc_host_is_spi(card->host) && rq_data_dir(req) != READ) {