Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

usb: gadget: f_tcm: add configfs support

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

Signed-off-by: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
Acked-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>

authored by

Andrzej Pietrasiewicz and committed by
Nicholas Bellinger
4bb8548d 9beab5d4

+88 -4
+6
Documentation/ABI/testing/configfs-usb-gadget-tcm
··· 1 + What: /config/usb-gadget/gadget/functions/tcm.name 2 + Date: Dec 2015 3 + KernelVersion: 4.5 4 + Description: 5 + There are no attributes because all the configuration 6 + is performed in the "target" subsystem of configfs.
+14
drivers/usb/gadget/Kconfig
··· 454 454 For more information, see Documentation/usb/gadget_printer.txt 455 455 which includes sample code for accessing the device file. 456 456 457 + config USB_CONFIGFS_F_TCM 458 + bool "USB Gadget Target Fabric" 459 + depends on TARGET_CORE 460 + depends on USB_CONFIGFS 461 + select USB_LIBCOMPOSITE 462 + select USB_F_TCM 463 + help 464 + This fabric is a USB gadget component. Two USB protocols are 465 + supported that is BBB or BOT (Bulk Only Transport) and UAS 466 + (USB Attached SCSI). BOT is advertised on alternative 467 + interface 0 (primary) and UAS is on alternative interface 1. 468 + Both protocols can work on USB2.0 and USB3.0. 469 + UAS utilizes the USB 3.0 feature called streams support. 470 + 457 471 source "drivers/usb/gadget/legacy/Kconfig" 458 472 459 473 endchoice
+68 -4
drivers/usb/gadget/function/f_tcm.c
··· 23 23 24 24 #include "tcm.h" 25 25 #include "u_tcm.h" 26 + #include "configfs.h" 26 27 27 28 #define TPG_INSTANCES 1 28 29 ··· 1403 1402 if (!opts->ready) 1404 1403 goto unlock_dep; 1405 1404 1406 - if (opts->has_dep && !try_module_get(opts->dependent)) 1407 - goto unlock_dep; 1405 + if (opts->has_dep) { 1406 + if (!try_module_get(opts->dependent)) 1407 + goto unlock_dep; 1408 + } else { 1409 + ret = configfs_depend_item_unlocked( 1410 + group->cg_subsys, 1411 + &opts->func_inst.group.cg_item); 1412 + if (ret) 1413 + goto unlock_dep; 1414 + } 1408 1415 1409 1416 tpg = kzalloc(sizeof(struct usbg_tpg), GFP_KERNEL); 1410 1417 ret = -ENOMEM; ··· 1446 1437 free_tpg: 1447 1438 kfree(tpg); 1448 1439 unref_dep: 1449 - module_put(opts->dependent); 1440 + if (opts->has_dep) 1441 + module_put(opts->dependent); 1442 + else 1443 + configfs_undepend_item_unlocked(&opts->func_inst.group.cg_item); 1450 1444 unlock_dep: 1451 1445 mutex_unlock(&opts->dep_lock); 1452 1446 unlock_inst: ··· 1480 1468 opts = container_of(tpg_instances[i].func_inst, 1481 1469 struct f_tcm_opts, func_inst); 1482 1470 mutex_lock(&opts->dep_lock); 1483 - module_put(opts->dependent); 1471 + if (opts->has_dep) 1472 + module_put(opts->dependent); 1473 + else 1474 + configfs_undepend_item_unlocked(&opts->func_inst.group.cg_item); 1484 1475 mutex_unlock(&opts->dep_lock); 1485 1476 mutex_unlock(&tpg_instances_lock); 1486 1477 ··· 2190 2175 return usbg_bot_setup(f, ctrl); 2191 2176 } 2192 2177 2178 + static inline struct f_tcm_opts *to_f_tcm_opts(struct config_item *item) 2179 + { 2180 + return container_of(to_config_group(item), struct f_tcm_opts, 2181 + func_inst.group); 2182 + } 2183 + 2184 + static void tcm_attr_release(struct config_item *item) 2185 + { 2186 + struct f_tcm_opts *opts = to_f_tcm_opts(item); 2187 + 2188 + usb_put_function_instance(&opts->func_inst); 2189 + } 2190 + 2191 + static struct configfs_item_operations tcm_item_ops = { 2192 + .release = tcm_attr_release, 2193 + }; 2194 + 2195 + static struct config_item_type tcm_func_type = { 2196 + .ct_item_ops = &tcm_item_ops, 2197 + .ct_owner = THIS_MODULE, 2198 + }; 2199 + 2193 2200 static void tcm_free_inst(struct usb_function_instance *f) 2194 2201 { 2195 2202 struct f_tcm_opts *opts; ··· 2228 2191 mutex_unlock(&tpg_instances_lock); 2229 2192 2230 2193 kfree(opts); 2194 + } 2195 + 2196 + static int tcm_register_callback(struct usb_function_instance *f) 2197 + { 2198 + struct f_tcm_opts *opts = container_of(f, struct f_tcm_opts, func_inst); 2199 + 2200 + mutex_lock(&opts->dep_lock); 2201 + opts->can_attach = true; 2202 + mutex_unlock(&opts->dep_lock); 2203 + 2204 + return 0; 2205 + } 2206 + 2207 + static void tcm_unregister_callback(struct usb_function_instance *f) 2208 + { 2209 + struct f_tcm_opts *opts = container_of(f, struct f_tcm_opts, func_inst); 2210 + 2211 + mutex_lock(&opts->dep_lock); 2212 + unregister_gadget_item(opts-> 2213 + func_inst.group.cg_item.ci_parent->ci_parent); 2214 + opts->can_attach = false; 2215 + mutex_unlock(&opts->dep_lock); 2231 2216 } 2232 2217 2233 2218 static int usbg_attach(struct usbg_tpg *tpg) ··· 2311 2252 mutex_init(&opts->dep_lock); 2312 2253 opts->func_inst.set_inst_name = tcm_set_name; 2313 2254 opts->func_inst.free_func_inst = tcm_free_inst; 2255 + opts->tcm_register_callback = tcm_register_callback; 2256 + opts->tcm_unregister_callback = tcm_unregister_callback; 2257 + 2258 + config_group_init_type_name(&opts->func_inst.group, "", 2259 + &tcm_func_type); 2314 2260 2315 2261 return &opts->func_inst; 2316 2262 }