On Mon, 2019-06-17 at 13:42 +0200, Johannes Berg wrote: > But anyway, as I alluded to above, I had something like this in mind: I forgot to state this here, but this was *heavily* influenced by discussions with Dan - many thanks to him. > driver_dev > struct device *dev (USB, PCI, ...) > net_device NA > net_device NB > tty TA > ... > > (I'm cutting out the rmnet layer here for now) > > while having a separate that just links all the pieces together: > > wwan_device W > ---> dev > ---> NA > ---> NB > ---> TA > > So the driver is still responsible for creating the netdevs (or can of > course delegate that to an "rmnet" library), but then all it also does > is register the netdevs with the WWAN core like > > wwan_add_netdev(dev, NA) [snip] So to put some more meat to this, here's an API definition for both userspace and internal APIs: diff --git a/include/net/wwan.h b/include/net/wwan.h new file mode 100644 index 000000000000..91413ec01def --- /dev/null +++ b/include/net/wwan.h @@ -0,0 +1,104 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * WWAN stack interfaces + * + * Copyright (C) 2019 Intel Corporation + * + * This defines the interaction of WWAN drivers with the WWAN stack, + * which allows userspace configuration of sessions etc. + */ +#ifndef __NET_WWAN_H +#define __NET_WWAN_H +#include <linux/list.h> +#include <linux/types.h> +#include <linux/device.h> + +struct wwan_device { + u32 id; + void *data; +/* private: */ + struct list_head list; + struct device *dev; + struct wwan_device_ops *ops; +}; + +/** + * struct wwan_netdev_config - WWAN netdevice configuration + * @pdn: PDN identifier this netdev uses + */ +struct wwan_netdev_config { + u32 pdn; +}; + +/** + * wwan_device_ops - WWAN device operations + */ +struct wwan_device_ops { + /** + * @add_netdev: Add a new netdev with the given configuration, must + * return the new netdev pointer but not call wwan_attach_netdev(). + */ + struct net_device *(*add_netdev)(struct wwan_device *wwan, + struct wwan_netdev_config *config); + /** + * @remove_netdev: remove the given netdev + */ + int (*remove_netdev)(struct wwan_device *wwan, struct net_device *dev); + + /* + * More TBD: + * - add/remove serial port channels? + * ideally with some common (library) code to support this + * Or maybe not - serial is pretty limiting. Perhaps instead: + * - support something like AF_WWAN sockets for control data + */ +}; + +/** + * wwan_add - add a WWAN device without preconfigured channels + * @dev: underlying struct device + * @ops: methods to create new channels + * @data: data for the new WWAN device + * + * Returns: a struct wwan_device pointer, or an ERR_PTR(). + */ +struct wwan_device * +wwan_add(struct device *dev, struct wwan_device_ops *ops, void *data); + +/** + * wwan_remove - remove the given WWAN device + * @wwan: WWAN device to remove. + * + * Note that the WWAN device may not be fully removed if it still has + * any channels attached, but nonetheless callers must assume that the + * pointer is no longer valid after calling this function. + */ +void wwan_remove(struct wwan_device *wwan); + +/** + * wwan_attach_netdev - attach a preconfigured netdev to the WWAN device + * @dev: struct device underlying the WWAN device + * @netdev: netdev to attach + * @config: configuration for this netdev + * @tentative: mark the attachment as tentative, don't consider this as + * part of a WWAN device unless other channels are attached as well. + * Set this to %false in drivers that know they're a WWAN device + * and to %true in generic drivers that may or may not be a WWAN + * device and want to wait for other channels. + * + * Returns: a struct wwan_device pointer or ERR_PTR(). Note that a valid + * pointer is returned even for the tentative case. + * + * Note that there's no need to detach again, this happens automatically + * when the netdev is removed. + */ +struct wwan_device * +wwan_attach_netdev(struct device *dev, struct net_device *netdev, + struct wwan_netdev_config *config, bool tentative); + +/* TBD */ +struct wwan_device * +wwan_attach_tty(struct device *dev, struct tty_port *port, bool tentative); +void wwan_detach_tty(struct device *dev, struct tty_port *port); + +#endif /* __NET_WWAN_H */ diff --git a/include/uapi/linux/wwan.h b/include/uapi/linux/wwan.h new file mode 100644 index 000000000000..af327aab881c --- /dev/null +++ b/include/uapi/linux/wwan.h @@ -0,0 +1,94 @@ +// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note +/* + * WWAN generic netlink interfaces + * + * Copyright (C) 2019 Intel Corporation + * + * This defines the WWAN generic netlink family APIs for userspace + * to control WWAN devices. + */ +#ifndef __UAPI_LINUX_WWAN_H +#define __UAPI_LINUX_WWAN_H +#include <linux/types.h> + +#define WWAN_NAME "wwan" + +enum wwan_commands { + WWAN_CMD_UNSPEC, + + WWAN_CMD_GET_DEVICE, /* get or dump */ + WWAN_CMD_SET_DEVICE, /* set name or similar */ + WWAN_CMD_NEW_DEVICE, /* notification */ + WWAN_CMD_DEL_DEVICE, /* notification */ + + WWAN_CMD_GET_NETDEV, /* probably not needed - show all data in GET_DEVICE dump? */ + WWAN_CMD_SET_NETDEV, /* probably not supported? */ + WWAN_CMD_NEW_NETDEV, + WWAN_CMD_DEL_NETDEV, +}; + +/* TODO DOCS */ +enum wwan_chan_type { + WWAN_CHAN_TYPE_UNDEFINED, + WWAN_CHAN_TYPE_NETDEV, + WWAN_CHAN_TYPE_TTY, + /* ... */ +}; + +enum wwan_chan_attrs { + /** + * @WWAN_CHAN_ATTR_UNSPEC: unused/reserved + */ + WWAN_CHAN_ATTR_UNSPEC, + + /** + * @WWAN_CHAN_ATTR_TYPE: channel type according to &enum wwan_chan_type + */ + WWAN_CHAN_ATTR_TYPE, + + /** + * @WWAN_CHAN_ATTR_IFIDX: interface index (for netdev channels) + */ + WWAN_CHAN_ATTR_IFIDX, + + /* need something for TTY - major/minor number? /dev/ name? */ + + /* ... */ +}; + +enum wwan_attrs { + /** + * @WWAN_ATTR_UNSPEC: unused/reserved + */ + WWAN_ATTR_UNSPEC, + + /** + * @WWAN_ATTR_DEVICE_ID: device ID + */ + WWAN_ATTR_DEVICE_ID, + + /** + * @WWAN_ATTR_DEVICE_NAME: name of the underlying struct device + */ + WWAN_ATTR_DEVICE_NAME, + + /** + * @WWAN_ATTR_IFIDX: interface index for %WWAN_CMD_NEW_NETDEV + */ + WWAN_ATTR_IFIDX, + + /** + * @WWAN_ATTR_PDN: PDN for %WWAN_CMD_NEW_NETDEV + */ + WWAN_ATTR_PDN, + + /** + * @WWAN_ATTR_CHANNELS: nested array of channels in dump, using + * the &enum wwan_chan_attrs. + */ + WWAN_ATTR_CHANNELS, + + /* ... */ +}; + +#endif /* __UAPI_LINUX_WWAN_H */