Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge patch series "UFS Advanced RPMB"

Bean Huo <beanhuo@iokpp.de> says:

This series of changes is to add support for UFS advanced RPMB in
ufs_bsg. The advanced RPMB application of user space is ufs_utils, the
reference code is at:

https://github.com/beanhuo/ufs-utils-Micron/blob/ufs_arpmb/ufs_arpmb.c.

Changes to ufs_utils will be pushed to:

https://github.com/westerndigitalcorporation/ufs-utils

Link: https://lore.kernel.org/r/20221201140437.549272-1-beanhuo@iokpp.de
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>

+318 -81
+89 -48
drivers/ufs/core/ufs_bsg.c
··· 6 6 */ 7 7 8 8 #include <linux/bsg-lib.h> 9 + #include <linux/dma-mapping.h> 9 10 #include <scsi/scsi.h> 10 11 #include <scsi/scsi_host.h> 11 12 #include "ufs_bsg.h" ··· 27 26 return -EINVAL; 28 27 29 28 *desc_len = min_t(int, *desc_len, desc_size); 30 - 31 - return 0; 32 - } 33 - 34 - static int ufs_bsg_verify_query_size(struct ufs_hba *hba, 35 - unsigned int request_len, 36 - unsigned int reply_len) 37 - { 38 - int min_req_len = sizeof(struct ufs_bsg_request); 39 - int min_rsp_len = sizeof(struct ufs_bsg_reply); 40 - 41 - if (min_req_len > request_len || min_rsp_len > reply_len) { 42 - dev_err(hba->dev, "not enough space assigned\n"); 43 - return -EINVAL; 44 - } 45 29 46 30 return 0; 47 31 } ··· 69 83 return 0; 70 84 } 71 85 86 + static int ufs_bsg_exec_advanced_rpmb_req(struct ufs_hba *hba, struct bsg_job *job) 87 + { 88 + struct ufs_rpmb_request *rpmb_request = job->request; 89 + struct ufs_rpmb_reply *rpmb_reply = job->reply; 90 + struct bsg_buffer *payload = NULL; 91 + enum dma_data_direction dir; 92 + struct scatterlist *sg_list; 93 + int rpmb_req_type; 94 + int sg_cnt; 95 + int ret; 96 + int data_len; 97 + 98 + if (hba->ufs_version < ufshci_version(4, 0) || !hba->dev_info.b_advanced_rpmb_en || 99 + !(hba->capabilities & MASK_EHSLUTRD_SUPPORTED)) 100 + return -EINVAL; 101 + 102 + if (rpmb_request->ehs_req.length != 2 || rpmb_request->ehs_req.ehs_type != 1) 103 + return -EINVAL; 104 + 105 + rpmb_req_type = be16_to_cpu(rpmb_request->ehs_req.meta.req_resp_type); 106 + 107 + switch (rpmb_req_type) { 108 + case UFS_RPMB_WRITE_KEY: 109 + case UFS_RPMB_READ_CNT: 110 + case UFS_RPMB_PURGE_ENABLE: 111 + dir = DMA_NONE; 112 + break; 113 + case UFS_RPMB_WRITE: 114 + case UFS_RPMB_SEC_CONF_WRITE: 115 + dir = DMA_TO_DEVICE; 116 + break; 117 + case UFS_RPMB_READ: 118 + case UFS_RPMB_SEC_CONF_READ: 119 + case UFS_RPMB_PURGE_STATUS_READ: 120 + dir = DMA_FROM_DEVICE; 121 + break; 122 + default: 123 + return -EINVAL; 124 + } 125 + 126 + if (dir != DMA_NONE) { 127 + payload = &job->request_payload; 128 + if (!payload || !payload->payload_len || !payload->sg_cnt) 129 + return -EINVAL; 130 + 131 + sg_cnt = dma_map_sg(hba->host->dma_dev, payload->sg_list, payload->sg_cnt, dir); 132 + if (unlikely(!sg_cnt)) 133 + return -ENOMEM; 134 + sg_list = payload->sg_list; 135 + data_len = payload->payload_len; 136 + } 137 + 138 + ret = ufshcd_advanced_rpmb_req_handler(hba, &rpmb_request->bsg_request.upiu_req, 139 + &rpmb_reply->bsg_reply.upiu_rsp, &rpmb_request->ehs_req, 140 + &rpmb_reply->ehs_rsp, sg_cnt, sg_list, dir); 141 + 142 + if (dir != DMA_NONE) { 143 + dma_unmap_sg(hba->host->dma_dev, payload->sg_list, payload->sg_cnt, dir); 144 + 145 + if (!ret) 146 + rpmb_reply->bsg_reply.reply_payload_rcv_len = data_len; 147 + } 148 + 149 + return ret; 150 + } 151 + 72 152 static int ufs_bsg_request(struct bsg_job *job) 73 153 { 74 154 struct ufs_bsg_request *bsg_request = job->request; 75 155 struct ufs_bsg_reply *bsg_reply = job->reply; 76 156 struct ufs_hba *hba = shost_priv(dev_to_shost(job->dev->parent)); 77 - unsigned int req_len = job->request_len; 78 - unsigned int reply_len = job->reply_len; 79 157 struct uic_command uc = {}; 80 158 int msgcode; 81 - uint8_t *desc_buff = NULL; 159 + uint8_t *buff = NULL; 82 160 int desc_len = 0; 83 161 enum query_opcode desc_op = UPIU_QUERY_OPCODE_NOP; 84 162 int ret; 85 - 86 - ret = ufs_bsg_verify_query_size(hba, req_len, reply_len); 87 - if (ret) 88 - goto out; 163 + bool rpmb = false; 89 164 90 165 bsg_reply->reply_payload_rcv_len = 0; 91 166 ··· 156 109 switch (msgcode) { 157 110 case UPIU_TRANSACTION_QUERY_REQ: 158 111 desc_op = bsg_request->upiu_req.qr.opcode; 159 - ret = ufs_bsg_alloc_desc_buffer(hba, job, &desc_buff, 160 - &desc_len, desc_op); 161 - if (ret) { 162 - ufshcd_rpm_put_sync(hba); 112 + ret = ufs_bsg_alloc_desc_buffer(hba, job, &buff, &desc_len, desc_op); 113 + if (ret) 163 114 goto out; 164 - } 165 - 166 115 fallthrough; 167 116 case UPIU_TRANSACTION_NOP_OUT: 168 117 case UPIU_TRANSACTION_TASK_REQ: 169 118 ret = ufshcd_exec_raw_upiu_cmd(hba, &bsg_request->upiu_req, 170 119 &bsg_reply->upiu_rsp, msgcode, 171 - desc_buff, &desc_len, desc_op); 120 + buff, &desc_len, desc_op); 172 121 if (ret) 173 - dev_err(hba->dev, 174 - "exe raw upiu: error code %d\n", ret); 175 - 122 + dev_err(hba->dev, "exe raw upiu: error code %d\n", ret); 123 + else if (desc_op == UPIU_QUERY_OPCODE_READ_DESC && desc_len) { 124 + bsg_reply->reply_payload_rcv_len = 125 + sg_copy_from_buffer(job->request_payload.sg_list, 126 + job->request_payload.sg_cnt, 127 + buff, desc_len); 128 + } 176 129 break; 177 130 case UPIU_TRANSACTION_UIC_CMD: 178 131 memcpy(&uc, &bsg_request->upiu_req.uc, UIC_CMD_SIZE); 179 132 ret = ufshcd_send_uic_cmd(hba, &uc); 180 133 if (ret) 181 - dev_err(hba->dev, 182 - "send uic cmd: error code %d\n", ret); 134 + dev_err(hba->dev, "send uic cmd: error code %d\n", ret); 183 135 184 136 memcpy(&bsg_reply->upiu_rsp.uc, &uc, UIC_CMD_SIZE); 185 137 138 + break; 139 + case UPIU_TRANSACTION_ARPMB_CMD: 140 + rpmb = true; 141 + ret = ufs_bsg_exec_advanced_rpmb_req(hba, job); 142 + if (ret) 143 + dev_err(hba->dev, "ARPMB OP failed: error code %d\n", ret); 186 144 break; 187 145 default: 188 146 ret = -ENOTSUPP; ··· 196 144 break; 197 145 } 198 146 199 - ufshcd_rpm_put_sync(hba); 200 - 201 - if (!desc_buff) 202 - goto out; 203 - 204 - if (desc_op == UPIU_QUERY_OPCODE_READ_DESC && desc_len) 205 - bsg_reply->reply_payload_rcv_len = 206 - sg_copy_from_buffer(job->request_payload.sg_list, 207 - job->request_payload.sg_cnt, 208 - desc_buff, desc_len); 209 - 210 - kfree(desc_buff); 211 - 212 147 out: 148 + ufshcd_rpm_put_sync(hba); 149 + kfree(buff); 213 150 bsg_reply->result = ret; 214 - job->reply_len = sizeof(struct ufs_bsg_reply); 151 + job->reply_len = !rpmb ? sizeof(struct ufs_bsg_reply) : sizeof(struct ufs_rpmb_reply); 215 152 /* complete the job here only if no error */ 216 153 if (ret == 0) 217 154 bsg_job_done(job, ret, bsg_reply->reply_payload_rcv_len);
+148 -30
drivers/ufs/core/ufshcd.c
··· 56 56 /* Query request timeout */ 57 57 #define QUERY_REQ_TIMEOUT 1500 /* 1.5 seconds */ 58 58 59 + /* Advanced RPMB request timeout */ 60 + #define ADVANCED_RPMB_REQ_TIMEOUT 3000 /* 3 seconds */ 61 + 59 62 /* Task management command timeout */ 60 63 #define TM_CMD_TIMEOUT 100 /* msecs */ 61 64 ··· 2402 2399 } 2403 2400 2404 2401 /** 2405 - * ufshcd_map_sg - Map scatter-gather list to prdt 2406 - * @hba: per adapter instance 2407 - * @lrbp: pointer to local reference block 2408 - * 2409 - * Returns 0 in case of success, non-zero value in case of failure 2402 + * ufshcd_sgl_to_prdt - SG list to PRTD (Physical Region Description Table, 4DW format) 2403 + * @hba: per-adapter instance 2404 + * @lrbp: pointer to local reference block 2405 + * @sg_entries: The number of sg lists actually used 2406 + * @sg_list: Pointer to SG list 2410 2407 */ 2411 - static int ufshcd_map_sg(struct ufs_hba *hba, struct ufshcd_lrb *lrbp) 2408 + static void ufshcd_sgl_to_prdt(struct ufs_hba *hba, struct ufshcd_lrb *lrbp, int sg_entries, 2409 + struct scatterlist *sg_list) 2412 2410 { 2413 2411 struct ufshcd_sg_entry *prd_table; 2414 2412 struct scatterlist *sg; 2415 - struct scsi_cmnd *cmd; 2416 - int sg_segments; 2417 2413 int i; 2418 2414 2419 - cmd = lrbp->cmd; 2420 - sg_segments = scsi_dma_map(cmd); 2421 - if (sg_segments < 0) 2422 - return sg_segments; 2423 - 2424 - if (sg_segments) { 2415 + if (sg_entries) { 2425 2416 2426 2417 if (hba->quirks & UFSHCD_QUIRK_PRDT_BYTE_GRAN) 2427 2418 lrbp->utr_descriptor_ptr->prd_table_length = 2428 - cpu_to_le16((sg_segments * 2429 - sizeof(struct ufshcd_sg_entry))); 2419 + cpu_to_le16((sg_entries * sizeof(struct ufshcd_sg_entry))); 2430 2420 else 2431 - lrbp->utr_descriptor_ptr->prd_table_length = 2432 - cpu_to_le16(sg_segments); 2421 + lrbp->utr_descriptor_ptr->prd_table_length = cpu_to_le16(sg_entries); 2433 2422 2434 2423 prd_table = lrbp->ucd_prdt_ptr; 2435 2424 2436 - scsi_for_each_sg(cmd, sg, sg_segments, i) { 2425 + for_each_sg(sg_list, sg, sg_entries, i) { 2437 2426 const unsigned int len = sg_dma_len(sg); 2438 2427 2439 2428 /* ··· 2444 2449 } else { 2445 2450 lrbp->utr_descriptor_ptr->prd_table_length = 0; 2446 2451 } 2452 + } 2453 + 2454 + /** 2455 + * ufshcd_map_sg - Map scatter-gather list to prdt 2456 + * @hba: per adapter instance 2457 + * @lrbp: pointer to local reference block 2458 + * 2459 + * Returns 0 in case of success, non-zero value in case of failure 2460 + */ 2461 + static int ufshcd_map_sg(struct ufs_hba *hba, struct ufshcd_lrb *lrbp) 2462 + { 2463 + struct scsi_cmnd *cmd = lrbp->cmd; 2464 + int sg_segments = scsi_dma_map(cmd); 2465 + 2466 + if (sg_segments < 0) 2467 + return sg_segments; 2468 + 2469 + ufshcd_sgl_to_prdt(hba, lrbp, sg_segments, scsi_sglist(cmd)); 2447 2470 2448 2471 return 0; 2449 2472 } ··· 2509 2496 } 2510 2497 2511 2498 /** 2512 - * ufshcd_prepare_req_desc_hdr() - Fills the requests header 2499 + * ufshcd_prepare_req_desc_hdr - Fill UTP Transfer request descriptor header according to request 2513 2500 * descriptor according to request 2514 2501 * @lrbp: pointer to local reference block 2515 2502 * @upiu_flags: flags required in the header 2516 2503 * @cmd_dir: requests data direction 2504 + * @ehs_length: Total EHS Length (in 32‐bytes units of all Extra Header Segments) 2517 2505 */ 2518 - static void ufshcd_prepare_req_desc_hdr(struct ufshcd_lrb *lrbp, 2519 - u8 *upiu_flags, enum dma_data_direction cmd_dir) 2506 + static void ufshcd_prepare_req_desc_hdr(struct ufshcd_lrb *lrbp, u8 *upiu_flags, 2507 + enum dma_data_direction cmd_dir, int ehs_length) 2520 2508 { 2521 2509 struct utp_transfer_req_desc *req_desc = lrbp->utr_descriptor_ptr; 2522 2510 u32 data_direction; ··· 2536 2522 *upiu_flags = UPIU_CMD_FLAGS_NONE; 2537 2523 } 2538 2524 2539 - dword_0 = data_direction | (lrbp->command_type 2540 - << UPIU_COMMAND_TYPE_OFFSET); 2525 + dword_0 = data_direction | (lrbp->command_type << UPIU_COMMAND_TYPE_OFFSET) | 2526 + ehs_length << 8; 2541 2527 if (lrbp->intr_cmd) 2542 2528 dword_0 |= UTP_REQ_DESC_INT_CMD; 2543 2529 ··· 2592 2578 } 2593 2579 2594 2580 /** 2595 - * ufshcd_prepare_utp_query_req_upiu() - fills the utp_transfer_req_desc, 2596 - * for query requsts 2581 + * ufshcd_prepare_utp_query_req_upiu() - fill the utp_transfer_req_desc for query request 2597 2582 * @hba: UFS hba 2598 2583 * @lrbp: local reference block pointer 2599 2584 * @upiu_flags: flags ··· 2663 2650 else 2664 2651 lrbp->command_type = UTP_CMD_TYPE_UFS_STORAGE; 2665 2652 2666 - ufshcd_prepare_req_desc_hdr(lrbp, &upiu_flags, DMA_NONE); 2653 + ufshcd_prepare_req_desc_hdr(lrbp, &upiu_flags, DMA_NONE, 0); 2667 2654 if (hba->dev_cmd.type == DEV_CMD_TYPE_QUERY) 2668 2655 ufshcd_prepare_utp_query_req_upiu(hba, lrbp, upiu_flags); 2669 2656 else if (hba->dev_cmd.type == DEV_CMD_TYPE_NOP) ··· 2691 2678 lrbp->command_type = UTP_CMD_TYPE_UFS_STORAGE; 2692 2679 2693 2680 if (likely(lrbp->cmd)) { 2694 - ufshcd_prepare_req_desc_hdr(lrbp, &upiu_flags, 2695 - lrbp->cmd->sc_data_direction); 2681 + ufshcd_prepare_req_desc_hdr(lrbp, &upiu_flags, lrbp->cmd->sc_data_direction, 0); 2696 2682 ufshcd_prepare_utp_scsi_cmd_upiu(lrbp, upiu_flags); 2697 2683 } else { 2698 2684 ret = -EINVAL; ··· 2956 2944 err = -EPERM; 2957 2945 dev_err(hba->dev, "%s: Reject UPIU not fully implemented\n", 2958 2946 __func__); 2947 + break; 2948 + case UPIU_TRANSACTION_RESPONSE: 2949 + if (hba->dev_cmd.type != DEV_CMD_TYPE_RPMB) { 2950 + err = -EINVAL; 2951 + dev_err(hba->dev, "%s: unexpected response %x\n", __func__, resp); 2952 + } 2959 2953 break; 2960 2954 default: 2961 2955 err = -EINVAL; ··· 4962 4944 desc_buf[UNIT_DESC_PARAM_LU_WR_PROTECT] == UFS_LU_POWER_ON_WP) 4963 4945 hba->dev_info.is_lu_power_on_wp = true; 4964 4946 4947 + /* In case of RPMB LU, check if advanced RPMB mode is enabled */ 4948 + if (desc_buf[UNIT_DESC_PARAM_UNIT_INDEX] == UFS_UPIU_RPMB_WLUN && 4949 + desc_buf[RPMB_UNIT_DESC_PARAM_REGION_EN] & BIT(4)) 4950 + hba->dev_info.b_advanced_rpmb_en = true; 4951 + 4952 + 4965 4953 kfree(desc_buf); 4966 4954 set_qdepth: 4967 4955 /* ··· 6892 6868 /* update the task tag in the request upiu */ 6893 6869 req_upiu->header.dword_0 |= cpu_to_be32(tag); 6894 6870 6895 - ufshcd_prepare_req_desc_hdr(lrbp, &upiu_flags, DMA_NONE); 6871 + ufshcd_prepare_req_desc_hdr(lrbp, &upiu_flags, DMA_NONE, 0); 6896 6872 6897 6873 /* just copy the upiu request as it is */ 6898 6874 memcpy(lrbp->ucd_req_ptr, req_upiu, sizeof(*lrbp->ucd_req_ptr)); ··· 7013 6989 } 7014 6990 7015 6991 return err; 6992 + } 6993 + 6994 + /** 6995 + * ufshcd_advanced_rpmb_req_handler - handle advanced RPMB request 6996 + * @hba: per adapter instance 6997 + * @req_upiu: upiu request 6998 + * @rsp_upiu: upiu reply 6999 + * @req_ehs: EHS field which contains Advanced RPMB Request Message 7000 + * @rsp_ehs: EHS field which returns Advanced RPMB Response Message 7001 + * @sg_cnt: The number of sg lists actually used 7002 + * @sg_list: Pointer to SG list when DATA IN/OUT UPIU is required in ARPMB operation 7003 + * @dir: DMA direction 7004 + * 7005 + * Returns zero on success, non-zero on failure 7006 + */ 7007 + int ufshcd_advanced_rpmb_req_handler(struct ufs_hba *hba, struct utp_upiu_req *req_upiu, 7008 + struct utp_upiu_req *rsp_upiu, struct ufs_ehs *req_ehs, 7009 + struct ufs_ehs *rsp_ehs, int sg_cnt, struct scatterlist *sg_list, 7010 + enum dma_data_direction dir) 7011 + { 7012 + DECLARE_COMPLETION_ONSTACK(wait); 7013 + const u32 tag = hba->reserved_slot; 7014 + struct ufshcd_lrb *lrbp; 7015 + int err = 0; 7016 + int result; 7017 + u8 upiu_flags; 7018 + u8 *ehs_data; 7019 + u16 ehs_len; 7020 + 7021 + /* Protects use of hba->reserved_slot. */ 7022 + ufshcd_hold(hba, false); 7023 + mutex_lock(&hba->dev_cmd.lock); 7024 + down_read(&hba->clk_scaling_lock); 7025 + 7026 + lrbp = &hba->lrb[tag]; 7027 + WARN_ON(lrbp->cmd); 7028 + lrbp->cmd = NULL; 7029 + lrbp->task_tag = tag; 7030 + lrbp->lun = UFS_UPIU_RPMB_WLUN; 7031 + 7032 + lrbp->intr_cmd = true; 7033 + ufshcd_prepare_lrbp_crypto(NULL, lrbp); 7034 + hba->dev_cmd.type = DEV_CMD_TYPE_RPMB; 7035 + 7036 + /* Advanced RPMB starts from UFS 4.0, so its command type is UTP_CMD_TYPE_UFS_STORAGE */ 7037 + lrbp->command_type = UTP_CMD_TYPE_UFS_STORAGE; 7038 + 7039 + ufshcd_prepare_req_desc_hdr(lrbp, &upiu_flags, dir, 2); 7040 + 7041 + /* update the task tag and LUN in the request upiu */ 7042 + req_upiu->header.dword_0 |= cpu_to_be32(upiu_flags << 16 | UFS_UPIU_RPMB_WLUN << 8 | tag); 7043 + 7044 + /* copy the UPIU(contains CDB) request as it is */ 7045 + memcpy(lrbp->ucd_req_ptr, req_upiu, sizeof(*lrbp->ucd_req_ptr)); 7046 + /* Copy EHS, starting with byte32, immediately after the CDB package */ 7047 + memcpy(lrbp->ucd_req_ptr + 1, req_ehs, sizeof(*req_ehs)); 7048 + 7049 + if (dir != DMA_NONE && sg_list) 7050 + ufshcd_sgl_to_prdt(hba, lrbp, sg_cnt, sg_list); 7051 + 7052 + memset(lrbp->ucd_rsp_ptr, 0, sizeof(struct utp_upiu_rsp)); 7053 + 7054 + hba->dev_cmd.complete = &wait; 7055 + 7056 + ufshcd_send_command(hba, tag); 7057 + 7058 + err = ufshcd_wait_for_dev_cmd(hba, lrbp, ADVANCED_RPMB_REQ_TIMEOUT); 7059 + 7060 + if (!err) { 7061 + /* Just copy the upiu response as it is */ 7062 + memcpy(rsp_upiu, lrbp->ucd_rsp_ptr, sizeof(*rsp_upiu)); 7063 + /* Get the response UPIU result */ 7064 + result = ufshcd_get_rsp_upiu_result(lrbp->ucd_rsp_ptr); 7065 + 7066 + ehs_len = be32_to_cpu(lrbp->ucd_rsp_ptr->header.dword_2) >> 24; 7067 + /* 7068 + * Since the bLength in EHS indicates the total size of the EHS Header and EHS Data 7069 + * in 32 Byte units, the value of the bLength Request/Response for Advanced RPMB 7070 + * Message is 02h 7071 + */ 7072 + if (ehs_len == 2 && rsp_ehs) { 7073 + /* 7074 + * ucd_rsp_ptr points to a buffer with a length of 512 bytes 7075 + * (ALIGNED_UPIU_SIZE = 512), and the EHS data just starts from byte32 7076 + */ 7077 + ehs_data = (u8 *)lrbp->ucd_rsp_ptr + EHS_OFFSET_IN_RESPONSE; 7078 + memcpy(rsp_ehs, ehs_data, ehs_len * 32); 7079 + } 7080 + } 7081 + 7082 + up_read(&hba->clk_scaling_lock); 7083 + mutex_unlock(&hba->dev_cmd.lock); 7084 + ufshcd_release(hba); 7085 + return err ? : result; 7016 7086 } 7017 7087 7018 7088 /**
+46 -2
include/uapi/scsi/scsi_bsg_ufs.h
··· 14 14 */ 15 15 16 16 #define UFS_CDB_SIZE 16 17 - #define UPIU_TRANSACTION_UIC_CMD 0x1F 18 17 /* uic commands are 4DW long, per UFSHCI V2.1 paragraph 5.6.1 */ 19 18 #define UIC_CMD_SIZE (sizeof(__u32) * 4) 19 + 20 + enum ufs_bsg_msg_code { 21 + UPIU_TRANSACTION_UIC_CMD = 0x1F, 22 + UPIU_TRANSACTION_ARPMB_CMD, 23 + }; 24 + 25 + /* UFS RPMB Request Message Types */ 26 + enum ufs_rpmb_op_type { 27 + UFS_RPMB_WRITE_KEY = 0x01, 28 + UFS_RPMB_READ_CNT = 0x02, 29 + UFS_RPMB_WRITE = 0x03, 30 + UFS_RPMB_READ = 0x04, 31 + UFS_RPMB_READ_RESP = 0x05, 32 + UFS_RPMB_SEC_CONF_WRITE = 0x06, 33 + UFS_RPMB_SEC_CONF_READ = 0x07, 34 + UFS_RPMB_PURGE_ENABLE = 0x08, 35 + UFS_RPMB_PURGE_STATUS_READ = 0x09, 36 + }; 20 37 21 38 /** 22 39 * struct utp_upiu_header - UPIU header structure ··· 96 79 }; 97 80 }; 98 81 82 + struct ufs_arpmb_meta { 83 + __u16 req_resp_type; 84 + __u8 nonce[16]; 85 + __u32 write_counter; 86 + __u16 addr_lun; 87 + __u16 block_count; 88 + __u16 result; 89 + } __attribute__((__packed__)); 90 + 91 + struct ufs_ehs { 92 + __u8 length; 93 + __u8 ehs_type; 94 + __u16 ehssub_type; 95 + struct ufs_arpmb_meta meta; 96 + __u8 mac_key[32]; 97 + } __attribute__((__packed__)); 98 + 99 99 /* request (CDB) structure of the sg_io_v4 */ 100 100 struct ufs_bsg_request { 101 101 __u32 msgcode; ··· 129 95 * msg and status fields. The per-msgcode reply structure 130 96 * will contain valid data. 131 97 */ 132 - __u32 result; 98 + int result; 133 99 134 100 /* If there was reply_payload, how much was received? */ 135 101 __u32 reply_payload_rcv_len; 136 102 137 103 struct utp_upiu_req upiu_rsp; 104 + }; 105 + 106 + struct ufs_rpmb_request { 107 + struct ufs_bsg_request bsg_request; 108 + struct ufs_ehs ehs_req; 109 + }; 110 + 111 + struct ufs_rpmb_reply { 112 + struct ufs_bsg_reply bsg_reply; 113 + struct ufs_ehs ehs_rsp; 138 114 }; 139 115 #endif /* UFS_BSG_H */
+29
include/ufs/ufs.h
··· 49 49 */ 50 50 #define UFS_WB_EXCEED_LIFETIME 0x0B 51 51 52 + /* 53 + * In UFS Spec, the Extra Header Segment (EHS) starts from byte 32 in UPIU request/response packet 54 + */ 55 + #define EHS_OFFSET_IN_RESPONSE 32 56 + 52 57 /* Well known logical unit id in LUN field of UPIU */ 53 58 enum { 54 59 UFS_UPIU_REPORT_LUNS_WLUN = 0x81, ··· 215 210 UNIT_DESC_PARAM_HPB_PIN_RGN_START_OFF = 0x25, 216 211 UNIT_DESC_PARAM_HPB_NUM_PIN_RGNS = 0x27, 217 212 UNIT_DESC_PARAM_WB_BUF_ALLOC_UNITS = 0x29, 213 + }; 214 + 215 + /* RPMB Unit descriptor parameters offsets in bytes*/ 216 + enum rpmb_unit_desc_param { 217 + RPMB_UNIT_DESC_PARAM_LEN = 0x0, 218 + RPMB_UNIT_DESC_PARAM_TYPE = 0x1, 219 + RPMB_UNIT_DESC_PARAM_UNIT_INDEX = 0x2, 220 + RPMB_UNIT_DESC_PARAM_LU_ENABLE = 0x3, 221 + RPMB_UNIT_DESC_PARAM_BOOT_LUN_ID = 0x4, 222 + RPMB_UNIT_DESC_PARAM_LU_WR_PROTECT = 0x5, 223 + RPMB_UNIT_DESC_PARAM_LU_Q_DEPTH = 0x6, 224 + RPMB_UNIT_DESC_PARAM_PSA_SENSITIVE = 0x7, 225 + RPMB_UNIT_DESC_PARAM_MEM_TYPE = 0x8, 226 + RPMB_UNIT_DESC_PARAM_REGION_EN = 0x9, 227 + RPMB_UNIT_DESC_PARAM_LOGICAL_BLK_SIZE = 0xA, 228 + RPMB_UNIT_DESC_PARAM_LOGICAL_BLK_COUNT = 0xB, 229 + RPMB_UNIT_DESC_PARAM_REGION0_SIZE = 0x13, 230 + RPMB_UNIT_DESC_PARAM_REGION1_SIZE = 0x14, 231 + RPMB_UNIT_DESC_PARAM_REGION2_SIZE = 0x15, 232 + RPMB_UNIT_DESC_PARAM_REGION3_SIZE = 0x16, 233 + RPMB_UNIT_DESC_PARAM_PROVISIONING_TYPE = 0x17, 234 + RPMB_UNIT_DESC_PARAM_PHY_MEM_RSRC_CNT = 0x18, 218 235 }; 219 236 220 237 /* Device descriptor parameters offsets in bytes*/ ··· 628 601 629 602 bool b_rpm_dev_flush_capable; 630 603 u8 b_presrv_uspc_en; 604 + 605 + bool b_advanced_rpmb_en; 631 606 }; 632 607 633 608 /*
+5 -1
include/ufs/ufshcd.h
··· 30 30 enum dev_cmd_type { 31 31 DEV_CMD_TYPE_NOP = 0x0, 32 32 DEV_CMD_TYPE_QUERY = 0x1, 33 + DEV_CMD_TYPE_RPMB = 0x2, 33 34 }; 34 35 35 36 enum ufs_event_type { ··· 1202 1201 int msgcode, 1203 1202 u8 *desc_buff, int *buff_len, 1204 1203 enum query_opcode desc_op); 1205 - 1204 + int ufshcd_advanced_rpmb_req_handler(struct ufs_hba *hba, struct utp_upiu_req *req_upiu, 1205 + struct utp_upiu_req *rsp_upiu, struct ufs_ehs *ehs_req, 1206 + struct ufs_ehs *ehs_rsp, int sg_cnt, 1207 + struct scatterlist *sg_list, enum dma_data_direction dir); 1206 1208 int ufshcd_wb_toggle(struct ufs_hba *hba, bool enable); 1207 1209 int ufshcd_wb_toggle_buf_flush(struct ufs_hba *hba, bool enable); 1208 1210 int ufshcd_suspend_prepare(struct device *dev);
+1
include/ufs/ufshci.h
··· 63 63 enum { 64 64 MASK_TRANSFER_REQUESTS_SLOTS = 0x0000001F, 65 65 MASK_TASK_MANAGEMENT_REQUEST_SLOTS = 0x00070000, 66 + MASK_EHSLUTRD_SUPPORTED = 0x00400000, 66 67 MASK_AUTO_HIBERN8_SUPPORT = 0x00800000, 67 68 MASK_64_ADDRESSING_SUPPORT = 0x01000000, 68 69 MASK_OUT_OF_ORDER_DATA_DELIVERY_SUPPORT = 0x02000000,