1// SPDX-License-Identifier: GPL-2.0 2/* 3 * bsg endpoint that supports UPIUs 4 * 5 * Copyright (C) 2018 Western Digital Corporation 6 */ 7#include "ufs_bsg.h" 8 9static int ufs_bsg_get_query_desc_size(struct ufs_hba *hba, int *desc_len, 10 struct utp_upiu_query *qr) 11{ 12 int desc_size = be16_to_cpu(qr->length); 13 int desc_id = qr->idn; 14 15 if (desc_size <= 0) 16 return -EINVAL; 17 18 ufshcd_map_desc_id_to_length(hba, desc_id, desc_len); 19 if (!*desc_len) 20 return -EINVAL; 21 22 *desc_len = min_t(int, *desc_len, desc_size); 23 24 return 0; 25} 26 27static int ufs_bsg_verify_query_size(struct ufs_hba *hba, 28 unsigned int request_len, 29 unsigned int reply_len) 30{ 31 int min_req_len = sizeof(struct ufs_bsg_request); 32 int min_rsp_len = sizeof(struct ufs_bsg_reply); 33 34 if (min_req_len > request_len || min_rsp_len > reply_len) { 35 dev_err(hba->dev, "not enough space assigned\n"); 36 return -EINVAL; 37 } 38 39 return 0; 40} 41 42static int ufs_bsg_alloc_desc_buffer(struct ufs_hba *hba, struct bsg_job *job, 43 uint8_t **desc_buff, int *desc_len, 44 enum query_opcode desc_op) 45{ 46 struct ufs_bsg_request *bsg_request = job->request; 47 struct utp_upiu_query *qr; 48 u8 *descp; 49 50 if (desc_op != UPIU_QUERY_OPCODE_WRITE_DESC && 51 desc_op != UPIU_QUERY_OPCODE_READ_DESC) 52 goto out; 53 54 qr = &bsg_request->upiu_req.qr; 55 if (ufs_bsg_get_query_desc_size(hba, desc_len, qr)) { 56 dev_err(hba->dev, "Illegal desc size\n"); 57 return -EINVAL; 58 } 59 60 if (*desc_len > job->request_payload.payload_len) { 61 dev_err(hba->dev, "Illegal desc size\n"); 62 return -EINVAL; 63 } 64 65 descp = kzalloc(*desc_len, GFP_KERNEL); 66 if (!descp) 67 return -ENOMEM; 68 69 if (desc_op == UPIU_QUERY_OPCODE_WRITE_DESC) 70 sg_copy_to_buffer(job->request_payload.sg_list, 71 job->request_payload.sg_cnt, descp, 72 *desc_len); 73 74 *desc_buff = descp; 75 76out: 77 return 0; 78} 79 80static int ufs_bsg_request(struct bsg_job *job) 81{ 82 struct ufs_bsg_request *bsg_request = job->request; 83 struct ufs_bsg_reply *bsg_reply = job->reply; 84 struct ufs_hba *hba = shost_priv(dev_to_shost(job->dev->parent)); 85 unsigned int req_len = job->request_len; 86 unsigned int reply_len = job->reply_len; 87 struct uic_command uc = {}; 88 int msgcode; 89 uint8_t *desc_buff = NULL; 90 int desc_len = 0; 91 enum query_opcode desc_op = UPIU_QUERY_OPCODE_NOP; 92 int ret; 93 94 ret = ufs_bsg_verify_query_size(hba, req_len, reply_len); 95 if (ret) 96 goto out; 97 98 bsg_reply->reply_payload_rcv_len = 0; 99 100 pm_runtime_get_sync(hba->dev); 101 102 msgcode = bsg_request->msgcode; 103 switch (msgcode) { 104 case UPIU_TRANSACTION_QUERY_REQ: 105 desc_op = bsg_request->upiu_req.qr.opcode; 106 ret = ufs_bsg_alloc_desc_buffer(hba, job, &desc_buff, 107 &desc_len, desc_op); 108 if (ret) { 109 pm_runtime_put_sync(hba->dev); 110 goto out; 111 } 112 113 fallthrough; 114 case UPIU_TRANSACTION_NOP_OUT: 115 case UPIU_TRANSACTION_TASK_REQ: 116 ret = ufshcd_exec_raw_upiu_cmd(hba, &bsg_request->upiu_req, 117 &bsg_reply->upiu_rsp, msgcode, 118 desc_buff, &desc_len, desc_op); 119 if (ret) 120 dev_err(hba->dev, 121 "exe raw upiu: error code %d\n", ret); 122 123 break; 124 case UPIU_TRANSACTION_UIC_CMD: 125 memcpy(&uc, &bsg_request->upiu_req.uc, UIC_CMD_SIZE); 126 ret = ufshcd_send_uic_cmd(hba, &uc); 127 if (ret) 128 dev_err(hba->dev, 129 "send uic cmd: error code %d\n", ret); 130 131 memcpy(&bsg_reply->upiu_rsp.uc, &uc, UIC_CMD_SIZE); 132 133 break; 134 default: 135 ret = -ENOTSUPP; 136 dev_err(hba->dev, "unsupported msgcode 0x%x\n", msgcode); 137 138 break; 139 } 140 141 pm_runtime_put_sync(hba->dev); 142 143 if (!desc_buff) 144 goto out; 145 146 if (desc_op == UPIU_QUERY_OPCODE_READ_DESC && desc_len) 147 bsg_reply->reply_payload_rcv_len = 148 sg_copy_from_buffer(job->request_payload.sg_list, 149 job->request_payload.sg_cnt, 150 desc_buff, desc_len); 151 152 kfree(desc_buff); 153 154out: 155 bsg_reply->result = ret; 156 job->reply_len = sizeof(struct ufs_bsg_reply); 157 /* complete the job here only if no error */ 158 if (ret == 0) 159 bsg_job_done(job, ret, bsg_reply->reply_payload_rcv_len); 160 161 return ret; 162} 163 164/** 165 * ufs_bsg_remove - detach and remove the added ufs-bsg node 166 * @hba: per adapter object 167 * 168 * Should be called when unloading the driver. 169 */ 170void ufs_bsg_remove(struct ufs_hba *hba) 171{ 172 struct device *bsg_dev = &hba->bsg_dev; 173 174 if (!hba->bsg_queue) 175 return; 176 177 bsg_remove_queue(hba->bsg_queue); 178 179 device_del(bsg_dev); 180 put_device(bsg_dev); 181} 182 183static inline void ufs_bsg_node_release(struct device *dev) 184{ 185 put_device(dev->parent); 186} 187 188/** 189 * ufs_bsg_probe - Add ufs bsg device node 190 * @hba: per adapter object 191 * 192 * Called during initial loading of the driver, and before scsi_scan_host. 193 */ 194int ufs_bsg_probe(struct ufs_hba *hba) 195{ 196 struct device *bsg_dev = &hba->bsg_dev; 197 struct Scsi_Host *shost = hba->host; 198 struct device *parent = &shost->shost_gendev; 199 struct request_queue *q; 200 int ret; 201 202 device_initialize(bsg_dev); 203 204 bsg_dev->parent = get_device(parent); 205 bsg_dev->release = ufs_bsg_node_release; 206 207 dev_set_name(bsg_dev, "ufs-bsg%u", shost->host_no); 208 209 ret = device_add(bsg_dev); 210 if (ret) 211 goto out; 212 213 q = bsg_setup_queue(bsg_dev, dev_name(bsg_dev), ufs_bsg_request, NULL, 0); 214 if (IS_ERR(q)) { 215 ret = PTR_ERR(q); 216 goto out; 217 } 218 219 hba->bsg_queue = q; 220 221 return 0; 222 223out: 224 dev_err(bsg_dev, "fail to initialize a bsg dev %d\n", shost->host_no); 225 put_device(bsg_dev); 226 return ret; 227} 228