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) { |
