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