Merge remote-tracking branch 'sm8350/lineage-20' into lineage-22.2

* sm8350/lineage-20:
  usb: gadget: f_ncm: Always set current gadget in ncm_bind()
  FROMGIT: usb: gadget: u_ether: support configuring interface names.
  usb: gadget: f_ncm: Revert to upstream

Change-Id: I22e19c48a42cc4f436131de72b59dfb87aca6e3c
This commit is contained in:
Michael Bestas 2025-04-27 22:08:35 +03:00
commit 3da233d881
No known key found for this signature in database
5 changed files with 102 additions and 96 deletions

View file

@ -91,9 +91,9 @@ The ECM function provides these attributes in its function directory:
and after creating the functions/ecm.<instance name> they contain default
values: qmult is 5, dev_addr and host_addr are randomly selected.
Except for ifname they can be written to until the function is linked to a
configuration. The ifname is read-only and contains the name of the interface
which was assigned by the net core, e. g. usb0.
The ifname can be written to if the function is not bound. A write must be an
interface pattern such as "usb%d", which will cause the net core to choose the
next free usbX interface. By default, it is set to "usb%d".
Testing the ECM function
------------------------
@ -131,9 +131,9 @@ The ECM subset function provides these attributes in its function directory:
and after creating the functions/ecm.<instance name> they contain default
values: qmult is 5, dev_addr and host_addr are randomly selected.
Except for ifname they can be written to until the function is linked to a
configuration. The ifname is read-only and contains the name of the interface
which was assigned by the net core, e. g. usb0.
The ifname can be written to if the function is not bound. A write must be an
interface pattern such as "usb%d", which will cause the net core to choose the
next free usbX interface. By default, it is set to "usb%d".
Testing the ECM subset function
-------------------------------
@ -171,9 +171,9 @@ The EEM function provides these attributes in its function directory:
and after creating the functions/eem.<instance name> they contain default
values: qmult is 5, dev_addr and host_addr are randomly selected.
Except for ifname they can be written to until the function is linked to a
configuration. The ifname is read-only and contains the name of the interface
which was assigned by the net core, e. g. usb0.
The ifname can be written to if the function is not bound. A write must be an
interface pattern such as "usb%d", which will cause the net core to choose the
next free usbX interface. By default, it is set to "usb%d".
Testing the EEM function
------------------------
@ -453,9 +453,9 @@ The NCM function provides these attributes in its function directory:
and after creating the functions/ncm.<instance name> they contain default
values: qmult is 5, dev_addr and host_addr are randomly selected.
Except for ifname they can be written to until the function is linked to a
configuration. The ifname is read-only and contains the name of the interface
which was assigned by the net core, e. g. usb0.
The ifname can be written to if the function is not bound. A write must be an
interface pattern such as "usb%d", which will cause the net core to choose the
next free usbX interface. By default, it is set to "usb%d".
Testing the NCM function
------------------------
@ -591,9 +591,9 @@ The RNDIS function provides these attributes in its function directory:
and after creating the functions/rndis.<instance name> they contain default
values: qmult is 5, dev_addr and host_addr are randomly selected.
Except for ifname they can be written to until the function is linked to a
configuration. The ifname is read-only and contains the name of the interface
which was assigned by the net core, e. g. usb0.
The ifname can be written to if the function is not bound. A write must be an
interface pattern such as "usb%d", which will cause the net core to choose the
next free usbX interface. By default, it is set to "usb%d".
Testing the RNDIS function
--------------------------

View file

