aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-05-21 20:40:42 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-05-21 20:40:42 -0400
commitba01a87e37d3ca9efe141e2907c2ec3f89490b4f (patch)
tree144f2b3534b5428192c6d3645ec49c6de2fcdaa2
parentc9bfa7d75ba7269c97595f03c3152372e8b37823 (diff)
parentc52661d60f636d17e26ad834457db333bd1df494 (diff)
Merge branch 'usb-target-merge' of git://git.kernel.org/pub/scm/linux/kernel/git/nab/target-pending
Pull usb-gadget scsi-target merge from Nicholas Bellinger: "As promised, here is the pull request for Sebastian's usb-gadget target UASP / BOT driver for v3.5-rc1. This code has been in linux-next for a number of weeks, and is now ready for an initial merge. This fabric uses the target framework to provide a usb gadget device. This gadget supports the USB Attached SCSI Protocol (UASP) and Bulk Only Transfers (BOT or BBB). BOT is the primary interface, UAS is the alternative interface. Note this series is dependent upon a single target core patch for adding se_cmd->unknown_data_length in target-pending/for-next, that got merged in the parent. Kudos to Sebastian for making this driver happen so easily, and for his patches to improve usb-core and target core along the way to his goal. Also thanks to Felipe + Greg-KH for their help in getting this driver ready for mainline." * 'usb-target-merge' of git://git.kernel.org/pub/scm/linux/kernel/git/nab/target-pending: usb-gadget: Initial merge of target module for UASP + BOT
-rw-r--r--drivers/usb/gadget/Kconfig10
-rw-r--r--drivers/usb/gadget/Makefile2
-rw-r--r--drivers/usb/gadget/tcm_usb_gadget.c2480
-rw-r--r--drivers/usb/gadget/tcm_usb_gadget.h146
4 files changed, 2638 insertions, 0 deletions
diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
index 2633f759511..569b33e754b 100644
--- a/drivers/usb/gadget/Kconfig
+++ b/drivers/usb/gadget/Kconfig
@@ -798,6 +798,16 @@ config USB_MASS_STORAGE
798 Say "y" to link the driver statically, or "m" to build 798 Say "y" to link the driver statically, or "m" to build
799 a dynamically linked module called "g_mass_storage". 799 a dynamically linked module called "g_mass_storage".
800 800
801config USB_GADGET_TARGET
802 tristate "USB Gadget Target Fabric Module"
803 depends on TARGET_CORE
804 help
805 This fabric is an USB gadget. Two USB protocols are supported that is
806 BBB or BOT (Bulk Only Transport) and UAS (USB Attached SCSI). BOT is
807 advertised on alternative interface 0 (primary) and UAS is on
808 alternative interface 1. Both protocols can work on USB2.0 and USB3.0.
809 UAS utilizes the USB 3.0 feature called streams support.
810
801config USB_G_SERIAL 811config USB_G_SERIAL
802 tristate "Serial Gadget (with CDC ACM and CDC OBEX support)" 812 tristate "Serial Gadget (with CDC ACM and CDC OBEX support)"
803 help 813 help
diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile
index b7f6eefc392..fc5b83683de 100644
--- a/drivers/usb/gadget/Makefile
+++ b/drivers/usb/gadget/Makefile
@@ -52,6 +52,7 @@ g_nokia-y := nokia.o
52g_webcam-y := webcam.o 52g_webcam-y := webcam.o
53g_ncm-y := ncm.o 53g_ncm-y := ncm.o
54g_acm_ms-y := acm_ms.o 54g_acm_ms-y := acm_ms.o
55g_tcm_usb_gadget-y := tcm_usb_gadget.o
55 56
56obj-$(CONFIG_USB_ZERO) += g_zero.o 57obj-$(CONFIG_USB_ZERO) += g_zero.o
57obj-$(CONFIG_USB_AUDIO) += g_audio.o 58obj-$(CONFIG_USB_AUDIO) += g_audio.o
@@ -71,3 +72,4 @@ obj-$(CONFIG_USB_G_NOKIA) += g_nokia.o
71obj-$(CONFIG_USB_G_WEBCAM) += g_webcam.o 72obj-$(CONFIG_USB_G_WEBCAM) += g_webcam.o
72obj-$(CONFIG_USB_G_NCM) += g_ncm.o 73obj-$(CONFIG_USB_G_NCM) += g_ncm.o
73obj-$(CONFIG_USB_G_ACM_MS) += g_acm_ms.o 74obj-$(CONFIG_USB_G_ACM_MS) += g_acm_ms.o
75obj-$(CONFIG_USB_GADGET_TARGET) += tcm_usb_gadget.o
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
35static struct target_fabric_configfs *usbg_fabric_configfs;
36
37static inline struct f_uas *to_f_uas(struct usb_function *f)
38{
39 return container_of(f, struct f_uas, function);
40}
41
42static void usbg_cmd_release(struct kref *);
43
44static 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
51static 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
64static 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
79static 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
103static 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
126static 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