diff options
-rw-r--r-- | drivers/mmc/card/block.c | 44 |
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 | ||
210 | static 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 | |||
210 | static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req) | 227 | static 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) { |