Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * bsg endpoint that supports UPIUs
0004  *
0005  * Copyright (C) 2018 Western Digital Corporation
0006  */
0007 
0008 #include <linux/bsg-lib.h>
0009 #include <scsi/scsi.h>
0010 #include <scsi/scsi_host.h>
0011 #include "ufs_bsg.h"
0012 #include <ufs/ufshcd.h>
0013 #include "ufshcd-priv.h"
0014 
0015 static int ufs_bsg_get_query_desc_size(struct ufs_hba *hba, int *desc_len,
0016                        struct utp_upiu_query *qr)
0017 {
0018     int desc_size = be16_to_cpu(qr->length);
0019     int desc_id = qr->idn;
0020 
0021     if (desc_size <= 0)
0022         return -EINVAL;
0023 
0024     ufshcd_map_desc_id_to_length(hba, desc_id, desc_len);
0025     if (!*desc_len)
0026         return -EINVAL;
0027 
0028     *desc_len = min_t(int, *desc_len, desc_size);
0029 
0030     return 0;
0031 }
0032 
0033 static int ufs_bsg_verify_query_size(struct ufs_hba *hba,
0034                      unsigned int request_len,
0035                      unsigned int reply_len)
0036 {
0037     int min_req_len = sizeof(struct ufs_bsg_request);
0038     int min_rsp_len = sizeof(struct ufs_bsg_reply);
0039 
0040     if (min_req_len > request_len || min_rsp_len > reply_len) {
0041         dev_err(hba->dev, "not enough space assigned\n");
0042         return -EINVAL;
0043     }
0044 
0045     return 0;
0046 }
0047 
0048 static int ufs_bsg_alloc_desc_buffer(struct ufs_hba *hba, struct bsg_job *job,
0049                      uint8_t **desc_buff, int *desc_len,
0050                      enum query_opcode desc_op)
0051 {
0052     struct ufs_bsg_request *bsg_request = job->request;
0053     struct utp_upiu_query *qr;
0054     u8 *descp;
0055 
0056     if (desc_op != UPIU_QUERY_OPCODE_WRITE_DESC &&
0057         desc_op != UPIU_QUERY_OPCODE_READ_DESC)
0058         goto out;
0059 
0060     qr = &bsg_request->upiu_req.qr;
0061     if (ufs_bsg_get_query_desc_size(hba, desc_len, qr)) {
0062         dev_err(hba->dev, "Illegal desc size\n");
0063         return -EINVAL;
0064     }
0065 
0066     if (*desc_len > job->request_payload.payload_len) {
0067         dev_err(hba->dev, "Illegal desc size\n");
0068         return -EINVAL;
0069     }
0070 
0071     descp = kzalloc(*desc_len, GFP_KERNEL);
0072     if (!descp)
0073         return -ENOMEM;
0074 
0075     if (desc_op == UPIU_QUERY_OPCODE_WRITE_DESC)
0076         sg_copy_to_buffer(job->request_payload.sg_list,
0077                   job->request_payload.sg_cnt, descp,
0078                   *desc_len);
0079 
0080     *desc_buff = descp;
0081 
0082 out:
0083     return 0;
0084 }
0085 
0086 static int ufs_bsg_request(struct bsg_job *job)
0087 {
0088     struct ufs_bsg_request *bsg_request = job->request;
0089     struct ufs_bsg_reply *bsg_reply = job->reply;
0090     struct ufs_hba *hba = shost_priv(dev_to_shost(job->dev->parent));
0091     unsigned int req_len = job->request_len;
0092     unsigned int reply_len = job->reply_len;
0093     struct uic_command uc = {};
0094     int msgcode;
0095     uint8_t *desc_buff = NULL;
0096     int desc_len = 0;
0097     enum query_opcode desc_op = UPIU_QUERY_OPCODE_NOP;
0098     int ret;
0099 
0100     ret = ufs_bsg_verify_query_size(hba, req_len, reply_len);
0101     if (ret)
0102         goto out;
0103 
0104     bsg_reply->reply_payload_rcv_len = 0;
0105 
0106     ufshcd_rpm_get_sync(hba);
0107 
0108     msgcode = bsg_request->msgcode;
0109     switch (msgcode) {
0110     case UPIU_TRANSACTION_QUERY_REQ:
0111         desc_op = bsg_request->upiu_req.qr.opcode;
0112         ret = ufs_bsg_alloc_desc_buffer(hba, job, &desc_buff,
0113                         &desc_len, desc_op);
0114         if (ret) {
0115             ufshcd_rpm_put_sync(hba);
0116             goto out;
0117         }
0118 
0119         fallthrough;
0120     case UPIU_TRANSACTION_NOP_OUT:
0121     case UPIU_TRANSACTION_TASK_REQ:
0122         ret = ufshcd_exec_raw_upiu_cmd(hba, &bsg_request->upiu_req,
0123                            &bsg_reply->upiu_rsp, msgcode,
0124                            desc_buff, &desc_len, desc_op);
0125         if (ret)
0126             dev_err(hba->dev,
0127                 "exe raw upiu: error code %d\n", ret);
0128 
0129         break;
0130     case UPIU_TRANSACTION_UIC_CMD:
0131         memcpy(&uc, &bsg_request->upiu_req.uc, UIC_CMD_SIZE);
0132         ret = ufshcd_send_uic_cmd(hba, &uc);
0133         if (ret)
0134             dev_err(hba->dev,
0135                 "send uic cmd: error code %d\n", ret);
0136 
0137         memcpy(&bsg_reply->upiu_rsp.uc, &uc, UIC_CMD_SIZE);
0138 
0139         break;
0140     default:
0141         ret = -ENOTSUPP;
0142         dev_err(hba->dev, "unsupported msgcode 0x%x\n", msgcode);
0143 
0144         break;
0145     }
0146 
0147     ufshcd_rpm_put_sync(hba);
0148 
0149     if (!desc_buff)
0150         goto out;
0151 
0152     if (desc_op == UPIU_QUERY_OPCODE_READ_DESC && desc_len)
0153         bsg_reply->reply_payload_rcv_len =
0154             sg_copy_from_buffer(job->request_payload.sg_list,
0155                         job->request_payload.sg_cnt,
0156                         desc_buff, desc_len);
0157 
0158     kfree(desc_buff);
0159 
0160 out:
0161     bsg_reply->result = ret;
0162     job->reply_len = sizeof(struct ufs_bsg_reply);
0163     /* complete the job here only if no error */
0164     if (ret == 0)
0165         bsg_job_done(job, ret, bsg_reply->reply_payload_rcv_len);
0166 
0167     return ret;
0168 }
0169 
0170 /**
0171  * ufs_bsg_remove - detach and remove the added ufs-bsg node
0172  * @hba: per adapter object
0173  *
0174  * Should be called when unloading the driver.
0175  */
0176 void ufs_bsg_remove(struct ufs_hba *hba)
0177 {
0178     struct device *bsg_dev = &hba->bsg_dev;
0179 
0180     if (!hba->bsg_queue)
0181         return;
0182 
0183     bsg_remove_queue(hba->bsg_queue);
0184 
0185     device_del(bsg_dev);
0186     put_device(bsg_dev);
0187 }
0188 
0189 static inline void ufs_bsg_node_release(struct device *dev)
0190 {
0191     put_device(dev->parent);
0192 }
0193 
0194 /**
0195  * ufs_bsg_probe - Add ufs bsg device node
0196  * @hba: per adapter object
0197  *
0198  * Called during initial loading of the driver, and before scsi_scan_host.
0199  */
0200 int ufs_bsg_probe(struct ufs_hba *hba)
0201 {
0202     struct device *bsg_dev = &hba->bsg_dev;
0203     struct Scsi_Host *shost = hba->host;
0204     struct device *parent = &shost->shost_gendev;
0205     struct request_queue *q;
0206     int ret;
0207 
0208     device_initialize(bsg_dev);
0209 
0210     bsg_dev->parent = get_device(parent);
0211     bsg_dev->release = ufs_bsg_node_release;
0212 
0213     dev_set_name(bsg_dev, "ufs-bsg%u", shost->host_no);
0214 
0215     ret = device_add(bsg_dev);
0216     if (ret)
0217         goto out;
0218 
0219     q = bsg_setup_queue(bsg_dev, dev_name(bsg_dev), ufs_bsg_request, NULL, 0);
0220     if (IS_ERR(q)) {
0221         ret = PTR_ERR(q);
0222         goto out;
0223     }
0224 
0225     hba->bsg_queue = q;
0226 
0227     return 0;
0228 
0229 out:
0230     dev_err(bsg_dev, "fail to initialize a bsg dev %d\n", shost->host_no);
0231     put_device(bsg_dev);
0232     return ret;
0233 }