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

usb: gadget: f_tcm: convert to new function interface with backward compatibility

Converting tcm to the new function interface requires converting
USB tcm's function code and its users.

This patch converts the f_tcm.c to the new function interface.

The file can be now compiled into a separate module usb_f_tcm.ko.

The old function interface is provided by means of preprocessor conditional
directives. After all users are converted, the old interface can be
removed.

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
dc8c46a5 08a1cb0f

+339 -5
+3
drivers/usb/gadget/Kconfig
··· 199 199 config USB_F_PRINTER 200 200 tristate 201 201 202 + config USB_F_TCM 203 + tristate 204 + 202 205 choice 203 206 tristate "USB Gadget Drivers" 204 207 default USB_ETH
+2
drivers/usb/gadget/function/Makefile
··· 44 44 obj-$(CONFIG_USB_F_HID) += usb_f_hid.o 45 45 usb_f_printer-y := f_printer.o 46 46 obj-$(CONFIG_USB_F_PRINTER) += usb_f_printer.o 47 + usb_f_tcm-y := f_tcm.o 48 + obj-$(CONFIG_USB_F_TCM) += usb_f_tcm.o
+281 -5
drivers/usb/gadget/function/f_tcm.c
··· 22 22 #include <asm/unaligned.h> 23 23 24 24 #include "tcm.h" 25 + #include "u_tcm.h" 26 + 27 + #ifndef USBF_TCM_INCLUDED 28 + 29 + #define TPG_INSTANCES 1 30 + 31 + struct tpg_instance { 32 + struct usb_function_instance *func_inst; 33 + struct usbg_tpg *tpg; 34 + }; 35 + 36 + static struct tpg_instance tpg_instances[TPG_INSTANCES]; 37 + 38 + static DEFINE_MUTEX(tpg_instances_lock); 39 + #endif 25 40 26 41 static inline struct f_uas *to_f_uas(struct usb_function *f) 27 42 { ··· 1386 1371 struct usbg_tpg *tpg; 1387 1372 unsigned long tpgt; 1388 1373 int ret; 1374 + #ifndef USBF_TCM_INCLUDED 1375 + struct f_tcm_opts *opts; 1376 + unsigned i; 1377 + #endif 1389 1378 1390 1379 if (strstr(name, "tpgt_") != name) 1391 1380 return ERR_PTR(-EINVAL); ··· 1400 1381 pr_err("gadgets, you can't do this here.\n"); 1401 1382 return ERR_PTR(-EBUSY); 1402 1383 } 1384 + #ifndef USBF_TCM_INCLUDED 1385 + ret = -ENODEV; 1386 + mutex_lock(&tpg_instances_lock); 1387 + for (i = 0; i < TPG_INSTANCES; ++i) 1388 + if (tpg_instances[i].func_inst && !tpg_instances[i].tpg) 1389 + break; 1390 + if (i == TPG_INSTANCES) 1391 + goto unlock_inst; 1392 + 1393 + opts = container_of(tpg_instances[i].func_inst, struct f_tcm_opts, 1394 + func_inst); 1395 + mutex_lock(&opts->dep_lock); 1396 + if (!opts->ready) 1397 + goto unlock_dep; 1398 + 1399 + if (opts->has_dep && !try_module_get(opts->dependent)) 1400 + goto unlock_dep; 1401 + #endif 1403 1402 1404 1403 tpg = kzalloc(sizeof(struct usbg_tpg), GFP_KERNEL); 1404 + ret = -ENOMEM; 1405 1405 if (!tpg) 1406 + #ifdef USBF_TCM_INCLUDED 1406 1407 return ERR_PTR(-ENOMEM); 1408 + #else 1409 + goto unref_dep; 1410 + #endif 1407 1411 mutex_init(&tpg->tpg_mutex); 1408 1412 atomic_set(&tpg->tpg_port_count, 0); 1409 1413 tpg->workqueue = alloc_workqueue("tcm_usb_gadget", 0, 1); 1410 1414 if (!tpg->workqueue) { 1415 + #ifndef USBF_TCM_INCLUDED 1416 + goto free_tpg; 1417 + #endif 1411 1418 kfree(tpg); 1412 1419 return NULL; 1413 1420 } ··· 1447 1402 */ 1448 1403 ret = core_tpg_register(wwn, &tpg->se_tpg, SCSI_PROTOCOL_SAS); 1449 1404 if (ret < 0) { 1405 + #ifndef USBF_TCM_INCLUDED 1406 + goto free_workqueue; 1407 + #endif 1450 1408 destroy_workqueue(tpg->workqueue); 1451 1409 kfree(tpg); 1452 1410 return NULL; 1453 1411 } 1412 + #ifndef USBF_TCM_INCLUDED 1413 + tpg_instances[i].tpg = tpg; 1414 + tpg->fi = tpg_instances[i].func_inst; 1415 + mutex_unlock(&opts->dep_lock); 1416 + mutex_unlock(&tpg_instances_lock); 1417 + #endif 1454 1418 the_only_tpg_I_currently_have = tpg; 1455 1419 return &tpg->se_tpg; 1420 + #ifndef USBF_TCM_INCLUDED 1421 + free_workqueue: 1422 + destroy_workqueue(tpg->workqueue); 1423 + free_tpg: 1424 + kfree(tpg); 1425 + unref_dep: 1426 + module_put(opts->dependent); 1427 + unlock_dep: 1428 + mutex_unlock(&opts->dep_lock); 1429 + unlock_inst: 1430 + mutex_unlock(&tpg_instances_lock); 1431 + 1432 + return ERR_PTR(ret); 1433 + #endif 1456 1434 } 1457 1435 1458 1436 static int tcm_usbg_drop_nexus(struct usbg_tpg *); ··· 1484 1416 { 1485 1417 struct usbg_tpg *tpg = container_of(se_tpg, 1486 1418 struct usbg_tpg, se_tpg); 1419 + #ifndef USBF_TCM_INCLUDED 1420 + unsigned i; 1421 + struct f_tcm_opts *opts; 1422 + #endif 1487 1423 1488 1424 tcm_usbg_drop_nexus(tpg); 1489 1425 core_tpg_deregister(se_tpg); 1490 1426 destroy_workqueue(tpg->workqueue); 1427 + 1428 + #ifndef USBF_TCM_INCLUDED 1429 + mutex_lock(&tpg_instances_lock); 1430 + for (i = 0; i < TPG_INSTANCES; ++i) 1431 + if (tpg_instances[i].tpg == tpg) 1432 + break; 1433 + if (i < TPG_INSTANCES) 1434 + tpg_instances[i].tpg = NULL; 1435 + opts = container_of(tpg_instances[i].func_inst, 1436 + struct f_tcm_opts, func_inst); 1437 + mutex_lock(&opts->dep_lock); 1438 + module_put(opts->dependent); 1439 + mutex_unlock(&opts->dep_lock); 1440 + mutex_unlock(&tpg_instances_lock); 1441 + #endif 1491 1442 kfree(tpg); 1492 1443 the_only_tpg_I_currently_have = NULL; 1493 1444 } ··· 1527 1440 tport = kzalloc(sizeof(struct usbg_tport), GFP_KERNEL); 1528 1441 if (!(tport)) 1529 1442 return ERR_PTR(-ENOMEM); 1443 + 1530 1444 tport->tport_wwpn = wwpn; 1531 1445 snprintf(tport->tport_name, sizeof(tport->tport_name), "%s", wnn_name); 1532 1446 return &tport->tport_wwn; ··· 2066 1978 struct f_uas *fu = to_f_uas(f); 2067 1979 struct usb_gadget *gadget = c->cdev->gadget; 2068 1980 struct usb_ep *ep; 1981 + #ifndef USBF_TCM_INCLUDED 1982 + struct f_tcm_opts *opts; 1983 + #endif 2069 1984 int iface; 2070 1985 int ret; 1986 + 1987 + #ifndef USBF_TCM_INCLUDED 1988 + opts = container_of(f->fi, struct f_tcm_opts, func_inst); 1989 + 1990 + mutex_lock(&opts->dep_lock); 1991 + if (!opts->can_attach) { 1992 + mutex_unlock(&opts->dep_lock); 1993 + return -ENODEV; 1994 + } 1995 + mutex_unlock(&opts->dep_lock); 1996 + #endif 1997 + if (tcm_us_strings[0].id == 0) { 1998 + ret = usb_string_ids_tab(c->cdev, tcm_us_strings); 1999 + if (ret < 0) 2000 + return ret; 2001 + 2002 + bot_intf_desc.iInterface = tcm_us_strings[USB_G_STR_INT_BBB].id; 2003 + uasp_intf_desc.iInterface = 2004 + tcm_us_strings[USB_G_STR_INT_UAS].id; 2005 + } 2071 2006 2072 2007 iface = usb_interface_id(c, f); 2073 2008 if (iface < 0) ··· 2149 2038 return -ENOTSUPP; 2150 2039 } 2151 2040 2152 - static void tcm_unbind(struct usb_configuration *c, struct usb_function *f) 2041 + #ifdef USBF_TCM_INCLUDED 2042 + 2043 + static void tcm_old_unbind(struct usb_configuration *c, struct usb_function *f) 2153 2044 { 2154 2045 struct f_uas *fu = to_f_uas(f); 2155 2046 2156 2047 usb_free_all_descriptors(f); 2157 2048 kfree(fu); 2158 2049 } 2050 + 2051 + #endif 2159 2052 2160 2053 struct guas_setup_wq { 2161 2054 struct work_struct work; ··· 2229 2114 return usbg_bot_setup(f, ctrl); 2230 2115 } 2231 2116 2117 + #ifdef USBF_TCM_INCLUDED 2118 + 2232 2119 static int tcm_bind_config(struct usb_configuration *c) 2233 2120 { 2234 2121 struct f_uas *fu; ··· 2241 2124 return -ENOMEM; 2242 2125 fu->function.name = "Target Function"; 2243 2126 fu->function.bind = tcm_bind; 2244 - fu->function.unbind = tcm_unbind; 2127 + fu->function.unbind = tcm_old_unbind; 2245 2128 fu->function.set_alt = tcm_set_alt; 2246 2129 fu->function.setup = tcm_setup; 2247 2130 fu->function.disable = tcm_disable; 2248 2131 fu->function.strings = tcm_strings; 2249 2132 fu->tpg = the_only_tpg_I_currently_have; 2250 - 2251 - bot_intf_desc.iInterface = tcm_us_strings[USB_G_STR_INT_BBB].id; 2252 - uasp_intf_desc.iInterface = tcm_us_strings[USB_G_STR_INT_UAS].id; 2253 2133 2254 2134 ret = usb_add_function(c, &fu->function); 2255 2135 if (ret) ··· 2257 2143 kfree(fu); 2258 2144 return ret; 2259 2145 } 2146 + 2147 + #else 2148 + 2149 + static void tcm_free_inst(struct usb_function_instance *f) 2150 + { 2151 + struct f_tcm_opts *opts; 2152 + unsigned i; 2153 + 2154 + opts = container_of(f, struct f_tcm_opts, func_inst); 2155 + 2156 + mutex_lock(&tpg_instances_lock); 2157 + for (i = 0; i < TPG_INSTANCES; ++i) 2158 + if (tpg_instances[i].func_inst == f) 2159 + break; 2160 + if (i < TPG_INSTANCES) 2161 + tpg_instances[i].func_inst = NULL; 2162 + mutex_unlock(&tpg_instances_lock); 2163 + 2164 + kfree(opts); 2165 + } 2166 + 2167 + static int usbg_attach(struct usbg_tpg *tpg) 2168 + { 2169 + struct usb_function_instance *f = tpg->fi; 2170 + struct f_tcm_opts *opts = container_of(f, struct f_tcm_opts, func_inst); 2171 + 2172 + if (opts->tcm_register_callback) 2173 + return opts->tcm_register_callback(f); 2174 + 2175 + return 0; 2176 + } 2177 + 2178 + static void usbg_detach(struct usbg_tpg *tpg) 2179 + { 2180 + struct usb_function_instance *f = tpg->fi; 2181 + struct f_tcm_opts *opts = container_of(f, struct f_tcm_opts, func_inst); 2182 + 2183 + if (opts->tcm_unregister_callback) 2184 + opts->tcm_unregister_callback(f); 2185 + } 2186 + 2187 + static int tcm_set_name(struct usb_function_instance *f, const char *name) 2188 + { 2189 + struct f_tcm_opts *opts = container_of(f, struct f_tcm_opts, func_inst); 2190 + 2191 + pr_debug("tcm: Activating %s\n", name); 2192 + 2193 + mutex_lock(&opts->dep_lock); 2194 + opts->ready = true; 2195 + mutex_unlock(&opts->dep_lock); 2196 + 2197 + return 0; 2198 + } 2199 + 2200 + static struct usb_function_instance *tcm_alloc_inst(void) 2201 + { 2202 + struct f_tcm_opts *opts; 2203 + int i; 2204 + 2205 + 2206 + opts = kzalloc(sizeof(*opts), GFP_KERNEL); 2207 + if (!opts) 2208 + return ERR_PTR(-ENOMEM); 2209 + 2210 + mutex_lock(&tpg_instances_lock); 2211 + for (i = 0; i < TPG_INSTANCES; ++i) 2212 + if (!tpg_instances[i].func_inst) 2213 + break; 2214 + 2215 + if (i == TPG_INSTANCES) { 2216 + mutex_unlock(&tpg_instances_lock); 2217 + kfree(opts); 2218 + return ERR_PTR(-EBUSY); 2219 + } 2220 + tpg_instances[i].func_inst = &opts->func_inst; 2221 + mutex_unlock(&tpg_instances_lock); 2222 + 2223 + mutex_init(&opts->dep_lock); 2224 + opts->func_inst.set_inst_name = tcm_set_name; 2225 + opts->func_inst.free_func_inst = tcm_free_inst; 2226 + 2227 + return &opts->func_inst; 2228 + } 2229 + 2230 + static void tcm_free(struct usb_function *f) 2231 + { 2232 + struct f_uas *tcm = to_f_uas(f); 2233 + 2234 + kfree(tcm); 2235 + } 2236 + 2237 + static void tcm_unbind(struct usb_configuration *c, struct usb_function *f) 2238 + { 2239 + usb_free_all_descriptors(f); 2240 + } 2241 + 2242 + static struct usb_function *tcm_alloc(struct usb_function_instance *fi) 2243 + { 2244 + struct f_uas *fu; 2245 + struct f_tcm_opts *opts; 2246 + unsigned i; 2247 + 2248 + mutex_lock(&tpg_instances_lock); 2249 + for (i = 0; i < TPG_INSTANCES; ++i) 2250 + if (tpg_instances[i].func_inst == fi) 2251 + break; 2252 + if (i == TPG_INSTANCES) { 2253 + mutex_unlock(&tpg_instances_lock); 2254 + return ERR_PTR(-ENODEV); 2255 + } 2256 + 2257 + opts = container_of(fi, struct f_tcm_opts, func_inst); 2258 + 2259 + fu = kzalloc(sizeof(*fu), GFP_KERNEL); 2260 + if (!fu) { 2261 + mutex_unlock(&tpg_instances_lock); 2262 + return ERR_PTR(-ENOMEM); 2263 + } 2264 + 2265 + fu->function.name = "Target Function"; 2266 + fu->function.bind = tcm_bind; 2267 + fu->function.unbind = tcm_unbind; 2268 + fu->function.set_alt = tcm_set_alt; 2269 + fu->function.setup = tcm_setup; 2270 + fu->function.disable = tcm_disable; 2271 + fu->function.strings = tcm_strings; 2272 + fu->function.free_func = tcm_free; 2273 + fu->tpg = tpg_instances[i].tpg; 2274 + mutex_unlock(&tpg_instances_lock); 2275 + 2276 + return &fu->function; 2277 + } 2278 + 2279 + DECLARE_USB_FUNCTION(tcm, tcm_alloc_inst, tcm_alloc); 2280 + 2281 + static int tcm_init(void) 2282 + { 2283 + int ret; 2284 + 2285 + ret = usb_function_register(&tcmusb_func); 2286 + if (ret) 2287 + return ret; 2288 + 2289 + ret = target_register_template(&usbg_ops); 2290 + if (ret) 2291 + usb_function_unregister(&tcmusb_func); 2292 + 2293 + return ret; 2294 + } 2295 + module_init(tcm_init); 2296 + 2297 + static void tcm_exit(void) 2298 + { 2299 + target_unregister_template(&usbg_ops); 2300 + usb_function_unregister(&tcmusb_func); 2301 + } 2302 + module_exit(tcm_exit); 2303 + 2304 + MODULE_LICENSE("GPL"); 2305 + MODULE_AUTHOR("Sebastian Andrzej Siewior"); 2306 + 2307 + #endif
+2
drivers/usb/gadget/function/tcm.h
··· 39 39 u32 gadget_connect; 40 40 struct tcm_usbg_nexus *tpg_nexus; 41 41 atomic_t tpg_port_count; 42 + 43 + struct usb_function_instance *fi; 42 44 }; 43 45 44 46 struct usbg_tport {
+50
drivers/usb/gadget/function/u_tcm.h
··· 1 + /* 2 + * u_tcm.h 3 + * 4 + * Utility definitions for the tcm function 5 + * 6 + * Copyright (c) 2015 Samsung Electronics Co., Ltd. 7 + * http://www.samsung.com 8 + * 9 + * Author: Andrzej Pietrasiewicz <andrzej.p@xxxxxxxxxxx> 10 + * 11 + * This program is free software; you can redistribute it and/or modify 12 + * it under the terms of the GNU General Public License version 2 as 13 + * published by the Free Software Foundation. 14 + */ 15 + 16 + #ifndef U_TCM_H 17 + #define U_TCM_H 18 + 19 + #include <linux/usb/composite.h> 20 + 21 + /** 22 + * @dependent: optional dependent module. Meant for legacy gadget. 23 + * If non-null its refcount will be increased when a tpg is created and 24 + * decreased when tpg is dropped. 25 + * @dep_lock: lock for dependent module operations. 26 + * @ready: true if the dependent module information is set. 27 + * @can_attach: true a function can be bound to gadget 28 + * @has_dep: true if there is a dependent module 29 + * 30 + */ 31 + struct f_tcm_opts { 32 + struct usb_function_instance func_inst; 33 + struct module *dependent; 34 + struct mutex dep_lock; 35 + bool ready; 36 + bool can_attach; 37 + bool has_dep; 38 + 39 + /* 40 + * Callbacks to be removed when legacy tcm gadget disappears. 41 + * 42 + * If you use the new function registration interface 43 + * programmatically, you MUST set these callbacks to 44 + * something sensible (e.g. probe/remove the composite). 45 + */ 46 + int (*tcm_register_callback)(struct usb_function_instance *); 47 + void (*tcm_unregister_callback)(struct usb_function_instance *); 48 + }; 49 + 50 + #endif /* U_TCM_H */
+1
drivers/usb/gadget/legacy/tcm_usb_gadget.c
··· 24 24 USB_GADGET_COMPOSITE_OPTIONS(); 25 25 26 26 /* #include to be removed when new function registration interface is used */ 27 + #define USBF_TCM_INCLUDED 27 28 #include "../function/f_tcm.c" 28 29 29 30 #define UAS_VENDOR_ID 0x0525 /* NetChip */