1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun /* Target based USB-Gadget
3*4882a593Smuzhiyun *
4*4882a593Smuzhiyun * UAS protocol handling, target callbacks, configfs handling,
5*4882a593Smuzhiyun * BBB (USB Mass Storage Class Bulk-Only (BBB) and Transport protocol handling.
6*4882a593Smuzhiyun *
7*4882a593Smuzhiyun * Author: Sebastian Andrzej Siewior <bigeasy at linutronix dot de>
8*4882a593Smuzhiyun */
9*4882a593Smuzhiyun #include <linux/kernel.h>
10*4882a593Smuzhiyun #include <linux/module.h>
11*4882a593Smuzhiyun #include <linux/types.h>
12*4882a593Smuzhiyun #include <linux/string.h>
13*4882a593Smuzhiyun #include <linux/configfs.h>
14*4882a593Smuzhiyun #include <linux/ctype.h>
15*4882a593Smuzhiyun #include <linux/usb/ch9.h>
16*4882a593Smuzhiyun #include <linux/usb/composite.h>
17*4882a593Smuzhiyun #include <linux/usb/gadget.h>
18*4882a593Smuzhiyun #include <linux/usb/storage.h>
19*4882a593Smuzhiyun #include <scsi/scsi_tcq.h>
20*4882a593Smuzhiyun #include <target/target_core_base.h>
21*4882a593Smuzhiyun #include <target/target_core_fabric.h>
22*4882a593Smuzhiyun #include <asm/unaligned.h>
23*4882a593Smuzhiyun
24*4882a593Smuzhiyun #include "tcm.h"
25*4882a593Smuzhiyun #include "u_tcm.h"
26*4882a593Smuzhiyun #include "configfs.h"
27*4882a593Smuzhiyun
28*4882a593Smuzhiyun #define TPG_INSTANCES 1
29*4882a593Smuzhiyun
30*4882a593Smuzhiyun struct tpg_instance {
31*4882a593Smuzhiyun struct usb_function_instance *func_inst;
32*4882a593Smuzhiyun struct usbg_tpg *tpg;
33*4882a593Smuzhiyun };
34*4882a593Smuzhiyun
35*4882a593Smuzhiyun static struct tpg_instance tpg_instances[TPG_INSTANCES];
36*4882a593Smuzhiyun
37*4882a593Smuzhiyun static DEFINE_MUTEX(tpg_instances_lock);
38*4882a593Smuzhiyun
to_f_uas(struct usb_function * f)39*4882a593Smuzhiyun static inline struct f_uas *to_f_uas(struct usb_function *f)
40*4882a593Smuzhiyun {
41*4882a593Smuzhiyun return container_of(f, struct f_uas, function);
42*4882a593Smuzhiyun }
43*4882a593Smuzhiyun
44*4882a593Smuzhiyun /* Start bot.c code */
45*4882a593Smuzhiyun
bot_enqueue_cmd_cbw(struct f_uas * fu)46*4882a593Smuzhiyun static int bot_enqueue_cmd_cbw(struct f_uas *fu)
47*4882a593Smuzhiyun {
48*4882a593Smuzhiyun int ret;
49*4882a593Smuzhiyun
50*4882a593Smuzhiyun if (fu->flags & USBG_BOT_CMD_PEND)
51*4882a593Smuzhiyun return 0;
52*4882a593Smuzhiyun
53*4882a593Smuzhiyun ret = usb_ep_queue(fu->ep_out, fu->cmd.req, GFP_ATOMIC);
54*4882a593Smuzhiyun if (!ret)
55*4882a593Smuzhiyun fu->flags |= USBG_BOT_CMD_PEND;
56*4882a593Smuzhiyun return ret;
57*4882a593Smuzhiyun }
58*4882a593Smuzhiyun
bot_status_complete(struct usb_ep * ep,struct usb_request * req)59*4882a593Smuzhiyun static void bot_status_complete(struct usb_ep *ep, struct usb_request *req)
60*4882a593Smuzhiyun {
61*4882a593Smuzhiyun struct usbg_cmd *cmd = req->context;
62*4882a593Smuzhiyun struct f_uas *fu = cmd->fu;
63*4882a593Smuzhiyun
64*4882a593Smuzhiyun transport_generic_free_cmd(&cmd->se_cmd, 0);
65*4882a593Smuzhiyun if (req->status < 0) {
66*4882a593Smuzhiyun pr_err("ERR %s(%d)\n", __func__, __LINE__);
67*4882a593Smuzhiyun return;
68*4882a593Smuzhiyun }
69*4882a593Smuzhiyun
70*4882a593Smuzhiyun /* CSW completed, wait for next CBW */
71*4882a593Smuzhiyun bot_enqueue_cmd_cbw(fu);
72*4882a593Smuzhiyun }
73*4882a593Smuzhiyun
bot_enqueue_sense_code(struct f_uas * fu,struct usbg_cmd * cmd)74*4882a593Smuzhiyun static void bot_enqueue_sense_code(struct f_uas *fu, struct usbg_cmd *cmd)
75*4882a593Smuzhiyun {
76*4882a593Smuzhiyun struct bulk_cs_wrap *csw = &fu->bot_status.csw;
77*4882a593Smuzhiyun int ret;
78*4882a593Smuzhiyun unsigned int csw_stat;
79*4882a593Smuzhiyun
80*4882a593Smuzhiyun csw_stat = cmd->csw_code;
81*4882a593Smuzhiyun csw->Tag = cmd->bot_tag;
82*4882a593Smuzhiyun csw->Status = csw_stat;
83*4882a593Smuzhiyun fu->bot_status.req->context = cmd;
84*4882a593Smuzhiyun ret = usb_ep_queue(fu->ep_in, fu->bot_status.req, GFP_ATOMIC);
85*4882a593Smuzhiyun if (ret)
86*4882a593Smuzhiyun pr_err("%s(%d) ERR: %d\n", __func__, __LINE__, ret);
87*4882a593Smuzhiyun }
88*4882a593Smuzhiyun
bot_err_compl(struct usb_ep * ep,struct usb_request * req)89*4882a593Smuzhiyun static void bot_err_compl(struct usb_ep *ep, struct usb_request *req)
90*4882a593Smuzhiyun {
91*4882a593Smuzhiyun struct usbg_cmd *cmd = req->context;
92*4882a593Smuzhiyun struct f_uas *fu = cmd->fu;
93*4882a593Smuzhiyun
94*4882a593Smuzhiyun if (req->status < 0)
95*4882a593Smuzhiyun pr_err("ERR %s(%d)\n", __func__, __LINE__);
96*4882a593Smuzhiyun
97*4882a593Smuzhiyun if (cmd->data_len) {
98*4882a593Smuzhiyun if (cmd->data_len > ep->maxpacket) {
99*4882a593Smuzhiyun req->length = ep->maxpacket;
100*4882a593Smuzhiyun cmd->data_len -= ep->maxpacket;
101*4882a593Smuzhiyun } else {
102*4882a593Smuzhiyun req->length = cmd->data_len;
103*4882a593Smuzhiyun cmd->data_len = 0;
104*4882a593Smuzhiyun }
105*4882a593Smuzhiyun
106*4882a593Smuzhiyun usb_ep_queue(ep, req, GFP_ATOMIC);
107*4882a593Smuzhiyun return;
108*4882a593Smuzhiyun }
109*4882a593Smuzhiyun bot_enqueue_sense_code(fu, cmd);
110*4882a593Smuzhiyun }
111*4882a593Smuzhiyun
bot_send_bad_status(struct usbg_cmd * cmd)112*4882a593Smuzhiyun static void bot_send_bad_status(struct usbg_cmd *cmd)
113*4882a593Smuzhiyun {
114*4882a593Smuzhiyun struct f_uas *fu = cmd->fu;
115*4882a593Smuzhiyun struct bulk_cs_wrap *csw = &fu->bot_status.csw;
116*4882a593Smuzhiyun struct usb_request *req;
117*4882a593Smuzhiyun struct usb_ep *ep;
118*4882a593Smuzhiyun
119*4882a593Smuzhiyun csw->Residue = cpu_to_le32(cmd->data_len);
120*4882a593Smuzhiyun
121*4882a593Smuzhiyun if (cmd->data_len) {
122*4882a593Smuzhiyun if (cmd->is_read) {
123*4882a593Smuzhiyun ep = fu->ep_in;
124*4882a593Smuzhiyun req = fu->bot_req_in;
125*4882a593Smuzhiyun } else {
126*4882a593Smuzhiyun ep = fu->ep_out;
127*4882a593Smuzhiyun req = fu->bot_req_out;
128*4882a593Smuzhiyun }
129*4882a593Smuzhiyun
130*4882a593Smuzhiyun if (cmd->data_len > fu->ep_in->maxpacket) {
131*4882a593Smuzhiyun req->length = ep->maxpacket;
132*4882a593Smuzhiyun cmd->data_len -= ep->maxpacket;
133*4882a593Smuzhiyun } else {
134*4882a593Smuzhiyun req->length = cmd->data_len;
135*4882a593Smuzhiyun cmd->data_len = 0;
136*4882a593Smuzhiyun }
137*4882a593Smuzhiyun req->complete = bot_err_compl;
138*4882a593Smuzhiyun req->context = cmd;
139*4882a593Smuzhiyun req->buf = fu->cmd.buf;
140*4882a593Smuzhiyun usb_ep_queue(ep, req, GFP_KERNEL);
141*4882a593Smuzhiyun } else {
142*4882a593Smuzhiyun bot_enqueue_sense_code(fu, cmd);
143*4882a593Smuzhiyun }
144*4882a593Smuzhiyun }
145*4882a593Smuzhiyun
bot_send_status(struct usbg_cmd * cmd,bool moved_data)146*4882a593Smuzhiyun static int bot_send_status(struct usbg_cmd *cmd, bool moved_data)
147*4882a593Smuzhiyun {
148*4882a593Smuzhiyun struct f_uas *fu = cmd->fu;
149*4882a593Smuzhiyun struct bulk_cs_wrap *csw = &fu->bot_status.csw;
150*4882a593Smuzhiyun int ret;
151*4882a593Smuzhiyun
152*4882a593Smuzhiyun if (cmd->se_cmd.scsi_status == SAM_STAT_GOOD) {
153*4882a593Smuzhiyun if (!moved_data && cmd->data_len) {
154*4882a593Smuzhiyun /*
155*4882a593Smuzhiyun * the host wants to move data, we don't. Fill / empty
156*4882a593Smuzhiyun * the pipe and then send the csw with reside set.
157*4882a593Smuzhiyun */
158*4882a593Smuzhiyun cmd->csw_code = US_BULK_STAT_OK;
159*4882a593Smuzhiyun bot_send_bad_status(cmd);
160*4882a593Smuzhiyun return 0;
161*4882a593Smuzhiyun }
162*4882a593Smuzhiyun
163*4882a593Smuzhiyun csw->Tag = cmd->bot_tag;
164*4882a593Smuzhiyun csw->Residue = cpu_to_le32(0);
165*4882a593Smuzhiyun csw->Status = US_BULK_STAT_OK;
166*4882a593Smuzhiyun fu->bot_status.req->context = cmd;
167*4882a593Smuzhiyun
168*4882a593Smuzhiyun ret = usb_ep_queue(fu->ep_in, fu->bot_status.req, GFP_KERNEL);
169*4882a593Smuzhiyun if (ret)
170*4882a593Smuzhiyun pr_err("%s(%d) ERR: %d\n", __func__, __LINE__, ret);
171*4882a593Smuzhiyun } else {
172*4882a593Smuzhiyun cmd->csw_code = US_BULK_STAT_FAIL;
173*4882a593Smuzhiyun bot_send_bad_status(cmd);
174*4882a593Smuzhiyun }
175*4882a593Smuzhiyun return 0;
176*4882a593Smuzhiyun }
177*4882a593Smuzhiyun
178*4882a593Smuzhiyun /*
179*4882a593Smuzhiyun * Called after command (no data transfer) or after the write (to device)
180*4882a593Smuzhiyun * operation is completed
181*4882a593Smuzhiyun */
bot_send_status_response(struct usbg_cmd * cmd)182*4882a593Smuzhiyun static int bot_send_status_response(struct usbg_cmd *cmd)
183*4882a593Smuzhiyun {
184*4882a593Smuzhiyun bool moved_data = false;
185*4882a593Smuzhiyun
186*4882a593Smuzhiyun if (!cmd->is_read)
187*4882a593Smuzhiyun moved_data = true;
188*4882a593Smuzhiyun return bot_send_status(cmd, moved_data);
189*4882a593Smuzhiyun }
190*4882a593Smuzhiyun
191*4882a593Smuzhiyun /* Read request completed, now we have to send the CSW */
bot_read_compl(struct usb_ep * ep,struct usb_request * req)192*4882a593Smuzhiyun static void bot_read_compl(struct usb_ep *ep, struct usb_request *req)
193*4882a593Smuzhiyun {
194*4882a593Smuzhiyun struct usbg_cmd *cmd = req->context;
195*4882a593Smuzhiyun
196*4882a593Smuzhiyun if (req->status < 0)
197*4882a593Smuzhiyun pr_err("ERR %s(%d)\n", __func__, __LINE__);
198*4882a593Smuzhiyun
199*4882a593Smuzhiyun bot_send_status(cmd, true);
200*4882a593Smuzhiyun }
201*4882a593Smuzhiyun
bot_send_read_response(struct usbg_cmd * cmd)202*4882a593Smuzhiyun static int bot_send_read_response(struct usbg_cmd *cmd)
203*4882a593Smuzhiyun {
204*4882a593Smuzhiyun struct f_uas *fu = cmd->fu;
205*4882a593Smuzhiyun struct se_cmd *se_cmd = &cmd->se_cmd;
206*4882a593Smuzhiyun struct usb_gadget *gadget = fuas_to_gadget(fu);
207*4882a593Smuzhiyun int ret;
208*4882a593Smuzhiyun
209*4882a593Smuzhiyun if (!cmd->data_len) {
210*4882a593Smuzhiyun cmd->csw_code = US_BULK_STAT_PHASE;
211*4882a593Smuzhiyun bot_send_bad_status(cmd);
212*4882a593Smuzhiyun return 0;
213*4882a593Smuzhiyun }
214*4882a593Smuzhiyun
215*4882a593Smuzhiyun if (!gadget->sg_supported) {
216*4882a593Smuzhiyun cmd->data_buf = kmalloc(se_cmd->data_length, GFP_ATOMIC);
217*4882a593Smuzhiyun if (!cmd->data_buf)
218*4882a593Smuzhiyun return -ENOMEM;
219*4882a593Smuzhiyun
220*4882a593Smuzhiyun sg_copy_to_buffer(se_cmd->t_data_sg,
221*4882a593Smuzhiyun se_cmd->t_data_nents,
222*4882a593Smuzhiyun cmd->data_buf,
223*4882a593Smuzhiyun se_cmd->data_length);
224*4882a593Smuzhiyun
225*4882a593Smuzhiyun fu->bot_req_in->buf = cmd->data_buf;
226*4882a593Smuzhiyun } else {
227*4882a593Smuzhiyun fu->bot_req_in->buf = NULL;
228*4882a593Smuzhiyun fu->bot_req_in->num_sgs = se_cmd->t_data_nents;
229*4882a593Smuzhiyun fu->bot_req_in->sg = se_cmd->t_data_sg;
230*4882a593Smuzhiyun }
231*4882a593Smuzhiyun
232*4882a593Smuzhiyun fu->bot_req_in->complete = bot_read_compl;
233*4882a593Smuzhiyun fu->bot_req_in->length = se_cmd->data_length;
234*4882a593Smuzhiyun fu->bot_req_in->context = cmd;
235*4882a593Smuzhiyun ret = usb_ep_queue(fu->ep_in, fu->bot_req_in, GFP_ATOMIC);
236*4882a593Smuzhiyun if (ret)
237*4882a593Smuzhiyun pr_err("%s(%d)\n", __func__, __LINE__);
238*4882a593Smuzhiyun return 0;
239*4882a593Smuzhiyun }
240*4882a593Smuzhiyun
241*4882a593Smuzhiyun static void usbg_data_write_cmpl(struct usb_ep *, struct usb_request *);
242*4882a593Smuzhiyun static int usbg_prepare_w_request(struct usbg_cmd *, struct usb_request *);
243*4882a593Smuzhiyun
bot_send_write_request(struct usbg_cmd * cmd)244*4882a593Smuzhiyun static int bot_send_write_request(struct usbg_cmd *cmd)
245*4882a593Smuzhiyun {
246*4882a593Smuzhiyun struct f_uas *fu = cmd->fu;
247*4882a593Smuzhiyun struct se_cmd *se_cmd = &cmd->se_cmd;
248*4882a593Smuzhiyun struct usb_gadget *gadget = fuas_to_gadget(fu);
249*4882a593Smuzhiyun int ret;
250*4882a593Smuzhiyun
251*4882a593Smuzhiyun init_completion(&cmd->write_complete);
252*4882a593Smuzhiyun cmd->fu = fu;
253*4882a593Smuzhiyun
254*4882a593Smuzhiyun if (!cmd->data_len) {
255*4882a593Smuzhiyun cmd->csw_code = US_BULK_STAT_PHASE;
256*4882a593Smuzhiyun return -EINVAL;
257*4882a593Smuzhiyun }
258*4882a593Smuzhiyun
259*4882a593Smuzhiyun if (!gadget->sg_supported) {
260*4882a593Smuzhiyun cmd->data_buf = kmalloc(se_cmd->data_length, GFP_KERNEL);
261*4882a593Smuzhiyun if (!cmd->data_buf)
262*4882a593Smuzhiyun return -ENOMEM;
263*4882a593Smuzhiyun
264*4882a593Smuzhiyun fu->bot_req_out->buf = cmd->data_buf;
265*4882a593Smuzhiyun } else {
266*4882a593Smuzhiyun fu->bot_req_out->buf = NULL;
267*4882a593Smuzhiyun fu->bot_req_out->num_sgs = se_cmd->t_data_nents;
268*4882a593Smuzhiyun fu->bot_req_out->sg = se_cmd->t_data_sg;
269*4882a593Smuzhiyun }
270*4882a593Smuzhiyun
271*4882a593Smuzhiyun fu->bot_req_out->complete = usbg_data_write_cmpl;
272*4882a593Smuzhiyun fu->bot_req_out->length = se_cmd->data_length;
273*4882a593Smuzhiyun fu->bot_req_out->context = cmd;
274*4882a593Smuzhiyun
275*4882a593Smuzhiyun ret = usbg_prepare_w_request(cmd, fu->bot_req_out);
276*4882a593Smuzhiyun if (ret)
277*4882a593Smuzhiyun goto cleanup;
278*4882a593Smuzhiyun ret = usb_ep_queue(fu->ep_out, fu->bot_req_out, GFP_KERNEL);
279*4882a593Smuzhiyun if (ret)
280*4882a593Smuzhiyun pr_err("%s(%d)\n", __func__, __LINE__);
281*4882a593Smuzhiyun
282*4882a593Smuzhiyun wait_for_completion(&cmd->write_complete);
283*4882a593Smuzhiyun target_execute_cmd(se_cmd);
284*4882a593Smuzhiyun cleanup:
285*4882a593Smuzhiyun return ret;
286*4882a593Smuzhiyun }
287*4882a593Smuzhiyun
288*4882a593Smuzhiyun static int bot_submit_command(struct f_uas *, void *, unsigned int);
289*4882a593Smuzhiyun
bot_cmd_complete(struct usb_ep * ep,struct usb_request * req)290*4882a593Smuzhiyun static void bot_cmd_complete(struct usb_ep *ep, struct usb_request *req)
291*4882a593Smuzhiyun {
292*4882a593Smuzhiyun struct f_uas *fu = req->context;
293*4882a593Smuzhiyun int ret;
294*4882a593Smuzhiyun
295*4882a593Smuzhiyun fu->flags &= ~USBG_BOT_CMD_PEND;
296*4882a593Smuzhiyun
297*4882a593Smuzhiyun if (req->status < 0)
298*4882a593Smuzhiyun return;
299*4882a593Smuzhiyun
300*4882a593Smuzhiyun ret = bot_submit_command(fu, req->buf, req->actual);
301*4882a593Smuzhiyun if (ret)
302*4882a593Smuzhiyun pr_err("%s(%d): %d\n", __func__, __LINE__, ret);
303*4882a593Smuzhiyun }
304*4882a593Smuzhiyun
bot_prepare_reqs(struct f_uas * fu)305*4882a593Smuzhiyun static int bot_prepare_reqs(struct f_uas *fu)
306*4882a593Smuzhiyun {
307*4882a593Smuzhiyun int ret;
308*4882a593Smuzhiyun
309*4882a593Smuzhiyun fu->bot_req_in = usb_ep_alloc_request(fu->ep_in, GFP_KERNEL);
310*4882a593Smuzhiyun if (!fu->bot_req_in)
311*4882a593Smuzhiyun goto err;
312*4882a593Smuzhiyun
313*4882a593Smuzhiyun fu->bot_req_out = usb_ep_alloc_request(fu->ep_out, GFP_KERNEL);
314*4882a593Smuzhiyun if (!fu->bot_req_out)
315*4882a593Smuzhiyun goto err_out;
316*4882a593Smuzhiyun
317*4882a593Smuzhiyun fu->cmd.req = usb_ep_alloc_request(fu->ep_out, GFP_KERNEL);
318*4882a593Smuzhiyun if (!fu->cmd.req)
319*4882a593Smuzhiyun goto err_cmd;
320*4882a593Smuzhiyun
321*4882a593Smuzhiyun fu->bot_status.req = usb_ep_alloc_request(fu->ep_in, GFP_KERNEL);
322*4882a593Smuzhiyun if (!fu->bot_status.req)
323*4882a593Smuzhiyun goto err_sts;
324*4882a593Smuzhiyun
325*4882a593Smuzhiyun fu->bot_status.req->buf = &fu->bot_status.csw;
326*4882a593Smuzhiyun fu->bot_status.req->length = US_BULK_CS_WRAP_LEN;
327*4882a593Smuzhiyun fu->bot_status.req->complete = bot_status_complete;
328*4882a593Smuzhiyun fu->bot_status.csw.Signature = cpu_to_le32(US_BULK_CS_SIGN);
329*4882a593Smuzhiyun
330*4882a593Smuzhiyun fu->cmd.buf = kmalloc(fu->ep_out->maxpacket, GFP_KERNEL);
331*4882a593Smuzhiyun if (!fu->cmd.buf)
332*4882a593Smuzhiyun goto err_buf;
333*4882a593Smuzhiyun
334*4882a593Smuzhiyun fu->cmd.req->complete = bot_cmd_complete;
335*4882a593Smuzhiyun fu->cmd.req->buf = fu->cmd.buf;
336*4882a593Smuzhiyun fu->cmd.req->length = fu->ep_out->maxpacket;
337*4882a593Smuzhiyun fu->cmd.req->context = fu;
338*4882a593Smuzhiyun
339*4882a593Smuzhiyun ret = bot_enqueue_cmd_cbw(fu);
340*4882a593Smuzhiyun if (ret)
341*4882a593Smuzhiyun goto err_queue;
342*4882a593Smuzhiyun return 0;
343*4882a593Smuzhiyun err_queue:
344*4882a593Smuzhiyun kfree(fu->cmd.buf);
345*4882a593Smuzhiyun fu->cmd.buf = NULL;
346*4882a593Smuzhiyun err_buf:
347*4882a593Smuzhiyun usb_ep_free_request(fu->ep_in, fu->bot_status.req);
348*4882a593Smuzhiyun err_sts:
349*4882a593Smuzhiyun usb_ep_free_request(fu->ep_out, fu->cmd.req);
350*4882a593Smuzhiyun fu->cmd.req = NULL;
351*4882a593Smuzhiyun err_cmd:
352*4882a593Smuzhiyun usb_ep_free_request(fu->ep_out, fu->bot_req_out);
353*4882a593Smuzhiyun fu->bot_req_out = NULL;
354*4882a593Smuzhiyun err_out:
355*4882a593Smuzhiyun usb_ep_free_request(fu->ep_in, fu->bot_req_in);
356*4882a593Smuzhiyun fu->bot_req_in = NULL;
357*4882a593Smuzhiyun err:
358*4882a593Smuzhiyun pr_err("BOT: endpoint setup failed\n");
359*4882a593Smuzhiyun return -ENOMEM;
360*4882a593Smuzhiyun }
361*4882a593Smuzhiyun
bot_cleanup_old_alt(struct f_uas * fu)362*4882a593Smuzhiyun static void bot_cleanup_old_alt(struct f_uas *fu)
363*4882a593Smuzhiyun {
364*4882a593Smuzhiyun if (!(fu->flags & USBG_ENABLED))
365*4882a593Smuzhiyun return;
366*4882a593Smuzhiyun
367*4882a593Smuzhiyun usb_ep_disable(fu->ep_in);
368*4882a593Smuzhiyun usb_ep_disable(fu->ep_out);
369*4882a593Smuzhiyun
370*4882a593Smuzhiyun if (!fu->bot_req_in)
371*4882a593Smuzhiyun return;
372*4882a593Smuzhiyun
373*4882a593Smuzhiyun usb_ep_free_request(fu->ep_in, fu->bot_req_in);
374*4882a593Smuzhiyun usb_ep_free_request(fu->ep_out, fu->bot_req_out);
375*4882a593Smuzhiyun usb_ep_free_request(fu->ep_out, fu->cmd.req);
376*4882a593Smuzhiyun usb_ep_free_request(fu->ep_in, fu->bot_status.req);
377*4882a593Smuzhiyun
378*4882a593Smuzhiyun kfree(fu->cmd.buf);
379*4882a593Smuzhiyun
380*4882a593Smuzhiyun fu->bot_req_in = NULL;
381*4882a593Smuzhiyun fu->bot_req_out = NULL;
382*4882a593Smuzhiyun fu->cmd.req = NULL;
383*4882a593Smuzhiyun fu->bot_status.req = NULL;
384*4882a593Smuzhiyun fu->cmd.buf = NULL;
385*4882a593Smuzhiyun }
386*4882a593Smuzhiyun
bot_set_alt(struct f_uas * fu)387*4882a593Smuzhiyun static void bot_set_alt(struct f_uas *fu)
388*4882a593Smuzhiyun {
389*4882a593Smuzhiyun struct usb_function *f = &fu->function;
390*4882a593Smuzhiyun struct usb_gadget *gadget = f->config->cdev->gadget;
391*4882a593Smuzhiyun int ret;
392*4882a593Smuzhiyun
393*4882a593Smuzhiyun fu->flags = USBG_IS_BOT;
394*4882a593Smuzhiyun
395*4882a593Smuzhiyun config_ep_by_speed_and_alt(gadget, f, fu->ep_in, USB_G_ALT_INT_BBB);
396*4882a593Smuzhiyun ret = usb_ep_enable(fu->ep_in);
397*4882a593Smuzhiyun if (ret)
398*4882a593Smuzhiyun goto err_b_in;
399*4882a593Smuzhiyun
400*4882a593Smuzhiyun config_ep_by_speed_and_alt(gadget, f, fu->ep_out, USB_G_ALT_INT_BBB);
401*4882a593Smuzhiyun ret = usb_ep_enable(fu->ep_out);
402*4882a593Smuzhiyun if (ret)
403*4882a593Smuzhiyun goto err_b_out;
404*4882a593Smuzhiyun
405*4882a593Smuzhiyun ret = bot_prepare_reqs(fu);
406*4882a593Smuzhiyun if (ret)
407*4882a593Smuzhiyun goto err_wq;
408*4882a593Smuzhiyun fu->flags |= USBG_ENABLED;
409*4882a593Smuzhiyun pr_info("Using the BOT protocol\n");
410*4882a593Smuzhiyun return;
411*4882a593Smuzhiyun err_wq:
412*4882a593Smuzhiyun usb_ep_disable(fu->ep_out);
413*4882a593Smuzhiyun err_b_out:
414*4882a593Smuzhiyun usb_ep_disable(fu->ep_in);
415*4882a593Smuzhiyun err_b_in:
416*4882a593Smuzhiyun fu->flags = USBG_IS_BOT;
417*4882a593Smuzhiyun }
418*4882a593Smuzhiyun
usbg_bot_setup(struct usb_function * f,const struct usb_ctrlrequest * ctrl)419*4882a593Smuzhiyun static int usbg_bot_setup(struct usb_function *f,
420*4882a593Smuzhiyun const struct usb_ctrlrequest *ctrl)
421*4882a593Smuzhiyun {
422*4882a593Smuzhiyun struct f_uas *fu = to_f_uas(f);
423*4882a593Smuzhiyun struct usb_composite_dev *cdev = f->config->cdev;
424*4882a593Smuzhiyun u16 w_value = le16_to_cpu(ctrl->wValue);
425*4882a593Smuzhiyun u16 w_length = le16_to_cpu(ctrl->wLength);
426*4882a593Smuzhiyun int luns;
427*4882a593Smuzhiyun u8 *ret_lun;
428*4882a593Smuzhiyun
429*4882a593Smuzhiyun switch (ctrl->bRequest) {
430*4882a593Smuzhiyun case US_BULK_GET_MAX_LUN:
431*4882a593Smuzhiyun if (ctrl->bRequestType != (USB_DIR_IN | USB_TYPE_CLASS |
432*4882a593Smuzhiyun USB_RECIP_INTERFACE))
433*4882a593Smuzhiyun return -ENOTSUPP;
434*4882a593Smuzhiyun
435*4882a593Smuzhiyun if (w_length < 1)
436*4882a593Smuzhiyun return -EINVAL;
437*4882a593Smuzhiyun if (w_value != 0)
438*4882a593Smuzhiyun return -EINVAL;
439*4882a593Smuzhiyun luns = atomic_read(&fu->tpg->tpg_port_count);
440*4882a593Smuzhiyun if (!luns) {
441*4882a593Smuzhiyun pr_err("No LUNs configured?\n");
442*4882a593Smuzhiyun return -EINVAL;
443*4882a593Smuzhiyun }
444*4882a593Smuzhiyun /*
445*4882a593Smuzhiyun * If 4 LUNs are present we return 3 i.e. LUN 0..3 can be
446*4882a593Smuzhiyun * accessed. The upper limit is 0xf
447*4882a593Smuzhiyun */
448*4882a593Smuzhiyun luns--;
449*4882a593Smuzhiyun if (luns > 0xf) {
450*4882a593Smuzhiyun pr_info_once("Limiting the number of luns to 16\n");
451*4882a593Smuzhiyun luns = 0xf;
452*4882a593Smuzhiyun }
453*4882a593Smuzhiyun ret_lun = cdev->req->buf;
454*4882a593Smuzhiyun *ret_lun = luns;
455*4882a593Smuzhiyun cdev->req->length = 1;
456*4882a593Smuzhiyun return usb_ep_queue(cdev->gadget->ep0, cdev->req, GFP_ATOMIC);
457*4882a593Smuzhiyun
458*4882a593Smuzhiyun case US_BULK_RESET_REQUEST:
459*4882a593Smuzhiyun /* XXX maybe we should remove previous requests for IN + OUT */
460*4882a593Smuzhiyun bot_enqueue_cmd_cbw(fu);
461*4882a593Smuzhiyun return 0;
462*4882a593Smuzhiyun }
463*4882a593Smuzhiyun return -ENOTSUPP;
464*4882a593Smuzhiyun }
465*4882a593Smuzhiyun
466*4882a593Smuzhiyun /* Start uas.c code */
467*4882a593Smuzhiyun
uasp_cleanup_one_stream(struct f_uas * fu,struct uas_stream * stream)468*4882a593Smuzhiyun static void uasp_cleanup_one_stream(struct f_uas *fu, struct uas_stream *stream)
469*4882a593Smuzhiyun {
470*4882a593Smuzhiyun /* We have either all three allocated or none */
471*4882a593Smuzhiyun if (!stream->req_in)
472*4882a593Smuzhiyun return;
473*4882a593Smuzhiyun
474*4882a593Smuzhiyun usb_ep_free_request(fu->ep_in, stream->req_in);
475*4882a593Smuzhiyun usb_ep_free_request(fu->ep_out, stream->req_out);
476*4882a593Smuzhiyun usb_ep_free_request(fu->ep_status, stream->req_status);
477*4882a593Smuzhiyun
478*4882a593Smuzhiyun stream->req_in = NULL;
479*4882a593Smuzhiyun stream->req_out = NULL;
480*4882a593Smuzhiyun stream->req_status = NULL;
481*4882a593Smuzhiyun }
482*4882a593Smuzhiyun
uasp_free_cmdreq(struct f_uas * fu)483*4882a593Smuzhiyun static void uasp_free_cmdreq(struct f_uas *fu)
484*4882a593Smuzhiyun {
485*4882a593Smuzhiyun usb_ep_free_request(fu->ep_cmd, fu->cmd.req);
486*4882a593Smuzhiyun kfree(fu->cmd.buf);
487*4882a593Smuzhiyun fu->cmd.req = NULL;
488*4882a593Smuzhiyun fu->cmd.buf = NULL;
489*4882a593Smuzhiyun }
490*4882a593Smuzhiyun
uasp_cleanup_old_alt(struct f_uas * fu)491*4882a593Smuzhiyun static void uasp_cleanup_old_alt(struct f_uas *fu)
492*4882a593Smuzhiyun {
493*4882a593Smuzhiyun int i;
494*4882a593Smuzhiyun
495*4882a593Smuzhiyun if (!(fu->flags & USBG_ENABLED))
496*4882a593Smuzhiyun return;
497*4882a593Smuzhiyun
498*4882a593Smuzhiyun usb_ep_disable(fu->ep_in);
499*4882a593Smuzhiyun usb_ep_disable(fu->ep_out);
500*4882a593Smuzhiyun usb_ep_disable(fu->ep_status);
501*4882a593Smuzhiyun usb_ep_disable(fu->ep_cmd);
502*4882a593Smuzhiyun
503*4882a593Smuzhiyun for (i = 0; i < UASP_SS_EP_COMP_NUM_STREAMS; i++)
504*4882a593Smuzhiyun uasp_cleanup_one_stream(fu, &fu->stream[i]);
505*4882a593Smuzhiyun uasp_free_cmdreq(fu);
506*4882a593Smuzhiyun }
507*4882a593Smuzhiyun
508*4882a593Smuzhiyun static void uasp_status_data_cmpl(struct usb_ep *ep, struct usb_request *req);
509*4882a593Smuzhiyun
uasp_prepare_r_request(struct usbg_cmd * cmd)510*4882a593Smuzhiyun static int uasp_prepare_r_request(struct usbg_cmd *cmd)
511*4882a593Smuzhiyun {
512*4882a593Smuzhiyun struct se_cmd *se_cmd = &cmd->se_cmd;
513*4882a593Smuzhiyun struct f_uas *fu = cmd->fu;
514*4882a593Smuzhiyun struct usb_gadget *gadget = fuas_to_gadget(fu);
515*4882a593Smuzhiyun struct uas_stream *stream = cmd->stream;
516*4882a593Smuzhiyun
517*4882a593Smuzhiyun if (!gadget->sg_supported) {
518*4882a593Smuzhiyun cmd->data_buf = kmalloc(se_cmd->data_length, GFP_ATOMIC);
519*4882a593Smuzhiyun if (!cmd->data_buf)
520*4882a593Smuzhiyun return -ENOMEM;
521*4882a593Smuzhiyun
522*4882a593Smuzhiyun sg_copy_to_buffer(se_cmd->t_data_sg,
523*4882a593Smuzhiyun se_cmd->t_data_nents,
524*4882a593Smuzhiyun cmd->data_buf,
525*4882a593Smuzhiyun se_cmd->data_length);
526*4882a593Smuzhiyun
527*4882a593Smuzhiyun stream->req_in->buf = cmd->data_buf;
528*4882a593Smuzhiyun } else {
529*4882a593Smuzhiyun stream->req_in->buf = NULL;
530*4882a593Smuzhiyun stream->req_in->num_sgs = se_cmd->t_data_nents;
531*4882a593Smuzhiyun stream->req_in->sg = se_cmd->t_data_sg;
532*4882a593Smuzhiyun }
533*4882a593Smuzhiyun
534*4882a593Smuzhiyun stream->req_in->is_last = 1;
535*4882a593Smuzhiyun stream->req_in->complete = uasp_status_data_cmpl;
536*4882a593Smuzhiyun stream->req_in->length = se_cmd->data_length;
537*4882a593Smuzhiyun stream->req_in->context = cmd;
538*4882a593Smuzhiyun
539*4882a593Smuzhiyun cmd->state = UASP_SEND_STATUS;
540*4882a593Smuzhiyun return 0;
541*4882a593Smuzhiyun }
542*4882a593Smuzhiyun
uasp_prepare_status(struct usbg_cmd * cmd)543*4882a593Smuzhiyun static void uasp_prepare_status(struct usbg_cmd *cmd)
544*4882a593Smuzhiyun {
545*4882a593Smuzhiyun struct se_cmd *se_cmd = &cmd->se_cmd;
546*4882a593Smuzhiyun struct sense_iu *iu = &cmd->sense_iu;
547*4882a593Smuzhiyun struct uas_stream *stream = cmd->stream;
548*4882a593Smuzhiyun
549*4882a593Smuzhiyun cmd->state = UASP_QUEUE_COMMAND;
550*4882a593Smuzhiyun iu->iu_id = IU_ID_STATUS;
551*4882a593Smuzhiyun iu->tag = cpu_to_be16(cmd->tag);
552*4882a593Smuzhiyun
553*4882a593Smuzhiyun /*
554*4882a593Smuzhiyun * iu->status_qual = cpu_to_be16(STATUS QUALIFIER SAM-4. Where R U?);
555*4882a593Smuzhiyun */
556*4882a593Smuzhiyun iu->len = cpu_to_be16(se_cmd->scsi_sense_length);
557*4882a593Smuzhiyun iu->status = se_cmd->scsi_status;
558*4882a593Smuzhiyun stream->req_status->is_last = 1;
559*4882a593Smuzhiyun stream->req_status->context = cmd;
560*4882a593Smuzhiyun stream->req_status->length = se_cmd->scsi_sense_length + 16;
561*4882a593Smuzhiyun stream->req_status->buf = iu;
562*4882a593Smuzhiyun stream->req_status->complete = uasp_status_data_cmpl;
563*4882a593Smuzhiyun }
564*4882a593Smuzhiyun
uasp_status_data_cmpl(struct usb_ep * ep,struct usb_request * req)565*4882a593Smuzhiyun static void uasp_status_data_cmpl(struct usb_ep *ep, struct usb_request *req)
566*4882a593Smuzhiyun {
567*4882a593Smuzhiyun struct usbg_cmd *cmd = req->context;
568*4882a593Smuzhiyun struct uas_stream *stream = cmd->stream;
569*4882a593Smuzhiyun struct f_uas *fu = cmd->fu;
570*4882a593Smuzhiyun int ret;
571*4882a593Smuzhiyun
572*4882a593Smuzhiyun if (req->status < 0)
573*4882a593Smuzhiyun goto cleanup;
574*4882a593Smuzhiyun
575*4882a593Smuzhiyun switch (cmd->state) {
576*4882a593Smuzhiyun case UASP_SEND_DATA:
577*4882a593Smuzhiyun ret = uasp_prepare_r_request(cmd);
578*4882a593Smuzhiyun if (ret)
579*4882a593Smuzhiyun goto cleanup;
580*4882a593Smuzhiyun ret = usb_ep_queue(fu->ep_in, stream->req_in, GFP_ATOMIC);
581*4882a593Smuzhiyun if (ret)
582*4882a593Smuzhiyun pr_err("%s(%d) => %d\n", __func__, __LINE__, ret);
583*4882a593Smuzhiyun break;
584*4882a593Smuzhiyun
585*4882a593Smuzhiyun case UASP_RECEIVE_DATA:
586*4882a593Smuzhiyun ret = usbg_prepare_w_request(cmd, stream->req_out);
587*4882a593Smuzhiyun if (ret)
588*4882a593Smuzhiyun goto cleanup;
589*4882a593Smuzhiyun ret = usb_ep_queue(fu->ep_out, stream->req_out, GFP_ATOMIC);
590*4882a593Smuzhiyun if (ret)
591*4882a593Smuzhiyun pr_err("%s(%d) => %d\n", __func__, __LINE__, ret);
592*4882a593Smuzhiyun break;
593*4882a593Smuzhiyun
594*4882a593Smuzhiyun case UASP_SEND_STATUS:
595*4882a593Smuzhiyun uasp_prepare_status(cmd);
596*4882a593Smuzhiyun ret = usb_ep_queue(fu->ep_status, stream->req_status,
597*4882a593Smuzhiyun GFP_ATOMIC);
598*4882a593Smuzhiyun if (ret)
599*4882a593Smuzhiyun pr_err("%s(%d) => %d\n", __func__, __LINE__, ret);
600*4882a593Smuzhiyun break;
601*4882a593Smuzhiyun
602*4882a593Smuzhiyun case UASP_QUEUE_COMMAND:
603*4882a593Smuzhiyun transport_generic_free_cmd(&cmd->se_cmd, 0);
604*4882a593Smuzhiyun usb_ep_queue(fu->ep_cmd, fu->cmd.req, GFP_ATOMIC);
605*4882a593Smuzhiyun break;
606*4882a593Smuzhiyun
607*4882a593Smuzhiyun default:
608*4882a593Smuzhiyun BUG();
609*4882a593Smuzhiyun }
610*4882a593Smuzhiyun return;
611*4882a593Smuzhiyun
612*4882a593Smuzhiyun cleanup:
613*4882a593Smuzhiyun transport_generic_free_cmd(&cmd->se_cmd, 0);
614*4882a593Smuzhiyun }
615*4882a593Smuzhiyun
uasp_send_status_response(struct usbg_cmd * cmd)616*4882a593Smuzhiyun static int uasp_send_status_response(struct usbg_cmd *cmd)
617*4882a593Smuzhiyun {
618*4882a593Smuzhiyun struct f_uas *fu = cmd->fu;
619*4882a593Smuzhiyun struct uas_stream *stream = cmd->stream;
620*4882a593Smuzhiyun struct sense_iu *iu = &cmd->sense_iu;
621*4882a593Smuzhiyun
622*4882a593Smuzhiyun iu->tag = cpu_to_be16(cmd->tag);
623*4882a593Smuzhiyun stream->req_status->complete = uasp_status_data_cmpl;
624*4882a593Smuzhiyun stream->req_status->context = cmd;
625*4882a593Smuzhiyun cmd->fu = fu;
626*4882a593Smuzhiyun uasp_prepare_status(cmd);
627*4882a593Smuzhiyun return usb_ep_queue(fu->ep_status, stream->req_status, GFP_ATOMIC);
628*4882a593Smuzhiyun }
629*4882a593Smuzhiyun
uasp_send_read_response(struct usbg_cmd * cmd)630*4882a593Smuzhiyun static int uasp_send_read_response(struct usbg_cmd *cmd)
631*4882a593Smuzhiyun {
632*4882a593Smuzhiyun struct f_uas *fu = cmd->fu;
633*4882a593Smuzhiyun struct uas_stream *stream = cmd->stream;
634*4882a593Smuzhiyun struct sense_iu *iu = &cmd->sense_iu;
635*4882a593Smuzhiyun int ret;
636*4882a593Smuzhiyun
637*4882a593Smuzhiyun cmd->fu = fu;
638*4882a593Smuzhiyun
639*4882a593Smuzhiyun iu->tag = cpu_to_be16(cmd->tag);
640*4882a593Smuzhiyun if (fu->flags & USBG_USE_STREAMS) {
641*4882a593Smuzhiyun
642*4882a593Smuzhiyun ret = uasp_prepare_r_request(cmd);
643*4882a593Smuzhiyun if (ret)
644*4882a593Smuzhiyun goto out;
645*4882a593Smuzhiyun ret = usb_ep_queue(fu->ep_in, stream->req_in, GFP_ATOMIC);
646*4882a593Smuzhiyun if (ret) {
647*4882a593Smuzhiyun pr_err("%s(%d) => %d\n", __func__, __LINE__, ret);
648*4882a593Smuzhiyun kfree(cmd->data_buf);
649*4882a593Smuzhiyun cmd->data_buf = NULL;
650*4882a593Smuzhiyun }
651*4882a593Smuzhiyun
652*4882a593Smuzhiyun } else {
653*4882a593Smuzhiyun
654*4882a593Smuzhiyun iu->iu_id = IU_ID_READ_READY;
655*4882a593Smuzhiyun iu->tag = cpu_to_be16(cmd->tag);
656*4882a593Smuzhiyun
657*4882a593Smuzhiyun stream->req_status->complete = uasp_status_data_cmpl;
658*4882a593Smuzhiyun stream->req_status->context = cmd;
659*4882a593Smuzhiyun
660*4882a593Smuzhiyun cmd->state = UASP_SEND_DATA;
661*4882a593Smuzhiyun stream->req_status->buf = iu;
662*4882a593Smuzhiyun stream->req_status->length = sizeof(struct iu);
663*4882a593Smuzhiyun
664*4882a593Smuzhiyun ret = usb_ep_queue(fu->ep_status, stream->req_status,
665*4882a593Smuzhiyun GFP_ATOMIC);
666*4882a593Smuzhiyun if (ret)
667*4882a593Smuzhiyun pr_err("%s(%d) => %d\n", __func__, __LINE__, ret);
668*4882a593Smuzhiyun }
669*4882a593Smuzhiyun out:
670*4882a593Smuzhiyun return ret;
671*4882a593Smuzhiyun }
672*4882a593Smuzhiyun
uasp_send_write_request(struct usbg_cmd * cmd)673*4882a593Smuzhiyun static int uasp_send_write_request(struct usbg_cmd *cmd)
674*4882a593Smuzhiyun {
675*4882a593Smuzhiyun struct f_uas *fu = cmd->fu;
676*4882a593Smuzhiyun struct se_cmd *se_cmd = &cmd->se_cmd;
677*4882a593Smuzhiyun struct uas_stream *stream = cmd->stream;
678*4882a593Smuzhiyun struct sense_iu *iu = &cmd->sense_iu;
679*4882a593Smuzhiyun int ret;
680*4882a593Smuzhiyun
681*4882a593Smuzhiyun init_completion(&cmd->write_complete);
682*4882a593Smuzhiyun cmd->fu = fu;
683*4882a593Smuzhiyun
684*4882a593Smuzhiyun iu->tag = cpu_to_be16(cmd->tag);
685*4882a593Smuzhiyun
686*4882a593Smuzhiyun if (fu->flags & USBG_USE_STREAMS) {
687*4882a593Smuzhiyun
688*4882a593Smuzhiyun ret = usbg_prepare_w_request(cmd, stream->req_out);
689*4882a593Smuzhiyun if (ret)
690*4882a593Smuzhiyun goto cleanup;
691*4882a593Smuzhiyun ret = usb_ep_queue(fu->ep_out, stream->req_out, GFP_ATOMIC);
692*4882a593Smuzhiyun if (ret)
693*4882a593Smuzhiyun pr_err("%s(%d)\n", __func__, __LINE__);
694*4882a593Smuzhiyun
695*4882a593Smuzhiyun } else {
696*4882a593Smuzhiyun
697*4882a593Smuzhiyun iu->iu_id = IU_ID_WRITE_READY;
698*4882a593Smuzhiyun iu->tag = cpu_to_be16(cmd->tag);
699*4882a593Smuzhiyun
700*4882a593Smuzhiyun stream->req_status->complete = uasp_status_data_cmpl;
701*4882a593Smuzhiyun stream->req_status->context = cmd;
702*4882a593Smuzhiyun
703*4882a593Smuzhiyun cmd->state = UASP_RECEIVE_DATA;
704*4882a593Smuzhiyun stream->req_status->buf = iu;
705*4882a593Smuzhiyun stream->req_status->length = sizeof(struct iu);
706*4882a593Smuzhiyun
707*4882a593Smuzhiyun ret = usb_ep_queue(fu->ep_status, stream->req_status,
708*4882a593Smuzhiyun GFP_ATOMIC);
709*4882a593Smuzhiyun if (ret)
710*4882a593Smuzhiyun pr_err("%s(%d)\n", __func__, __LINE__);
711*4882a593Smuzhiyun }
712*4882a593Smuzhiyun
713*4882a593Smuzhiyun wait_for_completion(&cmd->write_complete);
714*4882a593Smuzhiyun target_execute_cmd(se_cmd);
715*4882a593Smuzhiyun cleanup:
716*4882a593Smuzhiyun return ret;
717*4882a593Smuzhiyun }
718*4882a593Smuzhiyun
719*4882a593Smuzhiyun static int usbg_submit_command(struct f_uas *, void *, unsigned int);
720*4882a593Smuzhiyun
uasp_cmd_complete(struct usb_ep * ep,struct usb_request * req)721*4882a593Smuzhiyun static void uasp_cmd_complete(struct usb_ep *ep, struct usb_request *req)
722*4882a593Smuzhiyun {
723*4882a593Smuzhiyun struct f_uas *fu = req->context;
724*4882a593Smuzhiyun int ret;
725*4882a593Smuzhiyun
726*4882a593Smuzhiyun if (req->status < 0)
727*4882a593Smuzhiyun return;
728*4882a593Smuzhiyun
729*4882a593Smuzhiyun ret = usbg_submit_command(fu, req->buf, req->actual);
730*4882a593Smuzhiyun /*
731*4882a593Smuzhiyun * Once we tune for performance enqueue the command req here again so
732*4882a593Smuzhiyun * we can receive a second command while we processing this one. Pay
733*4882a593Smuzhiyun * attention to properly sync STAUS endpoint with DATA IN + OUT so you
734*4882a593Smuzhiyun * don't break HS.
735*4882a593Smuzhiyun */
736*4882a593Smuzhiyun if (!ret)
737*4882a593Smuzhiyun return;
738*4882a593Smuzhiyun usb_ep_queue(fu->ep_cmd, fu->cmd.req, GFP_ATOMIC);
739*4882a593Smuzhiyun }
740*4882a593Smuzhiyun
uasp_alloc_stream_res(struct f_uas * fu,struct uas_stream * stream)741*4882a593Smuzhiyun static int uasp_alloc_stream_res(struct f_uas *fu, struct uas_stream *stream)
742*4882a593Smuzhiyun {
743*4882a593Smuzhiyun stream->req_in = usb_ep_alloc_request(fu->ep_in, GFP_KERNEL);
744*4882a593Smuzhiyun if (!stream->req_in)
745*4882a593Smuzhiyun goto out;
746*4882a593Smuzhiyun
747*4882a593Smuzhiyun stream->req_out = usb_ep_alloc_request(fu->ep_out, GFP_KERNEL);
748*4882a593Smuzhiyun if (!stream->req_out)
749*4882a593Smuzhiyun goto err_out;
750*4882a593Smuzhiyun
751*4882a593Smuzhiyun stream->req_status = usb_ep_alloc_request(fu->ep_status, GFP_KERNEL);
752*4882a593Smuzhiyun if (!stream->req_status)
753*4882a593Smuzhiyun goto err_sts;
754*4882a593Smuzhiyun
755*4882a593Smuzhiyun return 0;
756*4882a593Smuzhiyun
757*4882a593Smuzhiyun err_sts:
758*4882a593Smuzhiyun usb_ep_free_request(fu->ep_out, stream->req_out);
759*4882a593Smuzhiyun stream->req_out = NULL;
760*4882a593Smuzhiyun err_out:
761*4882a593Smuzhiyun usb_ep_free_request(fu->ep_in, stream->req_in);
762*4882a593Smuzhiyun stream->req_in = NULL;
763*4882a593Smuzhiyun out:
764*4882a593Smuzhiyun return -ENOMEM;
765*4882a593Smuzhiyun }
766*4882a593Smuzhiyun
uasp_alloc_cmd(struct f_uas * fu)767*4882a593Smuzhiyun static int uasp_alloc_cmd(struct f_uas *fu)
768*4882a593Smuzhiyun {
769*4882a593Smuzhiyun fu->cmd.req = usb_ep_alloc_request(fu->ep_cmd, GFP_KERNEL);
770*4882a593Smuzhiyun if (!fu->cmd.req)
771*4882a593Smuzhiyun goto err;
772*4882a593Smuzhiyun
773*4882a593Smuzhiyun fu->cmd.buf = kmalloc(fu->ep_cmd->maxpacket, GFP_KERNEL);
774*4882a593Smuzhiyun if (!fu->cmd.buf)
775*4882a593Smuzhiyun goto err_buf;
776*4882a593Smuzhiyun
777*4882a593Smuzhiyun fu->cmd.req->complete = uasp_cmd_complete;
778*4882a593Smuzhiyun fu->cmd.req->buf = fu->cmd.buf;
779*4882a593Smuzhiyun fu->cmd.req->length = fu->ep_cmd->maxpacket;
780*4882a593Smuzhiyun fu->cmd.req->context = fu;
781*4882a593Smuzhiyun return 0;
782*4882a593Smuzhiyun
783*4882a593Smuzhiyun err_buf:
784*4882a593Smuzhiyun usb_ep_free_request(fu->ep_cmd, fu->cmd.req);
785*4882a593Smuzhiyun err:
786*4882a593Smuzhiyun return -ENOMEM;
787*4882a593Smuzhiyun }
788*4882a593Smuzhiyun
uasp_setup_stream_res(struct f_uas * fu,int max_streams)789*4882a593Smuzhiyun static void uasp_setup_stream_res(struct f_uas *fu, int max_streams)
790*4882a593Smuzhiyun {
791*4882a593Smuzhiyun int i;
792*4882a593Smuzhiyun
793*4882a593Smuzhiyun for (i = 0; i < max_streams; i++) {
794*4882a593Smuzhiyun struct uas_stream *s = &fu->stream[i];
795*4882a593Smuzhiyun
796*4882a593Smuzhiyun s->req_in->stream_id = i + 1;
797*4882a593Smuzhiyun s->req_out->stream_id = i + 1;
798*4882a593Smuzhiyun s->req_status->stream_id = i + 1;
799*4882a593Smuzhiyun }
800*4882a593Smuzhiyun }
801*4882a593Smuzhiyun
uasp_prepare_reqs(struct f_uas * fu)802*4882a593Smuzhiyun static int uasp_prepare_reqs(struct f_uas *fu)
803*4882a593Smuzhiyun {
804*4882a593Smuzhiyun int ret;
805*4882a593Smuzhiyun int i;
806*4882a593Smuzhiyun int max_streams;
807*4882a593Smuzhiyun
808*4882a593Smuzhiyun if (fu->flags & USBG_USE_STREAMS)
809*4882a593Smuzhiyun max_streams = UASP_SS_EP_COMP_NUM_STREAMS;
810*4882a593Smuzhiyun else
811*4882a593Smuzhiyun max_streams = 1;
812*4882a593Smuzhiyun
813*4882a593Smuzhiyun for (i = 0; i < max_streams; i++) {
814*4882a593Smuzhiyun ret = uasp_alloc_stream_res(fu, &fu->stream[i]);
815*4882a593Smuzhiyun if (ret)
816*4882a593Smuzhiyun goto err_cleanup;
817*4882a593Smuzhiyun }
818*4882a593Smuzhiyun
819*4882a593Smuzhiyun ret = uasp_alloc_cmd(fu);
820*4882a593Smuzhiyun if (ret)
821*4882a593Smuzhiyun goto err_free_stream;
822*4882a593Smuzhiyun uasp_setup_stream_res(fu, max_streams);
823*4882a593Smuzhiyun
824*4882a593Smuzhiyun ret = usb_ep_queue(fu->ep_cmd, fu->cmd.req, GFP_ATOMIC);
825*4882a593Smuzhiyun if (ret)
826*4882a593Smuzhiyun goto err_free_stream;
827*4882a593Smuzhiyun
828*4882a593Smuzhiyun return 0;
829*4882a593Smuzhiyun
830*4882a593Smuzhiyun err_free_stream:
831*4882a593Smuzhiyun uasp_free_cmdreq(fu);
832*4882a593Smuzhiyun
833*4882a593Smuzhiyun err_cleanup:
834*4882a593Smuzhiyun if (i) {
835*4882a593Smuzhiyun do {
836*4882a593Smuzhiyun uasp_cleanup_one_stream(fu, &fu->stream[i - 1]);
837*4882a593Smuzhiyun i--;
838*4882a593Smuzhiyun } while (i);
839*4882a593Smuzhiyun }
840*4882a593Smuzhiyun pr_err("UASP: endpoint setup failed\n");
841*4882a593Smuzhiyun return ret;
842*4882a593Smuzhiyun }
843*4882a593Smuzhiyun
uasp_set_alt(struct f_uas * fu)844*4882a593Smuzhiyun static void uasp_set_alt(struct f_uas *fu)
845*4882a593Smuzhiyun {
846*4882a593Smuzhiyun struct usb_function *f = &fu->function;
847*4882a593Smuzhiyun struct usb_gadget *gadget = f->config->cdev->gadget;
848*4882a593Smuzhiyun int ret;
849*4882a593Smuzhiyun
850*4882a593Smuzhiyun fu->flags = USBG_IS_UAS;
851*4882a593Smuzhiyun
852*4882a593Smuzhiyun if (gadget->speed >= USB_SPEED_SUPER)
853*4882a593Smuzhiyun fu->flags |= USBG_USE_STREAMS;
854*4882a593Smuzhiyun
855*4882a593Smuzhiyun config_ep_by_speed_and_alt(gadget, f, fu->ep_in, USB_G_ALT_INT_UAS);
856*4882a593Smuzhiyun ret = usb_ep_enable(fu->ep_in);
857*4882a593Smuzhiyun if (ret)
858*4882a593Smuzhiyun goto err_b_in;
859*4882a593Smuzhiyun
860*4882a593Smuzhiyun config_ep_by_speed_and_alt(gadget, f, fu->ep_out, USB_G_ALT_INT_UAS);
861*4882a593Smuzhiyun ret = usb_ep_enable(fu->ep_out);
862*4882a593Smuzhiyun if (ret)
863*4882a593Smuzhiyun goto err_b_out;
864*4882a593Smuzhiyun
865*4882a593Smuzhiyun config_ep_by_speed_and_alt(gadget, f, fu->ep_cmd, USB_G_ALT_INT_UAS);
866*4882a593Smuzhiyun ret = usb_ep_enable(fu->ep_cmd);
867*4882a593Smuzhiyun if (ret)
868*4882a593Smuzhiyun goto err_cmd;
869*4882a593Smuzhiyun config_ep_by_speed_and_alt(gadget, f, fu->ep_status, USB_G_ALT_INT_UAS);
870*4882a593Smuzhiyun ret = usb_ep_enable(fu->ep_status);
871*4882a593Smuzhiyun if (ret)
872*4882a593Smuzhiyun goto err_status;
873*4882a593Smuzhiyun
874*4882a593Smuzhiyun ret = uasp_prepare_reqs(fu);
875*4882a593Smuzhiyun if (ret)
876*4882a593Smuzhiyun goto err_wq;
877*4882a593Smuzhiyun fu->flags |= USBG_ENABLED;
878*4882a593Smuzhiyun
879*4882a593Smuzhiyun pr_info("Using the UAS protocol\n");
880*4882a593Smuzhiyun return;
881*4882a593Smuzhiyun err_wq:
882*4882a593Smuzhiyun usb_ep_disable(fu->ep_status);
883*4882a593Smuzhiyun err_status:
884*4882a593Smuzhiyun usb_ep_disable(fu->ep_cmd);
885*4882a593Smuzhiyun err_cmd:
886*4882a593Smuzhiyun usb_ep_disable(fu->ep_out);
887*4882a593Smuzhiyun err_b_out:
888*4882a593Smuzhiyun usb_ep_disable(fu->ep_in);
889*4882a593Smuzhiyun err_b_in:
890*4882a593Smuzhiyun fu->flags = 0;
891*4882a593Smuzhiyun }
892*4882a593Smuzhiyun
get_cmd_dir(const unsigned char * cdb)893*4882a593Smuzhiyun static int get_cmd_dir(const unsigned char *cdb)
894*4882a593Smuzhiyun {
895*4882a593Smuzhiyun int ret;
896*4882a593Smuzhiyun
897*4882a593Smuzhiyun switch (cdb[0]) {
898*4882a593Smuzhiyun case READ_6:
899*4882a593Smuzhiyun case READ_10:
900*4882a593Smuzhiyun case READ_12:
901*4882a593Smuzhiyun case READ_16:
902*4882a593Smuzhiyun case INQUIRY:
903*4882a593Smuzhiyun case MODE_SENSE:
904*4882a593Smuzhiyun case MODE_SENSE_10:
905*4882a593Smuzhiyun case SERVICE_ACTION_IN_16:
906*4882a593Smuzhiyun case MAINTENANCE_IN:
907*4882a593Smuzhiyun case PERSISTENT_RESERVE_IN:
908*4882a593Smuzhiyun case SECURITY_PROTOCOL_IN:
909*4882a593Smuzhiyun case ACCESS_CONTROL_IN:
910*4882a593Smuzhiyun case REPORT_LUNS:
911*4882a593Smuzhiyun case READ_BLOCK_LIMITS:
912*4882a593Smuzhiyun case READ_POSITION:
913*4882a593Smuzhiyun case READ_CAPACITY:
914*4882a593Smuzhiyun case READ_TOC:
915*4882a593Smuzhiyun case READ_FORMAT_CAPACITIES:
916*4882a593Smuzhiyun case REQUEST_SENSE:
917*4882a593Smuzhiyun ret = DMA_FROM_DEVICE;
918*4882a593Smuzhiyun break;
919*4882a593Smuzhiyun
920*4882a593Smuzhiyun case WRITE_6:
921*4882a593Smuzhiyun case WRITE_10:
922*4882a593Smuzhiyun case WRITE_12:
923*4882a593Smuzhiyun case WRITE_16:
924*4882a593Smuzhiyun case MODE_SELECT:
925*4882a593Smuzhiyun case MODE_SELECT_10:
926*4882a593Smuzhiyun case WRITE_VERIFY:
927*4882a593Smuzhiyun case WRITE_VERIFY_12:
928*4882a593Smuzhiyun case PERSISTENT_RESERVE_OUT:
929*4882a593Smuzhiyun case MAINTENANCE_OUT:
930*4882a593Smuzhiyun case SECURITY_PROTOCOL_OUT:
931*4882a593Smuzhiyun case ACCESS_CONTROL_OUT:
932*4882a593Smuzhiyun ret = DMA_TO_DEVICE;
933*4882a593Smuzhiyun break;
934*4882a593Smuzhiyun case ALLOW_MEDIUM_REMOVAL:
935*4882a593Smuzhiyun case TEST_UNIT_READY:
936*4882a593Smuzhiyun case SYNCHRONIZE_CACHE:
937*4882a593Smuzhiyun case START_STOP:
938*4882a593Smuzhiyun case ERASE:
939*4882a593Smuzhiyun case REZERO_UNIT:
940*4882a593Smuzhiyun case SEEK_10:
941*4882a593Smuzhiyun case SPACE:
942*4882a593Smuzhiyun case VERIFY:
943*4882a593Smuzhiyun case WRITE_FILEMARKS:
944*4882a593Smuzhiyun ret = DMA_NONE;
945*4882a593Smuzhiyun break;
946*4882a593Smuzhiyun default:
947*4882a593Smuzhiyun #define CMD_DIR_MSG "target: Unknown data direction for SCSI Opcode 0x%02x\n"
948*4882a593Smuzhiyun pr_warn(CMD_DIR_MSG, cdb[0]);
949*4882a593Smuzhiyun #undef CMD_DIR_MSG
950*4882a593Smuzhiyun ret = -EINVAL;
951*4882a593Smuzhiyun }
952*4882a593Smuzhiyun return ret;
953*4882a593Smuzhiyun }
954*4882a593Smuzhiyun
usbg_data_write_cmpl(struct usb_ep * ep,struct usb_request * req)955*4882a593Smuzhiyun static void usbg_data_write_cmpl(struct usb_ep *ep, struct usb_request *req)
956*4882a593Smuzhiyun {
957*4882a593Smuzhiyun struct usbg_cmd *cmd = req->context;
958*4882a593Smuzhiyun struct se_cmd *se_cmd = &cmd->se_cmd;
959*4882a593Smuzhiyun
960*4882a593Smuzhiyun if (req->status < 0) {
961*4882a593Smuzhiyun pr_err("%s() state %d transfer failed\n", __func__, cmd->state);
962*4882a593Smuzhiyun goto cleanup;
963*4882a593Smuzhiyun }
964*4882a593Smuzhiyun
965*4882a593Smuzhiyun if (req->num_sgs == 0) {
966*4882a593Smuzhiyun sg_copy_from_buffer(se_cmd->t_data_sg,
967*4882a593Smuzhiyun se_cmd->t_data_nents,
968*4882a593Smuzhiyun cmd->data_buf,
969*4882a593Smuzhiyun se_cmd->data_length);
970*4882a593Smuzhiyun }
971*4882a593Smuzhiyun
972*4882a593Smuzhiyun complete(&cmd->write_complete);
973*4882a593Smuzhiyun return;
974*4882a593Smuzhiyun
975*4882a593Smuzhiyun cleanup:
976*4882a593Smuzhiyun transport_generic_free_cmd(&cmd->se_cmd, 0);
977*4882a593Smuzhiyun }
978*4882a593Smuzhiyun
usbg_prepare_w_request(struct usbg_cmd * cmd,struct usb_request * req)979*4882a593Smuzhiyun static int usbg_prepare_w_request(struct usbg_cmd *cmd, struct usb_request *req)
980*4882a593Smuzhiyun {
981*4882a593Smuzhiyun struct se_cmd *se_cmd = &cmd->se_cmd;
982*4882a593Smuzhiyun struct f_uas *fu = cmd->fu;
983*4882a593Smuzhiyun struct usb_gadget *gadget = fuas_to_gadget(fu);
984*4882a593Smuzhiyun
985*4882a593Smuzhiyun if (!gadget->sg_supported) {
986*4882a593Smuzhiyun cmd->data_buf = kmalloc(se_cmd->data_length, GFP_ATOMIC);
987*4882a593Smuzhiyun if (!cmd->data_buf)
988*4882a593Smuzhiyun return -ENOMEM;
989*4882a593Smuzhiyun
990*4882a593Smuzhiyun req->buf = cmd->data_buf;
991*4882a593Smuzhiyun } else {
992*4882a593Smuzhiyun req->buf = NULL;
993*4882a593Smuzhiyun req->num_sgs = se_cmd->t_data_nents;
994*4882a593Smuzhiyun req->sg = se_cmd->t_data_sg;
995*4882a593Smuzhiyun }
996*4882a593Smuzhiyun
997*4882a593Smuzhiyun req->is_last = 1;
998*4882a593Smuzhiyun req->complete = usbg_data_write_cmpl;
999*4882a593Smuzhiyun req->length = se_cmd->data_length;
1000*4882a593Smuzhiyun req->context = cmd;
1001*4882a593Smuzhiyun return 0;
1002*4882a593Smuzhiyun }
1003*4882a593Smuzhiyun
usbg_send_status_response(struct se_cmd * se_cmd)1004*4882a593Smuzhiyun static int usbg_send_status_response(struct se_cmd *se_cmd)
1005*4882a593Smuzhiyun {
1006*4882a593Smuzhiyun struct usbg_cmd *cmd = container_of(se_cmd, struct usbg_cmd,
1007*4882a593Smuzhiyun se_cmd);
1008*4882a593Smuzhiyun struct f_uas *fu = cmd->fu;
1009*4882a593Smuzhiyun
1010*4882a593Smuzhiyun if (fu->flags & USBG_IS_BOT)
1011*4882a593Smuzhiyun return bot_send_status_response(cmd);
1012*4882a593Smuzhiyun else
1013*4882a593Smuzhiyun return uasp_send_status_response(cmd);
1014*4882a593Smuzhiyun }
1015*4882a593Smuzhiyun
usbg_send_write_request(struct se_cmd * se_cmd)1016*4882a593Smuzhiyun static int usbg_send_write_request(struct se_cmd *se_cmd)
1017*4882a593Smuzhiyun {
1018*4882a593Smuzhiyun struct usbg_cmd *cmd = container_of(se_cmd, struct usbg_cmd,
1019*4882a593Smuzhiyun se_cmd);
1020*4882a593Smuzhiyun struct f_uas *fu = cmd->fu;
1021*4882a593Smuzhiyun
1022*4882a593Smuzhiyun if (fu->flags & USBG_IS_BOT)
1023*4882a593Smuzhiyun return bot_send_write_request(cmd);
1024*4882a593Smuzhiyun else
1025*4882a593Smuzhiyun return uasp_send_write_request(cmd);
1026*4882a593Smuzhiyun }
1027*4882a593Smuzhiyun
usbg_send_read_response(struct se_cmd * se_cmd)1028*4882a593Smuzhiyun static int usbg_send_read_response(struct se_cmd *se_cmd)
1029*4882a593Smuzhiyun {
1030*4882a593Smuzhiyun struct usbg_cmd *cmd = container_of(se_cmd, struct usbg_cmd,
1031*4882a593Smuzhiyun se_cmd);
1032*4882a593Smuzhiyun struct f_uas *fu = cmd->fu;
1033*4882a593Smuzhiyun
1034*4882a593Smuzhiyun if (fu->flags & USBG_IS_BOT)
1035*4882a593Smuzhiyun return bot_send_read_response(cmd);
1036*4882a593Smuzhiyun else
1037*4882a593Smuzhiyun return uasp_send_read_response(cmd);
1038*4882a593Smuzhiyun }
1039*4882a593Smuzhiyun
usbg_cmd_work(struct work_struct * work)1040*4882a593Smuzhiyun static void usbg_cmd_work(struct work_struct *work)
1041*4882a593Smuzhiyun {
1042*4882a593Smuzhiyun struct usbg_cmd *cmd = container_of(work, struct usbg_cmd, work);
1043*4882a593Smuzhiyun struct se_cmd *se_cmd;
1044*4882a593Smuzhiyun struct tcm_usbg_nexus *tv_nexus;
1045*4882a593Smuzhiyun struct usbg_tpg *tpg;
1046*4882a593Smuzhiyun int dir, flags = (TARGET_SCF_UNKNOWN_SIZE | TARGET_SCF_ACK_KREF);
1047*4882a593Smuzhiyun
1048*4882a593Smuzhiyun se_cmd = &cmd->se_cmd;
1049*4882a593Smuzhiyun tpg = cmd->fu->tpg;
1050*4882a593Smuzhiyun tv_nexus = tpg->tpg_nexus;
1051*4882a593Smuzhiyun dir = get_cmd_dir(cmd->cmd_buf);
1052*4882a593Smuzhiyun if (dir < 0) {
1053*4882a593Smuzhiyun transport_init_se_cmd(se_cmd,
1054*4882a593Smuzhiyun tv_nexus->tvn_se_sess->se_tpg->se_tpg_tfo,
1055*4882a593Smuzhiyun tv_nexus->tvn_se_sess, cmd->data_len, DMA_NONE,
1056*4882a593Smuzhiyun cmd->prio_attr, cmd->sense_iu.sense,
1057*4882a593Smuzhiyun cmd->unpacked_lun);
1058*4882a593Smuzhiyun goto out;
1059*4882a593Smuzhiyun }
1060*4882a593Smuzhiyun
1061*4882a593Smuzhiyun if (target_submit_cmd(se_cmd, tv_nexus->tvn_se_sess, cmd->cmd_buf,
1062*4882a593Smuzhiyun cmd->sense_iu.sense, cmd->unpacked_lun, 0,
1063*4882a593Smuzhiyun cmd->prio_attr, dir, flags) < 0)
1064*4882a593Smuzhiyun goto out;
1065*4882a593Smuzhiyun
1066*4882a593Smuzhiyun return;
1067*4882a593Smuzhiyun
1068*4882a593Smuzhiyun out:
1069*4882a593Smuzhiyun transport_send_check_condition_and_sense(se_cmd,
1070*4882a593Smuzhiyun TCM_UNSUPPORTED_SCSI_OPCODE, 1);
1071*4882a593Smuzhiyun transport_generic_free_cmd(&cmd->se_cmd, 0);
1072*4882a593Smuzhiyun }
1073*4882a593Smuzhiyun
usbg_get_cmd(struct f_uas * fu,struct tcm_usbg_nexus * tv_nexus,u32 scsi_tag)1074*4882a593Smuzhiyun static struct usbg_cmd *usbg_get_cmd(struct f_uas *fu,
1075*4882a593Smuzhiyun struct tcm_usbg_nexus *tv_nexus, u32 scsi_tag)
1076*4882a593Smuzhiyun {
1077*4882a593Smuzhiyun struct se_session *se_sess = tv_nexus->tvn_se_sess;
1078*4882a593Smuzhiyun struct usbg_cmd *cmd;
1079*4882a593Smuzhiyun int tag, cpu;
1080*4882a593Smuzhiyun
1081*4882a593Smuzhiyun tag = sbitmap_queue_get(&se_sess->sess_tag_pool, &cpu);
1082*4882a593Smuzhiyun if (tag < 0)
1083*4882a593Smuzhiyun return ERR_PTR(-ENOMEM);
1084*4882a593Smuzhiyun
1085*4882a593Smuzhiyun cmd = &((struct usbg_cmd *)se_sess->sess_cmd_map)[tag];
1086*4882a593Smuzhiyun memset(cmd, 0, sizeof(*cmd));
1087*4882a593Smuzhiyun cmd->se_cmd.map_tag = tag;
1088*4882a593Smuzhiyun cmd->se_cmd.map_cpu = cpu;
1089*4882a593Smuzhiyun cmd->se_cmd.tag = cmd->tag = scsi_tag;
1090*4882a593Smuzhiyun cmd->fu = fu;
1091*4882a593Smuzhiyun
1092*4882a593Smuzhiyun return cmd;
1093*4882a593Smuzhiyun }
1094*4882a593Smuzhiyun
1095*4882a593Smuzhiyun static void usbg_release_cmd(struct se_cmd *);
1096*4882a593Smuzhiyun
usbg_submit_command(struct f_uas * fu,void * cmdbuf,unsigned int len)1097*4882a593Smuzhiyun static int usbg_submit_command(struct f_uas *fu,
1098*4882a593Smuzhiyun void *cmdbuf, unsigned int len)
1099*4882a593Smuzhiyun {
1100*4882a593Smuzhiyun struct command_iu *cmd_iu = cmdbuf;
1101*4882a593Smuzhiyun struct usbg_cmd *cmd;
1102*4882a593Smuzhiyun struct usbg_tpg *tpg = fu->tpg;
1103*4882a593Smuzhiyun struct tcm_usbg_nexus *tv_nexus;
1104*4882a593Smuzhiyun u32 cmd_len;
1105*4882a593Smuzhiyun u16 scsi_tag;
1106*4882a593Smuzhiyun
1107*4882a593Smuzhiyun if (cmd_iu->iu_id != IU_ID_COMMAND) {
1108*4882a593Smuzhiyun pr_err("Unsupported type %d\n", cmd_iu->iu_id);
1109*4882a593Smuzhiyun return -EINVAL;
1110*4882a593Smuzhiyun }
1111*4882a593Smuzhiyun
1112*4882a593Smuzhiyun tv_nexus = tpg->tpg_nexus;
1113*4882a593Smuzhiyun if (!tv_nexus) {
1114*4882a593Smuzhiyun pr_err("Missing nexus, ignoring command\n");
1115*4882a593Smuzhiyun return -EINVAL;
1116*4882a593Smuzhiyun }
1117*4882a593Smuzhiyun
1118*4882a593Smuzhiyun cmd_len = (cmd_iu->len & ~0x3) + 16;
1119*4882a593Smuzhiyun if (cmd_len > USBG_MAX_CMD)
1120*4882a593Smuzhiyun return -EINVAL;
1121*4882a593Smuzhiyun
1122*4882a593Smuzhiyun scsi_tag = be16_to_cpup(&cmd_iu->tag);
1123*4882a593Smuzhiyun cmd = usbg_get_cmd(fu, tv_nexus, scsi_tag);
1124*4882a593Smuzhiyun if (IS_ERR(cmd)) {
1125*4882a593Smuzhiyun pr_err("usbg_get_cmd failed\n");
1126*4882a593Smuzhiyun return -ENOMEM;
1127*4882a593Smuzhiyun }
1128*4882a593Smuzhiyun memcpy(cmd->cmd_buf, cmd_iu->cdb, cmd_len);
1129*4882a593Smuzhiyun
1130*4882a593Smuzhiyun if (fu->flags & USBG_USE_STREAMS) {
1131*4882a593Smuzhiyun if (cmd->tag > UASP_SS_EP_COMP_NUM_STREAMS)
1132*4882a593Smuzhiyun goto err;
1133*4882a593Smuzhiyun if (!cmd->tag)
1134*4882a593Smuzhiyun cmd->stream = &fu->stream[0];
1135*4882a593Smuzhiyun else
1136*4882a593Smuzhiyun cmd->stream = &fu->stream[cmd->tag - 1];
1137*4882a593Smuzhiyun } else {
1138*4882a593Smuzhiyun cmd->stream = &fu->stream[0];
1139*4882a593Smuzhiyun }
1140*4882a593Smuzhiyun
1141*4882a593Smuzhiyun switch (cmd_iu->prio_attr & 0x7) {
1142*4882a593Smuzhiyun case UAS_HEAD_TAG:
1143*4882a593Smuzhiyun cmd->prio_attr = TCM_HEAD_TAG;
1144*4882a593Smuzhiyun break;
1145*4882a593Smuzhiyun case UAS_ORDERED_TAG:
1146*4882a593Smuzhiyun cmd->prio_attr = TCM_ORDERED_TAG;
1147*4882a593Smuzhiyun break;
1148*4882a593Smuzhiyun case UAS_ACA:
1149*4882a593Smuzhiyun cmd->prio_attr = TCM_ACA_TAG;
1150*4882a593Smuzhiyun break;
1151*4882a593Smuzhiyun default:
1152*4882a593Smuzhiyun pr_debug_once("Unsupported prio_attr: %02x.\n",
1153*4882a593Smuzhiyun cmd_iu->prio_attr);
1154*4882a593Smuzhiyun fallthrough;
1155*4882a593Smuzhiyun case UAS_SIMPLE_TAG:
1156*4882a593Smuzhiyun cmd->prio_attr = TCM_SIMPLE_TAG;
1157*4882a593Smuzhiyun break;
1158*4882a593Smuzhiyun }
1159*4882a593Smuzhiyun
1160*4882a593Smuzhiyun cmd->unpacked_lun = scsilun_to_int(&cmd_iu->lun);
1161*4882a593Smuzhiyun
1162*4882a593Smuzhiyun INIT_WORK(&cmd->work, usbg_cmd_work);
1163*4882a593Smuzhiyun queue_work(tpg->workqueue, &cmd->work);
1164*4882a593Smuzhiyun
1165*4882a593Smuzhiyun return 0;
1166*4882a593Smuzhiyun err:
1167*4882a593Smuzhiyun usbg_release_cmd(&cmd->se_cmd);
1168*4882a593Smuzhiyun return -EINVAL;
1169*4882a593Smuzhiyun }
1170*4882a593Smuzhiyun
bot_cmd_work(struct work_struct * work)1171*4882a593Smuzhiyun static void bot_cmd_work(struct work_struct *work)
1172*4882a593Smuzhiyun {
1173*4882a593Smuzhiyun struct usbg_cmd *cmd = container_of(work, struct usbg_cmd, work);
1174*4882a593Smuzhiyun struct se_cmd *se_cmd;
1175*4882a593Smuzhiyun struct tcm_usbg_nexus *tv_nexus;
1176*4882a593Smuzhiyun struct usbg_tpg *tpg;
1177*4882a593Smuzhiyun int dir;
1178*4882a593Smuzhiyun
1179*4882a593Smuzhiyun se_cmd = &cmd->se_cmd;
1180*4882a593Smuzhiyun tpg = cmd->fu->tpg;
1181*4882a593Smuzhiyun tv_nexus = tpg->tpg_nexus;
1182*4882a593Smuzhiyun dir = get_cmd_dir(cmd->cmd_buf);
1183*4882a593Smuzhiyun if (dir < 0) {
1184*4882a593Smuzhiyun transport_init_se_cmd(se_cmd,
1185*4882a593Smuzhiyun tv_nexus->tvn_se_sess->se_tpg->se_tpg_tfo,
1186*4882a593Smuzhiyun tv_nexus->tvn_se_sess, cmd->data_len, DMA_NONE,
1187*4882a593Smuzhiyun cmd->prio_attr, cmd->sense_iu.sense,
1188*4882a593Smuzhiyun cmd->unpacked_lun);
1189*4882a593Smuzhiyun goto out;
1190*4882a593Smuzhiyun }
1191*4882a593Smuzhiyun
1192*4882a593Smuzhiyun if (target_submit_cmd(se_cmd, tv_nexus->tvn_se_sess,
1193*4882a593Smuzhiyun cmd->cmd_buf, cmd->sense_iu.sense, cmd->unpacked_lun,
1194*4882a593Smuzhiyun cmd->data_len, cmd->prio_attr, dir, 0) < 0)
1195*4882a593Smuzhiyun goto out;
1196*4882a593Smuzhiyun
1197*4882a593Smuzhiyun return;
1198*4882a593Smuzhiyun
1199*4882a593Smuzhiyun out:
1200*4882a593Smuzhiyun transport_send_check_condition_and_sense(se_cmd,
1201*4882a593Smuzhiyun TCM_UNSUPPORTED_SCSI_OPCODE, 1);
1202*4882a593Smuzhiyun transport_generic_free_cmd(&cmd->se_cmd, 0);
1203*4882a593Smuzhiyun }
1204*4882a593Smuzhiyun
bot_submit_command(struct f_uas * fu,void * cmdbuf,unsigned int len)1205*4882a593Smuzhiyun static int bot_submit_command(struct f_uas *fu,
1206*4882a593Smuzhiyun void *cmdbuf, unsigned int len)
1207*4882a593Smuzhiyun {
1208*4882a593Smuzhiyun struct bulk_cb_wrap *cbw = cmdbuf;
1209*4882a593Smuzhiyun struct usbg_cmd *cmd;
1210*4882a593Smuzhiyun struct usbg_tpg *tpg = fu->tpg;
1211*4882a593Smuzhiyun struct tcm_usbg_nexus *tv_nexus;
1212*4882a593Smuzhiyun u32 cmd_len;
1213*4882a593Smuzhiyun
1214*4882a593Smuzhiyun if (cbw->Signature != cpu_to_le32(US_BULK_CB_SIGN)) {
1215*4882a593Smuzhiyun pr_err("Wrong signature on CBW\n");
1216*4882a593Smuzhiyun return -EINVAL;
1217*4882a593Smuzhiyun }
1218*4882a593Smuzhiyun if (len != 31) {
1219*4882a593Smuzhiyun pr_err("Wrong length for CBW\n");
1220*4882a593Smuzhiyun return -EINVAL;
1221*4882a593Smuzhiyun }
1222*4882a593Smuzhiyun
1223*4882a593Smuzhiyun cmd_len = cbw->Length;
1224*4882a593Smuzhiyun if (cmd_len < 1 || cmd_len > 16)
1225*4882a593Smuzhiyun return -EINVAL;
1226*4882a593Smuzhiyun
1227*4882a593Smuzhiyun tv_nexus = tpg->tpg_nexus;
1228*4882a593Smuzhiyun if (!tv_nexus) {
1229*4882a593Smuzhiyun pr_err("Missing nexus, ignoring command\n");
1230*4882a593Smuzhiyun return -ENODEV;
1231*4882a593Smuzhiyun }
1232*4882a593Smuzhiyun
1233*4882a593Smuzhiyun cmd = usbg_get_cmd(fu, tv_nexus, cbw->Tag);
1234*4882a593Smuzhiyun if (IS_ERR(cmd)) {
1235*4882a593Smuzhiyun pr_err("usbg_get_cmd failed\n");
1236*4882a593Smuzhiyun return -ENOMEM;
1237*4882a593Smuzhiyun }
1238*4882a593Smuzhiyun memcpy(cmd->cmd_buf, cbw->CDB, cmd_len);
1239*4882a593Smuzhiyun
1240*4882a593Smuzhiyun cmd->bot_tag = cbw->Tag;
1241*4882a593Smuzhiyun cmd->prio_attr = TCM_SIMPLE_TAG;
1242*4882a593Smuzhiyun cmd->unpacked_lun = cbw->Lun;
1243*4882a593Smuzhiyun cmd->is_read = cbw->Flags & US_BULK_FLAG_IN ? 1 : 0;
1244*4882a593Smuzhiyun cmd->data_len = le32_to_cpu(cbw->DataTransferLength);
1245*4882a593Smuzhiyun cmd->se_cmd.tag = le32_to_cpu(cmd->bot_tag);
1246*4882a593Smuzhiyun
1247*4882a593Smuzhiyun INIT_WORK(&cmd->work, bot_cmd_work);
1248*4882a593Smuzhiyun queue_work(tpg->workqueue, &cmd->work);
1249*4882a593Smuzhiyun
1250*4882a593Smuzhiyun return 0;
1251*4882a593Smuzhiyun }
1252*4882a593Smuzhiyun
1253*4882a593Smuzhiyun /* Start fabric.c code */
1254*4882a593Smuzhiyun
usbg_check_true(struct se_portal_group * se_tpg)1255*4882a593Smuzhiyun static int usbg_check_true(struct se_portal_group *se_tpg)
1256*4882a593Smuzhiyun {
1257*4882a593Smuzhiyun return 1;
1258*4882a593Smuzhiyun }
1259*4882a593Smuzhiyun
usbg_check_false(struct se_portal_group * se_tpg)1260*4882a593Smuzhiyun static int usbg_check_false(struct se_portal_group *se_tpg)
1261*4882a593Smuzhiyun {
1262*4882a593Smuzhiyun return 0;
1263*4882a593Smuzhiyun }
1264*4882a593Smuzhiyun
usbg_get_fabric_wwn(struct se_portal_group * se_tpg)1265*4882a593Smuzhiyun static char *usbg_get_fabric_wwn(struct se_portal_group *se_tpg)
1266*4882a593Smuzhiyun {
1267*4882a593Smuzhiyun struct usbg_tpg *tpg = container_of(se_tpg,
1268*4882a593Smuzhiyun struct usbg_tpg, se_tpg);
1269*4882a593Smuzhiyun struct usbg_tport *tport = tpg->tport;
1270*4882a593Smuzhiyun
1271*4882a593Smuzhiyun return &tport->tport_name[0];
1272*4882a593Smuzhiyun }
1273*4882a593Smuzhiyun
usbg_get_tag(struct se_portal_group * se_tpg)1274*4882a593Smuzhiyun static u16 usbg_get_tag(struct se_portal_group *se_tpg)
1275*4882a593Smuzhiyun {
1276*4882a593Smuzhiyun struct usbg_tpg *tpg = container_of(se_tpg,
1277*4882a593Smuzhiyun struct usbg_tpg, se_tpg);
1278*4882a593Smuzhiyun return tpg->tport_tpgt;
1279*4882a593Smuzhiyun }
1280*4882a593Smuzhiyun
usbg_tpg_get_inst_index(struct se_portal_group * se_tpg)1281*4882a593Smuzhiyun static u32 usbg_tpg_get_inst_index(struct se_portal_group *se_tpg)
1282*4882a593Smuzhiyun {
1283*4882a593Smuzhiyun return 1;
1284*4882a593Smuzhiyun }
1285*4882a593Smuzhiyun
usbg_release_cmd(struct se_cmd * se_cmd)1286*4882a593Smuzhiyun static void usbg_release_cmd(struct se_cmd *se_cmd)
1287*4882a593Smuzhiyun {
1288*4882a593Smuzhiyun struct usbg_cmd *cmd = container_of(se_cmd, struct usbg_cmd,
1289*4882a593Smuzhiyun se_cmd);
1290*4882a593Smuzhiyun struct se_session *se_sess = se_cmd->se_sess;
1291*4882a593Smuzhiyun
1292*4882a593Smuzhiyun kfree(cmd->data_buf);
1293*4882a593Smuzhiyun target_free_tag(se_sess, se_cmd);
1294*4882a593Smuzhiyun }
1295*4882a593Smuzhiyun
usbg_sess_get_index(struct se_session * se_sess)1296*4882a593Smuzhiyun static u32 usbg_sess_get_index(struct se_session *se_sess)
1297*4882a593Smuzhiyun {
1298*4882a593Smuzhiyun return 0;
1299*4882a593Smuzhiyun }
1300*4882a593Smuzhiyun
usbg_set_default_node_attrs(struct se_node_acl * nacl)1301*4882a593Smuzhiyun static void usbg_set_default_node_attrs(struct se_node_acl *nacl)
1302*4882a593Smuzhiyun {
1303*4882a593Smuzhiyun }
1304*4882a593Smuzhiyun
usbg_get_cmd_state(struct se_cmd * se_cmd)1305*4882a593Smuzhiyun static int usbg_get_cmd_state(struct se_cmd *se_cmd)
1306*4882a593Smuzhiyun {
1307*4882a593Smuzhiyun return 0;
1308*4882a593Smuzhiyun }
1309*4882a593Smuzhiyun
usbg_queue_tm_rsp(struct se_cmd * se_cmd)1310*4882a593Smuzhiyun static void usbg_queue_tm_rsp(struct se_cmd *se_cmd)
1311*4882a593Smuzhiyun {
1312*4882a593Smuzhiyun }
1313*4882a593Smuzhiyun
usbg_aborted_task(struct se_cmd * se_cmd)1314*4882a593Smuzhiyun static void usbg_aborted_task(struct se_cmd *se_cmd)
1315*4882a593Smuzhiyun {
1316*4882a593Smuzhiyun }
1317*4882a593Smuzhiyun
usbg_check_wwn(const char * name)1318*4882a593Smuzhiyun static const char *usbg_check_wwn(const char *name)
1319*4882a593Smuzhiyun {
1320*4882a593Smuzhiyun const char *n;
1321*4882a593Smuzhiyun unsigned int len;
1322*4882a593Smuzhiyun
1323*4882a593Smuzhiyun n = strstr(name, "naa.");
1324*4882a593Smuzhiyun if (!n)
1325*4882a593Smuzhiyun return NULL;
1326*4882a593Smuzhiyun n += 4;
1327*4882a593Smuzhiyun len = strlen(n);
1328*4882a593Smuzhiyun if (len == 0 || len > USBG_NAMELEN - 1)
1329*4882a593Smuzhiyun return NULL;
1330*4882a593Smuzhiyun return n;
1331*4882a593Smuzhiyun }
1332*4882a593Smuzhiyun
usbg_init_nodeacl(struct se_node_acl * se_nacl,const char * name)1333*4882a593Smuzhiyun static int usbg_init_nodeacl(struct se_node_acl *se_nacl, const char *name)
1334*4882a593Smuzhiyun {
1335*4882a593Smuzhiyun if (!usbg_check_wwn(name))
1336*4882a593Smuzhiyun return -EINVAL;
1337*4882a593Smuzhiyun return 0;
1338*4882a593Smuzhiyun }
1339*4882a593Smuzhiyun
usbg_make_tpg(struct se_wwn * wwn,const char * name)1340*4882a593Smuzhiyun static struct se_portal_group *usbg_make_tpg(struct se_wwn *wwn,
1341*4882a593Smuzhiyun const char *name)
1342*4882a593Smuzhiyun {
1343*4882a593Smuzhiyun struct usbg_tport *tport = container_of(wwn, struct usbg_tport,
1344*4882a593Smuzhiyun tport_wwn);
1345*4882a593Smuzhiyun struct usbg_tpg *tpg;
1346*4882a593Smuzhiyun unsigned long tpgt;
1347*4882a593Smuzhiyun int ret;
1348*4882a593Smuzhiyun struct f_tcm_opts *opts;
1349*4882a593Smuzhiyun unsigned i;
1350*4882a593Smuzhiyun
1351*4882a593Smuzhiyun if (strstr(name, "tpgt_") != name)
1352*4882a593Smuzhiyun return ERR_PTR(-EINVAL);
1353*4882a593Smuzhiyun if (kstrtoul(name + 5, 0, &tpgt) || tpgt > UINT_MAX)
1354*4882a593Smuzhiyun return ERR_PTR(-EINVAL);
1355*4882a593Smuzhiyun ret = -ENODEV;
1356*4882a593Smuzhiyun mutex_lock(&tpg_instances_lock);
1357*4882a593Smuzhiyun for (i = 0; i < TPG_INSTANCES; ++i)
1358*4882a593Smuzhiyun if (tpg_instances[i].func_inst && !tpg_instances[i].tpg)
1359*4882a593Smuzhiyun break;
1360*4882a593Smuzhiyun if (i == TPG_INSTANCES)
1361*4882a593Smuzhiyun goto unlock_inst;
1362*4882a593Smuzhiyun
1363*4882a593Smuzhiyun opts = container_of(tpg_instances[i].func_inst, struct f_tcm_opts,
1364*4882a593Smuzhiyun func_inst);
1365*4882a593Smuzhiyun mutex_lock(&opts->dep_lock);
1366*4882a593Smuzhiyun if (!opts->ready)
1367*4882a593Smuzhiyun goto unlock_dep;
1368*4882a593Smuzhiyun
1369*4882a593Smuzhiyun if (opts->has_dep) {
1370*4882a593Smuzhiyun if (!try_module_get(opts->dependent))
1371*4882a593Smuzhiyun goto unlock_dep;
1372*4882a593Smuzhiyun } else {
1373*4882a593Smuzhiyun ret = configfs_depend_item_unlocked(
1374*4882a593Smuzhiyun wwn->wwn_group.cg_subsys,
1375*4882a593Smuzhiyun &opts->func_inst.group.cg_item);
1376*4882a593Smuzhiyun if (ret)
1377*4882a593Smuzhiyun goto unlock_dep;
1378*4882a593Smuzhiyun }
1379*4882a593Smuzhiyun
1380*4882a593Smuzhiyun tpg = kzalloc(sizeof(struct usbg_tpg), GFP_KERNEL);
1381*4882a593Smuzhiyun ret = -ENOMEM;
1382*4882a593Smuzhiyun if (!tpg)
1383*4882a593Smuzhiyun goto unref_dep;
1384*4882a593Smuzhiyun mutex_init(&tpg->tpg_mutex);
1385*4882a593Smuzhiyun atomic_set(&tpg->tpg_port_count, 0);
1386*4882a593Smuzhiyun tpg->workqueue = alloc_workqueue("tcm_usb_gadget", 0, 1);
1387*4882a593Smuzhiyun if (!tpg->workqueue)
1388*4882a593Smuzhiyun goto free_tpg;
1389*4882a593Smuzhiyun
1390*4882a593Smuzhiyun tpg->tport = tport;
1391*4882a593Smuzhiyun tpg->tport_tpgt = tpgt;
1392*4882a593Smuzhiyun
1393*4882a593Smuzhiyun /*
1394*4882a593Smuzhiyun * SPC doesn't assign a protocol identifier for USB-SCSI, so we
1395*4882a593Smuzhiyun * pretend to be SAS..
1396*4882a593Smuzhiyun */
1397*4882a593Smuzhiyun ret = core_tpg_register(wwn, &tpg->se_tpg, SCSI_PROTOCOL_SAS);
1398*4882a593Smuzhiyun if (ret < 0)
1399*4882a593Smuzhiyun goto free_workqueue;
1400*4882a593Smuzhiyun
1401*4882a593Smuzhiyun tpg_instances[i].tpg = tpg;
1402*4882a593Smuzhiyun tpg->fi = tpg_instances[i].func_inst;
1403*4882a593Smuzhiyun mutex_unlock(&opts->dep_lock);
1404*4882a593Smuzhiyun mutex_unlock(&tpg_instances_lock);
1405*4882a593Smuzhiyun return &tpg->se_tpg;
1406*4882a593Smuzhiyun
1407*4882a593Smuzhiyun free_workqueue:
1408*4882a593Smuzhiyun destroy_workqueue(tpg->workqueue);
1409*4882a593Smuzhiyun free_tpg:
1410*4882a593Smuzhiyun kfree(tpg);
1411*4882a593Smuzhiyun unref_dep:
1412*4882a593Smuzhiyun if (opts->has_dep)
1413*4882a593Smuzhiyun module_put(opts->dependent);
1414*4882a593Smuzhiyun else
1415*4882a593Smuzhiyun configfs_undepend_item_unlocked(&opts->func_inst.group.cg_item);
1416*4882a593Smuzhiyun unlock_dep:
1417*4882a593Smuzhiyun mutex_unlock(&opts->dep_lock);
1418*4882a593Smuzhiyun unlock_inst:
1419*4882a593Smuzhiyun mutex_unlock(&tpg_instances_lock);
1420*4882a593Smuzhiyun
1421*4882a593Smuzhiyun return ERR_PTR(ret);
1422*4882a593Smuzhiyun }
1423*4882a593Smuzhiyun
1424*4882a593Smuzhiyun static int tcm_usbg_drop_nexus(struct usbg_tpg *);
1425*4882a593Smuzhiyun
usbg_drop_tpg(struct se_portal_group * se_tpg)1426*4882a593Smuzhiyun static void usbg_drop_tpg(struct se_portal_group *se_tpg)
1427*4882a593Smuzhiyun {
1428*4882a593Smuzhiyun struct usbg_tpg *tpg = container_of(se_tpg,
1429*4882a593Smuzhiyun struct usbg_tpg, se_tpg);
1430*4882a593Smuzhiyun unsigned i;
1431*4882a593Smuzhiyun struct f_tcm_opts *opts;
1432*4882a593Smuzhiyun
1433*4882a593Smuzhiyun tcm_usbg_drop_nexus(tpg);
1434*4882a593Smuzhiyun core_tpg_deregister(se_tpg);
1435*4882a593Smuzhiyun destroy_workqueue(tpg->workqueue);
1436*4882a593Smuzhiyun
1437*4882a593Smuzhiyun mutex_lock(&tpg_instances_lock);
1438*4882a593Smuzhiyun for (i = 0; i < TPG_INSTANCES; ++i)
1439*4882a593Smuzhiyun if (tpg_instances[i].tpg == tpg)
1440*4882a593Smuzhiyun break;
1441*4882a593Smuzhiyun if (i < TPG_INSTANCES) {
1442*4882a593Smuzhiyun tpg_instances[i].tpg = NULL;
1443*4882a593Smuzhiyun opts = container_of(tpg_instances[i].func_inst,
1444*4882a593Smuzhiyun struct f_tcm_opts, func_inst);
1445*4882a593Smuzhiyun mutex_lock(&opts->dep_lock);
1446*4882a593Smuzhiyun if (opts->has_dep)
1447*4882a593Smuzhiyun module_put(opts->dependent);
1448*4882a593Smuzhiyun else
1449*4882a593Smuzhiyun configfs_undepend_item_unlocked(
1450*4882a593Smuzhiyun &opts->func_inst.group.cg_item);
1451*4882a593Smuzhiyun mutex_unlock(&opts->dep_lock);
1452*4882a593Smuzhiyun }
1453*4882a593Smuzhiyun mutex_unlock(&tpg_instances_lock);
1454*4882a593Smuzhiyun
1455*4882a593Smuzhiyun kfree(tpg);
1456*4882a593Smuzhiyun }
1457*4882a593Smuzhiyun
usbg_make_tport(struct target_fabric_configfs * tf,struct config_group * group,const char * name)1458*4882a593Smuzhiyun static struct se_wwn *usbg_make_tport(
1459*4882a593Smuzhiyun struct target_fabric_configfs *tf,
1460*4882a593Smuzhiyun struct config_group *group,
1461*4882a593Smuzhiyun const char *name)
1462*4882a593Smuzhiyun {
1463*4882a593Smuzhiyun struct usbg_tport *tport;
1464*4882a593Smuzhiyun const char *wnn_name;
1465*4882a593Smuzhiyun u64 wwpn = 0;
1466*4882a593Smuzhiyun
1467*4882a593Smuzhiyun wnn_name = usbg_check_wwn(name);
1468*4882a593Smuzhiyun if (!wnn_name)
1469*4882a593Smuzhiyun return ERR_PTR(-EINVAL);
1470*4882a593Smuzhiyun
1471*4882a593Smuzhiyun tport = kzalloc(sizeof(struct usbg_tport), GFP_KERNEL);
1472*4882a593Smuzhiyun if (!(tport))
1473*4882a593Smuzhiyun return ERR_PTR(-ENOMEM);
1474*4882a593Smuzhiyun
1475*4882a593Smuzhiyun tport->tport_wwpn = wwpn;
1476*4882a593Smuzhiyun snprintf(tport->tport_name, sizeof(tport->tport_name), "%s", wnn_name);
1477*4882a593Smuzhiyun return &tport->tport_wwn;
1478*4882a593Smuzhiyun }
1479*4882a593Smuzhiyun
usbg_drop_tport(struct se_wwn * wwn)1480*4882a593Smuzhiyun static void usbg_drop_tport(struct se_wwn *wwn)
1481*4882a593Smuzhiyun {
1482*4882a593Smuzhiyun struct usbg_tport *tport = container_of(wwn,
1483*4882a593Smuzhiyun struct usbg_tport, tport_wwn);
1484*4882a593Smuzhiyun kfree(tport);
1485*4882a593Smuzhiyun }
1486*4882a593Smuzhiyun
1487*4882a593Smuzhiyun /*
1488*4882a593Smuzhiyun * If somebody feels like dropping the version property, go ahead.
1489*4882a593Smuzhiyun */
usbg_wwn_version_show(struct config_item * item,char * page)1490*4882a593Smuzhiyun static ssize_t usbg_wwn_version_show(struct config_item *item, char *page)
1491*4882a593Smuzhiyun {
1492*4882a593Smuzhiyun return sprintf(page, "usb-gadget fabric module\n");
1493*4882a593Smuzhiyun }
1494*4882a593Smuzhiyun
1495*4882a593Smuzhiyun CONFIGFS_ATTR_RO(usbg_wwn_, version);
1496*4882a593Smuzhiyun
1497*4882a593Smuzhiyun static struct configfs_attribute *usbg_wwn_attrs[] = {
1498*4882a593Smuzhiyun &usbg_wwn_attr_version,
1499*4882a593Smuzhiyun NULL,
1500*4882a593Smuzhiyun };
1501*4882a593Smuzhiyun
tcm_usbg_tpg_enable_show(struct config_item * item,char * page)1502*4882a593Smuzhiyun static ssize_t tcm_usbg_tpg_enable_show(struct config_item *item, char *page)
1503*4882a593Smuzhiyun {
1504*4882a593Smuzhiyun struct se_portal_group *se_tpg = to_tpg(item);
1505*4882a593Smuzhiyun struct usbg_tpg *tpg = container_of(se_tpg, struct usbg_tpg, se_tpg);
1506*4882a593Smuzhiyun
1507*4882a593Smuzhiyun return snprintf(page, PAGE_SIZE, "%u\n", tpg->gadget_connect);
1508*4882a593Smuzhiyun }
1509*4882a593Smuzhiyun
1510*4882a593Smuzhiyun static int usbg_attach(struct usbg_tpg *);
1511*4882a593Smuzhiyun static void usbg_detach(struct usbg_tpg *);
1512*4882a593Smuzhiyun
tcm_usbg_tpg_enable_store(struct config_item * item,const char * page,size_t count)1513*4882a593Smuzhiyun static ssize_t tcm_usbg_tpg_enable_store(struct config_item *item,
1514*4882a593Smuzhiyun const char *page, size_t count)
1515*4882a593Smuzhiyun {
1516*4882a593Smuzhiyun struct se_portal_group *se_tpg = to_tpg(item);
1517*4882a593Smuzhiyun struct usbg_tpg *tpg = container_of(se_tpg, struct usbg_tpg, se_tpg);
1518*4882a593Smuzhiyun bool op;
1519*4882a593Smuzhiyun ssize_t ret;
1520*4882a593Smuzhiyun
1521*4882a593Smuzhiyun ret = strtobool(page, &op);
1522*4882a593Smuzhiyun if (ret)
1523*4882a593Smuzhiyun return ret;
1524*4882a593Smuzhiyun
1525*4882a593Smuzhiyun if ((op && tpg->gadget_connect) || (!op && !tpg->gadget_connect))
1526*4882a593Smuzhiyun return -EINVAL;
1527*4882a593Smuzhiyun
1528*4882a593Smuzhiyun if (op)
1529*4882a593Smuzhiyun ret = usbg_attach(tpg);
1530*4882a593Smuzhiyun else
1531*4882a593Smuzhiyun usbg_detach(tpg);
1532*4882a593Smuzhiyun if (ret)
1533*4882a593Smuzhiyun return ret;
1534*4882a593Smuzhiyun
1535*4882a593Smuzhiyun tpg->gadget_connect = op;
1536*4882a593Smuzhiyun
1537*4882a593Smuzhiyun return count;
1538*4882a593Smuzhiyun }
1539*4882a593Smuzhiyun
tcm_usbg_tpg_nexus_show(struct config_item * item,char * page)1540*4882a593Smuzhiyun static ssize_t tcm_usbg_tpg_nexus_show(struct config_item *item, char *page)
1541*4882a593Smuzhiyun {
1542*4882a593Smuzhiyun struct se_portal_group *se_tpg = to_tpg(item);
1543*4882a593Smuzhiyun struct usbg_tpg *tpg = container_of(se_tpg, struct usbg_tpg, se_tpg);
1544*4882a593Smuzhiyun struct tcm_usbg_nexus *tv_nexus;
1545*4882a593Smuzhiyun ssize_t ret;
1546*4882a593Smuzhiyun
1547*4882a593Smuzhiyun mutex_lock(&tpg->tpg_mutex);
1548*4882a593Smuzhiyun tv_nexus = tpg->tpg_nexus;
1549*4882a593Smuzhiyun if (!tv_nexus) {
1550*4882a593Smuzhiyun ret = -ENODEV;
1551*4882a593Smuzhiyun goto out;
1552*4882a593Smuzhiyun }
1553*4882a593Smuzhiyun ret = snprintf(page, PAGE_SIZE, "%s\n",
1554*4882a593Smuzhiyun tv_nexus->tvn_se_sess->se_node_acl->initiatorname);
1555*4882a593Smuzhiyun out:
1556*4882a593Smuzhiyun mutex_unlock(&tpg->tpg_mutex);
1557*4882a593Smuzhiyun return ret;
1558*4882a593Smuzhiyun }
1559*4882a593Smuzhiyun
usbg_alloc_sess_cb(struct se_portal_group * se_tpg,struct se_session * se_sess,void * p)1560*4882a593Smuzhiyun static int usbg_alloc_sess_cb(struct se_portal_group *se_tpg,
1561*4882a593Smuzhiyun struct se_session *se_sess, void *p)
1562*4882a593Smuzhiyun {
1563*4882a593Smuzhiyun struct usbg_tpg *tpg = container_of(se_tpg,
1564*4882a593Smuzhiyun struct usbg_tpg, se_tpg);
1565*4882a593Smuzhiyun
1566*4882a593Smuzhiyun tpg->tpg_nexus = p;
1567*4882a593Smuzhiyun return 0;
1568*4882a593Smuzhiyun }
1569*4882a593Smuzhiyun
tcm_usbg_make_nexus(struct usbg_tpg * tpg,char * name)1570*4882a593Smuzhiyun static int tcm_usbg_make_nexus(struct usbg_tpg *tpg, char *name)
1571*4882a593Smuzhiyun {
1572*4882a593Smuzhiyun struct tcm_usbg_nexus *tv_nexus;
1573*4882a593Smuzhiyun int ret = 0;
1574*4882a593Smuzhiyun
1575*4882a593Smuzhiyun mutex_lock(&tpg->tpg_mutex);
1576*4882a593Smuzhiyun if (tpg->tpg_nexus) {
1577*4882a593Smuzhiyun ret = -EEXIST;
1578*4882a593Smuzhiyun pr_debug("tpg->tpg_nexus already exists\n");
1579*4882a593Smuzhiyun goto out_unlock;
1580*4882a593Smuzhiyun }
1581*4882a593Smuzhiyun
1582*4882a593Smuzhiyun tv_nexus = kzalloc(sizeof(*tv_nexus), GFP_KERNEL);
1583*4882a593Smuzhiyun if (!tv_nexus) {
1584*4882a593Smuzhiyun ret = -ENOMEM;
1585*4882a593Smuzhiyun goto out_unlock;
1586*4882a593Smuzhiyun }
1587*4882a593Smuzhiyun
1588*4882a593Smuzhiyun tv_nexus->tvn_se_sess = target_setup_session(&tpg->se_tpg,
1589*4882a593Smuzhiyun USB_G_DEFAULT_SESSION_TAGS,
1590*4882a593Smuzhiyun sizeof(struct usbg_cmd),
1591*4882a593Smuzhiyun TARGET_PROT_NORMAL, name,
1592*4882a593Smuzhiyun tv_nexus, usbg_alloc_sess_cb);
1593*4882a593Smuzhiyun if (IS_ERR(tv_nexus->tvn_se_sess)) {
1594*4882a593Smuzhiyun #define MAKE_NEXUS_MSG "core_tpg_check_initiator_node_acl() failed for %s\n"
1595*4882a593Smuzhiyun pr_debug(MAKE_NEXUS_MSG, name);
1596*4882a593Smuzhiyun #undef MAKE_NEXUS_MSG
1597*4882a593Smuzhiyun ret = PTR_ERR(tv_nexus->tvn_se_sess);
1598*4882a593Smuzhiyun kfree(tv_nexus);
1599*4882a593Smuzhiyun }
1600*4882a593Smuzhiyun
1601*4882a593Smuzhiyun out_unlock:
1602*4882a593Smuzhiyun mutex_unlock(&tpg->tpg_mutex);
1603*4882a593Smuzhiyun return ret;
1604*4882a593Smuzhiyun }
1605*4882a593Smuzhiyun
tcm_usbg_drop_nexus(struct usbg_tpg * tpg)1606*4882a593Smuzhiyun static int tcm_usbg_drop_nexus(struct usbg_tpg *tpg)
1607*4882a593Smuzhiyun {
1608*4882a593Smuzhiyun struct se_session *se_sess;
1609*4882a593Smuzhiyun struct tcm_usbg_nexus *tv_nexus;
1610*4882a593Smuzhiyun int ret = -ENODEV;
1611*4882a593Smuzhiyun
1612*4882a593Smuzhiyun mutex_lock(&tpg->tpg_mutex);
1613*4882a593Smuzhiyun tv_nexus = tpg->tpg_nexus;
1614*4882a593Smuzhiyun if (!tv_nexus)
1615*4882a593Smuzhiyun goto out;
1616*4882a593Smuzhiyun
1617*4882a593Smuzhiyun se_sess = tv_nexus->tvn_se_sess;
1618*4882a593Smuzhiyun if (!se_sess)
1619*4882a593Smuzhiyun goto out;
1620*4882a593Smuzhiyun
1621*4882a593Smuzhiyun if (atomic_read(&tpg->tpg_port_count)) {
1622*4882a593Smuzhiyun ret = -EPERM;
1623*4882a593Smuzhiyun #define MSG "Unable to remove Host I_T Nexus with active TPG port count: %d\n"
1624*4882a593Smuzhiyun pr_err(MSG, atomic_read(&tpg->tpg_port_count));
1625*4882a593Smuzhiyun #undef MSG
1626*4882a593Smuzhiyun goto out;
1627*4882a593Smuzhiyun }
1628*4882a593Smuzhiyun
1629*4882a593Smuzhiyun pr_debug("Removing I_T Nexus to Initiator Port: %s\n",
1630*4882a593Smuzhiyun tv_nexus->tvn_se_sess->se_node_acl->initiatorname);
1631*4882a593Smuzhiyun /*
1632*4882a593Smuzhiyun * Release the SCSI I_T Nexus to the emulated vHost Target Port
1633*4882a593Smuzhiyun */
1634*4882a593Smuzhiyun target_remove_session(se_sess);
1635*4882a593Smuzhiyun tpg->tpg_nexus = NULL;
1636*4882a593Smuzhiyun
1637*4882a593Smuzhiyun kfree(tv_nexus);
1638*4882a593Smuzhiyun ret = 0;
1639*4882a593Smuzhiyun out:
1640*4882a593Smuzhiyun mutex_unlock(&tpg->tpg_mutex);
1641*4882a593Smuzhiyun return ret;
1642*4882a593Smuzhiyun }
1643*4882a593Smuzhiyun
tcm_usbg_tpg_nexus_store(struct config_item * item,const char * page,size_t count)1644*4882a593Smuzhiyun static ssize_t tcm_usbg_tpg_nexus_store(struct config_item *item,
1645*4882a593Smuzhiyun const char *page, size_t count)
1646*4882a593Smuzhiyun {
1647*4882a593Smuzhiyun struct se_portal_group *se_tpg = to_tpg(item);
1648*4882a593Smuzhiyun struct usbg_tpg *tpg = container_of(se_tpg, struct usbg_tpg, se_tpg);
1649*4882a593Smuzhiyun unsigned char i_port[USBG_NAMELEN], *ptr;
1650*4882a593Smuzhiyun int ret;
1651*4882a593Smuzhiyun
1652*4882a593Smuzhiyun if (!strncmp(page, "NULL", 4)) {
1653*4882a593Smuzhiyun ret = tcm_usbg_drop_nexus(tpg);
1654*4882a593Smuzhiyun return (!ret) ? count : ret;
1655*4882a593Smuzhiyun }
1656*4882a593Smuzhiyun if (strlen(page) >= USBG_NAMELEN) {
1657*4882a593Smuzhiyun
1658*4882a593Smuzhiyun #define NEXUS_STORE_MSG "Emulated NAA Sas Address: %s, exceeds max: %d\n"
1659*4882a593Smuzhiyun pr_err(NEXUS_STORE_MSG, page, USBG_NAMELEN);
1660*4882a593Smuzhiyun #undef NEXUS_STORE_MSG
1661*4882a593Smuzhiyun return -EINVAL;
1662*4882a593Smuzhiyun }
1663*4882a593Smuzhiyun snprintf(i_port, USBG_NAMELEN, "%s", page);
1664*4882a593Smuzhiyun
1665*4882a593Smuzhiyun ptr = strstr(i_port, "naa.");
1666*4882a593Smuzhiyun if (!ptr) {
1667*4882a593Smuzhiyun pr_err("Missing 'naa.' prefix\n");
1668*4882a593Smuzhiyun return -EINVAL;
1669*4882a593Smuzhiyun }
1670*4882a593Smuzhiyun
1671*4882a593Smuzhiyun if (i_port[strlen(i_port) - 1] == '\n')
1672*4882a593Smuzhiyun i_port[strlen(i_port) - 1] = '\0';
1673*4882a593Smuzhiyun
1674*4882a593Smuzhiyun ret = tcm_usbg_make_nexus(tpg, &i_port[0]);
1675*4882a593Smuzhiyun if (ret < 0)
1676*4882a593Smuzhiyun return ret;
1677*4882a593Smuzhiyun return count;
1678*4882a593Smuzhiyun }
1679*4882a593Smuzhiyun
1680*4882a593Smuzhiyun CONFIGFS_ATTR(tcm_usbg_tpg_, enable);
1681*4882a593Smuzhiyun CONFIGFS_ATTR(tcm_usbg_tpg_, nexus);
1682*4882a593Smuzhiyun
1683*4882a593Smuzhiyun static struct configfs_attribute *usbg_base_attrs[] = {
1684*4882a593Smuzhiyun &tcm_usbg_tpg_attr_enable,
1685*4882a593Smuzhiyun &tcm_usbg_tpg_attr_nexus,
1686*4882a593Smuzhiyun NULL,
1687*4882a593Smuzhiyun };
1688*4882a593Smuzhiyun
usbg_port_link(struct se_portal_group * se_tpg,struct se_lun * lun)1689*4882a593Smuzhiyun static int usbg_port_link(struct se_portal_group *se_tpg, struct se_lun *lun)
1690*4882a593Smuzhiyun {
1691*4882a593Smuzhiyun struct usbg_tpg *tpg = container_of(se_tpg, struct usbg_tpg, se_tpg);
1692*4882a593Smuzhiyun
1693*4882a593Smuzhiyun atomic_inc(&tpg->tpg_port_count);
1694*4882a593Smuzhiyun smp_mb__after_atomic();
1695*4882a593Smuzhiyun return 0;
1696*4882a593Smuzhiyun }
1697*4882a593Smuzhiyun
usbg_port_unlink(struct se_portal_group * se_tpg,struct se_lun * se_lun)1698*4882a593Smuzhiyun static void usbg_port_unlink(struct se_portal_group *se_tpg,
1699*4882a593Smuzhiyun struct se_lun *se_lun)
1700*4882a593Smuzhiyun {
1701*4882a593Smuzhiyun struct usbg_tpg *tpg = container_of(se_tpg, struct usbg_tpg, se_tpg);
1702*4882a593Smuzhiyun
1703*4882a593Smuzhiyun atomic_dec(&tpg->tpg_port_count);
1704*4882a593Smuzhiyun smp_mb__after_atomic();
1705*4882a593Smuzhiyun }
1706*4882a593Smuzhiyun
usbg_check_stop_free(struct se_cmd * se_cmd)1707*4882a593Smuzhiyun static int usbg_check_stop_free(struct se_cmd *se_cmd)
1708*4882a593Smuzhiyun {
1709*4882a593Smuzhiyun return target_put_sess_cmd(se_cmd);
1710*4882a593Smuzhiyun }
1711*4882a593Smuzhiyun
1712*4882a593Smuzhiyun static const struct target_core_fabric_ops usbg_ops = {
1713*4882a593Smuzhiyun .module = THIS_MODULE,
1714*4882a593Smuzhiyun .fabric_name = "usb_gadget",
1715*4882a593Smuzhiyun .tpg_get_wwn = usbg_get_fabric_wwn,
1716*4882a593Smuzhiyun .tpg_get_tag = usbg_get_tag,
1717*4882a593Smuzhiyun .tpg_check_demo_mode = usbg_check_true,
1718*4882a593Smuzhiyun .tpg_check_demo_mode_cache = usbg_check_false,
1719*4882a593Smuzhiyun .tpg_check_demo_mode_write_protect = usbg_check_false,
1720*4882a593Smuzhiyun .tpg_check_prod_mode_write_protect = usbg_check_false,
1721*4882a593Smuzhiyun .tpg_get_inst_index = usbg_tpg_get_inst_index,
1722*4882a593Smuzhiyun .release_cmd = usbg_release_cmd,
1723*4882a593Smuzhiyun .sess_get_index = usbg_sess_get_index,
1724*4882a593Smuzhiyun .sess_get_initiator_sid = NULL,
1725*4882a593Smuzhiyun .write_pending = usbg_send_write_request,
1726*4882a593Smuzhiyun .set_default_node_attributes = usbg_set_default_node_attrs,
1727*4882a593Smuzhiyun .get_cmd_state = usbg_get_cmd_state,
1728*4882a593Smuzhiyun .queue_data_in = usbg_send_read_response,
1729*4882a593Smuzhiyun .queue_status = usbg_send_status_response,
1730*4882a593Smuzhiyun .queue_tm_rsp = usbg_queue_tm_rsp,
1731*4882a593Smuzhiyun .aborted_task = usbg_aborted_task,
1732*4882a593Smuzhiyun .check_stop_free = usbg_check_stop_free,
1733*4882a593Smuzhiyun
1734*4882a593Smuzhiyun .fabric_make_wwn = usbg_make_tport,
1735*4882a593Smuzhiyun .fabric_drop_wwn = usbg_drop_tport,
1736*4882a593Smuzhiyun .fabric_make_tpg = usbg_make_tpg,
1737*4882a593Smuzhiyun .fabric_drop_tpg = usbg_drop_tpg,
1738*4882a593Smuzhiyun .fabric_post_link = usbg_port_link,
1739*4882a593Smuzhiyun .fabric_pre_unlink = usbg_port_unlink,
1740*4882a593Smuzhiyun .fabric_init_nodeacl = usbg_init_nodeacl,
1741*4882a593Smuzhiyun
1742*4882a593Smuzhiyun .tfc_wwn_attrs = usbg_wwn_attrs,
1743*4882a593Smuzhiyun .tfc_tpg_base_attrs = usbg_base_attrs,
1744*4882a593Smuzhiyun };
1745*4882a593Smuzhiyun
1746*4882a593Smuzhiyun /* Start gadget.c code */
1747*4882a593Smuzhiyun
1748*4882a593Smuzhiyun static struct usb_interface_descriptor bot_intf_desc = {
1749*4882a593Smuzhiyun .bLength = sizeof(bot_intf_desc),
1750*4882a593Smuzhiyun .bDescriptorType = USB_DT_INTERFACE,
1751*4882a593Smuzhiyun .bNumEndpoints = 2,
1752*4882a593Smuzhiyun .bAlternateSetting = USB_G_ALT_INT_BBB,
1753*4882a593Smuzhiyun .bInterfaceClass = USB_CLASS_MASS_STORAGE,
1754*4882a593Smuzhiyun .bInterfaceSubClass = USB_SC_SCSI,
1755*4882a593Smuzhiyun .bInterfaceProtocol = USB_PR_BULK,
1756*4882a593Smuzhiyun };
1757*4882a593Smuzhiyun
1758*4882a593Smuzhiyun static struct usb_interface_descriptor uasp_intf_desc = {
1759*4882a593Smuzhiyun .bLength = sizeof(uasp_intf_desc),
1760*4882a593Smuzhiyun .bDescriptorType = USB_DT_INTERFACE,
1761*4882a593Smuzhiyun .bNumEndpoints = 4,
1762*4882a593Smuzhiyun .bAlternateSetting = USB_G_ALT_INT_UAS,
1763*4882a593Smuzhiyun .bInterfaceClass = USB_CLASS_MASS_STORAGE,
1764*4882a593Smuzhiyun .bInterfaceSubClass = USB_SC_SCSI,
1765*4882a593Smuzhiyun .bInterfaceProtocol = USB_PR_UAS,
1766*4882a593Smuzhiyun };
1767*4882a593Smuzhiyun
1768*4882a593Smuzhiyun static struct usb_endpoint_descriptor uasp_bi_desc = {
1769*4882a593Smuzhiyun .bLength = USB_DT_ENDPOINT_SIZE,
1770*4882a593Smuzhiyun .bDescriptorType = USB_DT_ENDPOINT,
1771*4882a593Smuzhiyun .bEndpointAddress = USB_DIR_IN,
1772*4882a593Smuzhiyun .bmAttributes = USB_ENDPOINT_XFER_BULK,
1773*4882a593Smuzhiyun .wMaxPacketSize = cpu_to_le16(512),
1774*4882a593Smuzhiyun };
1775*4882a593Smuzhiyun
1776*4882a593Smuzhiyun static struct usb_endpoint_descriptor uasp_fs_bi_desc = {
1777*4882a593Smuzhiyun .bLength = USB_DT_ENDPOINT_SIZE,
1778*4882a593Smuzhiyun .bDescriptorType = USB_DT_ENDPOINT,
1779*4882a593Smuzhiyun .bEndpointAddress = USB_DIR_IN,
1780*4882a593Smuzhiyun .bmAttributes = USB_ENDPOINT_XFER_BULK,
1781*4882a593Smuzhiyun };
1782*4882a593Smuzhiyun
1783*4882a593Smuzhiyun static struct usb_pipe_usage_descriptor uasp_bi_pipe_desc = {
1784*4882a593Smuzhiyun .bLength = sizeof(uasp_bi_pipe_desc),
1785*4882a593Smuzhiyun .bDescriptorType = USB_DT_PIPE_USAGE,
1786*4882a593Smuzhiyun .bPipeID = DATA_IN_PIPE_ID,
1787*4882a593Smuzhiyun };
1788*4882a593Smuzhiyun
1789*4882a593Smuzhiyun static struct usb_endpoint_descriptor uasp_ss_bi_desc = {
1790*4882a593Smuzhiyun .bLength = USB_DT_ENDPOINT_SIZE,
1791*4882a593Smuzhiyun .bDescriptorType = USB_DT_ENDPOINT,
1792*4882a593Smuzhiyun .bEndpointAddress = USB_DIR_IN,
1793*4882a593Smuzhiyun .bmAttributes = USB_ENDPOINT_XFER_BULK,
1794*4882a593Smuzhiyun .wMaxPacketSize = cpu_to_le16(1024),
1795*4882a593Smuzhiyun };
1796*4882a593Smuzhiyun
1797*4882a593Smuzhiyun static struct usb_ss_ep_comp_descriptor uasp_bi_ep_comp_desc = {
1798*4882a593Smuzhiyun .bLength = sizeof(uasp_bi_ep_comp_desc),
1799*4882a593Smuzhiyun .bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
1800*4882a593Smuzhiyun .bMaxBurst = 0,
1801*4882a593Smuzhiyun .bmAttributes = UASP_SS_EP_COMP_LOG_STREAMS,
1802*4882a593Smuzhiyun .wBytesPerInterval = 0,
1803*4882a593Smuzhiyun };
1804*4882a593Smuzhiyun
1805*4882a593Smuzhiyun static struct usb_ss_ep_comp_descriptor bot_bi_ep_comp_desc = {
1806*4882a593Smuzhiyun .bLength = sizeof(bot_bi_ep_comp_desc),
1807*4882a593Smuzhiyun .bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
1808*4882a593Smuzhiyun .bMaxBurst = 0,
1809*4882a593Smuzhiyun };
1810*4882a593Smuzhiyun
1811*4882a593Smuzhiyun static struct usb_endpoint_descriptor uasp_bo_desc = {
1812*4882a593Smuzhiyun .bLength = USB_DT_ENDPOINT_SIZE,
1813*4882a593Smuzhiyun .bDescriptorType = USB_DT_ENDPOINT,
1814*4882a593Smuzhiyun .bEndpointAddress = USB_DIR_OUT,
1815*4882a593Smuzhiyun .bmAttributes = USB_ENDPOINT_XFER_BULK,
1816*4882a593Smuzhiyun .wMaxPacketSize = cpu_to_le16(512),
1817*4882a593Smuzhiyun };
1818*4882a593Smuzhiyun
1819*4882a593Smuzhiyun static struct usb_endpoint_descriptor uasp_fs_bo_desc = {
1820*4882a593Smuzhiyun .bLength = USB_DT_ENDPOINT_SIZE,
1821*4882a593Smuzhiyun .bDescriptorType = USB_DT_ENDPOINT,
1822*4882a593Smuzhiyun .bEndpointAddress = USB_DIR_OUT,
1823*4882a593Smuzhiyun .bmAttributes = USB_ENDPOINT_XFER_BULK,
1824*4882a593Smuzhiyun };
1825*4882a593Smuzhiyun
1826*4882a593Smuzhiyun static struct usb_pipe_usage_descriptor uasp_bo_pipe_desc = {
1827*4882a593Smuzhiyun .bLength = sizeof(uasp_bo_pipe_desc),
1828*4882a593Smuzhiyun .bDescriptorType = USB_DT_PIPE_USAGE,
1829*4882a593Smuzhiyun .bPipeID = DATA_OUT_PIPE_ID,
1830*4882a593Smuzhiyun };
1831*4882a593Smuzhiyun
1832*4882a593Smuzhiyun static struct usb_endpoint_descriptor uasp_ss_bo_desc = {
1833*4882a593Smuzhiyun .bLength = USB_DT_ENDPOINT_SIZE,
1834*4882a593Smuzhiyun .bDescriptorType = USB_DT_ENDPOINT,
1835*4882a593Smuzhiyun .bEndpointAddress = USB_DIR_OUT,
1836*4882a593Smuzhiyun .bmAttributes = USB_ENDPOINT_XFER_BULK,
1837*4882a593Smuzhiyun .wMaxPacketSize = cpu_to_le16(0x400),
1838*4882a593Smuzhiyun };
1839*4882a593Smuzhiyun
1840*4882a593Smuzhiyun static struct usb_ss_ep_comp_descriptor uasp_bo_ep_comp_desc = {
1841*4882a593Smuzhiyun .bLength = sizeof(uasp_bo_ep_comp_desc),
1842*4882a593Smuzhiyun .bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
1843*4882a593Smuzhiyun .bmAttributes = UASP_SS_EP_COMP_LOG_STREAMS,
1844*4882a593Smuzhiyun };
1845*4882a593Smuzhiyun
1846*4882a593Smuzhiyun static struct usb_ss_ep_comp_descriptor bot_bo_ep_comp_desc = {
1847*4882a593Smuzhiyun .bLength = sizeof(bot_bo_ep_comp_desc),
1848*4882a593Smuzhiyun .bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
1849*4882a593Smuzhiyun };
1850*4882a593Smuzhiyun
1851*4882a593Smuzhiyun static struct usb_endpoint_descriptor uasp_status_desc = {
1852*4882a593Smuzhiyun .bLength = USB_DT_ENDPOINT_SIZE,
1853*4882a593Smuzhiyun .bDescriptorType = USB_DT_ENDPOINT,
1854*4882a593Smuzhiyun .bEndpointAddress = USB_DIR_IN,
1855*4882a593Smuzhiyun .bmAttributes = USB_ENDPOINT_XFER_BULK,
1856*4882a593Smuzhiyun .wMaxPacketSize = cpu_to_le16(512),
1857*4882a593Smuzhiyun };
1858*4882a593Smuzhiyun
1859*4882a593Smuzhiyun static struct usb_endpoint_descriptor uasp_fs_status_desc = {
1860*4882a593Smuzhiyun .bLength = USB_DT_ENDPOINT_SIZE,
1861*4882a593Smuzhiyun .bDescriptorType = USB_DT_ENDPOINT,
1862*4882a593Smuzhiyun .bEndpointAddress = USB_DIR_IN,
1863*4882a593Smuzhiyun .bmAttributes = USB_ENDPOINT_XFER_BULK,
1864*4882a593Smuzhiyun };
1865*4882a593Smuzhiyun
1866*4882a593Smuzhiyun static struct usb_pipe_usage_descriptor uasp_status_pipe_desc = {
1867*4882a593Smuzhiyun .bLength = sizeof(uasp_status_pipe_desc),
1868*4882a593Smuzhiyun .bDescriptorType = USB_DT_PIPE_USAGE,
1869*4882a593Smuzhiyun .bPipeID = STATUS_PIPE_ID,
1870*4882a593Smuzhiyun };
1871*4882a593Smuzhiyun
1872*4882a593Smuzhiyun static struct usb_endpoint_descriptor uasp_ss_status_desc = {
1873*4882a593Smuzhiyun .bLength = USB_DT_ENDPOINT_SIZE,
1874*4882a593Smuzhiyun .bDescriptorType = USB_DT_ENDPOINT,
1875*4882a593Smuzhiyun .bEndpointAddress = USB_DIR_IN,
1876*4882a593Smuzhiyun .bmAttributes = USB_ENDPOINT_XFER_BULK,
1877*4882a593Smuzhiyun .wMaxPacketSize = cpu_to_le16(1024),
1878*4882a593Smuzhiyun };
1879*4882a593Smuzhiyun
1880*4882a593Smuzhiyun static struct usb_ss_ep_comp_descriptor uasp_status_in_ep_comp_desc = {
1881*4882a593Smuzhiyun .bLength = sizeof(uasp_status_in_ep_comp_desc),
1882*4882a593Smuzhiyun .bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
1883*4882a593Smuzhiyun .bmAttributes = UASP_SS_EP_COMP_LOG_STREAMS,
1884*4882a593Smuzhiyun };
1885*4882a593Smuzhiyun
1886*4882a593Smuzhiyun static struct usb_endpoint_descriptor uasp_cmd_desc = {
1887*4882a593Smuzhiyun .bLength = USB_DT_ENDPOINT_SIZE,
1888*4882a593Smuzhiyun .bDescriptorType = USB_DT_ENDPOINT,
1889*4882a593Smuzhiyun .bEndpointAddress = USB_DIR_OUT,
1890*4882a593Smuzhiyun .bmAttributes = USB_ENDPOINT_XFER_BULK,
1891*4882a593Smuzhiyun .wMaxPacketSize = cpu_to_le16(512),
1892*4882a593Smuzhiyun };
1893*4882a593Smuzhiyun
1894*4882a593Smuzhiyun static struct usb_endpoint_descriptor uasp_fs_cmd_desc = {
1895*4882a593Smuzhiyun .bLength = USB_DT_ENDPOINT_SIZE,
1896*4882a593Smuzhiyun .bDescriptorType = USB_DT_ENDPOINT,
1897*4882a593Smuzhiyun .bEndpointAddress = USB_DIR_OUT,
1898*4882a593Smuzhiyun .bmAttributes = USB_ENDPOINT_XFER_BULK,
1899*4882a593Smuzhiyun };
1900*4882a593Smuzhiyun
1901*4882a593Smuzhiyun static struct usb_pipe_usage_descriptor uasp_cmd_pipe_desc = {
1902*4882a593Smuzhiyun .bLength = sizeof(uasp_cmd_pipe_desc),
1903*4882a593Smuzhiyun .bDescriptorType = USB_DT_PIPE_USAGE,
1904*4882a593Smuzhiyun .bPipeID = CMD_PIPE_ID,
1905*4882a593Smuzhiyun };
1906*4882a593Smuzhiyun
1907*4882a593Smuzhiyun static struct usb_endpoint_descriptor uasp_ss_cmd_desc = {
1908*4882a593Smuzhiyun .bLength = USB_DT_ENDPOINT_SIZE,
1909*4882a593Smuzhiyun .bDescriptorType = USB_DT_ENDPOINT,
1910*4882a593Smuzhiyun .bEndpointAddress = USB_DIR_OUT,
1911*4882a593Smuzhiyun .bmAttributes = USB_ENDPOINT_XFER_BULK,
1912*4882a593Smuzhiyun .wMaxPacketSize = cpu_to_le16(1024),
1913*4882a593Smuzhiyun };
1914*4882a593Smuzhiyun
1915*4882a593Smuzhiyun static struct usb_ss_ep_comp_descriptor uasp_cmd_comp_desc = {
1916*4882a593Smuzhiyun .bLength = sizeof(uasp_cmd_comp_desc),
1917*4882a593Smuzhiyun .bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
1918*4882a593Smuzhiyun };
1919*4882a593Smuzhiyun
1920*4882a593Smuzhiyun static struct usb_descriptor_header *uasp_fs_function_desc[] = {
1921*4882a593Smuzhiyun (struct usb_descriptor_header *) &bot_intf_desc,
1922*4882a593Smuzhiyun (struct usb_descriptor_header *) &uasp_fs_bi_desc,
1923*4882a593Smuzhiyun (struct usb_descriptor_header *) &uasp_fs_bo_desc,
1924*4882a593Smuzhiyun
1925*4882a593Smuzhiyun (struct usb_descriptor_header *) &uasp_intf_desc,
1926*4882a593Smuzhiyun (struct usb_descriptor_header *) &uasp_fs_bi_desc,
1927*4882a593Smuzhiyun (struct usb_descriptor_header *) &uasp_bi_pipe_desc,
1928*4882a593Smuzhiyun (struct usb_descriptor_header *) &uasp_fs_bo_desc,
1929*4882a593Smuzhiyun (struct usb_descriptor_header *) &uasp_bo_pipe_desc,
1930*4882a593Smuzhiyun (struct usb_descriptor_header *) &uasp_fs_status_desc,
1931*4882a593Smuzhiyun (struct usb_descriptor_header *) &uasp_status_pipe_desc,
1932*4882a593Smuzhiyun (struct usb_descriptor_header *) &uasp_fs_cmd_desc,
1933*4882a593Smuzhiyun (struct usb_descriptor_header *) &uasp_cmd_pipe_desc,
1934*4882a593Smuzhiyun NULL,
1935*4882a593Smuzhiyun };
1936*4882a593Smuzhiyun
1937*4882a593Smuzhiyun static struct usb_descriptor_header *uasp_hs_function_desc[] = {
1938*4882a593Smuzhiyun (struct usb_descriptor_header *) &bot_intf_desc,
1939*4882a593Smuzhiyun (struct usb_descriptor_header *) &uasp_bi_desc,
1940*4882a593Smuzhiyun (struct usb_descriptor_header *) &uasp_bo_desc,
1941*4882a593Smuzhiyun
1942*4882a593Smuzhiyun (struct usb_descriptor_header *) &uasp_intf_desc,
1943*4882a593Smuzhiyun (struct usb_descriptor_header *) &uasp_bi_desc,
1944*4882a593Smuzhiyun (struct usb_descriptor_header *) &uasp_bi_pipe_desc,
1945*4882a593Smuzhiyun (struct usb_descriptor_header *) &uasp_bo_desc,
1946*4882a593Smuzhiyun (struct usb_descriptor_header *) &uasp_bo_pipe_desc,
1947*4882a593Smuzhiyun (struct usb_descriptor_header *) &uasp_status_desc,
1948*4882a593Smuzhiyun (struct usb_descriptor_header *) &uasp_status_pipe_desc,
1949*4882a593Smuzhiyun (struct usb_descriptor_header *) &uasp_cmd_desc,
1950*4882a593Smuzhiyun (struct usb_descriptor_header *) &uasp_cmd_pipe_desc,
1951*4882a593Smuzhiyun NULL,
1952*4882a593Smuzhiyun };
1953*4882a593Smuzhiyun
1954*4882a593Smuzhiyun static struct usb_descriptor_header *uasp_ss_function_desc[] = {
1955*4882a593Smuzhiyun (struct usb_descriptor_header *) &bot_intf_desc,
1956*4882a593Smuzhiyun (struct usb_descriptor_header *) &uasp_ss_bi_desc,
1957*4882a593Smuzhiyun (struct usb_descriptor_header *) &bot_bi_ep_comp_desc,
1958*4882a593Smuzhiyun (struct usb_descriptor_header *) &uasp_ss_bo_desc,
1959*4882a593Smuzhiyun (struct usb_descriptor_header *) &bot_bo_ep_comp_desc,
1960*4882a593Smuzhiyun
1961*4882a593Smuzhiyun (struct usb_descriptor_header *) &uasp_intf_desc,
1962*4882a593Smuzhiyun (struct usb_descriptor_header *) &uasp_ss_bi_desc,
1963*4882a593Smuzhiyun (struct usb_descriptor_header *) &uasp_bi_ep_comp_desc,
1964*4882a593Smuzhiyun (struct usb_descriptor_header *) &uasp_bi_pipe_desc,
1965*4882a593Smuzhiyun (struct usb_descriptor_header *) &uasp_ss_bo_desc,
1966*4882a593Smuzhiyun (struct usb_descriptor_header *) &uasp_bo_ep_comp_desc,
1967*4882a593Smuzhiyun (struct usb_descriptor_header *) &uasp_bo_pipe_desc,
1968*4882a593Smuzhiyun (struct usb_descriptor_header *) &uasp_ss_status_desc,
1969*4882a593Smuzhiyun (struct usb_descriptor_header *) &uasp_status_in_ep_comp_desc,
1970*4882a593Smuzhiyun (struct usb_descriptor_header *) &uasp_status_pipe_desc,
1971*4882a593Smuzhiyun (struct usb_descriptor_header *) &uasp_ss_cmd_desc,
1972*4882a593Smuzhiyun (struct usb_descriptor_header *) &uasp_cmd_comp_desc,
1973*4882a593Smuzhiyun (struct usb_descriptor_header *) &uasp_cmd_pipe_desc,
1974*4882a593Smuzhiyun NULL,
1975*4882a593Smuzhiyun };
1976*4882a593Smuzhiyun
1977*4882a593Smuzhiyun static struct usb_string tcm_us_strings[] = {
1978*4882a593Smuzhiyun [USB_G_STR_INT_UAS].s = "USB Attached SCSI",
1979*4882a593Smuzhiyun [USB_G_STR_INT_BBB].s = "Bulk Only Transport",
1980*4882a593Smuzhiyun { },
1981*4882a593Smuzhiyun };
1982*4882a593Smuzhiyun
1983*4882a593Smuzhiyun static struct usb_gadget_strings tcm_stringtab = {
1984*4882a593Smuzhiyun .language = 0x0409,
1985*4882a593Smuzhiyun .strings = tcm_us_strings,
1986*4882a593Smuzhiyun };
1987*4882a593Smuzhiyun
1988*4882a593Smuzhiyun static struct usb_gadget_strings *tcm_strings[] = {
1989*4882a593Smuzhiyun &tcm_stringtab,
1990*4882a593Smuzhiyun NULL,
1991*4882a593Smuzhiyun };
1992*4882a593Smuzhiyun
tcm_bind(struct usb_configuration * c,struct usb_function * f)1993*4882a593Smuzhiyun static int tcm_bind(struct usb_configuration *c, struct usb_function *f)
1994*4882a593Smuzhiyun {
1995*4882a593Smuzhiyun struct f_uas *fu = to_f_uas(f);
1996*4882a593Smuzhiyun struct usb_string *us;
1997*4882a593Smuzhiyun struct usb_gadget *gadget = c->cdev->gadget;
1998*4882a593Smuzhiyun struct usb_ep *ep;
1999*4882a593Smuzhiyun struct f_tcm_opts *opts;
2000*4882a593Smuzhiyun int iface;
2001*4882a593Smuzhiyun int ret;
2002*4882a593Smuzhiyun
2003*4882a593Smuzhiyun opts = container_of(f->fi, struct f_tcm_opts, func_inst);
2004*4882a593Smuzhiyun
2005*4882a593Smuzhiyun mutex_lock(&opts->dep_lock);
2006*4882a593Smuzhiyun if (!opts->can_attach) {
2007*4882a593Smuzhiyun mutex_unlock(&opts->dep_lock);
2008*4882a593Smuzhiyun return -ENODEV;
2009*4882a593Smuzhiyun }
2010*4882a593Smuzhiyun mutex_unlock(&opts->dep_lock);
2011*4882a593Smuzhiyun us = usb_gstrings_attach(c->cdev, tcm_strings,
2012*4882a593Smuzhiyun ARRAY_SIZE(tcm_us_strings));
2013*4882a593Smuzhiyun if (IS_ERR(us))
2014*4882a593Smuzhiyun return PTR_ERR(us);
2015*4882a593Smuzhiyun bot_intf_desc.iInterface = us[USB_G_STR_INT_BBB].id;
2016*4882a593Smuzhiyun uasp_intf_desc.iInterface = us[USB_G_STR_INT_UAS].id;
2017*4882a593Smuzhiyun
2018*4882a593Smuzhiyun iface = usb_interface_id(c, f);
2019*4882a593Smuzhiyun if (iface < 0)
2020*4882a593Smuzhiyun return iface;
2021*4882a593Smuzhiyun
2022*4882a593Smuzhiyun bot_intf_desc.bInterfaceNumber = iface;
2023*4882a593Smuzhiyun uasp_intf_desc.bInterfaceNumber = iface;
2024*4882a593Smuzhiyun fu->iface = iface;
2025*4882a593Smuzhiyun ep = usb_ep_autoconfig_ss(gadget, &uasp_ss_bi_desc,
2026*4882a593Smuzhiyun &uasp_bi_ep_comp_desc);
2027*4882a593Smuzhiyun if (!ep)
2028*4882a593Smuzhiyun goto ep_fail;
2029*4882a593Smuzhiyun
2030*4882a593Smuzhiyun fu->ep_in = ep;
2031*4882a593Smuzhiyun
2032*4882a593Smuzhiyun ep = usb_ep_autoconfig_ss(gadget, &uasp_ss_bo_desc,
2033*4882a593Smuzhiyun &uasp_bo_ep_comp_desc);
2034*4882a593Smuzhiyun if (!ep)
2035*4882a593Smuzhiyun goto ep_fail;
2036*4882a593Smuzhiyun fu->ep_out = ep;
2037*4882a593Smuzhiyun
2038*4882a593Smuzhiyun ep = usb_ep_autoconfig_ss(gadget, &uasp_ss_status_desc,
2039*4882a593Smuzhiyun &uasp_status_in_ep_comp_desc);
2040*4882a593Smuzhiyun if (!ep)
2041*4882a593Smuzhiyun goto ep_fail;
2042*4882a593Smuzhiyun fu->ep_status = ep;
2043*4882a593Smuzhiyun
2044*4882a593Smuzhiyun ep = usb_ep_autoconfig_ss(gadget, &uasp_ss_cmd_desc,
2045*4882a593Smuzhiyun &uasp_cmd_comp_desc);
2046*4882a593Smuzhiyun if (!ep)
2047*4882a593Smuzhiyun goto ep_fail;
2048*4882a593Smuzhiyun fu->ep_cmd = ep;
2049*4882a593Smuzhiyun
2050*4882a593Smuzhiyun /* Assume endpoint addresses are the same for both speeds */
2051*4882a593Smuzhiyun uasp_bi_desc.bEndpointAddress = uasp_ss_bi_desc.bEndpointAddress;
2052*4882a593Smuzhiyun uasp_bo_desc.bEndpointAddress = uasp_ss_bo_desc.bEndpointAddress;
2053*4882a593Smuzhiyun uasp_status_desc.bEndpointAddress =
2054*4882a593Smuzhiyun uasp_ss_status_desc.bEndpointAddress;
2055*4882a593Smuzhiyun uasp_cmd_desc.bEndpointAddress = uasp_ss_cmd_desc.bEndpointAddress;
2056*4882a593Smuzhiyun
2057*4882a593Smuzhiyun uasp_fs_bi_desc.bEndpointAddress = uasp_ss_bi_desc.bEndpointAddress;
2058*4882a593Smuzhiyun uasp_fs_bo_desc.bEndpointAddress = uasp_ss_bo_desc.bEndpointAddress;
2059*4882a593Smuzhiyun uasp_fs_status_desc.bEndpointAddress =
2060*4882a593Smuzhiyun uasp_ss_status_desc.bEndpointAddress;
2061*4882a593Smuzhiyun uasp_fs_cmd_desc.bEndpointAddress = uasp_ss_cmd_desc.bEndpointAddress;
2062*4882a593Smuzhiyun
2063*4882a593Smuzhiyun ret = usb_assign_descriptors(f, uasp_fs_function_desc,
2064*4882a593Smuzhiyun uasp_hs_function_desc, uasp_ss_function_desc,
2065*4882a593Smuzhiyun uasp_ss_function_desc);
2066*4882a593Smuzhiyun if (ret)
2067*4882a593Smuzhiyun goto ep_fail;
2068*4882a593Smuzhiyun
2069*4882a593Smuzhiyun return 0;
2070*4882a593Smuzhiyun ep_fail:
2071*4882a593Smuzhiyun pr_err("Can't claim all required eps\n");
2072*4882a593Smuzhiyun
2073*4882a593Smuzhiyun return -ENOTSUPP;
2074*4882a593Smuzhiyun }
2075*4882a593Smuzhiyun
2076*4882a593Smuzhiyun struct guas_setup_wq {
2077*4882a593Smuzhiyun struct work_struct work;
2078*4882a593Smuzhiyun struct f_uas *fu;
2079*4882a593Smuzhiyun unsigned int alt;
2080*4882a593Smuzhiyun };
2081*4882a593Smuzhiyun
tcm_delayed_set_alt(struct work_struct * wq)2082*4882a593Smuzhiyun static void tcm_delayed_set_alt(struct work_struct *wq)
2083*4882a593Smuzhiyun {
2084*4882a593Smuzhiyun struct guas_setup_wq *work = container_of(wq, struct guas_setup_wq,
2085*4882a593Smuzhiyun work);
2086*4882a593Smuzhiyun struct f_uas *fu = work->fu;
2087*4882a593Smuzhiyun int alt = work->alt;
2088*4882a593Smuzhiyun
2089*4882a593Smuzhiyun kfree(work);
2090*4882a593Smuzhiyun
2091*4882a593Smuzhiyun if (fu->flags & USBG_IS_BOT)
2092*4882a593Smuzhiyun bot_cleanup_old_alt(fu);
2093*4882a593Smuzhiyun if (fu->flags & USBG_IS_UAS)
2094*4882a593Smuzhiyun uasp_cleanup_old_alt(fu);
2095*4882a593Smuzhiyun
2096*4882a593Smuzhiyun if (alt == USB_G_ALT_INT_BBB)
2097*4882a593Smuzhiyun bot_set_alt(fu);
2098*4882a593Smuzhiyun else if (alt == USB_G_ALT_INT_UAS)
2099*4882a593Smuzhiyun uasp_set_alt(fu);
2100*4882a593Smuzhiyun usb_composite_setup_continue(fu->function.config->cdev);
2101*4882a593Smuzhiyun }
2102*4882a593Smuzhiyun
tcm_get_alt(struct usb_function * f,unsigned intf)2103*4882a593Smuzhiyun static int tcm_get_alt(struct usb_function *f, unsigned intf)
2104*4882a593Smuzhiyun {
2105*4882a593Smuzhiyun if (intf == bot_intf_desc.bInterfaceNumber)
2106*4882a593Smuzhiyun return USB_G_ALT_INT_BBB;
2107*4882a593Smuzhiyun if (intf == uasp_intf_desc.bInterfaceNumber)
2108*4882a593Smuzhiyun return USB_G_ALT_INT_UAS;
2109*4882a593Smuzhiyun
2110*4882a593Smuzhiyun return -EOPNOTSUPP;
2111*4882a593Smuzhiyun }
2112*4882a593Smuzhiyun
tcm_set_alt(struct usb_function * f,unsigned intf,unsigned alt)2113*4882a593Smuzhiyun static int tcm_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
2114*4882a593Smuzhiyun {
2115*4882a593Smuzhiyun struct f_uas *fu = to_f_uas(f);
2116*4882a593Smuzhiyun
2117*4882a593Smuzhiyun if ((alt == USB_G_ALT_INT_BBB) || (alt == USB_G_ALT_INT_UAS)) {
2118*4882a593Smuzhiyun struct guas_setup_wq *work;
2119*4882a593Smuzhiyun
2120*4882a593Smuzhiyun work = kmalloc(sizeof(*work), GFP_ATOMIC);
2121*4882a593Smuzhiyun if (!work)
2122*4882a593Smuzhiyun return -ENOMEM;
2123*4882a593Smuzhiyun INIT_WORK(&work->work, tcm_delayed_set_alt);
2124*4882a593Smuzhiyun work->fu = fu;
2125*4882a593Smuzhiyun work->alt = alt;
2126*4882a593Smuzhiyun schedule_work(&work->work);
2127*4882a593Smuzhiyun return USB_GADGET_DELAYED_STATUS;
2128*4882a593Smuzhiyun }
2129*4882a593Smuzhiyun return -EOPNOTSUPP;
2130*4882a593Smuzhiyun }
2131*4882a593Smuzhiyun
tcm_disable(struct usb_function * f)2132*4882a593Smuzhiyun static void tcm_disable(struct usb_function *f)
2133*4882a593Smuzhiyun {
2134*4882a593Smuzhiyun struct f_uas *fu = to_f_uas(f);
2135*4882a593Smuzhiyun
2136*4882a593Smuzhiyun if (fu->flags & USBG_IS_UAS)
2137*4882a593Smuzhiyun uasp_cleanup_old_alt(fu);
2138*4882a593Smuzhiyun else if (fu->flags & USBG_IS_BOT)
2139*4882a593Smuzhiyun bot_cleanup_old_alt(fu);
2140*4882a593Smuzhiyun fu->flags = 0;
2141*4882a593Smuzhiyun }
2142*4882a593Smuzhiyun
tcm_setup(struct usb_function * f,const struct usb_ctrlrequest * ctrl)2143*4882a593Smuzhiyun static int tcm_setup(struct usb_function *f,
2144*4882a593Smuzhiyun const struct usb_ctrlrequest *ctrl)
2145*4882a593Smuzhiyun {
2146*4882a593Smuzhiyun struct f_uas *fu = to_f_uas(f);
2147*4882a593Smuzhiyun
2148*4882a593Smuzhiyun if (!(fu->flags & USBG_IS_BOT))
2149*4882a593Smuzhiyun return -EOPNOTSUPP;
2150*4882a593Smuzhiyun
2151*4882a593Smuzhiyun return usbg_bot_setup(f, ctrl);
2152*4882a593Smuzhiyun }
2153*4882a593Smuzhiyun
to_f_tcm_opts(struct config_item * item)2154*4882a593Smuzhiyun static inline struct f_tcm_opts *to_f_tcm_opts(struct config_item *item)
2155*4882a593Smuzhiyun {
2156*4882a593Smuzhiyun return container_of(to_config_group(item), struct f_tcm_opts,
2157*4882a593Smuzhiyun func_inst.group);
2158*4882a593Smuzhiyun }
2159*4882a593Smuzhiyun
tcm_attr_release(struct config_item * item)2160*4882a593Smuzhiyun static void tcm_attr_release(struct config_item *item)
2161*4882a593Smuzhiyun {
2162*4882a593Smuzhiyun struct f_tcm_opts *opts = to_f_tcm_opts(item);
2163*4882a593Smuzhiyun
2164*4882a593Smuzhiyun usb_put_function_instance(&opts->func_inst);
2165*4882a593Smuzhiyun }
2166*4882a593Smuzhiyun
2167*4882a593Smuzhiyun static struct configfs_item_operations tcm_item_ops = {
2168*4882a593Smuzhiyun .release = tcm_attr_release,
2169*4882a593Smuzhiyun };
2170*4882a593Smuzhiyun
2171*4882a593Smuzhiyun static const struct config_item_type tcm_func_type = {
2172*4882a593Smuzhiyun .ct_item_ops = &tcm_item_ops,
2173*4882a593Smuzhiyun .ct_owner = THIS_MODULE,
2174*4882a593Smuzhiyun };
2175*4882a593Smuzhiyun
tcm_free_inst(struct usb_function_instance * f)2176*4882a593Smuzhiyun static void tcm_free_inst(struct usb_function_instance *f)
2177*4882a593Smuzhiyun {
2178*4882a593Smuzhiyun struct f_tcm_opts *opts;
2179*4882a593Smuzhiyun unsigned i;
2180*4882a593Smuzhiyun
2181*4882a593Smuzhiyun opts = container_of(f, struct f_tcm_opts, func_inst);
2182*4882a593Smuzhiyun
2183*4882a593Smuzhiyun mutex_lock(&tpg_instances_lock);
2184*4882a593Smuzhiyun for (i = 0; i < TPG_INSTANCES; ++i)
2185*4882a593Smuzhiyun if (tpg_instances[i].func_inst == f)
2186*4882a593Smuzhiyun break;
2187*4882a593Smuzhiyun if (i < TPG_INSTANCES)
2188*4882a593Smuzhiyun tpg_instances[i].func_inst = NULL;
2189*4882a593Smuzhiyun mutex_unlock(&tpg_instances_lock);
2190*4882a593Smuzhiyun
2191*4882a593Smuzhiyun kfree(opts);
2192*4882a593Smuzhiyun }
2193*4882a593Smuzhiyun
tcm_register_callback(struct usb_function_instance * f)2194*4882a593Smuzhiyun static int tcm_register_callback(struct usb_function_instance *f)
2195*4882a593Smuzhiyun {
2196*4882a593Smuzhiyun struct f_tcm_opts *opts = container_of(f, struct f_tcm_opts, func_inst);
2197*4882a593Smuzhiyun
2198*4882a593Smuzhiyun mutex_lock(&opts->dep_lock);
2199*4882a593Smuzhiyun opts->can_attach = true;
2200*4882a593Smuzhiyun mutex_unlock(&opts->dep_lock);
2201*4882a593Smuzhiyun
2202*4882a593Smuzhiyun return 0;
2203*4882a593Smuzhiyun }
2204*4882a593Smuzhiyun
tcm_unregister_callback(struct usb_function_instance * f)2205*4882a593Smuzhiyun static void tcm_unregister_callback(struct usb_function_instance *f)
2206*4882a593Smuzhiyun {
2207*4882a593Smuzhiyun struct f_tcm_opts *opts = container_of(f, struct f_tcm_opts, func_inst);
2208*4882a593Smuzhiyun
2209*4882a593Smuzhiyun mutex_lock(&opts->dep_lock);
2210*4882a593Smuzhiyun unregister_gadget_item(opts->
2211*4882a593Smuzhiyun func_inst.group.cg_item.ci_parent->ci_parent);
2212*4882a593Smuzhiyun opts->can_attach = false;
2213*4882a593Smuzhiyun mutex_unlock(&opts->dep_lock);
2214*4882a593Smuzhiyun }
2215*4882a593Smuzhiyun
usbg_attach(struct usbg_tpg * tpg)2216*4882a593Smuzhiyun static int usbg_attach(struct usbg_tpg *tpg)
2217*4882a593Smuzhiyun {
2218*4882a593Smuzhiyun struct usb_function_instance *f = tpg->fi;
2219*4882a593Smuzhiyun struct f_tcm_opts *opts = container_of(f, struct f_tcm_opts, func_inst);
2220*4882a593Smuzhiyun
2221*4882a593Smuzhiyun if (opts->tcm_register_callback)
2222*4882a593Smuzhiyun return opts->tcm_register_callback(f);
2223*4882a593Smuzhiyun
2224*4882a593Smuzhiyun return 0;
2225*4882a593Smuzhiyun }
2226*4882a593Smuzhiyun
usbg_detach(struct usbg_tpg * tpg)2227*4882a593Smuzhiyun static void usbg_detach(struct usbg_tpg *tpg)
2228*4882a593Smuzhiyun {
2229*4882a593Smuzhiyun struct usb_function_instance *f = tpg->fi;
2230*4882a593Smuzhiyun struct f_tcm_opts *opts = container_of(f, struct f_tcm_opts, func_inst);
2231*4882a593Smuzhiyun
2232*4882a593Smuzhiyun if (opts->tcm_unregister_callback)
2233*4882a593Smuzhiyun opts->tcm_unregister_callback(f);
2234*4882a593Smuzhiyun }
2235*4882a593Smuzhiyun
tcm_set_name(struct usb_function_instance * f,const char * name)2236*4882a593Smuzhiyun static int tcm_set_name(struct usb_function_instance *f, const char *name)
2237*4882a593Smuzhiyun {
2238*4882a593Smuzhiyun struct f_tcm_opts *opts = container_of(f, struct f_tcm_opts, func_inst);
2239*4882a593Smuzhiyun
2240*4882a593Smuzhiyun pr_debug("tcm: Activating %s\n", name);
2241*4882a593Smuzhiyun
2242*4882a593Smuzhiyun mutex_lock(&opts->dep_lock);
2243*4882a593Smuzhiyun opts->ready = true;
2244*4882a593Smuzhiyun mutex_unlock(&opts->dep_lock);
2245*4882a593Smuzhiyun
2246*4882a593Smuzhiyun return 0;
2247*4882a593Smuzhiyun }
2248*4882a593Smuzhiyun
tcm_alloc_inst(void)2249*4882a593Smuzhiyun static struct usb_function_instance *tcm_alloc_inst(void)
2250*4882a593Smuzhiyun {
2251*4882a593Smuzhiyun struct f_tcm_opts *opts;
2252*4882a593Smuzhiyun int i;
2253*4882a593Smuzhiyun
2254*4882a593Smuzhiyun
2255*4882a593Smuzhiyun opts = kzalloc(sizeof(*opts), GFP_KERNEL);
2256*4882a593Smuzhiyun if (!opts)
2257*4882a593Smuzhiyun return ERR_PTR(-ENOMEM);
2258*4882a593Smuzhiyun
2259*4882a593Smuzhiyun mutex_lock(&tpg_instances_lock);
2260*4882a593Smuzhiyun for (i = 0; i < TPG_INSTANCES; ++i)
2261*4882a593Smuzhiyun if (!tpg_instances[i].func_inst)
2262*4882a593Smuzhiyun break;
2263*4882a593Smuzhiyun
2264*4882a593Smuzhiyun if (i == TPG_INSTANCES) {
2265*4882a593Smuzhiyun mutex_unlock(&tpg_instances_lock);
2266*4882a593Smuzhiyun kfree(opts);
2267*4882a593Smuzhiyun return ERR_PTR(-EBUSY);
2268*4882a593Smuzhiyun }
2269*4882a593Smuzhiyun tpg_instances[i].func_inst = &opts->func_inst;
2270*4882a593Smuzhiyun mutex_unlock(&tpg_instances_lock);
2271*4882a593Smuzhiyun
2272*4882a593Smuzhiyun mutex_init(&opts->dep_lock);
2273*4882a593Smuzhiyun opts->func_inst.set_inst_name = tcm_set_name;
2274*4882a593Smuzhiyun opts->func_inst.free_func_inst = tcm_free_inst;
2275*4882a593Smuzhiyun opts->tcm_register_callback = tcm_register_callback;
2276*4882a593Smuzhiyun opts->tcm_unregister_callback = tcm_unregister_callback;
2277*4882a593Smuzhiyun
2278*4882a593Smuzhiyun config_group_init_type_name(&opts->func_inst.group, "",
2279*4882a593Smuzhiyun &tcm_func_type);
2280*4882a593Smuzhiyun
2281*4882a593Smuzhiyun return &opts->func_inst;
2282*4882a593Smuzhiyun }
2283*4882a593Smuzhiyun
tcm_free(struct usb_function * f)2284*4882a593Smuzhiyun static void tcm_free(struct usb_function *f)
2285*4882a593Smuzhiyun {
2286*4882a593Smuzhiyun struct f_uas *tcm = to_f_uas(f);
2287*4882a593Smuzhiyun
2288*4882a593Smuzhiyun kfree(tcm);
2289*4882a593Smuzhiyun }
2290*4882a593Smuzhiyun
tcm_unbind(struct usb_configuration * c,struct usb_function * f)2291*4882a593Smuzhiyun static void tcm_unbind(struct usb_configuration *c, struct usb_function *f)
2292*4882a593Smuzhiyun {
2293*4882a593Smuzhiyun usb_free_all_descriptors(f);
2294*4882a593Smuzhiyun }
2295*4882a593Smuzhiyun
tcm_alloc(struct usb_function_instance * fi)2296*4882a593Smuzhiyun static struct usb_function *tcm_alloc(struct usb_function_instance *fi)
2297*4882a593Smuzhiyun {
2298*4882a593Smuzhiyun struct f_uas *fu;
2299*4882a593Smuzhiyun unsigned i;
2300*4882a593Smuzhiyun
2301*4882a593Smuzhiyun mutex_lock(&tpg_instances_lock);
2302*4882a593Smuzhiyun for (i = 0; i < TPG_INSTANCES; ++i)
2303*4882a593Smuzhiyun if (tpg_instances[i].func_inst == fi)
2304*4882a593Smuzhiyun break;
2305*4882a593Smuzhiyun if (i == TPG_INSTANCES) {
2306*4882a593Smuzhiyun mutex_unlock(&tpg_instances_lock);
2307*4882a593Smuzhiyun return ERR_PTR(-ENODEV);
2308*4882a593Smuzhiyun }
2309*4882a593Smuzhiyun
2310*4882a593Smuzhiyun fu = kzalloc(sizeof(*fu), GFP_KERNEL);
2311*4882a593Smuzhiyun if (!fu) {
2312*4882a593Smuzhiyun mutex_unlock(&tpg_instances_lock);
2313*4882a593Smuzhiyun return ERR_PTR(-ENOMEM);
2314*4882a593Smuzhiyun }
2315*4882a593Smuzhiyun
2316*4882a593Smuzhiyun fu->function.name = "Target Function";
2317*4882a593Smuzhiyun fu->function.bind = tcm_bind;
2318*4882a593Smuzhiyun fu->function.unbind = tcm_unbind;
2319*4882a593Smuzhiyun fu->function.set_alt = tcm_set_alt;
2320*4882a593Smuzhiyun fu->function.get_alt = tcm_get_alt;
2321*4882a593Smuzhiyun fu->function.setup = tcm_setup;
2322*4882a593Smuzhiyun fu->function.disable = tcm_disable;
2323*4882a593Smuzhiyun fu->function.free_func = tcm_free;
2324*4882a593Smuzhiyun fu->tpg = tpg_instances[i].tpg;
2325*4882a593Smuzhiyun mutex_unlock(&tpg_instances_lock);
2326*4882a593Smuzhiyun
2327*4882a593Smuzhiyun return &fu->function;
2328*4882a593Smuzhiyun }
2329*4882a593Smuzhiyun
2330*4882a593Smuzhiyun DECLARE_USB_FUNCTION(tcm, tcm_alloc_inst, tcm_alloc);
2331*4882a593Smuzhiyun
tcm_init(void)2332*4882a593Smuzhiyun static int tcm_init(void)
2333*4882a593Smuzhiyun {
2334*4882a593Smuzhiyun int ret;
2335*4882a593Smuzhiyun
2336*4882a593Smuzhiyun ret = usb_function_register(&tcmusb_func);
2337*4882a593Smuzhiyun if (ret)
2338*4882a593Smuzhiyun return ret;
2339*4882a593Smuzhiyun
2340*4882a593Smuzhiyun ret = target_register_template(&usbg_ops);
2341*4882a593Smuzhiyun if (ret)
2342*4882a593Smuzhiyun usb_function_unregister(&tcmusb_func);
2343*4882a593Smuzhiyun
2344*4882a593Smuzhiyun return ret;
2345*4882a593Smuzhiyun }
2346*4882a593Smuzhiyun module_init(tcm_init);
2347*4882a593Smuzhiyun
tcm_exit(void)2348*4882a593Smuzhiyun static void tcm_exit(void)
2349*4882a593Smuzhiyun {
2350*4882a593Smuzhiyun target_unregister_template(&usbg_ops);
2351*4882a593Smuzhiyun usb_function_unregister(&tcmusb_func);
2352*4882a593Smuzhiyun }
2353*4882a593Smuzhiyun module_exit(tcm_exit);
2354*4882a593Smuzhiyun
2355*4882a593Smuzhiyun MODULE_LICENSE("GPL");
2356*4882a593Smuzhiyun MODULE_AUTHOR("Sebastian Andrzej Siewior");
2357