Commit 4b5f4907 authored by Daejun Park's avatar Daejun Park Committed by Martin K. Petersen
Browse files

scsi: ufs: ufshpb: L2P map management for HPB read

Implement L2P map management in HPB.

The HPB divides logical addresses into several regions. A region consists
of several sub-regions. The sub-region is a basic unit where L2P mapping is
managed. The driver loads L2P mapping data of each sub-region. The loaded
sub-region is called active-state. The HPB driver unloads L2P mapping data
as region unit. The unloaded region is called inactive-state.

Sub-region/region candidates to be loaded and unloaded are delivered from
the UFS device. The UFS device delivers the recommended active sub-region
and inactivate region to the driver using sense data. The HPB module
performs L2P mapping management on the host through the delivered
information.

A pinned region is a preset region on the UFS device that is always
in activate-state.

The data structures for map data requests and L2P mappings use the mempool
API, minimizing allocation overhead while avoiding static allocation.

The mininum size of the memory pool used in the HPB is implemented
as a module parameter so that it can be configurable by the user.

To guarantee a minimum memory pool size of 4MB: ufshpb_host_map_kbytes=4096.

The map_work manages active/inactive via 2 "to-do" lists:

 - hpb->lh_inact_rgn: regions to be inactivated
 - hpb->lh_act_srgn: subregions to be activated

These lists are maintained on I/O completion.

[mkp: switch to REQ_OP_DRV_*]

Link: https://lore.kernel.org/r/20210712085859epcms2p36e420f19564f6cd0c4a45d54949619eb@epcms2p3


Tested-by: default avatarBean Huo <beanhuo@micron.com>
Tested-by: default avatarCan Guo <cang@codeaurora.org>
Tested-by: default avatarStanley Chu <stanley.chu@mediatek.com>
Reviewed-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Reviewed-by: default avatarBart Van Assche <bvanassche@acm.org>
Reviewed-by: default avatarCan Guo <cang@codeaurora.org>
Reviewed-by: default avatarBean Huo <beanhuo@micron.com>
Reviewed-by: default avatarStanley Chu <stanley.chu@mediatek.com>
Acked-by: default avatarAvri Altman <Avri.Altman@wdc.com>
Signed-off-by: default avatarDaejun Park <daejun7.park@samsung.com>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent f02bc975
Loading
Loading
Loading
Loading
+36 −0
Original line number Diff line number Diff line
@@ -478,6 +478,41 @@ struct utp_cmd_rsp {
	u8 sense_data[UFS_SENSE_SIZE];
};

struct ufshpb_active_field {
	__be16 active_rgn;
	__be16 active_srgn;
};
#define HPB_ACT_FIELD_SIZE 4

/**
 * struct utp_hpb_rsp - Response UPIU structure
 * @residual_transfer_count: Residual transfer count DW-3
 * @reserved1: Reserved double words DW-4 to DW-7
 * @sense_data_len: Sense data length DW-8 U16
 * @desc_type: Descriptor type of sense data
 * @additional_len: Additional length of sense data
 * @hpb_op: HPB operation type
 * @lun: LUN of response UPIU
 * @active_rgn_cnt: Active region count
 * @inactive_rgn_cnt: Inactive region count
 * @hpb_active_field: Recommended to read HPB region and subregion
 * @hpb_inactive_field: To be inactivated HPB region and subregion
 */
struct utp_hpb_rsp {
	__be32 residual_transfer_count;
	__be32 reserved1[4];
	__be16 sense_data_len;
	u8 desc_type;
	u8 additional_len;
	u8 hpb_op;
	u8 lun;
	u8 active_rgn_cnt;
	u8 inactive_rgn_cnt;
	struct ufshpb_active_field hpb_active_field[2];
	__be16 hpb_inactive_field[2];
};
#define UTP_HPB_RSP_SIZE 40

/**
 * struct utp_upiu_rsp - general upiu response structure
 * @header: UPIU header structure DW-0 to DW-2
@@ -488,6 +523,7 @@ struct utp_upiu_rsp {
	struct utp_upiu_header header;
	union {
		struct utp_cmd_rsp sr;
		struct utp_hpb_rsp hr;
		struct utp_upiu_query qr;
	};
};
+4 −0
Original line number Diff line number Diff line
@@ -5148,6 +5148,9 @@ ufshcd_transfer_rsp_status(struct ufs_hba *hba, struct ufshcd_lrb *lrbp)
			    ufshcd_is_exception_event(lrbp->ucd_rsp_ptr))
				/* Flushed in suspend */
				schedule_work(&hba->eeh_work);

			if (scsi_status == SAM_STAT_GOOD)
				ufshpb_rsp_upiu(hba, lrbp);
			break;
		case UPIU_TRANSACTION_REJECT_UPIU:
			/* TODO: handle Reject UPIU Response */
@@ -9390,6 +9393,7 @@ void ufshcd_remove(struct ufs_hba *hba)
	if (hba->sdev_ufs_device)
		ufshcd_rpm_get_sync(hba);
	ufs_bsg_remove(hba);
	ufshpb_remove(hba);
	ufs_sysfs_remove_nodes(hba->dev);
	blk_cleanup_queue(hba->tmf_queue);
	blk_mq_free_tag_set(&hba->tmf_tag_set);