[PATCHv4 11/11] usb: gadget: f_tcm: add configfs support

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Allow using the tcm function as a component of a gadget composed with
ConfigFS.

Signed-off-by: Andrzej Pietrasiewicz <andrzej.p@xxxxxxxxxxx>
---
 Documentation/ABI/testing/configfs-usb-gadget-tcm |  6 ++
 drivers/usb/gadget/Kconfig                        | 14 +++++
 drivers/usb/gadget/function/f_tcm.c               | 72 +++++++++++++++++++++--
 3 files changed, 88 insertions(+), 4 deletions(-)
 create mode 100644 Documentation/ABI/testing/configfs-usb-gadget-tcm

diff --git a/Documentation/ABI/testing/configfs-usb-gadget-tcm b/Documentation/ABI/testing/configfs-usb-gadget-tcm
new file mode 100644
index 0000000..a29ed2d
--- /dev/null
+++ b/Documentation/ABI/testing/configfs-usb-gadget-tcm
@@ -0,0 +1,6 @@
+What:		/config/usb-gadget/gadget/functions/tcm.name
+Date:		Dec 2015
+KernelVersion:	4.5
+Description:
+		There are no attributes because all the configuration
+		is performed in the "target" subsystem of configfs.
diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
index 5bf50db..0527308 100644
--- a/drivers/usb/gadget/Kconfig
+++ b/drivers/usb/gadget/Kconfig
@@ -454,6 +454,20 @@ config USB_CONFIGFS_F_PRINTER
 	  For more information, see Documentation/usb/gadget_printer.txt
 	  which includes sample code for accessing the device file.
 
+config USB_CONFIGFS_F_TCM
+	bool "USB Gadget Target Fabric"
+	depends on TARGET_CORE
+	depends on USB_CONFIGFS
+	select USB_LIBCOMPOSITE
+	select USB_F_TCM
+	help
+	  This fabric is a USB gadget component. Two USB protocols are
+	  supported that is BBB or BOT (Bulk Only Transport) and UAS
+	  (USB Attached SCSI). BOT is advertised on alternative
+	  interface 0 (primary) and UAS is on alternative interface 1.
+	  Both protocols can work on USB2.0 and USB3.0.
+	  UAS utilizes the USB 3.0 feature called streams support.
+
 source "drivers/usb/gadget/legacy/Kconfig"
 
 endchoice
diff --git a/drivers/usb/gadget/function/f_tcm.c b/drivers/usb/gadget/function/f_tcm.c
index 0d86d7f..9cb4a6b 100644
--- a/drivers/usb/gadget/function/f_tcm.c
+++ b/drivers/usb/gadget/function/f_tcm.c
@@ -23,6 +23,7 @@
 
 #include "tcm.h"
 #include "u_tcm.h"
+#include "configfs.h"
 
 #define TPG_INSTANCES		1
 
@@ -1408,8 +1409,16 @@ static struct se_portal_group *usbg_make_tpg(
 	if (!opts->ready)
 		goto unlock_dep;
 
-	if (opts->has_dep && !try_module_get(opts->dependent))
-		goto unlock_dep;
+	if (opts->has_dep) {
+		if (!try_module_get(opts->dependent))
+			goto unlock_dep;
+	} else {
+		ret = configfs_depend_item_unlocked(
+			group->cg_subsys,
+			&opts->func_inst.group.cg_item);
+		if (ret)
+			goto unlock_dep;
+	}
 
 	tpg = kzalloc(sizeof(struct usbg_tpg), GFP_KERNEL);
 	ret = -ENOMEM;
@@ -1443,7 +1452,10 @@ free_workqueue:
 free_tpg:
 	kfree(tpg);
 unref_dep:
-	module_put(opts->dependent);
+	if (opts->has_dep)
+		module_put(opts->dependent);
+	else
+		configfs_undepend_item_unlocked(&opts->func_inst.group.cg_item);
 unlock_dep:
 	mutex_unlock(&opts->dep_lock);
 unlock_inst:
@@ -1474,7 +1486,10 @@ static void usbg_drop_tpg(struct se_portal_group *se_tpg)
 	opts = container_of(tpg_instances[i].func_inst,
 		struct f_tcm_opts, func_inst);
 	mutex_lock(&opts->dep_lock);
-	module_put(opts->dependent);
+	if (opts->has_dep)
+		module_put(opts->dependent);
+	else
+		configfs_undepend_item_unlocked(&opts->func_inst.group.cg_item);
 	mutex_unlock(&opts->dep_lock);
 	mutex_unlock(&tpg_instances_lock);
 
@@ -2181,6 +2196,28 @@ static int tcm_setup(struct usb_function *f,
 	return usbg_bot_setup(f, ctrl);
 }
 
+static inline struct f_tcm_opts *to_f_tcm_opts(struct config_item *item)
+{
+	return container_of(to_config_group(item), struct f_tcm_opts,
+		func_inst.group);
+}
+
+static void tcm_attr_release(struct config_item *item)
+{
+	struct f_tcm_opts *opts = to_f_tcm_opts(item);
+
+	usb_put_function_instance(&opts->func_inst);
+}
+
+static struct configfs_item_operations tcm_item_ops = {
+	.release		= tcm_attr_release,
+};
+
+static struct config_item_type tcm_func_type = {
+	.ct_item_ops	= &tcm_item_ops,
+	.ct_owner	= THIS_MODULE,
+};
+
 static void tcm_free_inst(struct usb_function_instance *f)
 {
 	struct f_tcm_opts *opts;
@@ -2199,6 +2236,28 @@ static void tcm_free_inst(struct usb_function_instance *f)
 	kfree(opts);
 }
 
+static int tcm_register_callback(struct usb_function_instance *f)
+{
+	struct f_tcm_opts *opts = container_of(f, struct f_tcm_opts, func_inst);
+
+	mutex_lock(&opts->dep_lock);
+	opts->can_attach = true;
+	mutex_unlock(&opts->dep_lock);
+
+	return 0;
+}
+
+static void tcm_unregister_callback(struct usb_function_instance *f)
+{
+	struct f_tcm_opts *opts = container_of(f, struct f_tcm_opts, func_inst);
+
+	mutex_lock(&opts->dep_lock);
+	unregister_gadget_item(opts->
+		func_inst.group.cg_item.ci_parent->ci_parent);
+	opts->can_attach = false;
+	mutex_unlock(&opts->dep_lock);
+}
+
 static int usbg_attach(struct usbg_tpg *tpg)
 {
 	struct usb_function_instance *f = tpg->fi;
@@ -2259,6 +2318,11 @@ static struct usb_function_instance *tcm_alloc_inst(void)
 	mutex_init(&opts->dep_lock);
 	opts->func_inst.set_inst_name = tcm_set_name;
 	opts->func_inst.free_func_inst = tcm_free_inst;
+	opts->tcm_register_callback = tcm_register_callback;
+	opts->tcm_unregister_callback = tcm_unregister_callback;
+
+	config_group_init_type_name(&opts->func_inst.group, "",
+			&tcm_func_type);
 
 	return &opts->func_inst;
 }
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux