ANDROID: scsi: ufs: Make CONFIG_SCSI_UFS_HPB compatible with the GKI

Move the ufshpb_dev member into a new structure such that enabling HPB
does not affect the layout of other members of struct ufs_hba. This change
does not affect the ABI since UFS HPB support is currently disabled.

The only function that allocates a struct ufs_hba instance is
ufshcd_alloc_host() and that function allocates struct ufs_hba dynamically.
Modify that function such that it also allocates memory for the HPB data if
necessary.

Bug: 194163838
Bug: 195507090
Test: Built the kernel with this patch applied and installed it on an Android device.
Change-Id: Ia4c5ba07ae343576373ec116553c5fdee8f75a94
Signed-off-by: Bart Van Assche <bvanassche@google.com>
This commit is contained in:
Bart Van Assche
2021-08-09 11:50:55 -07:00
parent b2cbc7e5aa
commit 82b96336e5
3 changed files with 26 additions and 10 deletions

View File

@@ -9313,7 +9313,7 @@ int ufshcd_alloc_host(struct device *dev, struct ufs_hba **hba_handle)
} }
host = scsi_host_alloc(&ufshcd_driver_template, host = scsi_host_alloc(&ufshcd_driver_template,
sizeof(struct ufs_hba)); sizeof(struct ufs_hba_with_hpb));
if (!host) { if (!host) {
dev_err(dev, "scsi_host_alloc failed\n"); dev_err(dev, "scsi_host_alloc failed\n");
err = -ENOMEM; err = -ENOMEM;

View File

@@ -912,7 +912,8 @@ struct ufs_hba {
bool wb_enabled; bool wb_enabled;
struct delayed_work rpm_dev_flush_recheck_work; struct delayed_work rpm_dev_flush_recheck_work;
#ifdef CONFIG_SCSI_UFS_HPB #if 0
/* This has been moved into struct ufs_hba_with_hpb. */
struct ufshpb_dev_info ufshpb_dev; struct ufshpb_dev_info ufshpb_dev;
#endif #endif
@@ -934,6 +935,17 @@ struct ufs_hba {
ANDROID_KABI_RESERVE(4); ANDROID_KABI_RESERVE(4);
}; };
/*
* Compared to the upstream equivalent, @hpb_dev has been moved from struct
* ufs_hba into struct ufs_hba_with_hpb to satisfy the Android ABI checks.
*/
struct ufs_hba_with_hpb {
struct ufs_hba hba;
#ifdef CONFIG_SCSI_UFS_HPB
struct ufshpb_dev_info hpb_dev;
#endif
};
/* Returns true if clocks can be gated. Otherwise false */ /* Returns true if clocks can be gated. Otherwise false */
static inline bool ufshcd_is_clkgating_allowed(struct ufs_hba *hba) static inline bool ufshcd_is_clkgating_allowed(struct ufs_hba *hba)
{ {

View File

@@ -35,15 +35,20 @@ static struct workqueue_struct *ufshpb_wq;
static void ufshpb_update_active_info(struct ufshpb_lu *hpb, int rgn_idx, static void ufshpb_update_active_info(struct ufshpb_lu *hpb, int rgn_idx,
int srgn_idx); int srgn_idx);
static inline struct ufshpb_dev_info *ufs_hba_to_hpb(struct ufs_hba *hba)
{
return &container_of(hba, struct ufs_hba_with_hpb, hba)->hpb_dev;
}
bool ufshpb_is_allowed(struct ufs_hba *hba) bool ufshpb_is_allowed(struct ufs_hba *hba)
{ {
return !(hba->ufshpb_dev.hpb_disabled); return !(ufs_hba_to_hpb(hba)->hpb_disabled);
} }
/* HPB version 1.0 is called as legacy version. */ /* HPB version 1.0 is called as legacy version. */
bool ufshpb_is_legacy(struct ufs_hba *hba) bool ufshpb_is_legacy(struct ufs_hba *hba)
{ {
return hba->ufshpb_dev.is_legacy; return ufs_hba_to_hpb(hba)->is_legacy;
} }
static struct ufshpb_lu *ufshpb_get_hpb_data(struct scsi_device *sdev) static struct ufshpb_lu *ufshpb_get_hpb_data(struct scsi_device *sdev)
@@ -2743,8 +2748,7 @@ void ufshpb_init_hpb_lu(struct ufs_hba *hba, struct scsi_device *sdev)
if (ret) if (ret)
goto out; goto out;
hpb = ufshpb_alloc_hpb_lu(hba, sdev, &hba->ufshpb_dev, hpb = ufshpb_alloc_hpb_lu(hba, sdev, ufs_hba_to_hpb(hba), &hpb_lu_info);
&hpb_lu_info);
if (!hpb) if (!hpb)
goto out; goto out;
@@ -2753,7 +2757,7 @@ void ufshpb_init_hpb_lu(struct ufs_hba *hba, struct scsi_device *sdev)
out: out:
/* All LUs are initialized */ /* All LUs are initialized */
if (atomic_dec_and_test(&hba->ufshpb_dev.slave_conf_cnt)) if (atomic_dec_and_test(&ufs_hba_to_hpb(hba)->slave_conf_cnt))
ufshpb_hpb_lu_prepared(hba); ufshpb_hpb_lu_prepared(hba);
} }
@@ -2810,7 +2814,7 @@ release_mctx_cache:
void ufshpb_get_geo_info(struct ufs_hba *hba, u8 *geo_buf) void ufshpb_get_geo_info(struct ufs_hba *hba, u8 *geo_buf)
{ {
struct ufshpb_dev_info *hpb_info = &hba->ufshpb_dev; struct ufshpb_dev_info *hpb_info = ufs_hba_to_hpb(hba);
int max_active_rgns = 0; int max_active_rgns = 0;
int hpb_num_lu; int hpb_num_lu;
@@ -2836,7 +2840,7 @@ void ufshpb_get_geo_info(struct ufs_hba *hba, u8 *geo_buf)
void ufshpb_get_dev_info(struct ufs_hba *hba, u8 *desc_buf) void ufshpb_get_dev_info(struct ufs_hba *hba, u8 *desc_buf)
{ {
struct ufshpb_dev_info *hpb_dev_info = &hba->ufshpb_dev; struct ufshpb_dev_info *hpb_dev_info = ufs_hba_to_hpb(hba);
int version, ret; int version, ret;
u32 max_hpb_single_cmd = HPB_MULTI_CHUNK_LOW; u32 max_hpb_single_cmd = HPB_MULTI_CHUNK_LOW;
@@ -2873,7 +2877,7 @@ void ufshpb_get_dev_info(struct ufs_hba *hba, u8 *desc_buf)
void ufshpb_init(struct ufs_hba *hba) void ufshpb_init(struct ufs_hba *hba)
{ {
struct ufshpb_dev_info *hpb_dev_info = &hba->ufshpb_dev; struct ufshpb_dev_info *hpb_dev_info = ufs_hba_to_hpb(hba);
int try; int try;
int ret; int ret;