@ -1461,47 +1461,22 @@ static int ncm_bind(struct usb_configuration *c, struct usb_function *f)
f->os_desc_table[0].os_desc = &ncm_opts->ncm_os_desc;
}
/*
* in drivers/usb/gadget/configfs.c:configfs_composite_bind()
* configurations are bound in sequence with list_for_each_entry,
* in each configuration its functions are bound in sequence
* with list_for_each_entry, so we assume no race condition
* with regard to ncm_opts->bound access
*/
if (!ncm_opts->bound) {
mutex_lock(&ncm_opts->lock);
ncm_opts->net = gether_setup_default();
if (IS_ERR(ncm_opts->net)) {
status = PTR_ERR(ncm_opts->net);
mutex_unlock(&ncm_opts->lock);
goto error;
}
gether_set_gadget(ncm_opts->net, cdev->gadget);
mutex_lock(&ncm_opts->lock);
gether_set_gadget(ncm_opts->net, cdev->gadget);
if (!ncm_opts->bound)
status = gether_register_netdev(ncm_opts->net);
mutex_unlock(&ncm_opts->lock);
if (status) {
free_netdev(ncm_opts->net);
goto error;
}
ncm_opts->bound = true;
}
mutex_unlock(&ncm_opts->lock);
/* export host's Ethernet address in CDC format */
status = gether_get_host_addr_cdc(ncm_opts->net, ncm->ethaddr,
sizeof(ncm->ethaddr));
if (status < 12) { /* strlen("01234567890a") */
ERROR(cdev, "%s: failed to get host eth addr, err %d\n",
__func__, status);
status = -EINVAL;
goto netdev_cleanup;
}
ncm->port.ioport = netdev_priv(ncm_opts->net);
if (status)
goto fail;
ncm_opts->bound = true;
us = usb_gstrings_attach(cdev, ncm_strings,
ARRAY_SIZE(ncm_string_defs));
if (IS_ERR(us)) {
status = PTR_ERR(us);
goto netdev_cleanup;
goto fail;
}
ncm_control_intf.iInterface = us[STRING_CTRL_IDX].id;
ncm_data_nop_intf.iInterface = us[STRING_DATA_IDX].id;
@ -1609,10 +1584,7 @@ fail:
kfree(ncm->notify_req->buf);
usb_ep_free_request(ncm->notify, ncm->notify_req);
}
netdev_cleanup:
gether_cleanup(netdev_priv(ncm_opts->net));
error:
ERROR(cdev, "%s: can't bind, err %d\n", f->name, status);
return status;
@ -1660,7 +1632,8 @@ static void ncm_free_inst(struct usb_function_instance *f)
opts = container_of(f, struct f_ncm_opts, func_inst);
if (opts->bound)
gether_cleanup(netdev_priv(opts->net));
else
free_netdev(opts->net);
kfree(opts->ncm_interf_group);
kfree(opts);
}
@ -1679,6 +1652,12 @@ static struct usb_function_instance *ncm_alloc_inst(void)
mutex_init(&opts->lock);
opts->func_inst.free_func_inst = ncm_free_inst;
opts->net = gether_setup_default();
if (IS_ERR(opts->net)) {
struct net_device *net = opts->net;
kfree(opts);
return ERR_CAST(net);
}
INIT_LIST_HEAD(&opts->ncm_os_desc.ext_prop);
descs[0] = &opts->ncm_os_desc;
@ -1713,13 +1692,9 @@ static void ncm_free(struct usb_function *f)
static void ncm_unbind(struct usb_configuration *c, struct usb_function *f)
{
struct f_ncm *ncm = func_to_ncm(f);
struct f_ncm_opts *opts = container_of(f->fi, struct f_ncm_opts,
func_inst);
DBG(c->cdev, "ncm unbind\n");
opts->bound = false;
hrtimer_cancel(&ncm->task_timer);
kfree(f->os_desc_table);
@ -1735,14 +1710,13 @@ static void ncm_unbind(struct usb_configuration *c, struct usb_function *f)
kfree(ncm->notify_req->buf);
usb_ep_free_request(ncm->notify, ncm->notify_req);
gether_cleanup(netdev_priv(opts->net));
}
static struct usb_function *ncm_alloc(struct usb_function_instance *fi)
{
struct f_ncm *ncm;
struct f_ncm_opts *opts;
int status;
/* allocate and initialize one new instance */
ncm = kzalloc(sizeof(*ncm), GFP_KERNEL);
@ -1752,9 +1726,20 @@ static struct usb_function *ncm_alloc(struct usb_function_instance *fi)
opts = container_of(fi, struct f_ncm_opts, func_inst);
mutex_lock(&opts->lock);
opts->refcnt++;
/* export host's Ethernet address in CDC format */
status = gether_get_host_addr_cdc(opts->net, ncm->ethaddr,
sizeof(ncm->ethaddr));
if (status < 12) { /* strlen("01234567890a") */
kfree(ncm);
mutex_unlock(&opts->lock);
return ERR_PTR(-EINVAL);
}
ncm_string_defs[STRING_MAC_IDX].s = ncm->ethaddr;
spin_lock_init(&ncm->lock);
ncm_reset_values(ncm);
ncm->port.ioport = netdev_priv(opts->net);
mutex_unlock(&opts->lock);
ncm->port.is_fixed = true;
ncm->port.supports_multi_frame = true;

View file

@ -82,6 +82,7 @@ struct eth_dev {
bool zlp;
bool no_skb_reserve;
bool ifname_set;
u8 host_mac[ETH_ALEN];
u8 dev_mac[ETH_ALEN];
};
@ -979,15 +980,45 @@ EXPORT_SYMBOL_GPL(gether_get_qmult);
int gether_get_ifname(struct net_device *net, char *name, int len)
{
struct eth_dev *dev = netdev_priv(net);
int ret;
rtnl_lock();
ret = scnprintf(name, len, "%s\n", netdev_name(net));
ret = scnprintf(name, len, "%s\n",
dev->ifname_set ? net->name : netdev_name(net));
rtnl_unlock();
return ret;
}
EXPORT_SYMBOL_GPL(gether_get_ifname);
int gether_set_ifname(struct net_device *net, const char *name, int len)
{
struct eth_dev *dev = netdev_priv(net);
char tmp[IFNAMSIZ];
const char *p;
if (name[len - 1] == '\n')
len--;
if (len >= sizeof(tmp))
return -E2BIG;
strscpy(tmp, name, len + 1);
if (!dev_valid_name(tmp))
return -EINVAL;
/* Require exactly one %d, so binding will not fail with EEXIST. */
p = strchr(name, '%');
if (!p || p[1] != 'd' || strchr(p + 2, '%'))
return -EINVAL;
strncpy(net->name, tmp, sizeof(net->name));
dev->ifname_set = true;
return 0;
}
EXPORT_SYMBOL_GPL(gether_set_ifname);
/**
* gether_cleanup - remove Ethernet-over-USB device
* Context: may sleep

View file

@ -244,6 +244,18 @@ unsigned gether_get_qmult(struct net_device *net);
*/
int gether_get_ifname(struct net_device *net, char *name, int len);
/**
* gether_set_ifname - set an ethernet-over-usb link interface name
* @net: device representing this link
* @name: new interface name
* @len: length of @name
*
* This sets the interface name of this ethernet-over-usb link.
* A single terminating newline, if any, is ignored.
* Returns zero on success, else negative errno.
*/
int gether_set_ifname(struct net_device *net, const char *name, int len);
void gether_cleanup(struct eth_dev *dev);
/* connect/disconnect is handled by individual functions */

View file

@ -32,11 +32,6 @@
struct f_##_f_##_opts *opts = to_f_##_f_##_opts(item); \
int result; \
\
if (opts->bound == false) { \
pr_err("Gadget function do not bind yet.\n"); \
return -ENODEV; \
} \
\
mutex_lock(&opts->lock); \
result = gether_get_dev_addr(opts->net, page, PAGE_SIZE); \
mutex_unlock(&opts->lock); \
@ -50,11 +45,6 @@
struct f_##_f_##_opts *opts = to_f_##_f_##_opts(item); \
int ret; \
\
if (opts->bound == false) { \
pr_err("Gadget function do not bind yet.\n"); \
return -ENODEV; \
} \
\
mutex_lock(&opts->lock); \
if (opts->refcnt) { \
mutex_unlock(&opts->lock); \
@ -77,11 +67,6 @@
struct f_##_f_##_opts *opts = to_f_##_f_##_opts(item); \
int result; \
\
if (opts->bound == false) { \
pr_err("Gadget function do not bind yet.\n"); \
return -ENODEV; \
} \
\
mutex_lock(&opts->lock); \
result = gether_get_host_addr(opts->net, page, PAGE_SIZE); \
mutex_unlock(&opts->lock); \
@ -95,11 +80,6 @@
struct f_##_f_##_opts *opts = to_f_##_f_##_opts(item); \
int ret; \
\
if (opts->bound == false) { \
pr_err("Gadget function do not bind yet.\n"); \
return -ENODEV; \
} \
\
mutex_lock(&opts->lock); \
if (opts->refcnt) { \
mutex_unlock(&opts->lock); \
@ -122,11 +102,6 @@
struct f_##_f_##_opts *opts = to_f_##_f_##_opts(item); \
unsigned qmult; \
\
if (opts->bound == false) { \
pr_err("Gadget function do not bind yet.\n"); \
return -ENODEV; \
} \
\
mutex_lock(&opts->lock); \
qmult = gether_get_qmult(opts->net); \
mutex_unlock(&opts->lock); \
@ -140,11 +115,6 @@
u8 val; \
int ret; \
\
if (opts->bound == false) { \
pr_err("Gadget function do not bind yet.\n"); \
return -ENODEV; \
} \
\
mutex_lock(&opts->lock); \
if (opts->refcnt) { \
ret = -EBUSY; \
@ -171,11 +141,6 @@ out: \
struct f_##_f_##_opts *opts = to_f_##_f_##_opts(item); \
int ret; \
\
if (opts->bound == false) { \
pr_err("Gadget function do not bind yet.\n"); \
return -ENODEV; \
} \
\
mutex_lock(&opts->lock); \
ret = gether_get_ifname(opts->net, page, PAGE_SIZE); \
mutex_unlock(&opts->lock); \
@ -183,7 +148,20 @@ out: \
return ret; \
} \
\
CONFIGFS_ATTR_RO(_f_##_opts_, ifname)
static ssize_t _f_##_opts_ifname_store(struct config_item *item, \
const char *page, size_t len)\
{ \
struct f_##_f_##_opts *opts = to_f_##_f_##_opts(item); \
int ret = -EBUSY; \
\
mutex_lock(&opts->lock); \
if (!opts->refcnt) \
ret = gether_set_ifname(opts->net, page, len); \
mutex_unlock(&opts->lock); \
return ret ?: len; \
} \
\
CONFIGFS_ATTR(_f_##_opts_, ifname)
#define USB_ETHER_CONFIGFS_ITEM_ATTR_U8_RW(_f_, _n_) \
static ssize_t _f_##_opts_##_n_##_show(struct config_item *item,\