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