[U-Boot] [PATCH v2 0/3] DM conversion of usb ether gadget

This patch series adopts driver model for usb ether gadget driver. This series is tested with MUSB driver model conversion on AM335x GP evm and AM335x BBB (logs [1]).
Also pushed a branch for testing [2]
Changes from v3: * Removed the patches already applied. * Changed to possitive approach for #ifndef CONFIG_DM_USB * Removed hardcoding of usb device mac id from Kconfig over enviroment. Now it is like use enviroment mac or use random mac generated by dm-eth framework. * Added a build error when DM_ETH is defined and DM_USB not defined as the driver doesn't support this combination * Added two new patches which removed tmp variable which is initialized and never been used and another to fix a crash when DM_USB and DM_ETH are defined.
Changes from v2: * Moved USB ether address from driver hard code to Kconfig entry * Optimized if check in patch 5/6 as mentioned by Marek Vasut.
Changes from initial version: * Separated out the usb gadget driver patches from earlier musb series [3] for testing and submitting of dwc3 dm musb patches.
[1] - http://pastebin.ubuntu.com/23628667/ [2] - git://git.ti.com/~mugunthanvnm/ti-u-boot/mugunth-ti-u-boot.git usb-ether-v4 [3] - http://lists.denx.de/pipermail/u-boot/2016-February/246827.html
Mugunthan V N (3): drivers: usb: gadget: ether: do not register usb when DM_USB and DM_ETH defined drivers: usb: gadget: ether: remove unused variable tmp drivers: usb: gadget: ether/rndis: convert driver to adopt device driver model
drivers/usb/gadget/ether.c | 164 ++++++++++++++++++++++++++++++++++++++++----- drivers/usb/gadget/rndis.c | 13 +++- drivers/usb/gadget/rndis.h | 19 ++++-- include/net.h | 8 +++ 4 files changed, 183 insertions(+), 21 deletions(-)

when both DM_USB and DM_ETH are defined which denoted that usb_ether has been registered from a usb device. So registering a USB device doesn't do any thing and de-register leads to crash as it try to remove its own parent. Sample dm-tree output below.
eth [ + ] |-- ethernet@4a100000 misc [ + ] `-- usb@47400000 usb_dev_gen [ + ] |-- usb@47401000 eth [ + ] | `-- usb_ether usb [ ] `-- usb@47401800
Signed-off-by: Mugunthan V N mugunthanvnm@ti.com --- drivers/usb/gadget/ether.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c index 046ad8ca2b..bcc8be86a5 100644 --- a/drivers/usb/gadget/ether.c +++ b/drivers/usb/gadget/ether.c @@ -105,7 +105,7 @@ struct eth_dev { struct usb_gadget *gadget; struct usb_request *req; /* for control responses */ struct usb_request *stat_req; /* for cdc & rndis status */ -#ifdef CONFIG_DM_USB +#if defined(CONFIG_DM_USB) && !defined(CONFIG_DM_ETH) struct udevice *usb_udev; #endif
@@ -2316,7 +2316,7 @@ fail:
/*-------------------------------------------------------------------------*/
-#ifdef CONFIG_DM_USB +#if defined(CONFIG_DM_USB) && !defined(CONFIG_DM_ETH) int dm_usb_init(struct eth_dev *e_dev) { struct udevice *dev = NULL; @@ -2342,10 +2342,12 @@ static int _usb_eth_init(struct ether_priv *priv) unsigned long timeout = USB_CONNECT_TIMEOUT;
#ifdef CONFIG_DM_USB +#ifndef CONFIG_DM_ETH if (dm_usb_init(dev)) { error("USB ether not found\n"); return -ENODEV; } +#endif #else board_usb_init(0, USB_INIT_DEVICE); #endif @@ -2521,7 +2523,9 @@ void _usb_eth_halt(struct ether_priv *priv)
usb_gadget_unregister_driver(&priv->eth_driver); #ifdef CONFIG_DM_USB +#ifndef CONFIG_DM_ETH device_remove(dev->usb_udev); +#endif #else board_usb_cleanup(0, USB_INIT_DEVICE); #endif

On 14 December 2016 at 06:32, Mugunthan V N mugunthanvnm@ti.com wrote:
when both DM_USB and DM_ETH are defined which denoted that usb_ether has been registered from a usb device. So registering a USB device doesn't do any thing and de-register leads to crash as it try to remove its own parent. Sample dm-tree output below.
eth [ + ] |-- ethernet@4a100000 misc [ + ] `-- usb@47400000 usb_dev_gen [ + ] |-- usb@47401000 eth [ + ] | `-- usb_ether usb [ ] `-- usb@47401800
Signed-off-by: Mugunthan V N mugunthanvnm@ti.com
drivers/usb/gadget/ether.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-)
Reviewed-by: Simon Glass sjg@chromium.org

