1 // SPDX-License-Identifier: GPL-2.0
4 #include <scsi/scsi_ioctl.h>
5 #include <scsi/scsi_cmnd.h>
6 #include <scsi/scsi_device.h>
10 #define uptr64(val) ((void __user *)(uintptr_t)(val))
12 static int scsi_bsg_sg_io_fn(struct request_queue
*q
, struct sg_io_v4
*hdr
,
13 bool open_for_write
, unsigned int timeout
)
15 struct scsi_cmnd
*scmd
;
20 if (hdr
->protocol
!= BSG_PROTOCOL_SCSI
||
21 hdr
->subprotocol
!= BSG_SUB_PROTOCOL_SCSI_CMD
)
23 if (hdr
->dout_xfer_len
&& hdr
->din_xfer_len
) {
24 pr_warn_once("BIDI support in bsg has been removed.\n");
28 rq
= scsi_alloc_request(q
, hdr
->dout_xfer_len
?
29 REQ_OP_DRV_OUT
: REQ_OP_DRV_IN
, 0);
32 rq
->timeout
= timeout
;
34 scmd
= blk_mq_rq_to_pdu(rq
);
35 scmd
->cmd_len
= hdr
->request_len
;
36 if (scmd
->cmd_len
> sizeof(scmd
->cmnd
)) {
42 if (copy_from_user(scmd
->cmnd
, uptr64(hdr
->request
), scmd
->cmd_len
))
45 if (!scsi_cmd_allowed(scmd
->cmnd
, open_for_write
))
49 if (hdr
->dout_xfer_len
) {
50 ret
= blk_rq_map_user(rq
->q
, rq
, NULL
, uptr64(hdr
->dout_xferp
),
51 hdr
->dout_xfer_len
, GFP_KERNEL
);
52 } else if (hdr
->din_xfer_len
) {
53 ret
= blk_rq_map_user(rq
->q
, rq
, NULL
, uptr64(hdr
->din_xferp
),
54 hdr
->din_xfer_len
, GFP_KERNEL
);
61 blk_execute_rq(rq
, !(hdr
->flags
& BSG_FLAG_Q_AT_TAIL
));
64 * fill in all the output members
66 hdr
->device_status
= scmd
->result
& 0xff;
67 hdr
->transport_status
= host_byte(scmd
->result
);
68 hdr
->driver_status
= 0;
69 if (scsi_status_is_check_condition(scmd
->result
))
70 hdr
->driver_status
= DRIVER_SENSE
;
72 if (hdr
->device_status
|| hdr
->transport_status
|| hdr
->driver_status
)
73 hdr
->info
|= SG_INFO_CHECK
;
74 hdr
->response_len
= 0;
76 if (scmd
->sense_len
&& hdr
->response
) {
77 int len
= min_t(unsigned int, hdr
->max_response_len
,
80 if (copy_to_user(uptr64(hdr
->response
), scmd
->sense_buffer
,
84 hdr
->response_len
= len
;
87 if (rq_data_dir(rq
) == READ
)
88 hdr
->din_resid
= scmd
->resid_len
;
90 hdr
->dout_resid
= scmd
->resid_len
;
92 blk_rq_unmap_user(bio
);
95 blk_mq_free_request(rq
);
99 struct bsg_device
*scsi_bsg_register_queue(struct scsi_device
*sdev
)
101 return bsg_register_queue(sdev
->request_queue
, &sdev
->sdev_gendev
,
102 dev_name(&sdev
->sdev_gendev
), scsi_bsg_sg_io_fn
);