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

wwan: core: add WWAN common private data for netdev

The WWAN core not only multiplex the netdev configuration data, but
process it too, and needs some space to store its private data
associated with the netdev. Add a structure to keep common WWAN core
data. The structure will be stored inside the netdev private data before
WWAN driver private data and have a field to make it easier to access
the driver data. Also add a helper function that simplifies drivers
access to their data.

At the moment we use the common WWAN private data to store the WWAN data
link (channel) id at the time the link is created, and report it back to
user using the .fill_info() RTNL callback. This should help the user to
be aware which network interface is bound to which WWAN device data
channel.

Signed-off-by: Sergey Ryazanov <ryazanov.s.a@gmail.com>
CC: M Chetan Kumar <m.chetan.kumar@intel.com>
CC: Intel Corporation <linuxwwan@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Sergey Ryazanov and committed by
David S. Miller
69940924 83068395

+61 -15
+6 -6
drivers/net/mhi/net.c
··· 32 32 33 33 static int mhi_ndo_open(struct net_device *ndev) 34 34 { 35 - struct mhi_net_dev *mhi_netdev = netdev_priv(ndev); 35 + struct mhi_net_dev *mhi_netdev = wwan_netdev_drvpriv(ndev); 36 36 37 37 /* Feed the rx buffer pool */ 38 38 schedule_delayed_work(&mhi_netdev->rx_refill, 0); ··· 47 47 48 48 static int mhi_ndo_stop(struct net_device *ndev) 49 49 { 50 - struct mhi_net_dev *mhi_netdev = netdev_priv(ndev); 50 + struct mhi_net_dev *mhi_netdev = wwan_netdev_drvpriv(ndev); 51 51 52 52 netif_stop_queue(ndev); 53 53 netif_carrier_off(ndev); ··· 58 58 59 59 static netdev_tx_t mhi_ndo_xmit(struct sk_buff *skb, struct net_device *ndev) 60 60 { 61 - struct mhi_net_dev *mhi_netdev = netdev_priv(ndev); 61 + struct mhi_net_dev *mhi_netdev = wwan_netdev_drvpriv(ndev); 62 62 const struct mhi_net_proto *proto = mhi_netdev->proto; 63 63 struct mhi_device *mdev = mhi_netdev->mdev; 64 64 int err; ··· 93 93 static void mhi_ndo_get_stats64(struct net_device *ndev, 94 94 struct rtnl_link_stats64 *stats) 95 95 { 96 - struct mhi_net_dev *mhi_netdev = netdev_priv(ndev); 96 + struct mhi_net_dev *mhi_netdev = wwan_netdev_drvpriv(ndev); 97 97 unsigned int start; 98 98 99 99 do { ··· 322 322 if (dev_get_drvdata(&mhi_dev->dev)) 323 323 return -EBUSY; 324 324 325 - mhi_netdev = netdev_priv(ndev); 325 + mhi_netdev = wwan_netdev_drvpriv(ndev); 326 326 327 327 dev_set_drvdata(&mhi_dev->dev, mhi_netdev); 328 328 mhi_netdev->ndev = ndev; ··· 367 367 static void mhi_net_dellink(void *ctxt, struct net_device *ndev, 368 368 struct list_head *head) 369 369 { 370 - struct mhi_net_dev *mhi_netdev = netdev_priv(ndev); 370 + struct mhi_net_dev *mhi_netdev = wwan_netdev_drvpriv(ndev); 371 371 struct mhi_device *mhi_dev = ctxt; 372 372 373 373 if (head)
+3 -2
drivers/net/mhi/proto_mbim.c
··· 16 16 #include <linux/ip.h> 17 17 #include <linux/mii.h> 18 18 #include <linux/netdevice.h> 19 + #include <linux/wwan.h> 19 20 #include <linux/skbuff.h> 20 21 #include <linux/usb.h> 21 22 #include <linux/usb/cdc.h> ··· 57 56 58 57 static int mbim_rx_verify_nth16(struct sk_buff *skb) 59 58 { 60 - struct mhi_net_dev *dev = netdev_priv(skb->dev); 59 + struct mhi_net_dev *dev = wwan_netdev_drvpriv(skb->dev); 61 60 struct mbim_context *ctx = dev->proto_data; 62 61 struct usb_cdc_ncm_nth16 *nth16; 63 62 int len; ··· 103 102 104 103 static int mbim_rx_verify_ndp16(struct sk_buff *skb, struct usb_cdc_ncm_ndp16 *ndp16) 105 104 { 106 - struct mhi_net_dev *dev = netdev_priv(skb->dev); 105 + struct mhi_net_dev *dev = wwan_netdev_drvpriv(skb->dev); 107 106 int ret; 108 107 109 108 if (le16_to_cpu(ndp16->wLength) < USB_CDC_NCM_NDP16_LENGTH_MIN) {
+6 -6
drivers/net/wwan/iosm/iosm_ipc_wwan.c
··· 20 20 #define IOSM_IF_ID_PAYLOAD 2 21 21 22 22 /** 23 - * struct iosm_netdev_priv - netdev private data 23 + * struct iosm_netdev_priv - netdev WWAN driver specific private data 24 24 * @ipc_wwan: Pointer to iosm_wwan struct 25 25 * @netdev: Pointer to network interface device structure 26 26 * @if_id: Interface id for device. ··· 51 51 /* Bring-up the wwan net link */ 52 52 static int ipc_wwan_link_open(struct net_device *netdev) 53 53 { 54 - struct iosm_netdev_priv *priv = netdev_priv(netdev); 54 + struct iosm_netdev_priv *priv = wwan_netdev_drvpriv(netdev); 55 55 struct iosm_wwan *ipc_wwan = priv->ipc_wwan; 56 56 int if_id = priv->if_id; 57 57 int ret; ··· 88 88 /* Bring-down the wwan net link */ 89 89 static int ipc_wwan_link_stop(struct net_device *netdev) 90 90 { 91 - struct iosm_netdev_priv *priv = netdev_priv(netdev); 91 + struct iosm_netdev_priv *priv = wwan_netdev_drvpriv(netdev); 92 92 93 93 netif_stop_queue(netdev); 94 94 ··· 105 105 static int ipc_wwan_link_transmit(struct sk_buff *skb, 106 106 struct net_device *netdev) 107 107 { 108 - struct iosm_netdev_priv *priv = netdev_priv(netdev); 108 + struct iosm_netdev_priv *priv = wwan_netdev_drvpriv(netdev); 109 109 struct iosm_wwan *ipc_wwan = priv->ipc_wwan; 110 110 int if_id = priv->if_id; 111 111 int ret; ··· 178 178 if_id >= ARRAY_SIZE(ipc_wwan->sub_netlist)) 179 179 return -EINVAL; 180 180 181 - priv = netdev_priv(dev); 181 + priv = wwan_netdev_drvpriv(dev); 182 182 priv->if_id = if_id; 183 183 priv->netdev = dev; 184 184 priv->ipc_wwan = ipc_wwan; ··· 208 208 static void ipc_wwan_dellink(void *ctxt, struct net_device *dev, 209 209 struct list_head *head) 210 210 { 211 + struct iosm_netdev_priv *priv = wwan_netdev_drvpriv(dev); 211 212 struct iosm_wwan *ipc_wwan = ctxt; 212 - struct iosm_netdev_priv *priv = netdev_priv(dev); 213 213 int if_id = priv->if_id; 214 214 215 215 if (WARN_ON(if_id < IP_MUX_SESSION_START ||
+28 -1
drivers/net/wwan/wwan_core.c
··· 815 815 const char *devname = nla_data(tb[IFLA_PARENT_DEV_NAME]); 816 816 struct wwan_device *wwandev = wwan_dev_get_by_name(devname); 817 817 struct net_device *dev; 818 + unsigned int priv_size; 818 819 819 820 if (IS_ERR(wwandev)) 820 821 return ERR_CAST(wwandev); ··· 826 825 goto out; 827 826 } 828 827 829 - dev = alloc_netdev_mqs(wwandev->ops->priv_size, ifname, name_assign_type, 828 + priv_size = sizeof(struct wwan_netdev_priv) + wwandev->ops->priv_size; 829 + dev = alloc_netdev_mqs(priv_size, ifname, name_assign_type, 830 830 wwandev->ops->setup, num_tx_queues, num_rx_queues); 831 831 832 832 if (dev) { ··· 847 845 { 848 846 struct wwan_device *wwandev = wwan_dev_get_by_parent(dev->dev.parent); 849 847 u32 link_id = nla_get_u32(data[IFLA_WWAN_LINK_ID]); 848 + struct wwan_netdev_priv *priv = netdev_priv(dev); 850 849 int ret; 851 850 852 851 if (IS_ERR(wwandev)) ··· 859 856 goto out; 860 857 } 861 858 859 + priv->link_id = link_id; 862 860 if (wwandev->ops->newlink) 863 861 ret = wwandev->ops->newlink(wwandev->ops_ctxt, dev, 864 862 link_id, extack); ··· 893 889 put_device(&wwandev->dev); 894 890 } 895 891 892 + static size_t wwan_rtnl_get_size(const struct net_device *dev) 893 + { 894 + return 895 + nla_total_size(4) + /* IFLA_WWAN_LINK_ID */ 896 + 0; 897 + } 898 + 899 + static int wwan_rtnl_fill_info(struct sk_buff *skb, 900 + const struct net_device *dev) 901 + { 902 + struct wwan_netdev_priv *priv = netdev_priv(dev); 903 + 904 + if (nla_put_u32(skb, IFLA_WWAN_LINK_ID, priv->link_id)) 905 + goto nla_put_failure; 906 + 907 + return 0; 908 + 909 + nla_put_failure: 910 + return -EMSGSIZE; 911 + } 912 + 896 913 static const struct nla_policy wwan_rtnl_policy[IFLA_WWAN_MAX + 1] = { 897 914 [IFLA_WWAN_LINK_ID] = { .type = NLA_U32 }, 898 915 }; ··· 925 900 .validate = wwan_rtnl_validate, 926 901 .newlink = wwan_rtnl_newlink, 927 902 .dellink = wwan_rtnl_dellink, 903 + .get_size = wwan_rtnl_get_size, 904 + .fill_info = wwan_rtnl_fill_info, 928 905 .policy = wwan_rtnl_policy, 929 906 }; 930 907
+18
include/linux/wwan.h
··· 9 9 #include <linux/poll.h> 10 10 #include <linux/skbuff.h> 11 11 #include <linux/netlink.h> 12 + #include <linux/netdevice.h> 12 13 13 14 /** 14 15 * enum wwan_port_type - WWAN port types ··· 126 125 * @port: Related WWAN port 127 126 */ 128 127 void *wwan_port_get_drvdata(struct wwan_port *port); 128 + 129 + /** 130 + * struct wwan_netdev_priv - WWAN core network device private data 131 + * @link_id: WWAN device data link id 132 + * @drv_priv: driver private data area, size is determined in &wwan_ops 133 + */ 134 + struct wwan_netdev_priv { 135 + u32 link_id; 136 + 137 + /* must be last */ 138 + u8 drv_priv[] __aligned(sizeof(void *)); 139 + }; 140 + 141 + static inline void *wwan_netdev_drvpriv(struct net_device *dev) 142 + { 143 + return ((struct wwan_netdev_priv *)netdev_priv(dev))->drv_priv; 144 + } 129 145 130 146 /* 131 147 * Used to indicate that the WWAN core should not create a default network