tmp variable in eth_bind() is never used any where, so remove it.
Signed-off-by: Mugunthan V N mugunthanvnm@ti.com --- drivers/usb/gadget/ether.c | 4 ---- 1 file changed, 4 deletions(-)
diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c index bcc8be86a5..e8d9e4a9c9 100644 --- a/drivers/usb/gadget/ether.c +++ b/drivers/usb/gadget/ether.c @@ -2000,7 +2000,6 @@ static int eth_bind(struct usb_gadget *gadget) struct usb_ep *in_ep, *out_ep, *status_ep = NULL; int status = -ENOMEM; int gcnum; - u8 tmp[7];
/* these flags are only ever cleared; compiler take note */ #ifndef CONFIG_USB_ETH_CDC @@ -2206,9 +2205,6 @@ autoconf_fail: */ get_ether_addr(dev_addr, dev->net->enetaddr);
- memset(tmp, 0, sizeof(tmp)); - memcpy(tmp, dev->net->enetaddr, sizeof(dev->net->enetaddr)); - get_ether_addr(host_addr, dev->host_mac);
sprintf(ethaddr, "%02X%02X%02X%02X%02X%02X",

On 14 December 2016 at 06:32, Mugunthan V N mugunthanvnm@ti.com wrote:
tmp variable in eth_bind() is never used any where, so remove it.
anywhere
Signed-off-by: Mugunthan V N mugunthanvnm@ti.com
drivers/usb/gadget/ether.c | 4 ---- 1 file changed, 4 deletions(-)
Reviewed-by: Simon Glass sjg@chromium.org

Adopt usb ether gadget and rndis driver to adopt driver model
Signed-off-by: Mugunthan V N mugunthanvnm@ti.com --- drivers/usb/gadget/ether.c | 152 ++++++++++++++++++++++++++++++++++++++++++--- drivers/usb/gadget/rndis.c | 13 +++- drivers/usb/gadget/rndis.h | 19 ++++-- include/net.h | 8 +++ 4 files changed, 177 insertions(+), 15 deletions(-)
diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c index e8d9e4a9c9..c5eb552129 100644 --- a/drivers/usb/gadget/ether.c +++ b/drivers/usb/gadget/ether.c @@ -25,11 +25,22 @@ #include "rndis.h"
#include <dm.h> +#include <dm/lists.h> #include <dm/uclass-internal.h> #include <dm/device-internal.h>
#define USB_NET_NAME "usb_ether"
+/* + * This driver support only the following combinations. + * DM_ETH + DM_USB + * !DM_ETH + DM_USB + * !DM_ETH + !DM_USB + */ +#if defined(CONFIG_DM_ETH) && !defined(CONFIG_DM_USB) +#error "This driver doesn't support the combination of DM_ETH and !DM_USB" +#endif + #define atomic_read extern struct platform_data brd;
@@ -116,7 +127,11 @@ struct eth_dev {
struct usb_request *tx_req, *rx_req;
+#ifdef CONFIG_DM_ETH + struct udevice *net; +#else struct eth_device *net; +#endif struct net_device_stats stats; unsigned int tx_qlen;
@@ -143,7 +158,11 @@ struct eth_dev { /*-------------------------------------------------------------------------*/ struct ether_priv { struct eth_dev ethdev; +#ifdef CONFIG_DM_ETH + struct udevice *netdev; +#else struct eth_device netdev; +#endif struct usb_gadget_driver eth_driver; };
@@ -1851,7 +1870,11 @@ static void rndis_control_ack_complete(struct usb_ep *ep,
static char rndis_resp_buf[8] __attribute__((aligned(sizeof(__le32))));
+#ifdef CONFIG_DM_ETH +static int rndis_control_ack(struct udevice *net) +#else static int rndis_control_ack(struct eth_device *net) +#endif { struct ether_priv *priv = (struct ether_priv *)net->priv; struct eth_dev *dev = &priv->ethdev; @@ -2000,6 +2023,9 @@ static int eth_bind(struct usb_gadget *gadget) struct usb_ep *in_ep, *out_ep, *status_ep = NULL; int status = -ENOMEM; int gcnum; +#ifdef CONFIG_DM_ETH + struct eth_pdata *pdata = dev_get_platdata(l_priv->netdev); +#endif
/* these flags are only ever cleared; compiler take note */ #ifndef CONFIG_USB_ETH_CDC @@ -2187,7 +2213,11 @@ autoconf_fail:
/* network device setup */ +#ifdef CONFIG_DM_ETH + dev->net = l_priv->netdev; +#else dev->net = &l_priv->netdev; +#endif
dev->cdc = cdc; dev->zlp = zlp; @@ -2203,7 +2233,13 @@ autoconf_fail: * host side code for the SAFE thing cares -- its original BLAN * thing didn't, Sharp never assigned those addresses on Zaurii. */ - get_ether_addr(dev_addr, dev->net->enetaddr); +#ifdef CONFIG_DM_ETH + if (is_eth_addr_valid(dev_addr)) + get_ether_addr(dev_addr, pdata->enetaddr); +#else + if (is_eth_addr_valid(dev_addr)) + get_ether_addr(dev_addr, dev->net->enetaddr); +#endif
get_ether_addr(host_addr, dev->host_mac);
@@ -2264,10 +2300,11 @@ autoconf_fail: status_ep ? " STATUS " : "", status_ep ? status_ep->name : "" ); - printf("MAC %02x:%02x:%02x:%02x:%02x:%02x\n", - dev->net->enetaddr[0], dev->net->enetaddr[1], - dev->net->enetaddr[2], dev->net->enetaddr[3], - dev->net->enetaddr[4], dev->net->enetaddr[5]); +#ifdef CONFIG_DM_ETH + printf("MAC %pM\n", pdata->enetaddr); +#else + printf("MAC %pM\n", dev->net->enetaddr); +#endif
if (cdc || rndis) printf("HOST MAC %02x:%02x:%02x:%02x:%02x:%02x\n", @@ -2364,10 +2401,6 @@ static int _usb_eth_init(struct ether_priv *priv) strlcpy(host_addr, getenv("usbnet_hostaddr"), sizeof(host_addr));
- if (!is_eth_addr_valid(dev_addr)) { - error("Need valid 'usbnet_devaddr' to be set"); - goto fail; - } if (!is_eth_addr_valid(host_addr)) { error("Need valid 'usbnet_hostaddr' to be set"); goto fail; @@ -2527,6 +2560,7 @@ void _usb_eth_halt(struct ether_priv *priv) #endif }
+#ifndef CONFIG_DM_ETH static int usb_eth_init(struct eth_device *netdev, bd_t *bd) { struct ether_priv *priv = (struct ether_priv *)netdev->priv; @@ -2593,3 +2627,103 @@ int usb_eth_initialize(bd_t *bi) eth_register(netdev); return 0; } +#else +static int usb_eth_start(struct udevice *dev) +{ + struct ether_priv *priv = dev_get_priv(dev); + + return _usb_eth_init(priv); +} + +static int usb_eth_send(struct udevice *dev, void *packet, int length) +{ + struct ether_priv *priv = dev_get_priv(dev); + + return _usb_eth_send(priv, packet, length); +} + +static int usb_eth_recv(struct udevice *dev, int flags, uchar **packetp) +{ + struct ether_priv *priv = dev_get_priv(dev); + struct eth_dev *ethdev = &priv->ethdev; + int ret; + + ret = _usb_eth_recv(priv); + if (ret) { + error("error packet receive\n"); + return ret; + } + + if (packet_received) { + if (ethdev->rx_req) { + *packetp = (uchar *)net_rx_packets[0]; + return ethdev->rx_req->length; + } else { + error("dev->rx_req invalid"); + return -EFAULT; + } + } + + return -EAGAIN; +} + +static int usb_eth_free_pkt(struct udevice *dev, uchar *packet, + int length) +{ + struct ether_priv *priv = dev_get_priv(dev); + struct eth_dev *ethdev = &priv->ethdev; + + packet_received = 0; + + return rx_submit(ethdev, ethdev->rx_req, 0); +} + +static void usb_eth_stop(struct udevice *dev) +{ + struct ether_priv *priv = dev_get_priv(dev); + + _usb_eth_halt(priv); +} + +static int usb_eth_probe(struct udevice *dev) +{ + struct ether_priv *priv = dev_get_priv(dev); + + priv->netdev = dev; + l_priv = priv; + + return 0; +} + +static const struct eth_ops usb_eth_ops = { + .start = usb_eth_start, + .send = usb_eth_send, + .recv = usb_eth_recv, + .free_pkt = usb_eth_free_pkt, + .stop = usb_eth_stop, +}; + +int usb_ether_init(struct udevice *usb_dev) +{ + struct udevice *dev; + int ret; + + ret = device_bind_driver(usb_dev, "usb_ether", "usb_ether", &dev); + if (!dev || ret) { + error("usb - not able to bind usb_ether device\n"); + return ret; + } + + return 0; +} + +U_BOOT_DRIVER(eth_usb) = { + .name = "usb_ether", + .id = UCLASS_ETH, + .probe = usb_eth_probe, + .ops = &usb_eth_ops, + .priv_auto_alloc_size = sizeof(struct ether_priv), + .platdata_auto_alloc_size = sizeof(struct eth_pdata), + .flags = DM_FLAG_ALLOC_PRIV_DMA, +}; +#endif /* CONFIG_DM_ETH */ diff --git a/drivers/usb/gadget/rndis.c b/drivers/usb/gadget/rndis.c index 844a0c7236..669eb3e59d 100644 --- a/drivers/usb/gadget/rndis.c +++ b/drivers/usb/gadget/rndis.c @@ -1121,7 +1121,11 @@ int rndis_msg_parser(u8 configNr, u8 *buf) return -ENOTSUPP; }
+#ifdef CONFIG_DM_ETH +int rndis_register(int (*rndis_control_ack)(struct udevice *)) +#else int rndis_register(int (*rndis_control_ack)(struct eth_device *)) +#endif { u8 i;
@@ -1149,8 +1153,13 @@ void rndis_deregister(int configNr) return; }
-int rndis_set_param_dev(u8 configNr, struct eth_device *dev, int mtu, - struct net_device_stats *stats, u16 *cdc_filter) +#ifdef CONFIG_DM_ETH +int rndis_set_param_dev(u8 configNr, struct udevice *dev, int mtu, + struct net_device_stats *stats, u16 *cdc_filter) +#else +int rndis_set_param_dev(u8 configNr, struct eth_device *dev, int mtu, + struct net_device_stats *stats, u16 *cdc_filter) +#endif { debug("%s: configNr = %d\n", __func__, configNr); if (!dev || !stats) diff --git a/drivers/usb/gadget/rndis.h b/drivers/usb/gadget/rndis.h index 7a389a580a..ac225e9846 100644 --- a/drivers/usb/gadget/rndis.h +++ b/drivers/usb/gadget/rndis.h @@ -222,23 +222,34 @@ typedef struct rndis_params {
const u8 *host_mac; u16 *filter; - struct eth_device *dev; struct net_device_stats *stats; int mtu;
u32 vendorID; const char *vendorDescr; - int (*ack)(struct eth_device *); +#ifdef CONFIG_DM_ETH + struct udevice *dev; + int (*ack)(struct udevice *); +#else + struct eth_device *dev; + int (*ack)(struct eth_device *); +#endif struct list_head resp_queue; } rndis_params;
/* RNDIS Message parser and other useless functions */ int rndis_msg_parser(u8 configNr, u8 *buf); enum rndis_state rndis_get_state(int configNr); -int rndis_register(int (*rndis_control_ack)(struct eth_device *)); void rndis_deregister(int configNr); +#ifdef CONFIG_DM_ETH +int rndis_register(int (*rndis_control_ack)(struct udevice *)); +int rndis_set_param_dev(u8 configNr, struct udevice *dev, int mtu, + struct net_device_stats *stats, u16 *cdc_filter); +#else +int rndis_register(int (*rndis_control_ack)(struct eth_device *)); int rndis_set_param_dev(u8 configNr, struct eth_device *dev, int mtu, - struct net_device_stats *stats, u16 *cdc_filter); + struct net_device_stats *stats, u16 *cdc_filter); +#endif int rndis_set_param_vendor(u8 configNr, u32 vendorID, const char *vendorDescr); int rndis_set_param_medium(u8 configNr, u32 medium, u32 speed); diff --git a/include/net.h b/include/net.h index 06320c6514..72a2961eed 100644 --- a/include/net.h +++ b/include/net.h @@ -156,6 +156,14 @@ unsigned char *eth_get_ethaddr(void); /* get the current device MAC */ int eth_is_active(struct udevice *dev); /* Test device for active state */ int eth_init_state_only(void); /* Set active state */ void eth_halt_state_only(void); /* Set passive state */ + +/* + * Initialize USB ethernet device with CONFIG_DM_ETH + * @usb_dev: usb device pointer to which the ethernet device to be atached to + * Returns: + * 0 is success, non-zero is error status. + */ +int usb_ether_init(struct udevice *usb_dev); #endif
#ifndef CONFIG_DM_ETH

On 14 December 2016 at 06:32, Mugunthan V N mugunthanvnm@ti.com wrote:
Adopt usb ether gadget and rndis driver to adopt driver model
Signed-off-by: Mugunthan V N mugunthanvnm@ti.com
drivers/usb/gadget/ether.c | 152 ++++++++++++++++++++++++++++++++++++++++++--- drivers/usb/gadget/rndis.c | 13 +++- drivers/usb/gadget/rndis.h | 19 ++++-- include/net.h | 8 +++ 4 files changed, 177 insertions(+), 15 deletions(-)
Do you think you can get rid of l_priv? Is there a way to instead find the device using uclass_first/next_device()?
- Simon
participants (2)
-
Mugunthan V N
-
Simon Glass