diff options
Diffstat (limited to 'drivers/mmc/host/rtsx_pci_sdmmc.c')
-rw-r--r-- | drivers/mmc/host/rtsx_pci_sdmmc.c | 418 |
1 files changed, 68 insertions, 350 deletions
diff --git a/drivers/mmc/host/rtsx_pci_sdmmc.c b/drivers/mmc/host/rtsx_pci_sdmmc.c index 5fb994f9a653..0b9ded13a3ae 100644 --- a/drivers/mmc/host/rtsx_pci_sdmmc.c +++ b/drivers/mmc/host/rtsx_pci_sdmmc.c | |||
@@ -31,28 +31,14 @@ | |||
31 | #include <linux/mfd/rtsx_pci.h> | 31 | #include <linux/mfd/rtsx_pci.h> |
32 | #include <asm/unaligned.h> | 32 | #include <asm/unaligned.h> |
33 | 33 | ||
34 | struct realtek_next { | ||
35 | unsigned int sg_count; | ||
36 | s32 cookie; | ||
37 | }; | ||
38 | |||
39 | struct realtek_pci_sdmmc { | 34 | struct realtek_pci_sdmmc { |
40 | struct platform_device *pdev; | 35 | struct platform_device *pdev; |
41 | struct rtsx_pcr *pcr; | 36 | struct rtsx_pcr *pcr; |
42 | struct mmc_host *mmc; | 37 | struct mmc_host *mmc; |
43 | struct mmc_request *mrq; | 38 | struct mmc_request *mrq; |
44 | struct mmc_command *cmd; | 39 | |
45 | struct mmc_data *data; | 40 | struct mutex host_mutex; |
46 | 41 | ||
47 | spinlock_t lock; | ||
48 | struct timer_list timer; | ||
49 | struct tasklet_struct cmd_tasklet; | ||
50 | struct tasklet_struct data_tasklet; | ||
51 | struct tasklet_struct finish_tasklet; | ||
52 | |||
53 | u8 rsp_type; | ||
54 | u8 rsp_len; | ||
55 | int sg_count; | ||
56 | u8 ssc_depth; | 42 | u8 ssc_depth; |
57 | unsigned int clock; | 43 | unsigned int clock; |
58 | bool vpclk; | 44 | bool vpclk; |
@@ -62,13 +48,8 @@ struct realtek_pci_sdmmc { | |||
62 | int power_state; | 48 | int power_state; |
63 | #define SDMMC_POWER_ON 1 | 49 | #define SDMMC_POWER_ON 1 |
64 | #define SDMMC_POWER_OFF 0 | 50 | #define SDMMC_POWER_OFF 0 |
65 | |||
66 | struct realtek_next next_data; | ||
67 | }; | 51 | }; |
68 | 52 | ||
69 | static int sd_start_multi_rw(struct realtek_pci_sdmmc *host, | ||
70 | struct mmc_request *mrq); | ||
71 | |||
72 | static inline struct device *sdmmc_dev(struct realtek_pci_sdmmc *host) | 53 | static inline struct device *sdmmc_dev(struct realtek_pci_sdmmc *host) |
73 | { | 54 | { |
74 | return &(host->pdev->dev); | 55 | return &(host->pdev->dev); |
@@ -105,95 +86,6 @@ static void sd_print_debug_regs(struct realtek_pci_sdmmc *host) | |||
105 | #define sd_print_debug_regs(host) | 86 | #define sd_print_debug_regs(host) |
106 | #endif /* DEBUG */ | 87 | #endif /* DEBUG */ |
107 | 88 | ||
108 | static void sd_isr_done_transfer(struct platform_device *pdev) | ||
109 | { | ||
110 | struct realtek_pci_sdmmc *host = platform_get_drvdata(pdev); | ||
111 | |||
112 | spin_lock(&host->lock); | ||
113 | if (host->cmd) | ||
114 | tasklet_schedule(&host->cmd_tasklet); | ||
115 | if (host->data) | ||
116 | tasklet_schedule(&host->data_tasklet); | ||
117 | spin_unlock(&host->lock); | ||
118 | } | ||
119 | |||
120 | static void sd_request_timeout(unsigned long host_addr) | ||
121 | { | ||
122 | struct realtek_pci_sdmmc *host = (struct realtek_pci_sdmmc *)host_addr; | ||
123 | unsigned long flags; | ||
124 | |||
125 | spin_lock_irqsave(&host->lock, flags); | ||
126 | |||
127 | if (!host->mrq) { | ||
128 | dev_err(sdmmc_dev(host), "error: no request exist\n"); | ||
129 | goto out; | ||
130 | } | ||
131 | |||
132 | if (host->cmd) | ||
133 | host->cmd->error = -ETIMEDOUT; | ||
134 | if (host->data) | ||
135 | host->data->error = -ETIMEDOUT; | ||
136 | |||
137 | dev_dbg(sdmmc_dev(host), "timeout for request\n"); | ||
138 | |||
139 | out: | ||
140 | tasklet_schedule(&host->finish_tasklet); | ||
141 | spin_unlock_irqrestore(&host->lock, flags); | ||
142 | } | ||
143 | |||
144 | static void sd_finish_request(unsigned long host_addr) | ||
145 | { | ||
146 | struct realtek_pci_sdmmc *host = (struct realtek_pci_sdmmc *)host_addr; | ||
147 | struct rtsx_pcr *pcr = host->pcr; | ||
148 | struct mmc_request *mrq; | ||
149 | struct mmc_command *cmd; | ||
150 | struct mmc_data *data; | ||
151 | unsigned long flags; | ||
152 | bool any_error; | ||
153 | |||
154 | spin_lock_irqsave(&host->lock, flags); | ||
155 | |||
156 | del_timer(&host->timer); | ||
157 | mrq = host->mrq; | ||
158 | if (!mrq) { | ||
159 | dev_err(sdmmc_dev(host), "error: no request need finish\n"); | ||
160 | goto out; | ||
161 | } | ||
162 | |||
163 | cmd = mrq->cmd; | ||
164 | data = mrq->data; | ||
165 | |||
166 | any_error = (mrq->sbc && mrq->sbc->error) || | ||
167 | (mrq->stop && mrq->stop->error) || | ||
168 | (cmd && cmd->error) || (data && data->error); | ||
169 | |||
170 | if (any_error) { | ||
171 | rtsx_pci_stop_cmd(pcr); | ||
172 | sd_clear_error(host); | ||
173 | } | ||
174 | |||
175 | if (data) { | ||
176 | if (any_error) | ||
177 | data->bytes_xfered = 0; | ||
178 | else | ||
179 | data->bytes_xfered = data->blocks * data->blksz; | ||
180 | |||
181 | if (!data->host_cookie) | ||
182 | rtsx_pci_dma_unmap_sg(pcr, data->sg, data->sg_len, | ||
183 | data->flags & MMC_DATA_READ); | ||
184 | |||
185 | } | ||
186 | |||
187 | host->mrq = NULL; | ||
188 | host->cmd = NULL; | ||
189 | host->data = NULL; | ||
190 | |||
191 | out: | ||
192 | spin_unlock_irqrestore(&host->lock, flags); | ||
193 | mutex_unlock(&pcr->pcr_mutex); | ||
194 | mmc_request_done(host->mmc, mrq); | ||
195 | } | ||
196 | |||
197 | static int sd_read_data(struct realtek_pci_sdmmc *host, u8 *cmd, u16 byte_cnt, | 89 | static int sd_read_data(struct realtek_pci_sdmmc *host, u8 *cmd, u16 byte_cnt, |
198 | u8 *buf, int buf_len, int timeout) | 90 | u8 *buf, int buf_len, int timeout) |
199 | { | 91 | { |
@@ -311,7 +203,8 @@ static int sd_write_data(struct realtek_pci_sdmmc *host, u8 *cmd, u16 byte_cnt, | |||
311 | return 0; | 203 | return 0; |
312 | } | 204 | } |
313 | 205 | ||
314 | static void sd_send_cmd(struct realtek_pci_sdmmc *host, struct mmc_command *cmd) | 206 | static void sd_send_cmd_get_rsp(struct realtek_pci_sdmmc *host, |
207 | struct mmc_command *cmd) | ||
315 | { | 208 | { |
316 | struct rtsx_pcr *pcr = host->pcr; | 209 | struct rtsx_pcr *pcr = host->pcr; |
317 | u8 cmd_idx = (u8)cmd->opcode; | 210 | u8 cmd_idx = (u8)cmd->opcode; |
@@ -319,14 +212,11 @@ static void sd_send_cmd(struct realtek_pci_sdmmc *host, struct mmc_command *cmd) | |||
319 | int err = 0; | 212 | int err = 0; |
320 | int timeout = 100; | 213 | int timeout = 100; |
321 | int i; | 214 | int i; |
215 | u8 *ptr; | ||
216 | int stat_idx = 0; | ||
322 | u8 rsp_type; | 217 | u8 rsp_type; |
323 | int rsp_len = 5; | 218 | int rsp_len = 5; |
324 | unsigned long flags; | 219 | bool clock_toggled = false; |
325 | |||
326 | if (host->cmd) | ||
327 | dev_err(sdmmc_dev(host), "error: cmd already exist\n"); | ||
328 | |||
329 | host->cmd = cmd; | ||
330 | 220 | ||
331 | dev_dbg(sdmmc_dev(host), "%s: SD/MMC CMD %d, arg = 0x%08x\n", | 221 | dev_dbg(sdmmc_dev(host), "%s: SD/MMC CMD %d, arg = 0x%08x\n", |
332 | __func__, cmd_idx, arg); | 222 | __func__, cmd_idx, arg); |
@@ -361,8 +251,6 @@ static void sd_send_cmd(struct realtek_pci_sdmmc *host, struct mmc_command *cmd) | |||
361 | err = -EINVAL; | 251 | err = -EINVAL; |
362 | goto out; | 252 | goto out; |
363 | } | 253 | } |
364 | host->rsp_type = rsp_type; | ||
365 | host->rsp_len = rsp_len; | ||
366 | 254 | ||
367 | if (rsp_type == SD_RSP_TYPE_R1b) | 255 | if (rsp_type == SD_RSP_TYPE_R1b) |
368 | timeout = 3000; | 256 | timeout = 3000; |
@@ -372,6 +260,8 @@ static void sd_send_cmd(struct realtek_pci_sdmmc *host, struct mmc_command *cmd) | |||
372 | 0xFF, SD_CLK_TOGGLE_EN); | 260 | 0xFF, SD_CLK_TOGGLE_EN); |
373 | if (err < 0) | 261 | if (err < 0) |
374 | goto out; | 262 | goto out; |
263 | |||
264 | clock_toggled = true; | ||
375 | } | 265 | } |
376 | 266 | ||
377 | rtsx_pci_init_cmd(pcr); | 267 | rtsx_pci_init_cmd(pcr); |
@@ -395,60 +285,25 @@ static void sd_send_cmd(struct realtek_pci_sdmmc *host, struct mmc_command *cmd) | |||
395 | /* Read data from ping-pong buffer */ | 285 | /* Read data from ping-pong buffer */ |
396 | for (i = PPBUF_BASE2; i < PPBUF_BASE2 + 16; i++) | 286 | for (i = PPBUF_BASE2; i < PPBUF_BASE2 + 16; i++) |
397 | rtsx_pci_add_cmd(pcr, READ_REG_CMD, (u16)i, 0, 0); | 287 | rtsx_pci_add_cmd(pcr, READ_REG_CMD, (u16)i, 0, 0); |
288 | stat_idx = 16; | ||
398 | } else if (rsp_type != SD_RSP_TYPE_R0) { | 289 | } else if (rsp_type != SD_RSP_TYPE_R0) { |
399 | /* Read data from SD_CMDx registers */ | 290 | /* Read data from SD_CMDx registers */ |
400 | for (i = SD_CMD0; i <= SD_CMD4; i++) | 291 | for (i = SD_CMD0; i <= SD_CMD4; i++) |
401 | rtsx_pci_add_cmd(pcr, READ_REG_CMD, (u16)i, 0, 0); | 292 | rtsx_pci_add_cmd(pcr, READ_REG_CMD, (u16)i, 0, 0); |
293 | stat_idx = 5; | ||
402 | } | 294 | } |
403 | 295 | ||
404 | rtsx_pci_add_cmd(pcr, READ_REG_CMD, SD_STAT1, 0, 0); | 296 | rtsx_pci_add_cmd(pcr, READ_REG_CMD, SD_STAT1, 0, 0); |
405 | 297 | ||
406 | mod_timer(&host->timer, jiffies + msecs_to_jiffies(timeout)); | 298 | err = rtsx_pci_send_cmd(pcr, timeout); |
407 | 299 | if (err < 0) { | |
408 | spin_lock_irqsave(&pcr->lock, flags); | 300 | sd_print_debug_regs(host); |
409 | pcr->trans_result = TRANS_NOT_READY; | 301 | sd_clear_error(host); |
410 | rtsx_pci_send_cmd_no_wait(pcr); | 302 | dev_dbg(sdmmc_dev(host), |
411 | spin_unlock_irqrestore(&pcr->lock, flags); | 303 | "rtsx_pci_send_cmd error (err = %d)\n", err); |
412 | |||
413 | return; | ||
414 | |||
415 | out: | ||
416 | cmd->error = err; | ||
417 | tasklet_schedule(&host->finish_tasklet); | ||
418 | } | ||
419 | |||
420 | static void sd_get_rsp(unsigned long host_addr) | ||
421 | { | ||
422 | struct realtek_pci_sdmmc *host = (struct realtek_pci_sdmmc *)host_addr; | ||
423 | struct rtsx_pcr *pcr = host->pcr; | ||
424 | struct mmc_command *cmd; | ||
425 | int i, err = 0, stat_idx; | ||
426 | u8 *ptr, rsp_type; | ||
427 | unsigned long flags; | ||
428 | |||
429 | spin_lock_irqsave(&host->lock, flags); | ||
430 | |||
431 | cmd = host->cmd; | ||
432 | host->cmd = NULL; | ||
433 | |||
434 | if (!cmd) { | ||
435 | dev_err(sdmmc_dev(host), "error: cmd not exist\n"); | ||
436 | goto out; | 304 | goto out; |
437 | } | 305 | } |
438 | 306 | ||
439 | spin_lock(&pcr->lock); | ||
440 | if (pcr->trans_result == TRANS_NO_DEVICE) | ||
441 | err = -ENODEV; | ||
442 | else if (pcr->trans_result != TRANS_RESULT_OK) | ||
443 | err = -EINVAL; | ||
444 | spin_unlock(&pcr->lock); | ||
445 | |||
446 | if (err < 0) | ||
447 | goto out; | ||
448 | |||
449 | rsp_type = host->rsp_type; | ||
450 | stat_idx = host->rsp_len; | ||
451 | |||
452 | if (rsp_type == SD_RSP_TYPE_R0) { | 307 | if (rsp_type == SD_RSP_TYPE_R0) { |
453 | err = 0; | 308 | err = 0; |
454 | goto out; | 309 | goto out; |
@@ -485,106 +340,26 @@ static void sd_get_rsp(unsigned long host_addr) | |||
485 | cmd->resp[0]); | 340 | cmd->resp[0]); |
486 | } | 341 | } |
487 | 342 | ||
488 | if (cmd == host->mrq->sbc) { | ||
489 | sd_send_cmd(host, host->mrq->cmd); | ||
490 | spin_unlock_irqrestore(&host->lock, flags); | ||
491 | return; | ||
492 | } | ||
493 | |||
494 | if (cmd == host->mrq->stop) | ||
495 | goto out; | ||
496 | |||
497 | if (cmd->data) { | ||
498 | sd_start_multi_rw(host, host->mrq); | ||
499 | spin_unlock_irqrestore(&host->lock, flags); | ||
500 | return; | ||
501 | } | ||
502 | |||
503 | out: | 343 | out: |
504 | cmd->error = err; | 344 | cmd->error = err; |
505 | 345 | ||
506 | tasklet_schedule(&host->finish_tasklet); | 346 | if (err && clock_toggled) |
507 | spin_unlock_irqrestore(&host->lock, flags); | 347 | rtsx_pci_write_register(pcr, SD_BUS_STAT, |
508 | } | 348 | SD_CLK_TOGGLE_EN | SD_CLK_FORCE_STOP, 0); |
509 | |||
510 | static int sd_pre_dma_transfer(struct realtek_pci_sdmmc *host, | ||
511 | struct mmc_data *data, struct realtek_next *next) | ||
512 | { | ||
513 | struct rtsx_pcr *pcr = host->pcr; | ||
514 | int read = data->flags & MMC_DATA_READ; | ||
515 | int sg_count = 0; | ||
516 | |||
517 | if (!next && data->host_cookie && | ||
518 | data->host_cookie != host->next_data.cookie) { | ||
519 | dev_err(sdmmc_dev(host), | ||
520 | "error: invalid cookie data[%d] host[%d]\n", | ||
521 | data->host_cookie, host->next_data.cookie); | ||
522 | data->host_cookie = 0; | ||
523 | } | ||
524 | |||
525 | if (next || (!next && data->host_cookie != host->next_data.cookie)) | ||
526 | sg_count = rtsx_pci_dma_map_sg(pcr, | ||
527 | data->sg, data->sg_len, read); | ||
528 | else | ||
529 | sg_count = host->next_data.sg_count; | ||
530 | |||
531 | if (next) { | ||
532 | next->sg_count = sg_count; | ||
533 | if (++next->cookie < 0) | ||
534 | next->cookie = 1; | ||
535 | data->host_cookie = next->cookie; | ||
536 | } | ||
537 | |||
538 | return sg_count; | ||
539 | } | ||
540 | |||
541 | static void sdmmc_pre_req(struct mmc_host *mmc, struct mmc_request *mrq, | ||
542 | bool is_first_req) | ||
543 | { | ||
544 | struct realtek_pci_sdmmc *host = mmc_priv(mmc); | ||
545 | struct mmc_data *data = mrq->data; | ||
546 | |||
547 | if (data->host_cookie) { | ||
548 | dev_err(sdmmc_dev(host), | ||
549 | "error: descard already cookie data[%d]\n", | ||
550 | data->host_cookie); | ||
551 | data->host_cookie = 0; | ||
552 | } | ||
553 | |||
554 | dev_dbg(sdmmc_dev(host), "dma sg prepared: %d\n", | ||
555 | sd_pre_dma_transfer(host, data, &host->next_data)); | ||
556 | } | ||
557 | |||
558 | static void sdmmc_post_req(struct mmc_host *mmc, struct mmc_request *mrq, | ||
559 | int err) | ||
560 | { | ||
561 | struct realtek_pci_sdmmc *host = mmc_priv(mmc); | ||
562 | struct rtsx_pcr *pcr = host->pcr; | ||
563 | struct mmc_data *data = mrq->data; | ||
564 | int read = data->flags & MMC_DATA_READ; | ||
565 | |||
566 | rtsx_pci_dma_unmap_sg(pcr, data->sg, data->sg_len, read); | ||
567 | data->host_cookie = 0; | ||
568 | } | 349 | } |
569 | 350 | ||
570 | static int sd_start_multi_rw(struct realtek_pci_sdmmc *host, | 351 | static int sd_rw_multi(struct realtek_pci_sdmmc *host, struct mmc_request *mrq) |
571 | struct mmc_request *mrq) | ||
572 | { | 352 | { |
573 | struct rtsx_pcr *pcr = host->pcr; | 353 | struct rtsx_pcr *pcr = host->pcr; |
574 | struct mmc_host *mmc = host->mmc; | 354 | struct mmc_host *mmc = host->mmc; |
575 | struct mmc_card *card = mmc->card; | 355 | struct mmc_card *card = mmc->card; |
576 | struct mmc_data *data = mrq->data; | 356 | struct mmc_data *data = mrq->data; |
577 | int uhs = mmc_card_uhs(card); | 357 | int uhs = mmc_card_uhs(card); |
578 | int read = data->flags & MMC_DATA_READ; | 358 | int read = (data->flags & MMC_DATA_READ) ? 1 : 0; |
579 | u8 cfg2, trans_mode; | 359 | u8 cfg2, trans_mode; |
580 | int err; | 360 | int err; |
581 | size_t data_len = data->blksz * data->blocks; | 361 | size_t data_len = data->blksz * data->blocks; |
582 | 362 | ||
583 | if (host->data) | ||
584 | dev_err(sdmmc_dev(host), "error: data already exist\n"); | ||
585 | |||
586 | host->data = data; | ||
587 | |||
588 | if (read) { | 363 | if (read) { |
589 | cfg2 = SD_CALCULATE_CRC7 | SD_CHECK_CRC16 | | 364 | cfg2 = SD_CALCULATE_CRC7 | SD_CHECK_CRC16 | |
590 | SD_NO_WAIT_BUSY_END | SD_CHECK_CRC7 | SD_RSP_LEN_0; | 365 | SD_NO_WAIT_BUSY_END | SD_CHECK_CRC7 | SD_RSP_LEN_0; |
@@ -635,54 +410,15 @@ static int sd_start_multi_rw(struct realtek_pci_sdmmc *host, | |||
635 | rtsx_pci_add_cmd(pcr, CHECK_REG_CMD, SD_TRANSFER, | 410 | rtsx_pci_add_cmd(pcr, CHECK_REG_CMD, SD_TRANSFER, |
636 | SD_TRANSFER_END, SD_TRANSFER_END); | 411 | SD_TRANSFER_END, SD_TRANSFER_END); |
637 | 412 | ||
638 | mod_timer(&host->timer, jiffies + 10 * HZ); | ||
639 | rtsx_pci_send_cmd_no_wait(pcr); | 413 | rtsx_pci_send_cmd_no_wait(pcr); |
640 | 414 | ||
641 | err = rtsx_pci_dma_transfer(pcr, data->sg, host->sg_count, read); | 415 | err = rtsx_pci_transfer_data(pcr, data->sg, data->sg_len, read, 10000); |
642 | if (err < 0) { | ||
643 | data->error = err; | ||
644 | tasklet_schedule(&host->finish_tasklet); | ||
645 | } | ||
646 | return 0; | ||
647 | } | ||
648 | |||
649 | static void sd_finish_multi_rw(unsigned long host_addr) | ||
650 | { | ||
651 | struct realtek_pci_sdmmc *host = (struct realtek_pci_sdmmc *)host_addr; | ||
652 | struct rtsx_pcr *pcr = host->pcr; | ||
653 | struct mmc_data *data; | ||
654 | int err = 0; | ||
655 | unsigned long flags; | ||
656 | |||
657 | spin_lock_irqsave(&host->lock, flags); | ||
658 | |||
659 | if (!host->data) { | ||
660 | dev_err(sdmmc_dev(host), "error: no data exist\n"); | ||
661 | goto out; | ||
662 | } | ||
663 | |||
664 | data = host->data; | ||
665 | host->data = NULL; | ||
666 | |||
667 | if (pcr->trans_result == TRANS_NO_DEVICE) | ||
668 | err = -ENODEV; | ||
669 | else if (pcr->trans_result != TRANS_RESULT_OK) | ||
670 | err = -EINVAL; | ||
671 | |||
672 | if (err < 0) { | 416 | if (err < 0) { |
673 | data->error = err; | 417 | sd_clear_error(host); |
674 | goto out; | 418 | return err; |
675 | } | ||
676 | |||
677 | if (!host->mrq->sbc && data->stop) { | ||
678 | sd_send_cmd(host, data->stop); | ||
679 | spin_unlock_irqrestore(&host->lock, flags); | ||
680 | return; | ||
681 | } | 419 | } |
682 | 420 | ||
683 | out: | 421 | return 0; |
684 | tasklet_schedule(&host->finish_tasklet); | ||
685 | spin_unlock_irqrestore(&host->lock, flags); | ||
686 | } | 422 | } |
687 | 423 | ||
688 | static inline void sd_enable_initial_mode(struct realtek_pci_sdmmc *host) | 424 | static inline void sd_enable_initial_mode(struct realtek_pci_sdmmc *host) |
@@ -901,13 +637,6 @@ static int sd_tuning_rx(struct realtek_pci_sdmmc *host, u8 opcode) | |||
901 | return 0; | 637 | return 0; |
902 | } | 638 | } |
903 | 639 | ||
904 | static inline bool sd_use_muti_rw(struct mmc_command *cmd) | ||
905 | { | ||
906 | return mmc_op_multi(cmd->opcode) || | ||
907 | (cmd->opcode == MMC_READ_SINGLE_BLOCK) || | ||
908 | (cmd->opcode == MMC_WRITE_BLOCK); | ||
909 | } | ||
910 | |||
911 | static void sdmmc_request(struct mmc_host *mmc, struct mmc_request *mrq) | 640 | static void sdmmc_request(struct mmc_host *mmc, struct mmc_request *mrq) |
912 | { | 641 | { |
913 | struct realtek_pci_sdmmc *host = mmc_priv(mmc); | 642 | struct realtek_pci_sdmmc *host = mmc_priv(mmc); |
@@ -916,14 +645,6 @@ static void sdmmc_request(struct mmc_host *mmc, struct mmc_request *mrq) | |||
916 | struct mmc_data *data = mrq->data; | 645 | struct mmc_data *data = mrq->data; |
917 | unsigned int data_size = 0; | 646 | unsigned int data_size = 0; |
918 | int err; | 647 | int err; |
919 | unsigned long flags; | ||
920 | |||
921 | mutex_lock(&pcr->pcr_mutex); | ||
922 | spin_lock_irqsave(&host->lock, flags); | ||
923 | |||
924 | if (host->mrq) | ||
925 | dev_err(sdmmc_dev(host), "error: request already exist\n"); | ||
926 | host->mrq = mrq; | ||
927 | 648 | ||
928 | if (host->eject) { | 649 | if (host->eject) { |
929 | cmd->error = -ENOMEDIUM; | 650 | cmd->error = -ENOMEDIUM; |
@@ -936,6 +657,8 @@ static void sdmmc_request(struct mmc_host *mmc, struct mmc_request *mrq) | |||
936 | goto finish; | 657 | goto finish; |
937 | } | 658 | } |
938 | 659 | ||
660 | mutex_lock(&pcr->pcr_mutex); | ||
661 | |||
939 | rtsx_pci_start_run(pcr); | 662 | rtsx_pci_start_run(pcr); |
940 | 663 | ||
941 | rtsx_pci_switch_clock(pcr, host->clock, host->ssc_depth, | 664 | rtsx_pci_switch_clock(pcr, host->clock, host->ssc_depth, |
@@ -944,28 +667,46 @@ static void sdmmc_request(struct mmc_host *mmc, struct mmc_request *mrq) | |||
944 | rtsx_pci_write_register(pcr, CARD_SHARE_MODE, | 667 | rtsx_pci_write_register(pcr, CARD_SHARE_MODE, |
945 | CARD_SHARE_MASK, CARD_SHARE_48_SD); | 668 | CARD_SHARE_MASK, CARD_SHARE_48_SD); |
946 | 669 | ||
670 | mutex_lock(&host->host_mutex); | ||
671 | host->mrq = mrq; | ||
672 | mutex_unlock(&host->host_mutex); | ||
673 | |||
947 | if (mrq->data) | 674 | if (mrq->data) |
948 | data_size = data->blocks * data->blksz; | 675 | data_size = data->blocks * data->blksz; |
949 | 676 | ||
950 | if (sd_use_muti_rw(cmd)) | 677 | if (!data_size || mmc_op_multi(cmd->opcode) || |
951 | host->sg_count = sd_pre_dma_transfer(host, data, NULL); | 678 | (cmd->opcode == MMC_READ_SINGLE_BLOCK) || |
679 | (cmd->opcode == MMC_WRITE_BLOCK)) { | ||
680 | sd_send_cmd_get_rsp(host, cmd); | ||
952 | 681 | ||
953 | if (!data_size || sd_use_muti_rw(cmd)) { | 682 | if (!cmd->error && data_size) { |
954 | if (mrq->sbc) | 683 | sd_rw_multi(host, mrq); |
955 | sd_send_cmd(host, mrq->sbc); | 684 | |
956 | else | 685 | if (mmc_op_multi(cmd->opcode) && mrq->stop) |
957 | sd_send_cmd(host, cmd); | 686 | sd_send_cmd_get_rsp(host, mrq->stop); |
958 | spin_unlock_irqrestore(&host->lock, flags); | 687 | } |
959 | } else { | 688 | } else { |
960 | spin_unlock_irqrestore(&host->lock, flags); | ||
961 | sd_normal_rw(host, mrq); | 689 | sd_normal_rw(host, mrq); |
962 | tasklet_schedule(&host->finish_tasklet); | ||
963 | } | 690 | } |
964 | return; | 691 | |
692 | if (mrq->data) { | ||
693 | if (cmd->error || data->error) | ||
694 | data->bytes_xfered = 0; | ||
695 | else | ||
696 | data->bytes_xfered = data->blocks * data->blksz; | ||
697 | } | ||
698 | |||
699 | mutex_unlock(&pcr->pcr_mutex); | ||
965 | 700 | ||
966 | finish: | 701 | finish: |
967 | tasklet_schedule(&host->finish_tasklet); | 702 | if (cmd->error) |
968 | spin_unlock_irqrestore(&host->lock, flags); | 703 | dev_dbg(sdmmc_dev(host), "cmd->error = %d\n", cmd->error); |
704 | |||
705 | mutex_lock(&host->host_mutex); | ||
706 | host->mrq = NULL; | ||
707 | mutex_unlock(&host->host_mutex); | ||
708 | |||
709 | mmc_request_done(mmc, mrq); | ||
969 | } | 710 | } |
970 | 711 | ||
971 | static int sd_set_bus_width(struct realtek_pci_sdmmc *host, | 712 | static int sd_set_bus_width(struct realtek_pci_sdmmc *host, |
@@ -1400,8 +1141,6 @@ out: | |||
1400 | } | 1141 | } |
1401 | 1142 | ||
1402 | static const struct mmc_host_ops realtek_pci_sdmmc_ops = { | 1143 | static const struct mmc_host_ops realtek_pci_sdmmc_ops = { |
1403 | .pre_req = sdmmc_pre_req, | ||
1404 | .post_req = sdmmc_post_req, | ||
1405 | .request = sdmmc_request, | 1144 | .request = sdmmc_request, |
1406 | .set_ios = sdmmc_set_ios, | 1145 | .set_ios = sdmmc_set_ios, |
1407 | .get_ro = sdmmc_get_ro, | 1146 | .get_ro = sdmmc_get_ro, |
@@ -1465,7 +1204,6 @@ static int rtsx_pci_sdmmc_drv_probe(struct platform_device *pdev) | |||
1465 | struct realtek_pci_sdmmc *host; | 1204 | struct realtek_pci_sdmmc *host; |
1466 | struct rtsx_pcr *pcr; | 1205 | struct rtsx_pcr *pcr; |
1467 | struct pcr_handle *handle = pdev->dev.platform_data; | 1206 | struct pcr_handle *handle = pdev->dev.platform_data; |
1468 | unsigned long host_addr; | ||
1469 | 1207 | ||
1470 | if (!handle) | 1208 | if (!handle) |
1471 | return -ENXIO; | 1209 | return -ENXIO; |
@@ -1489,15 +1227,8 @@ static int rtsx_pci_sdmmc_drv_probe(struct platform_device *pdev) | |||
1489 | pcr->slots[RTSX_SD_CARD].p_dev = pdev; | 1227 | pcr->slots[RTSX_SD_CARD].p_dev = pdev; |
1490 | pcr->slots[RTSX_SD_CARD].card_event = rtsx_pci_sdmmc_card_event; | 1228 | pcr->slots[RTSX_SD_CARD].card_event = rtsx_pci_sdmmc_card_event; |
1491 | 1229 | ||
1492 | host_addr = (unsigned long)host; | 1230 | mutex_init(&host->host_mutex); |
1493 | host->next_data.cookie = 1; | ||
1494 | setup_timer(&host->timer, sd_request_timeout, host_addr); | ||
1495 | tasklet_init(&host->cmd_tasklet, sd_get_rsp, host_addr); | ||
1496 | tasklet_init(&host->data_tasklet, sd_finish_multi_rw, host_addr); | ||
1497 | tasklet_init(&host->finish_tasklet, sd_finish_request, host_addr); | ||
1498 | spin_lock_init(&host->lock); | ||
1499 | 1231 | ||
1500 | pcr->slots[RTSX_SD_CARD].done_transfer = sd_isr_done_transfer; | ||
1501 | realtek_init_host(host); | 1232 | realtek_init_host(host); |
1502 | 1233 | ||
1503 | mmc_add_host(mmc); | 1234 | mmc_add_host(mmc); |
@@ -1510,8 +1241,6 @@ static int rtsx_pci_sdmmc_drv_remove(struct platform_device *pdev) | |||
1510 | struct realtek_pci_sdmmc *host = platform_get_drvdata(pdev); | 1241 | struct realtek_pci_sdmmc *host = platform_get_drvdata(pdev); |
1511 | struct rtsx_pcr *pcr; | 1242 | struct rtsx_pcr *pcr; |
1512 | struct mmc_host *mmc; | 1243 | struct mmc_host *mmc; |
1513 | struct mmc_request *mrq; | ||
1514 | unsigned long flags; | ||
1515 | 1244 | ||
1516 | if (!host) | 1245 | if (!host) |
1517 | return 0; | 1246 | return 0; |
@@ -1519,33 +1248,22 @@ static int rtsx_pci_sdmmc_drv_remove(struct platform_device *pdev) | |||
1519 | pcr = host->pcr; | 1248 | pcr = host->pcr; |
1520 | pcr->slots[RTSX_SD_CARD].p_dev = NULL; | 1249 | pcr->slots[RTSX_SD_CARD].p_dev = NULL; |
1521 | pcr->slots[RTSX_SD_CARD].card_event = NULL; | 1250 | pcr->slots[RTSX_SD_CARD].card_event = NULL; |
1522 | pcr->slots[RTSX_SD_CARD].done_transfer = NULL; | ||
1523 | mmc = host->mmc; | 1251 | mmc = host->mmc; |
1524 | mrq = host->mrq; | ||
1525 | 1252 | ||
1526 | spin_lock_irqsave(&host->lock, flags); | 1253 | mutex_lock(&host->host_mutex); |
1527 | if (host->mrq) { | 1254 | if (host->mrq) { |
1528 | dev_dbg(&(pdev->dev), | 1255 | dev_dbg(&(pdev->dev), |
1529 | "%s: Controller removed during transfer\n", | 1256 | "%s: Controller removed during transfer\n", |
1530 | mmc_hostname(mmc)); | 1257 | mmc_hostname(mmc)); |
1531 | 1258 | ||
1532 | if (mrq->sbc) | 1259 | rtsx_pci_complete_unfinished_transfer(pcr); |
1533 | mrq->sbc->error = -ENOMEDIUM; | ||
1534 | if (mrq->cmd) | ||
1535 | mrq->cmd->error = -ENOMEDIUM; | ||
1536 | if (mrq->stop) | ||
1537 | mrq->stop->error = -ENOMEDIUM; | ||
1538 | if (mrq->data) | ||
1539 | mrq->data->error = -ENOMEDIUM; | ||
1540 | 1260 | ||
1541 | tasklet_schedule(&host->finish_tasklet); | 1261 | host->mrq->cmd->error = -ENOMEDIUM; |
1262 | if (host->mrq->stop) | ||
1263 | host->mrq->stop->error = -ENOMEDIUM; | ||
1264 | mmc_request_done(mmc, host->mrq); | ||
1542 | } | 1265 | } |
1543 | spin_unlock_irqrestore(&host->lock, flags); | 1266 | mutex_unlock(&host->host_mutex); |
1544 | |||
1545 | del_timer_sync(&host->timer); | ||
1546 | tasklet_kill(&host->cmd_tasklet); | ||
1547 | tasklet_kill(&host->data_tasklet); | ||
1548 | tasklet_kill(&host->finish_tasklet); | ||
1549 | 1267 | ||
1550 | mmc_remove_host(mmc); | 1268 | mmc_remove_host(mmc); |
1551 | host->eject = true; | 1269 | host->eject = true; |