diff options
author | Mallikarjun Kasoju <mkasoju@nvidia.com> | 2021-08-20 07:25:46 -0400 |
---|---|---|
committer | mobile promotions <svcmobile_promotions@nvidia.com> | 2022-01-18 08:55:46 -0500 |
commit | 9ef60619cfb8d195715b798ac112cdd3d108da38 (patch) | |
tree | d0cc3d3563a4d0f4d4c9b280870e7c52b93c7b42 | |
parent | e76829b9c05e2dd0708d4074eeb9276b9f632ba2 (diff) |
ufs: Changes to support provision for UFS3.1 and UFS2.1
Get the device UFS spec and populate the descriptor offsets as per
the respective specs.
Bug 200765373
Change-Id: Id9a0d90d1aaf465cc6e581f7155b98cc5bcf0182
Signed-off-by: Mallikarjun Kasoju <mkasoju@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvidia/+/2645541
Tested-by: Prakhar Gupta <prakharg@nvidia.com>
Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
Reviewed-by: Vikram Kanigiri <vkanigiri@nvidia.com>
Reviewed-by: Rohit Upadhyay <rupadhyay@nvidia.com>
Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
GVS: Gerrit_Virtual_Submit
-rw-r--r-- | drivers/scsi/ufs/ufs-provision.c | 97 | ||||
-rw-r--r-- | drivers/scsi/ufs/ufs-tegra.c | 12 |
2 files changed, 93 insertions, 16 deletions
diff --git a/drivers/scsi/ufs/ufs-provision.c b/drivers/scsi/ufs/ufs-provision.c index e42ea57a8..3af4175fc 100644 --- a/drivers/scsi/ufs/ufs-provision.c +++ b/drivers/scsi/ufs/ufs-provision.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2017-2018, NVIDIA CORPORATION. All rights reserved. | 2 | * Copyright (c) 2017-2022, NVIDIA CORPORATION. All rights reserved. |
3 | * | 3 | * |
4 | * Author: | 4 | * Author: |
5 | * Abhinav Site <asite@nvidia.com> | 5 | * Abhinav Site <asite@nvidia.com> |
@@ -19,6 +19,7 @@ | |||
19 | #ifdef CONFIG_DEBUG_FS | 19 | #ifdef CONFIG_DEBUG_FS |
20 | 20 | ||
21 | #include "ufs-tegra.h" | 21 | #include "ufs-tegra.h" |
22 | #include "ufs.h" | ||
22 | 23 | ||
23 | #define CHECK_NULL(expr) \ | 24 | #define CHECK_NULL(expr) \ |
24 | { \ | 25 | { \ |
@@ -30,9 +31,14 @@ | |||
30 | 31 | ||
31 | #define START_PROVISIONING 1 | 32 | #define START_PROVISIONING 1 |
32 | #define MAX_LUN_COUNT 8 | 33 | #define MAX_LUN_COUNT 8 |
34 | #define CONFIG_DESC_301_SIZE 230 | ||
35 | #define UNIT_DESC_301_SIZE 26 | ||
36 | #define CONFIG_DESC_HEADER_301_SIZE 22 | ||
37 | |||
33 | #define CONFIG_DESC_SIZE 144 | 38 | #define CONFIG_DESC_SIZE 144 |
34 | #define UNIT_DESC_SIZE 16 | 39 | #define UNIT_DESC_SIZE 16 |
35 | #define CONFIG_DESC_HEADER_SIZE 16 | 40 | #define CONFIG_DESC_HEADER_SIZE 16 |
41 | |||
36 | #define ACTIVE_MODE 0x01 | 42 | #define ACTIVE_MODE 0x01 |
37 | #define EQUAL_PRIORITY 0x7F | 43 | #define EQUAL_PRIORITY 0x7F |
38 | 44 | ||
@@ -55,13 +61,52 @@ | |||
55 | #define INIT_PWR_MODE_OFFSET 5 | 61 | #define INIT_PWR_MODE_OFFSET 5 |
56 | #define HIGH_PRIORITY_LUN_OFFSET 6 | 62 | #define HIGH_PRIORITY_LUN_OFFSET 6 |
57 | 63 | ||
58 | void populate_desc_header(struct ufs_tegra_host *ufs_tegra) | 64 | static inline u8 get_config_desc_size(const u16 spec_version) |
65 | { | ||
66 | u8 desc_size; | ||
67 | |||
68 | if (spec_version >= 0x301) | ||
69 | desc_size = CONFIG_DESC_301_SIZE; | ||
70 | else | ||
71 | desc_size = CONFIG_DESC_SIZE; | ||
72 | |||
73 | return desc_size; | ||
74 | } | ||
75 | |||
76 | static inline u8 get_unit_desc_size(const u16 spec_version) | ||
77 | { | ||
78 | u8 unit_desc_size; | ||
79 | |||
80 | if (spec_version >= 0x301) | ||
81 | unit_desc_size = UNIT_DESC_301_SIZE; | ||
82 | else | ||
83 | unit_desc_size = UNIT_DESC_SIZE; | ||
84 | |||
85 | return unit_desc_size; | ||
86 | } | ||
87 | |||
88 | static inline u8 get_config_desc_hdr_size(const u16 spec_version) | ||
89 | { | ||
90 | u8 hdr_size; | ||
91 | |||
92 | if (spec_version >= 0x301) | ||
93 | hdr_size = CONFIG_DESC_HEADER_301_SIZE; | ||
94 | else | ||
95 | hdr_size = CONFIG_DESC_HEADER_SIZE; | ||
96 | |||
97 | return hdr_size; | ||
98 | } | ||
99 | |||
100 | static void populate_desc_header(struct ufs_tegra_host *ufs_tegra, const u16 spec_version) | ||
59 | { | 101 | { |
60 | u8 *lun_desc_buf; | 102 | u8 *lun_desc_buf; |
103 | u8 desc_size; | ||
104 | |||
105 | desc_size = get_config_desc_size(spec_version); | ||
61 | 106 | ||
62 | if ((ufs_tegra != NULL) && (ufs_tegra->lun_desc_buf != NULL)) { | 107 | if ((ufs_tegra != NULL) && (ufs_tegra->lun_desc_buf != NULL)) { |
63 | lun_desc_buf = ufs_tegra->lun_desc_buf; | 108 | lun_desc_buf = ufs_tegra->lun_desc_buf; |
64 | lun_desc_buf[LENGTH_OFFSET] = CONFIG_DESC_SIZE; | 109 | lun_desc_buf[LENGTH_OFFSET] = desc_size; |
65 | lun_desc_buf[DESC_TYPE_OFFFSET] = QUERY_DESC_IDN_CONFIGURATION; | 110 | lun_desc_buf[DESC_TYPE_OFFFSET] = QUERY_DESC_IDN_CONFIGURATION; |
66 | lun_desc_buf[BOOT_ENABLE_OFFFSET] = ufs_tegra->boot_enable; | 111 | lun_desc_buf[BOOT_ENABLE_OFFFSET] = ufs_tegra->boot_enable; |
67 | lun_desc_buf[DESCR_ACCESS_EN_OFFFSET] = | 112 | lun_desc_buf[DESCR_ACCESS_EN_OFFFSET] = |
@@ -103,13 +148,20 @@ int validate_bootlun_en_id_value(struct ufs_hba *hba, u32 bootlun_en_id) | |||
103 | return 0; | 148 | return 0; |
104 | } | 149 | } |
105 | 150 | ||
106 | int validate_desc_header(struct ufs_hba *hba, u8 *lun_desc_buf) | 151 | static int validate_desc_header(struct ufs_hba *hba, |
152 | u8 *lun_desc_buf, | ||
153 | u16 spec_version) | ||
107 | { | 154 | { |
108 | int i, err = 0; | 155 | int i, err = 0; |
109 | u8 desc_param; | 156 | u8 desc_param; |
157 | u8 desc_hdr_size, unit_desc_size; | ||
158 | |||
159 | desc_hdr_size = get_config_desc_hdr_size(spec_version); | ||
160 | unit_desc_size = get_unit_desc_size(spec_version); | ||
110 | 161 | ||
111 | #define GET_PARAM_VAL(i, offset) \ | 162 | #define GET_PARAM_VAL(i, offset) \ |
112 | ((lun_desc_buf + (i+1)*(UNIT_DESC_SIZE))[(offset)]) | 163 | ((lun_desc_buf + desc_hdr_size + \ |
164 | (i * unit_desc_size))[(offset)]) | ||
113 | 165 | ||
114 | if (lun_desc_buf == NULL) { | 166 | if (lun_desc_buf == NULL) { |
115 | dev_err(hba->dev, "lun_desc_buf is null\n"); | 167 | dev_err(hba->dev, "lun_desc_buf is null\n"); |
@@ -198,7 +250,6 @@ int validate_desc_header(struct ufs_hba *hba, u8 *lun_desc_buf) | |||
198 | } | 250 | } |
199 | 251 | ||
200 | #undef GET_PARAM_VAL | 252 | #undef GET_PARAM_VAL |
201 | |||
202 | return err; | 253 | return err; |
203 | } | 254 | } |
204 | 255 | ||
@@ -224,6 +275,8 @@ static ssize_t program_lun_debugfs_write(struct file *file, | |||
224 | u32 desc_lock; | 275 | u32 desc_lock; |
225 | struct ufs_hba *hba; | 276 | struct ufs_hba *hba; |
226 | struct ufs_tegra_host *ufs_tegra; | 277 | struct ufs_tegra_host *ufs_tegra; |
278 | u16 spec_version; | ||
279 | u8 desc_size; | ||
227 | 280 | ||
228 | /* | 281 | /* |
229 | * PROGRAM_LUN is set to 1 to trigeer programming of LUNS. | 282 | * PROGRAM_LUN is set to 1 to trigeer programming of LUNS. |
@@ -287,12 +340,19 @@ static ssize_t program_lun_debugfs_write(struct file *file, | |||
287 | goto out; | 340 | goto out; |
288 | } | 341 | } |
289 | 342 | ||
343 | if (ufs_get_device_specversion(hba, &spec_version)) { | ||
344 | dev_err(hba->dev, "%s: %d" | ||
345 | " Read Specversion failed\n", __func__, __LINE__); | ||
346 | goto out; | ||
347 | } | ||
348 | |||
290 | /* Populate Config Desc Header */ | 349 | /* Populate Config Desc Header */ |
291 | populate_desc_header(ufs_tegra); | 350 | populate_desc_header(ufs_tegra, spec_version); |
292 | 351 | ||
293 | /* Print descriptor array created */ | 352 | /* Print descriptor array created */ |
294 | dev_info(hba->dev, "Configuration Descriptor array:\n"); | 353 | dev_info(hba->dev, "Configuration Descriptor array:\n"); |
295 | for (i = 0; i < CONFIG_DESC_SIZE; i++) { | 354 | desc_size = get_config_desc_size(spec_version); |
355 | for (i = 0; i < desc_size; i++) { | ||
296 | if ((i%16 == 0) && i) | 356 | if ((i%16 == 0) && i) |
297 | pr_info("\n"); | 357 | pr_info("\n"); |
298 | pr_cont("0x%02x ", | 358 | pr_cont("0x%02x ", |
@@ -300,7 +360,8 @@ static ssize_t program_lun_debugfs_write(struct file *file, | |||
300 | } | 360 | } |
301 | 361 | ||
302 | /* Validate unit desc data given by user */ | 362 | /* Validate unit desc data given by user */ |
303 | err = validate_desc_header(hba, ufs_tegra->lun_desc_buf); | 363 | err = validate_desc_header(hba, |
364 | ufs_tegra->lun_desc_buf, spec_version); | ||
304 | if (err) { | 365 | if (err) { |
305 | dev_err(hba->dev, | 366 | dev_err(hba->dev, |
306 | "%s: Descriptor Valdiation Failed\n", __func__); | 367 | "%s: Descriptor Valdiation Failed\n", __func__); |
@@ -570,6 +631,8 @@ void debugfs_provision_init(struct ufs_hba *hba, struct dentry *device_root) | |||
570 | struct ufs_tegra_host *ufs_tegra = (struct ufs_tegra_host *)hba->priv; | 631 | struct ufs_tegra_host *ufs_tegra = (struct ufs_tegra_host *)hba->priv; |
571 | char lun_name[5]; | 632 | char lun_name[5]; |
572 | int i, err; | 633 | int i, err; |
634 | u16 spec_version; | ||
635 | u8 desc_size, unit_desc_size, config_desc_hdr_size; | ||
573 | 636 | ||
574 | refclk_root = debugfs_create_dir("ufs_refclk", device_root); | 637 | refclk_root = debugfs_create_dir("ufs_refclk", device_root); |
575 | CHECK_NULL(refclk_root); | 638 | CHECK_NULL(refclk_root); |
@@ -585,9 +648,18 @@ void debugfs_provision_init(struct ufs_hba *hba, struct dentry *device_root) | |||
585 | CHECK_NULL(debugfs_create_file("program_bootlun_en_id", 0644, | 648 | CHECK_NULL(debugfs_create_file("program_bootlun_en_id", 0644, |
586 | bootlun_en_id_root, hba, &bootlun_en_id_debugfs_ops)); | 649 | bootlun_en_id_root, hba, &bootlun_en_id_debugfs_ops)); |
587 | 650 | ||
651 | |||
652 | err = ufs_get_device_specversion(hba, &spec_version); | ||
653 | if (err) { | ||
654 | dev_err(hba->dev, "%s: Read Specversion failed\n", __func__); | ||
655 | goto out; | ||
656 | } | ||
657 | |||
658 | desc_size = get_config_desc_size(spec_version); | ||
659 | |||
588 | /* Create debugfs for LUN programming */ | 660 | /* Create debugfs for LUN programming */ |
589 | ufs_tegra->lun_desc_buf = (u8 *)devm_kzalloc(hba->dev, | 661 | ufs_tegra->lun_desc_buf = (u8 *)devm_kzalloc(hba->dev, |
590 | CONFIG_DESC_SIZE, GFP_KERNEL); | 662 | desc_size, GFP_KERNEL); |
591 | if (!ufs_tegra->lun_desc_buf) { | 663 | if (!ufs_tegra->lun_desc_buf) { |
592 | dev_err(hba->dev, | 664 | dev_err(hba->dev, |
593 | "No memory for Configuration Descriptor Array\n"); | 665 | "No memory for Configuration Descriptor Array\n"); |
@@ -604,6 +676,9 @@ void debugfs_provision_init(struct ufs_hba *hba, struct dentry *device_root) | |||
604 | CHECK_NULL(debugfs_create_file("program_lun", 0644, | 676 | CHECK_NULL(debugfs_create_file("program_lun", 0644, |
605 | lun_root, hba, &program_lun_debugfs_ops)); | 677 | lun_root, hba, &program_lun_debugfs_ops)); |
606 | 678 | ||
679 | unit_desc_size = get_unit_desc_size(spec_version); | ||
680 | config_desc_hdr_size = get_config_desc_hdr_size(spec_version); | ||
681 | |||
607 | for (i = 0; i < MAX_LUN_COUNT; i++) { | 682 | for (i = 0; i < MAX_LUN_COUNT; i++) { |
608 | 683 | ||
609 | snprintf(lun_name, sizeof(lun_name), "lun%d", i); | 684 | snprintf(lun_name, sizeof(lun_name), "lun%d", i); |
@@ -616,7 +691,7 @@ void debugfs_provision_init(struct ufs_hba *hba, struct dentry *device_root) | |||
616 | */ | 691 | */ |
617 | err = create_desc_debugfs_nodes(tmp_lun_root, | 692 | err = create_desc_debugfs_nodes(tmp_lun_root, |
618 | ufs_tegra->lun_desc_buf + | 693 | ufs_tegra->lun_desc_buf + |
619 | CONFIG_DESC_HEADER_SIZE + i*UNIT_DESC_SIZE); | 694 | config_desc_hdr_size + i * unit_desc_size); |
620 | if (err) | 695 | if (err) |
621 | goto out; | 696 | goto out; |
622 | } | 697 | } |
diff --git a/drivers/scsi/ufs/ufs-tegra.c b/drivers/scsi/ufs/ufs-tegra.c index d54b27b96..640c6508a 100644 --- a/drivers/scsi/ufs/ufs-tegra.c +++ b/drivers/scsi/ufs/ufs-tegra.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2015-2019, NVIDIA CORPORATION. All rights reserved. | 2 | * Copyright (c) 2015-2022, NVIDIA CORPORATION. All rights reserved. |
3 | * | 3 | * |
4 | * Authors: | 4 | * Authors: |
5 | * VenkataJagadish.p <vjagadish@nvidia.com> | 5 | * VenkataJagadish.p <vjagadish@nvidia.com> |
@@ -117,7 +117,7 @@ static const struct file_operations ufs_tegra_debugfs_ops = { | |||
117 | .release = single_release, | 117 | .release = single_release, |
118 | }; | 118 | }; |
119 | 119 | ||
120 | void ufs_tegra_init_debugfs(struct ufs_hba *hba) | 120 | static int ufs_tegra_init_debugfs(struct ufs_hba *hba) |
121 | { | 121 | { |
122 | struct dentry *device_root; | 122 | struct dentry *device_root; |
123 | struct ufs_tegra_host *ufs_tegra = hba->priv; | 123 | struct ufs_tegra_host *ufs_tegra = hba->priv; |
@@ -127,6 +127,8 @@ void ufs_tegra_init_debugfs(struct ufs_hba *hba) | |||
127 | device_root, hba, &ufs_tegra_debugfs_ops); | 127 | device_root, hba, &ufs_tegra_debugfs_ops); |
128 | if (ufs_tegra->enable_ufs_provisioning) | 128 | if (ufs_tegra->enable_ufs_provisioning) |
129 | debugfs_provision_init(hba, device_root); | 129 | debugfs_provision_init(hba, device_root); |
130 | |||
131 | return 0; | ||
130 | } | 132 | } |
131 | #endif | 133 | #endif |
132 | 134 | ||
@@ -1548,9 +1550,6 @@ static int ufs_tegra_init(struct ufs_hba *hba) | |||
1548 | ufs_tegra_aux_reset_enable(ufs_tegra); | 1550 | ufs_tegra_aux_reset_enable(ufs_tegra); |
1549 | ufs_tegra_ufs_aux_prog(ufs_tegra); | 1551 | ufs_tegra_ufs_aux_prog(ufs_tegra); |
1550 | ufs_tegra_cfg_vendor_registers(hba); | 1552 | ufs_tegra_cfg_vendor_registers(hba); |
1551 | #ifdef CONFIG_DEBUG_FS | ||
1552 | ufs_tegra_init_debugfs(hba); | ||
1553 | #endif | ||
1554 | } | 1553 | } |
1555 | return err; | 1554 | return err; |
1556 | 1555 | ||
@@ -1587,6 +1586,9 @@ static void ufs_tegra_exit(struct ufs_hba *hba) | |||
1587 | struct ufs_hba_variant_ops ufs_hba_tegra_vops = { | 1586 | struct ufs_hba_variant_ops ufs_hba_tegra_vops = { |
1588 | .name = "ufs-tegra", | 1587 | .name = "ufs-tegra", |
1589 | .init = ufs_tegra_init, | 1588 | .init = ufs_tegra_init, |
1589 | #ifdef CONFIG_DEBUG_FS | ||
1590 | .late_init = ufs_tegra_init_debugfs, | ||
1591 | #endif | ||
1590 | .exit = ufs_tegra_exit, | 1592 | .exit = ufs_tegra_exit, |
1591 | .suspend = ufs_tegra_suspend, | 1593 | .suspend = ufs_tegra_suspend, |
1592 | .resume = ufs_tegra_resume, | 1594 | .resume = ufs_tegra_resume, |