@@ -1198,19 +1198,30 @@ static int ufshcd_clock_scaling_prepare(struct ufs_hba *hba)
1198
1198
*/
1199
1199
ufshcd_scsi_block_requests (hba );
1200
1200
down_write (& hba -> clk_scaling_lock );
1201
- if (ufshcd_wait_for_doorbell_clr (hba , DOORBELL_CLR_TOUT_US )) {
1201
+
1202
+ if (!hba -> clk_scaling .is_allowed ||
1203
+ ufshcd_wait_for_doorbell_clr (hba , DOORBELL_CLR_TOUT_US )) {
1202
1204
ret = - EBUSY ;
1203
1205
up_write (& hba -> clk_scaling_lock );
1204
1206
ufshcd_scsi_unblock_requests (hba );
1207
+ goto out ;
1205
1208
}
1206
1209
1210
+ /* let's not get into low power until clock scaling is completed */
1211
+ ufshcd_hold (hba , false);
1212
+
1213
+ out :
1207
1214
return ret ;
1208
1215
}
1209
1216
1210
- static void ufshcd_clock_scaling_unprepare (struct ufs_hba * hba )
1217
+ static void ufshcd_clock_scaling_unprepare (struct ufs_hba * hba , bool writelock )
1211
1218
{
1212
- up_write (& hba -> clk_scaling_lock );
1219
+ if (writelock )
1220
+ up_write (& hba -> clk_scaling_lock );
1221
+ else
1222
+ up_read (& hba -> clk_scaling_lock );
1213
1223
ufshcd_scsi_unblock_requests (hba );
1224
+ ufshcd_release (hba );
1214
1225
}
1215
1226
1216
1227
/**
@@ -1225,13 +1236,11 @@ static void ufshcd_clock_scaling_unprepare(struct ufs_hba *hba)
1225
1236
static int ufshcd_devfreq_scale (struct ufs_hba * hba , bool scale_up )
1226
1237
{
1227
1238
int ret = 0 ;
1228
-
1229
- /* let's not get into low power until clock scaling is completed */
1230
- ufshcd_hold (hba , false);
1239
+ bool is_writelock = true;
1231
1240
1232
1241
ret = ufshcd_clock_scaling_prepare (hba );
1233
1242
if (ret )
1234
- goto out ;
1243
+ return ret ;
1235
1244
1236
1245
/* scale down the gear before scaling down clocks */
1237
1246
if (!scale_up ) {
@@ -1257,14 +1266,12 @@ static int ufshcd_devfreq_scale(struct ufs_hba *hba, bool scale_up)
1257
1266
}
1258
1267
1259
1268
/* Enable Write Booster if we have scaled up else disable it */
1260
- up_write (& hba -> clk_scaling_lock );
1269
+ downgrade_write (& hba -> clk_scaling_lock );
1270
+ is_writelock = false;
1261
1271
ufshcd_wb_ctrl (hba , scale_up );
1262
- down_write (& hba -> clk_scaling_lock );
1263
1272
1264
1273
out_unprepare :
1265
- ufshcd_clock_scaling_unprepare (hba );
1266
- out :
1267
- ufshcd_release (hba );
1274
+ ufshcd_clock_scaling_unprepare (hba , is_writelock );
1268
1275
return ret ;
1269
1276
}
1270
1277
@@ -1538,7 +1545,7 @@ static ssize_t ufshcd_clkscale_enable_show(struct device *dev,
1538
1545
{
1539
1546
struct ufs_hba * hba = dev_get_drvdata (dev );
1540
1547
1541
- return snprintf (buf , PAGE_SIZE , "%d\n" , hba -> clk_scaling .is_allowed );
1548
+ return snprintf (buf , PAGE_SIZE , "%d\n" , hba -> clk_scaling .is_enabled );
1542
1549
}
1543
1550
1544
1551
static ssize_t ufshcd_clkscale_enable_store (struct device * dev ,
@@ -1558,7 +1565,7 @@ static ssize_t ufshcd_clkscale_enable_store(struct device *dev,
1558
1565
}
1559
1566
1560
1567
value = !!value ;
1561
- if (value == hba -> clk_scaling .is_allowed )
1568
+ if (value == hba -> clk_scaling .is_enabled )
1562
1569
goto out ;
1563
1570
1564
1571
pm_runtime_get_sync (hba -> dev );
@@ -1567,7 +1574,7 @@ static ssize_t ufshcd_clkscale_enable_store(struct device *dev,
1567
1574
cancel_work_sync (& hba -> clk_scaling .suspend_work );
1568
1575
cancel_work_sync (& hba -> clk_scaling .resume_work );
1569
1576
1570
- hba -> clk_scaling .is_allowed = value ;
1577
+ hba -> clk_scaling .is_enabled = value ;
1571
1578
1572
1579
if (value ) {
1573
1580
ufshcd_resume_clkscaling (hba );
@@ -1906,15 +1913,15 @@ static void ufshcd_init_clk_scaling(struct ufs_hba *hba)
1906
1913
snprintf (wq_name , sizeof (wq_name ), "ufs_clkscaling_%d" ,
1907
1914
hba -> host -> host_no );
1908
1915
hba -> clk_scaling .workq = create_singlethread_workqueue (wq_name );
1909
-
1910
- ufshcd_clkscaling_init_sysfs (hba );
1911
1916
}
1912
1917
1913
1918
static void ufshcd_exit_clk_scaling (struct ufs_hba * hba )
1914
1919
{
1915
1920
if (!ufshcd_is_clkscaling_supported (hba ))
1916
1921
return ;
1917
1922
1923
+ if (hba -> clk_scaling .enable_attr .attr .name )
1924
+ device_remove_file (hba -> dev , & hba -> clk_scaling .enable_attr );
1918
1925
destroy_workqueue (hba -> clk_scaling .workq );
1919
1926
ufshcd_devfreq_remove (hba );
1920
1927
}
@@ -1979,7 +1986,7 @@ static void ufshcd_clk_scaling_start_busy(struct ufs_hba *hba)
1979
1986
if (!hba -> clk_scaling .active_reqs ++ )
1980
1987
queue_resume_work = true;
1981
1988
1982
- if (!hba -> clk_scaling .is_allowed || hba -> pm_op_in_progress )
1989
+ if (!hba -> clk_scaling .is_enabled || hba -> pm_op_in_progress )
1983
1990
return ;
1984
1991
1985
1992
if (queue_resume_work )
@@ -5763,18 +5770,24 @@ static void ufshcd_err_handling_prepare(struct ufs_hba *hba)
5763
5770
ufshcd_vops_resume (hba , pm_op );
5764
5771
} else {
5765
5772
ufshcd_hold (hba , false);
5766
- if (hba -> clk_scaling .is_allowed ) {
5773
+ if (hba -> clk_scaling .is_enabled ) {
5767
5774
cancel_work_sync (& hba -> clk_scaling .suspend_work );
5768
5775
cancel_work_sync (& hba -> clk_scaling .resume_work );
5769
5776
ufshcd_suspend_clkscaling (hba );
5770
5777
}
5778
+ down_write (& hba -> clk_scaling_lock );
5779
+ hba -> clk_scaling .is_allowed = false;
5780
+ up_write (& hba -> clk_scaling_lock );
5771
5781
}
5772
5782
}
5773
5783
5774
5784
static void ufshcd_err_handling_unprepare (struct ufs_hba * hba )
5775
5785
{
5776
5786
ufshcd_release (hba );
5777
- if (hba -> clk_scaling .is_allowed )
5787
+ down_write (& hba -> clk_scaling_lock );
5788
+ hba -> clk_scaling .is_allowed = true;
5789
+ up_write (& hba -> clk_scaling_lock );
5790
+ if (hba -> clk_scaling .is_enabled )
5778
5791
ufshcd_resume_clkscaling (hba );
5779
5792
pm_runtime_put (hba -> dev );
5780
5793
}
@@ -7747,12 +7760,14 @@ static int ufshcd_add_lus(struct ufs_hba *hba)
7747
7760
sizeof (struct ufs_pa_layer_attr ));
7748
7761
hba -> clk_scaling .saved_pwr_info .is_valid = true;
7749
7762
if (!hba -> devfreq ) {
7763
+ hba -> clk_scaling .is_allowed = true;
7750
7764
ret = ufshcd_devfreq_init (hba );
7751
7765
if (ret )
7752
7766
goto out ;
7753
- }
7754
7767
7755
- hba -> clk_scaling .is_allowed = true;
7768
+ hba -> clk_scaling .is_enabled = true;
7769
+ ufshcd_clkscaling_init_sysfs (hba );
7770
+ }
7756
7771
}
7757
7772
7758
7773
ufs_bsg_probe (hba );
@@ -8672,11 +8687,14 @@ static int ufshcd_suspend(struct ufs_hba *hba, enum ufs_pm_op pm_op)
8672
8687
ufshcd_hold (hba , false);
8673
8688
hba -> clk_gating .is_suspended = true;
8674
8689
8675
- if (hba -> clk_scaling .is_allowed ) {
8690
+ if (hba -> clk_scaling .is_enabled ) {
8676
8691
cancel_work_sync (& hba -> clk_scaling .suspend_work );
8677
8692
cancel_work_sync (& hba -> clk_scaling .resume_work );
8678
8693
ufshcd_suspend_clkscaling (hba );
8679
8694
}
8695
+ down_write (& hba -> clk_scaling_lock );
8696
+ hba -> clk_scaling .is_allowed = false;
8697
+ up_write (& hba -> clk_scaling_lock );
8680
8698
8681
8699
if (req_dev_pwr_mode == UFS_ACTIVE_PWR_MODE &&
8682
8700
req_link_state == UIC_LINK_ACTIVE_STATE ) {
@@ -8773,8 +8791,6 @@ static int ufshcd_suspend(struct ufs_hba *hba, enum ufs_pm_op pm_op)
8773
8791
goto out ;
8774
8792
8775
8793
set_link_active :
8776
- if (hba -> clk_scaling .is_allowed )
8777
- ufshcd_resume_clkscaling (hba );
8778
8794
ufshcd_vreg_set_hpm (hba );
8779
8795
/*
8780
8796
* Device hardware reset is required to exit DeepSleep. Also, for
@@ -8798,7 +8814,10 @@ static int ufshcd_suspend(struct ufs_hba *hba, enum ufs_pm_op pm_op)
8798
8814
if (!ufshcd_set_dev_pwr_mode (hba , UFS_ACTIVE_PWR_MODE ))
8799
8815
ufshcd_disable_auto_bkops (hba );
8800
8816
enable_gating :
8801
- if (hba -> clk_scaling .is_allowed )
8817
+ down_write (& hba -> clk_scaling_lock );
8818
+ hba -> clk_scaling .is_allowed = true;
8819
+ up_write (& hba -> clk_scaling_lock );
8820
+ if (hba -> clk_scaling .is_enabled )
8802
8821
ufshcd_resume_clkscaling (hba );
8803
8822
hba -> clk_gating .is_suspended = false;
8804
8823
hba -> dev_info .b_rpm_dev_flush_capable = false;
@@ -8901,7 +8920,10 @@ static int ufshcd_resume(struct ufs_hba *hba, enum ufs_pm_op pm_op)
8901
8920
8902
8921
hba -> clk_gating .is_suspended = false;
8903
8922
8904
- if (hba -> clk_scaling .is_allowed )
8923
+ down_write (& hba -> clk_scaling_lock );
8924
+ hba -> clk_scaling .is_allowed = true;
8925
+ up_write (& hba -> clk_scaling_lock );
8926
+ if (hba -> clk_scaling .is_enabled )
8905
8927
ufshcd_resume_clkscaling (hba );
8906
8928
8907
8929
/* Enable Auto-Hibernate if configured */
@@ -8923,8 +8945,6 @@ static int ufshcd_resume(struct ufs_hba *hba, enum ufs_pm_op pm_op)
8923
8945
ufshcd_vops_suspend (hba , pm_op );
8924
8946
disable_irq_and_vops_clks :
8925
8947
ufshcd_disable_irq (hba );
8926
- if (hba -> clk_scaling .is_allowed )
8927
- ufshcd_suspend_clkscaling (hba );
8928
8948
ufshcd_setup_clocks (hba , false);
8929
8949
if (ufshcd_is_clkgating_allowed (hba )) {
8930
8950
hba -> clk_gating .state = CLKS_OFF ;
@@ -9165,8 +9185,6 @@ void ufshcd_remove(struct ufs_hba *hba)
9165
9185
9166
9186
ufshcd_exit_clk_scaling (hba );
9167
9187
ufshcd_exit_clk_gating (hba );
9168
- if (ufshcd_is_clkscaling_supported (hba ))
9169
- device_remove_file (hba -> dev , & hba -> clk_scaling .enable_attr );
9170
9188
ufshcd_hba_exit (hba );
9171
9189
}
9172
9190
EXPORT_SYMBOL_GPL (ufshcd_remove );
0 commit comments