62
62
/* Task management command timeout */
63
63
#define TM_CMD_TIMEOUT 100 /* msecs */
64
64
65
+ /* maximum number of link-startup retries */
66
+ #define DME_LINKSTARTUP_RETRIES 3
67
+
68
+ /* maximum number of reset retries before giving up */
69
+ #define MAX_HOST_RESET_RETRIES 5
70
+
65
71
/* Expose the flag value from utp_upiu_query.value */
66
72
#define MASK_QUERY_UPIU_FLAG_LOC 0xFF
67
73
@@ -137,6 +143,8 @@ static void ufshcd_tmc_handler(struct ufs_hba *hba);
137
143
static void ufshcd_async_scan (void * data , async_cookie_t cookie );
138
144
static int ufshcd_reset_and_restore (struct ufs_hba * hba );
139
145
static int ufshcd_clear_tm_cmd (struct ufs_hba * hba , int tag );
146
+ static void ufshcd_hba_exit (struct ufs_hba * hba );
147
+ static int ufshcd_probe_hba (struct ufs_hba * hba );
140
148
141
149
/*
142
150
* ufshcd_wait_for_register - wait for register value to change
@@ -2043,6 +2051,9 @@ static int ufshcd_hba_enable(struct ufs_hba *hba)
2043
2051
msleep (5 );
2044
2052
}
2045
2053
2054
+ /* enable UIC related interrupts */
2055
+ ufshcd_enable_intr (hba , UIC_COMMAND_COMPL );
2056
+
2046
2057
if (hba -> vops && hba -> vops -> hce_enable_notify )
2047
2058
hba -> vops -> hce_enable_notify (hba , POST_CHANGE );
2048
2059
@@ -2058,23 +2069,33 @@ static int ufshcd_hba_enable(struct ufs_hba *hba)
2058
2069
static int ufshcd_link_startup (struct ufs_hba * hba )
2059
2070
{
2060
2071
int ret ;
2072
+ int retries = DME_LINKSTARTUP_RETRIES ;
2061
2073
2062
- /* enable UIC related interrupts */
2063
- ufshcd_enable_intr (hba , UIC_COMMAND_COMPL );
2074
+ do {
2075
+ if (hba -> vops && hba -> vops -> link_startup_notify )
2076
+ hba -> vops -> link_startup_notify (hba , PRE_CHANGE );
2064
2077
2065
- if (hba -> vops && hba -> vops -> link_startup_notify )
2066
- hba -> vops -> link_startup_notify (hba , PRE_CHANGE );
2078
+ ret = ufshcd_dme_link_startup (hba );
2067
2079
2068
- ret = ufshcd_dme_link_startup (hba );
2069
- if (ret )
2070
- goto out ;
2080
+ /* check if device is detected by inter-connect layer */
2081
+ if (!ret && !ufshcd_is_device_present (hba )) {
2082
+ dev_err (hba -> dev , "%s: Device not present\n" , __func__ );
2083
+ ret = - ENXIO ;
2084
+ goto out ;
2085
+ }
2071
2086
2072
- /* check if device is detected by inter-connect layer */
2073
- if (!ufshcd_is_device_present (hba )) {
2074
- dev_err (hba -> dev , "%s: Device not present\n" , __func__ );
2075
- ret = - ENXIO ;
2087
+ /*
2088
+ * DME link lost indication is only received when link is up,
2089
+ * but we can't be sure if the link is up until link startup
2090
+ * succeeds. So reset the local Uni-Pro and try again.
2091
+ */
2092
+ if (ret && ufshcd_hba_enable (hba ))
2093
+ goto out ;
2094
+ } while (ret && retries -- );
2095
+
2096
+ if (ret )
2097
+ /* failed to get the link up... retire */
2076
2098
goto out ;
2077
- }
2078
2099
2079
2100
/* Include any host controller configuration via UIC commands */
2080
2101
if (hba -> vops && hba -> vops -> link_startup_notify ) {
@@ -3139,7 +3160,6 @@ static int ufshcd_abort(struct scsi_cmnd *cmd)
3139
3160
static int ufshcd_host_reset_and_restore (struct ufs_hba * hba )
3140
3161
{
3141
3162
int err ;
3142
- async_cookie_t cookie ;
3143
3163
unsigned long flags ;
3144
3164
3145
3165
/* Reset the host controller */
@@ -3152,10 +3172,9 @@ static int ufshcd_host_reset_and_restore(struct ufs_hba *hba)
3152
3172
goto out ;
3153
3173
3154
3174
/* Establish the link again and restore the device */
3155
- cookie = async_schedule (ufshcd_async_scan , hba );
3156
- /* wait for async scan to be completed */
3157
- async_synchronize_cookie (++ cookie );
3158
- if (hba -> ufshcd_state != UFSHCD_STATE_OPERATIONAL )
3175
+ err = ufshcd_probe_hba (hba );
3176
+
3177
+ if (!err && (hba -> ufshcd_state != UFSHCD_STATE_OPERATIONAL ))
3159
3178
err = - EIO ;
3160
3179
out :
3161
3180
if (err )
@@ -3177,8 +3196,11 @@ static int ufshcd_reset_and_restore(struct ufs_hba *hba)
3177
3196
{
3178
3197
int err = 0 ;
3179
3198
unsigned long flags ;
3199
+ int retries = MAX_HOST_RESET_RETRIES ;
3180
3200
3181
- err = ufshcd_host_reset_and_restore (hba );
3201
+ do {
3202
+ err = ufshcd_host_reset_and_restore (hba );
3203
+ } while (err && -- retries );
3182
3204
3183
3205
/*
3184
3206
* After reset the door-bell might be cleared, complete
@@ -3243,13 +3265,13 @@ static int ufshcd_eh_host_reset_handler(struct scsi_cmnd *cmd)
3243
3265
}
3244
3266
3245
3267
/**
3246
- * ufshcd_async_scan - asynchronous execution for link startup
3247
- * @data: data pointer to pass to this function
3248
- * @cookie: cookie data
3268
+ * ufshcd_probe_hba - probe hba to detect device and initialize
3269
+ * @hba: per-adapter instance
3270
+ *
3271
+ * Execute link-startup and verify device initialization
3249
3272
*/
3250
- static void ufshcd_async_scan ( void * data , async_cookie_t cookie )
3273
+ static int ufshcd_probe_hba ( struct ufs_hba * hba )
3251
3274
{
3252
- struct ufs_hba * hba = (struct ufs_hba * )data ;
3253
3275
int ret ;
3254
3276
3255
3277
ret = ufshcd_link_startup (hba );
@@ -3275,7 +3297,26 @@ static void ufshcd_async_scan(void *data, async_cookie_t cookie)
3275
3297
pm_runtime_put_sync (hba -> dev );
3276
3298
}
3277
3299
out :
3278
- return ;
3300
+ /*
3301
+ * If we failed to initialize the device or the device is not
3302
+ * present, turn off the power/clocks etc.
3303
+ */
3304
+ if (ret && !ufshcd_eh_in_progress (hba ))
3305
+ ufshcd_hba_exit (hba );
3306
+
3307
+ return ret ;
3308
+ }
3309
+
3310
+ /**
3311
+ * ufshcd_async_scan - asynchronous execution for probing hba
3312
+ * @data: data pointer to pass to this function
3313
+ * @cookie: cookie data
3314
+ */
3315
+ static void ufshcd_async_scan (void * data , async_cookie_t cookie )
3316
+ {
3317
+ struct ufs_hba * hba = (struct ufs_hba * )data ;
3318
+
3319
+ ufshcd_probe_hba (hba );
3279
3320
}
3280
3321
3281
3322
static struct scsi_host_template ufshcd_driver_template = {
@@ -3631,6 +3672,7 @@ static int ufshcd_hba_init(struct ufs_hba *hba)
3631
3672
if (err )
3632
3673
goto out_disable_vreg ;
3633
3674
3675
+ hba -> is_powered = true;
3634
3676
goto out ;
3635
3677
3636
3678
out_disable_vreg :
@@ -3645,10 +3687,13 @@ static int ufshcd_hba_init(struct ufs_hba *hba)
3645
3687
3646
3688
static void ufshcd_hba_exit (struct ufs_hba * hba )
3647
3689
{
3648
- ufshcd_variant_hba_exit (hba );
3649
- ufshcd_setup_vreg (hba , false);
3650
- ufshcd_setup_clocks (hba , false);
3651
- ufshcd_setup_hba_vreg (hba , false);
3690
+ if (hba -> is_powered ) {
3691
+ ufshcd_variant_hba_exit (hba );
3692
+ ufshcd_setup_vreg (hba , false);
3693
+ ufshcd_setup_clocks (hba , false);
3694
+ ufshcd_setup_hba_vreg (hba , false);
3695
+ hba -> is_powered = false;
3696
+ }
3652
3697
}
3653
3698
3654
3699
/**
0 commit comments