diff options
author | Seungwon Jeon <tgih.jun@samsung.com> | 2013-06-26 13:09:29 -0400 |
---|---|---|
committer | James Bottomley <JBottomley@Parallels.com> | 2013-06-28 16:08:52 -0400 |
commit | 6ccf44fe4cd7c45a33f571788890a299d8bca448 (patch) | |
tree | 88a37909eb9729886a168de3ecf99be09de259ce /drivers/scsi/ufs | |
parent | 261ea452037471b7cab6a3913d308acba54f7933 (diff) |
[SCSI] ufs: rework link start-up process
Link start-up requires long time with multiphase handshakes
between UFS host and device. This affects driver's probe time.
This patch let link start-up run asynchronously. Link start-up
will be executed at the end of prove separately.
Along with this change, the following is worked.
Defined completion time of uic command to avoid a permanent wait.
Added mutex to guarantee of uic command at a time.
Adapted some sequence of controller initialization after link statup
according to HCI standard.
Signed-off-by: Seungwon Jeon <tgih.jun@samsung.com>
Signed-off-by: Sujit Reddy Thumma <sthumma@codeaurora.org>
Tested-by: Maya Erez <merez@codeaurora.org>
Signed-off-by: Santosh Y <santoshsy@gmail.com>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
Diffstat (limited to 'drivers/scsi/ufs')
-rw-r--r-- | drivers/scsi/ufs/ufshcd.c | 295 | ||||
-rw-r--r-- | drivers/scsi/ufs/ufshcd.h | 10 |
2 files changed, 208 insertions, 97 deletions
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index 2e0248302e8d..48a76459a5c9 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c | |||
@@ -33,11 +33,15 @@ | |||
33 | * this program. | 33 | * this program. |
34 | */ | 34 | */ |
35 | 35 | ||
36 | #include <linux/async.h> | ||
37 | |||
36 | #include "ufshcd.h" | 38 | #include "ufshcd.h" |
37 | 39 | ||
38 | #define UFSHCD_ENABLE_INTRS (UTP_TRANSFER_REQ_COMPL |\ | 40 | #define UFSHCD_ENABLE_INTRS (UTP_TRANSFER_REQ_COMPL |\ |
39 | UTP_TASK_REQ_COMPL |\ | 41 | UTP_TASK_REQ_COMPL |\ |
40 | UFSHCD_ERROR_MASK) | 42 | UFSHCD_ERROR_MASK) |
43 | /* UIC command timeout, unit: ms */ | ||
44 | #define UIC_CMD_TIMEOUT 500 | ||
41 | 45 | ||
42 | enum { | 46 | enum { |
43 | UFSHCD_MAX_CHANNEL = 0, | 47 | UFSHCD_MAX_CHANNEL = 0, |
@@ -349,24 +353,122 @@ static inline void ufshcd_hba_capabilities(struct ufs_hba *hba) | |||
349 | } | 353 | } |
350 | 354 | ||
351 | /** | 355 | /** |
352 | * ufshcd_send_uic_command - Send UIC commands to unipro layers | 356 | * ufshcd_ready_for_uic_cmd - Check if controller is ready |
357 | * to accept UIC commands | ||
353 | * @hba: per adapter instance | 358 | * @hba: per adapter instance |
354 | * @uic_command: UIC command | 359 | * Return true on success, else false |
360 | */ | ||
361 | static inline bool ufshcd_ready_for_uic_cmd(struct ufs_hba *hba) | ||
362 | { | ||
363 | if (ufshcd_readl(hba, REG_CONTROLLER_STATUS) & UIC_COMMAND_READY) | ||
364 | return true; | ||
365 | else | ||
366 | return false; | ||
367 | } | ||
368 | |||
369 | /** | ||
370 | * ufshcd_dispatch_uic_cmd - Dispatch UIC commands to unipro layers | ||
371 | * @hba: per adapter instance | ||
372 | * @uic_cmd: UIC command | ||
373 | * | ||
374 | * Mutex must be held. | ||
355 | */ | 375 | */ |
356 | static inline void | 376 | static inline void |
357 | ufshcd_send_uic_command(struct ufs_hba *hba, struct uic_command *uic_cmnd) | 377 | ufshcd_dispatch_uic_cmd(struct ufs_hba *hba, struct uic_command *uic_cmd) |
358 | { | 378 | { |
379 | WARN_ON(hba->active_uic_cmd); | ||
380 | |||
381 | hba->active_uic_cmd = uic_cmd; | ||
382 | |||
359 | /* Write Args */ | 383 | /* Write Args */ |
360 | ufshcd_writel(hba, uic_cmnd->argument1, REG_UIC_COMMAND_ARG_1); | 384 | ufshcd_writel(hba, uic_cmd->argument1, REG_UIC_COMMAND_ARG_1); |
361 | ufshcd_writel(hba, uic_cmnd->argument2, REG_UIC_COMMAND_ARG_2); | 385 | ufshcd_writel(hba, uic_cmd->argument2, REG_UIC_COMMAND_ARG_2); |
362 | ufshcd_writel(hba, uic_cmnd->argument3, REG_UIC_COMMAND_ARG_3); | 386 | ufshcd_writel(hba, uic_cmd->argument3, REG_UIC_COMMAND_ARG_3); |
363 | 387 | ||
364 | /* Write UIC Cmd */ | 388 | /* Write UIC Cmd */ |
365 | ufshcd_writel(hba, uic_cmnd->command & COMMAND_OPCODE_MASK, | 389 | ufshcd_writel(hba, uic_cmd->command & COMMAND_OPCODE_MASK, |
366 | REG_UIC_COMMAND); | 390 | REG_UIC_COMMAND); |
367 | } | 391 | } |
368 | 392 | ||
369 | /** | 393 | /** |
394 | * ufshcd_wait_for_uic_cmd - Wait complectioin of UIC command | ||
395 | * @hba: per adapter instance | ||
396 | * @uic_command: UIC command | ||
397 | * | ||
398 | * Must be called with mutex held. | ||
399 | * Returns 0 only if success. | ||
400 | */ | ||
401 | static int | ||
402 | ufshcd_wait_for_uic_cmd(struct ufs_hba *hba, struct uic_command *uic_cmd) | ||
403 | { | ||
404 | int ret; | ||
405 | unsigned long flags; | ||
406 | |||
407 | if (wait_for_completion_timeout(&uic_cmd->done, | ||
408 | msecs_to_jiffies(UIC_CMD_TIMEOUT))) | ||
409 | ret = uic_cmd->argument2 & MASK_UIC_COMMAND_RESULT; | ||
410 | else | ||
411 | ret = -ETIMEDOUT; | ||
412 | |||
413 | spin_lock_irqsave(hba->host->host_lock, flags); | ||
414 | hba->active_uic_cmd = NULL; | ||
415 | spin_unlock_irqrestore(hba->host->host_lock, flags); | ||
416 | |||
417 | return ret; | ||
418 | } | ||
419 | |||
420 | /** | ||
421 | * __ufshcd_send_uic_cmd - Send UIC commands and retrieve the result | ||
422 | * @hba: per adapter instance | ||
423 | * @uic_cmd: UIC command | ||
424 | * | ||
425 | * Identical to ufshcd_send_uic_cmd() expect mutex. Must be called | ||
426 | * with mutex held. | ||
427 | * Returns 0 only if success. | ||
428 | */ | ||
429 | static int | ||
430 | __ufshcd_send_uic_cmd(struct ufs_hba *hba, struct uic_command *uic_cmd) | ||
431 | { | ||
432 | int ret; | ||
433 | unsigned long flags; | ||
434 | |||
435 | if (!ufshcd_ready_for_uic_cmd(hba)) { | ||
436 | dev_err(hba->dev, | ||
437 | "Controller not ready to accept UIC commands\n"); | ||
438 | return -EIO; | ||
439 | } | ||
440 | |||
441 | init_completion(&uic_cmd->done); | ||
442 | |||
443 | spin_lock_irqsave(hba->host->host_lock, flags); | ||
444 | ufshcd_dispatch_uic_cmd(hba, uic_cmd); | ||
445 | spin_unlock_irqrestore(hba->host->host_lock, flags); | ||
446 | |||
447 | ret = ufshcd_wait_for_uic_cmd(hba, uic_cmd); | ||
448 | |||
449 | return ret; | ||
450 | } | ||
451 | |||
452 | /** | ||
453 | * ufshcd_send_uic_cmd - Send UIC commands and retrieve the result | ||
454 | * @hba: per adapter instance | ||
455 | * @uic_cmd: UIC command | ||
456 | * | ||
457 | * Returns 0 only if success. | ||
458 | */ | ||
459 | static int | ||
460 | ufshcd_send_uic_cmd(struct ufs_hba *hba, struct uic_command *uic_cmd) | ||
461 | { | ||
462 | int ret; | ||
463 | |||
464 | mutex_lock(&hba->uic_cmd_mutex); | ||
465 | ret = __ufshcd_send_uic_cmd(hba, uic_cmd); | ||
466 | mutex_unlock(&hba->uic_cmd_mutex); | ||
467 | |||
468 | return ret; | ||
469 | } | ||
470 | |||
471 | /** | ||
370 | * ufshcd_map_sg - Map scatter-gather list to prdt | 472 | * ufshcd_map_sg - Map scatter-gather list to prdt |
371 | * @lrbp - pointer to local reference block | 473 | * @lrbp - pointer to local reference block |
372 | * | 474 | * |
@@ -725,34 +827,16 @@ static void ufshcd_host_memory_configure(struct ufs_hba *hba) | |||
725 | */ | 827 | */ |
726 | static int ufshcd_dme_link_startup(struct ufs_hba *hba) | 828 | static int ufshcd_dme_link_startup(struct ufs_hba *hba) |
727 | { | 829 | { |
728 | struct uic_command *uic_cmd; | 830 | struct uic_command uic_cmd = {0}; |
729 | unsigned long flags; | 831 | int ret; |
730 | 832 | ||
731 | /* check if controller is ready to accept UIC commands */ | 833 | uic_cmd.command = UIC_CMD_DME_LINK_STARTUP; |
732 | if ((ufshcd_readl(hba, REG_CONTROLLER_STATUS) & | ||
733 | UIC_COMMAND_READY) == 0x0) { | ||
734 | dev_err(hba->dev, | ||
735 | "Controller not ready" | ||
736 | " to accept UIC commands\n"); | ||
737 | return -EIO; | ||
738 | } | ||
739 | 834 | ||
740 | spin_lock_irqsave(hba->host->host_lock, flags); | 835 | ret = ufshcd_send_uic_cmd(hba, &uic_cmd); |
741 | 836 | if (ret) | |
742 | /* form UIC command */ | 837 | dev_err(hba->dev, |
743 | uic_cmd = &hba->active_uic_cmd; | 838 | "dme-link-startup: error code %d\n", ret); |
744 | uic_cmd->command = UIC_CMD_DME_LINK_STARTUP; | 839 | return ret; |
745 | uic_cmd->argument1 = 0; | ||
746 | uic_cmd->argument2 = 0; | ||
747 | uic_cmd->argument3 = 0; | ||
748 | |||
749 | /* enable UIC related interrupts */ | ||
750 | ufshcd_enable_intr(hba, UIC_COMMAND_COMPL); | ||
751 | |||
752 | /* sending UIC commands to controller */ | ||
753 | ufshcd_send_uic_command(hba, uic_cmd); | ||
754 | spin_unlock_irqrestore(hba->host->host_lock, flags); | ||
755 | return 0; | ||
756 | } | 840 | } |
757 | 841 | ||
758 | /** | 842 | /** |
@@ -761,9 +845,10 @@ static int ufshcd_dme_link_startup(struct ufs_hba *hba) | |||
761 | * | 845 | * |
762 | * To bring UFS host controller to operational state, | 846 | * To bring UFS host controller to operational state, |
763 | * 1. Check if device is present | 847 | * 1. Check if device is present |
764 | * 2. Configure run-stop-registers | 848 | * 2. Enable required interrupts |
765 | * 3. Enable required interrupts | 849 | * 3. Configure interrupt aggregation |
766 | * 4. Configure interrupt aggregation | 850 | * 4. Program UTRL and UTMRL base addres |
851 | * 5. Configure run-stop-registers | ||
767 | * | 852 | * |
768 | * Returns 0 on success, non-zero value on failure | 853 | * Returns 0 on success, non-zero value on failure |
769 | */ | 854 | */ |
@@ -780,6 +865,22 @@ static int ufshcd_make_hba_operational(struct ufs_hba *hba) | |||
780 | goto out; | 865 | goto out; |
781 | } | 866 | } |
782 | 867 | ||
868 | /* Enable required interrupts */ | ||
869 | ufshcd_enable_intr(hba, UFSHCD_ENABLE_INTRS); | ||
870 | |||
871 | /* Configure interrupt aggregation */ | ||
872 | ufshcd_config_int_aggr(hba, INT_AGGR_CONFIG); | ||
873 | |||
874 | /* Configure UTRL and UTMRL base address registers */ | ||
875 | ufshcd_writel(hba, lower_32_bits(hba->utrdl_dma_addr), | ||
876 | REG_UTP_TRANSFER_REQ_LIST_BASE_L); | ||
877 | ufshcd_writel(hba, upper_32_bits(hba->utrdl_dma_addr), | ||
878 | REG_UTP_TRANSFER_REQ_LIST_BASE_H); | ||
879 | ufshcd_writel(hba, lower_32_bits(hba->utmrdl_dma_addr), | ||
880 | REG_UTP_TASK_REQ_LIST_BASE_L); | ||
881 | ufshcd_writel(hba, upper_32_bits(hba->utmrdl_dma_addr), | ||
882 | REG_UTP_TASK_REQ_LIST_BASE_H); | ||
883 | |||
783 | /* | 884 | /* |
784 | * UCRDY, UTMRLDY and UTRLRDY bits must be 1 | 885 | * UCRDY, UTMRLDY and UTRLRDY bits must be 1 |
785 | * DEI, HEI bits must be 0 | 886 | * DEI, HEI bits must be 0 |
@@ -793,17 +894,11 @@ static int ufshcd_make_hba_operational(struct ufs_hba *hba) | |||
793 | goto out; | 894 | goto out; |
794 | } | 895 | } |
795 | 896 | ||
796 | /* Enable required interrupts */ | ||
797 | ufshcd_enable_intr(hba, UFSHCD_ENABLE_INTRS); | ||
798 | |||
799 | /* Configure interrupt aggregation */ | ||
800 | ufshcd_config_int_aggr(hba, INT_AGGR_CONFIG); | ||
801 | |||
802 | if (hba->ufshcd_state == UFSHCD_STATE_RESET) | 897 | if (hba->ufshcd_state == UFSHCD_STATE_RESET) |
803 | scsi_unblock_requests(hba->host); | 898 | scsi_unblock_requests(hba->host); |
804 | 899 | ||
805 | hba->ufshcd_state = UFSHCD_STATE_OPERATIONAL; | 900 | hba->ufshcd_state = UFSHCD_STATE_OPERATIONAL; |
806 | scsi_scan_host(hba->host); | 901 | |
807 | out: | 902 | out: |
808 | return err; | 903 | return err; |
809 | } | 904 | } |
@@ -872,34 +967,28 @@ static int ufshcd_hba_enable(struct ufs_hba *hba) | |||
872 | } | 967 | } |
873 | 968 | ||
874 | /** | 969 | /** |
875 | * ufshcd_initialize_hba - start the initialization process | 970 | * ufshcd_link_startup - Initialize unipro link startup |
876 | * @hba: per adapter instance | 971 | * @hba: per adapter instance |
877 | * | 972 | * |
878 | * 1. Enable the controller via ufshcd_hba_enable. | 973 | * Returns 0 for success, non-zero in case of failure |
879 | * 2. Program the Transfer Request List Address with the starting address of | ||
880 | * UTRDL. | ||
881 | * 3. Program the Task Management Request List Address with starting address | ||
882 | * of UTMRDL. | ||
883 | * | ||
884 | * Returns 0 on success, non-zero value on failure. | ||
885 | */ | 974 | */ |
886 | static int ufshcd_initialize_hba(struct ufs_hba *hba) | 975 | static int ufshcd_link_startup(struct ufs_hba *hba) |
887 | { | 976 | { |
888 | if (ufshcd_hba_enable(hba)) | 977 | int ret; |
889 | return -EIO; | ||
890 | 978 | ||
891 | /* Configure UTRL and UTMRL base address registers */ | 979 | /* enable UIC related interrupts */ |
892 | ufshcd_writel(hba, lower_32_bits(hba->utrdl_dma_addr), | 980 | ufshcd_enable_intr(hba, UIC_COMMAND_COMPL); |
893 | REG_UTP_TRANSFER_REQ_LIST_BASE_L); | 981 | |
894 | ufshcd_writel(hba, upper_32_bits(hba->utrdl_dma_addr), | 982 | ret = ufshcd_dme_link_startup(hba); |
895 | REG_UTP_TRANSFER_REQ_LIST_BASE_H); | 983 | if (ret) |
896 | ufshcd_writel(hba, lower_32_bits(hba->utmrdl_dma_addr), | 984 | goto out; |
897 | REG_UTP_TASK_REQ_LIST_BASE_L); | 985 | |
898 | ufshcd_writel(hba, upper_32_bits(hba->utmrdl_dma_addr), | 986 | ret = ufshcd_make_hba_operational(hba); |
899 | REG_UTP_TASK_REQ_LIST_BASE_H); | ||
900 | 987 | ||
901 | /* Initialize unipro link startup procedure */ | 988 | out: |
902 | return ufshcd_dme_link_startup(hba); | 989 | if (ret) |
990 | dev_err(hba->dev, "link startup failed %d\n", ret); | ||
991 | return ret; | ||
903 | } | 992 | } |
904 | 993 | ||
905 | /** | 994 | /** |
@@ -939,12 +1028,19 @@ static int ufshcd_do_reset(struct ufs_hba *hba) | |||
939 | hba->outstanding_reqs = 0; | 1028 | hba->outstanding_reqs = 0; |
940 | hba->outstanding_tasks = 0; | 1029 | hba->outstanding_tasks = 0; |
941 | 1030 | ||
942 | /* start the initialization process */ | 1031 | /* Host controller enable */ |
943 | if (ufshcd_initialize_hba(hba)) { | 1032 | if (ufshcd_hba_enable(hba)) { |
944 | dev_err(hba->dev, | 1033 | dev_err(hba->dev, |
945 | "Reset: Controller initialization failed\n"); | 1034 | "Reset: Controller initialization failed\n"); |
946 | return FAILED; | 1035 | return FAILED; |
947 | } | 1036 | } |
1037 | |||
1038 | if (ufshcd_link_startup(hba)) { | ||
1039 | dev_err(hba->dev, | ||
1040 | "Reset: Link start-up failed\n"); | ||
1041 | return FAILED; | ||
1042 | } | ||
1043 | |||
948 | return SUCCESS; | 1044 | return SUCCESS; |
949 | } | 1045 | } |
950 | 1046 | ||
@@ -1176,6 +1272,19 @@ ufshcd_transfer_rsp_status(struct ufs_hba *hba, struct ufshcd_lrb *lrbp) | |||
1176 | } | 1272 | } |
1177 | 1273 | ||
1178 | /** | 1274 | /** |
1275 | * ufshcd_uic_cmd_compl - handle completion of uic command | ||
1276 | * @hba: per adapter instance | ||
1277 | */ | ||
1278 | static void ufshcd_uic_cmd_compl(struct ufs_hba *hba) | ||
1279 | { | ||
1280 | if (hba->active_uic_cmd) { | ||
1281 | hba->active_uic_cmd->argument2 |= | ||
1282 | ufshcd_get_uic_cmd_result(hba); | ||
1283 | complete(&hba->active_uic_cmd->done); | ||
1284 | } | ||
1285 | } | ||
1286 | |||
1287 | /** | ||
1179 | * ufshcd_transfer_req_compl - handle SCSI and query command completion | 1288 | * ufshcd_transfer_req_compl - handle SCSI and query command completion |
1180 | * @hba: per adapter instance | 1289 | * @hba: per adapter instance |
1181 | */ | 1290 | */ |
@@ -1215,28 +1324,6 @@ static void ufshcd_transfer_req_compl(struct ufs_hba *hba) | |||
1215 | } | 1324 | } |
1216 | 1325 | ||
1217 | /** | 1326 | /** |
1218 | * ufshcd_uic_cc_handler - handle UIC command completion | ||
1219 | * @work: pointer to a work queue structure | ||
1220 | * | ||
1221 | * Returns 0 on success, non-zero value on failure | ||
1222 | */ | ||
1223 | static void ufshcd_uic_cc_handler (struct work_struct *work) | ||
1224 | { | ||
1225 | struct ufs_hba *hba; | ||
1226 | |||
1227 | hba = container_of(work, struct ufs_hba, uic_workq); | ||
1228 | |||
1229 | if ((hba->active_uic_cmd.command == UIC_CMD_DME_LINK_STARTUP) && | ||
1230 | !(ufshcd_get_uic_cmd_result(hba))) { | ||
1231 | |||
1232 | if (ufshcd_make_hba_operational(hba)) | ||
1233 | dev_err(hba->dev, | ||
1234 | "cc: hba not operational state\n"); | ||
1235 | return; | ||
1236 | } | ||
1237 | } | ||
1238 | |||
1239 | /** | ||
1240 | * ufshcd_fatal_err_handler - handle fatal errors | 1327 | * ufshcd_fatal_err_handler - handle fatal errors |
1241 | * @hba: per adapter instance | 1328 | * @hba: per adapter instance |
1242 | */ | 1329 | */ |
@@ -1297,7 +1384,7 @@ static void ufshcd_sl_intr(struct ufs_hba *hba, u32 intr_status) | |||
1297 | ufshcd_err_handler(hba); | 1384 | ufshcd_err_handler(hba); |
1298 | 1385 | ||
1299 | if (intr_status & UIC_COMMAND_COMPL) | 1386 | if (intr_status & UIC_COMMAND_COMPL) |
1300 | schedule_work(&hba->uic_workq); | 1387 | ufshcd_uic_cmd_compl(hba); |
1301 | 1388 | ||
1302 | if (intr_status & UTP_TASK_REQ_COMPL) | 1389 | if (intr_status & UTP_TASK_REQ_COMPL) |
1303 | ufshcd_tmc_handler(hba); | 1390 | ufshcd_tmc_handler(hba); |
@@ -1520,6 +1607,21 @@ out: | |||
1520 | return err; | 1607 | return err; |
1521 | } | 1608 | } |
1522 | 1609 | ||
1610 | /** | ||
1611 | * ufshcd_async_scan - asynchronous execution for link startup | ||
1612 | * @data: data pointer to pass to this function | ||
1613 | * @cookie: cookie data | ||
1614 | */ | ||
1615 | static void ufshcd_async_scan(void *data, async_cookie_t cookie) | ||
1616 | { | ||
1617 | struct ufs_hba *hba = (struct ufs_hba *)data; | ||
1618 | int ret; | ||
1619 | |||
1620 | ret = ufshcd_link_startup(hba); | ||
1621 | if (!ret) | ||
1622 | scsi_scan_host(hba->host); | ||
1623 | } | ||
1624 | |||
1523 | static struct scsi_host_template ufshcd_driver_template = { | 1625 | static struct scsi_host_template ufshcd_driver_template = { |
1524 | .module = THIS_MODULE, | 1626 | .module = THIS_MODULE, |
1525 | .name = UFSHCD, | 1627 | .name = UFSHCD, |
@@ -1681,9 +1783,11 @@ int ufshcd_init(struct device *dev, struct ufs_hba **hba_handle, | |||
1681 | init_waitqueue_head(&hba->ufshcd_tm_wait_queue); | 1783 | init_waitqueue_head(&hba->ufshcd_tm_wait_queue); |
1682 | 1784 | ||
1683 | /* Initialize work queues */ | 1785 | /* Initialize work queues */ |
1684 | INIT_WORK(&hba->uic_workq, ufshcd_uic_cc_handler); | ||
1685 | INIT_WORK(&hba->feh_workq, ufshcd_fatal_err_handler); | 1786 | INIT_WORK(&hba->feh_workq, ufshcd_fatal_err_handler); |
1686 | 1787 | ||
1788 | /* Initialize UIC command mutex */ | ||
1789 | mutex_init(&hba->uic_cmd_mutex); | ||
1790 | |||
1687 | /* IRQ registration */ | 1791 | /* IRQ registration */ |
1688 | err = request_irq(irq, ufshcd_intr, IRQF_SHARED, UFSHCD, hba); | 1792 | err = request_irq(irq, ufshcd_intr, IRQF_SHARED, UFSHCD, hba); |
1689 | if (err) { | 1793 | if (err) { |
@@ -1704,14 +1808,17 @@ int ufshcd_init(struct device *dev, struct ufs_hba **hba_handle, | |||
1704 | goto out_free_irq; | 1808 | goto out_free_irq; |
1705 | } | 1809 | } |
1706 | 1810 | ||
1707 | /* Initialization routine */ | 1811 | /* Host controller enable */ |
1708 | err = ufshcd_initialize_hba(hba); | 1812 | err = ufshcd_hba_enable(hba); |
1709 | if (err) { | 1813 | if (err) { |
1710 | dev_err(hba->dev, "Initialization failed\n"); | 1814 | dev_err(hba->dev, "Host controller enable failed\n"); |
1711 | goto out_remove_scsi_host; | 1815 | goto out_remove_scsi_host; |
1712 | } | 1816 | } |
1817 | |||
1713 | *hba_handle = hba; | 1818 | *hba_handle = hba; |
1714 | 1819 | ||
1820 | async_schedule(ufshcd_async_scan, hba); | ||
1821 | |||
1715 | return 0; | 1822 | return 0; |
1716 | 1823 | ||
1717 | out_remove_scsi_host: | 1824 | out_remove_scsi_host: |
diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h index 4213600b89d6..49590ee07acc 100644 --- a/drivers/scsi/ufs/ufshcd.h +++ b/drivers/scsi/ufs/ufshcd.h | |||
@@ -51,6 +51,7 @@ | |||
51 | #include <linux/bitops.h> | 51 | #include <linux/bitops.h> |
52 | #include <linux/pm_runtime.h> | 52 | #include <linux/pm_runtime.h> |
53 | #include <linux/clk.h> | 53 | #include <linux/clk.h> |
54 | #include <linux/completion.h> | ||
54 | 55 | ||
55 | #include <asm/irq.h> | 56 | #include <asm/irq.h> |
56 | #include <asm/byteorder.h> | 57 | #include <asm/byteorder.h> |
@@ -75,6 +76,7 @@ | |||
75 | * @argument3: UIC command argument 3 | 76 | * @argument3: UIC command argument 3 |
76 | * @cmd_active: Indicate if UIC command is outstanding | 77 | * @cmd_active: Indicate if UIC command is outstanding |
77 | * @result: UIC command result | 78 | * @result: UIC command result |
79 | * @done: UIC command completion | ||
78 | */ | 80 | */ |
79 | struct uic_command { | 81 | struct uic_command { |
80 | u32 command; | 82 | u32 command; |
@@ -83,6 +85,7 @@ struct uic_command { | |||
83 | u32 argument3; | 85 | u32 argument3; |
84 | int cmd_active; | 86 | int cmd_active; |
85 | int result; | 87 | int result; |
88 | struct completion done; | ||
86 | }; | 89 | }; |
87 | 90 | ||
88 | /** | 91 | /** |
@@ -136,11 +139,11 @@ struct ufshcd_lrb { | |||
136 | * @ufs_version: UFS Version to which controller complies | 139 | * @ufs_version: UFS Version to which controller complies |
137 | * @irq: Irq number of the controller | 140 | * @irq: Irq number of the controller |
138 | * @active_uic_cmd: handle of active UIC command | 141 | * @active_uic_cmd: handle of active UIC command |
142 | * @uic_cmd_mutex: mutex for uic command | ||
139 | * @ufshcd_tm_wait_queue: wait queue for task management | 143 | * @ufshcd_tm_wait_queue: wait queue for task management |
140 | * @tm_condition: condition variable for task management | 144 | * @tm_condition: condition variable for task management |
141 | * @ufshcd_state: UFSHCD states | 145 | * @ufshcd_state: UFSHCD states |
142 | * @intr_mask: Interrupt Mask Bits | 146 | * @intr_mask: Interrupt Mask Bits |
143 | * @uic_workq: Work queue for UIC completion handling | ||
144 | * @feh_workq: Work queue for fatal controller error handling | 147 | * @feh_workq: Work queue for fatal controller error handling |
145 | * @errors: HBA errors | 148 | * @errors: HBA errors |
146 | */ | 149 | */ |
@@ -171,7 +174,9 @@ struct ufs_hba { | |||
171 | u32 ufs_version; | 174 | u32 ufs_version; |
172 | unsigned int irq; | 175 | unsigned int irq; |
173 | 176 | ||
174 | struct uic_command active_uic_cmd; | 177 | struct uic_command *active_uic_cmd; |
178 | struct mutex uic_cmd_mutex; | ||
179 | |||
175 | wait_queue_head_t ufshcd_tm_wait_queue; | 180 | wait_queue_head_t ufshcd_tm_wait_queue; |
176 | unsigned long tm_condition; | 181 | unsigned long tm_condition; |
177 | 182 | ||
@@ -179,7 +184,6 @@ struct ufs_hba { | |||
179 | u32 intr_mask; | 184 | u32 intr_mask; |
180 | 185 | ||
181 | /* Work Queues */ | 186 | /* Work Queues */ |
182 | struct work_struct uic_workq; | ||
183 | struct work_struct feh_workq; | 187 | struct work_struct feh_workq; |
184 | 188 | ||
185 | /* HBA Errors */ | 189 | /* HBA Errors */ |