static int mhi_ndo_open(struct net_device *ndev)
{
- struct mhi_net_dev *mhi_netdev = netdev_priv(ndev);
+ struct mhi_net_dev *mhi_netdev = wwan_netdev_drvpriv(ndev);
/* Feed the rx buffer pool */
schedule_delayed_work(&mhi_netdev->rx_refill, 0);
static int mhi_ndo_stop(struct net_device *ndev)
{
- struct mhi_net_dev *mhi_netdev = netdev_priv(ndev);
+ struct mhi_net_dev *mhi_netdev = wwan_netdev_drvpriv(ndev);
netif_stop_queue(ndev);
netif_carrier_off(ndev);
static netdev_tx_t mhi_ndo_xmit(struct sk_buff *skb, struct net_device *ndev)
{
- struct mhi_net_dev *mhi_netdev = netdev_priv(ndev);
+ struct mhi_net_dev *mhi_netdev = wwan_netdev_drvpriv(ndev);
const struct mhi_net_proto *proto = mhi_netdev->proto;
struct mhi_device *mdev = mhi_netdev->mdev;
int err;
static void mhi_ndo_get_stats64(struct net_device *ndev,
struct rtnl_link_stats64 *stats)
{
- struct mhi_net_dev *mhi_netdev = netdev_priv(ndev);
+ struct mhi_net_dev *mhi_netdev = wwan_netdev_drvpriv(ndev);
unsigned int start;
do {
if (dev_get_drvdata(&mhi_dev->dev))
return -EBUSY;
- mhi_netdev = netdev_priv(ndev);
+ mhi_netdev = wwan_netdev_drvpriv(ndev);
dev_set_drvdata(&mhi_dev->dev, mhi_netdev);
mhi_netdev->ndev = ndev;
static void mhi_net_dellink(void *ctxt, struct net_device *ndev,
struct list_head *head)
{
- struct mhi_net_dev *mhi_netdev = netdev_priv(ndev);
+ struct mhi_net_dev *mhi_netdev = wwan_netdev_drvpriv(ndev);
struct mhi_device *mhi_dev = ctxt;
if (head)
#include <linux/ip.h>
#include <linux/mii.h>
#include <linux/netdevice.h>
+#include <linux/wwan.h>
#include <linux/skbuff.h>
#include <linux/usb.h>
#include <linux/usb/cdc.h>
static int mbim_rx_verify_nth16(struct sk_buff *skb)
{
- struct mhi_net_dev *dev = netdev_priv(skb->dev);
+ struct mhi_net_dev *dev = wwan_netdev_drvpriv(skb->dev);
struct mbim_context *ctx = dev->proto_data;
struct usb_cdc_ncm_nth16 *nth16;
int len;
static int mbim_rx_verify_ndp16(struct sk_buff *skb, struct usb_cdc_ncm_ndp16 *ndp16)
{
- struct mhi_net_dev *dev = netdev_priv(skb->dev);
+ struct mhi_net_dev *dev = wwan_netdev_drvpriv(skb->dev);
int ret;
if (le16_to_cpu(ndp16->wLength) < USB_CDC_NCM_NDP16_LENGTH_MIN) {
#define IOSM_IF_ID_PAYLOAD 2
/**
- * struct iosm_netdev_priv - netdev private data
+ * struct iosm_netdev_priv - netdev WWAN driver specific private data
* @ipc_wwan: Pointer to iosm_wwan struct
* @netdev: Pointer to network interface device structure
* @if_id: Interface id for device.
/* Bring-up the wwan net link */
static int ipc_wwan_link_open(struct net_device *netdev)
{
- struct iosm_netdev_priv *priv = netdev_priv(netdev);
+ struct iosm_netdev_priv *priv = wwan_netdev_drvpriv(netdev);
struct iosm_wwan *ipc_wwan = priv->ipc_wwan;
int if_id = priv->if_id;
int ret;
/* Bring-down the wwan net link */
static int ipc_wwan_link_stop(struct net_device *netdev)
{
- struct iosm_netdev_priv *priv = netdev_priv(netdev);
+ struct iosm_netdev_priv *priv = wwan_netdev_drvpriv(netdev);
netif_stop_queue(netdev);
static int ipc_wwan_link_transmit(struct sk_buff *skb,
struct net_device *netdev)
{
- struct iosm_netdev_priv *priv = netdev_priv(netdev);
+ struct iosm_netdev_priv *priv = wwan_netdev_drvpriv(netdev);
struct iosm_wwan *ipc_wwan = priv->ipc_wwan;
int if_id = priv->if_id;
int ret;
if_id >= ARRAY_SIZE(ipc_wwan->sub_netlist))
return -EINVAL;
- priv = netdev_priv(dev);
+ priv = wwan_netdev_drvpriv(dev);
priv->if_id = if_id;
priv->netdev = dev;
priv->ipc_wwan = ipc_wwan;
static void ipc_wwan_dellink(void *ctxt, struct net_device *dev,
struct list_head *head)
{
+ struct iosm_netdev_priv *priv = wwan_netdev_drvpriv(dev);
struct iosm_wwan *ipc_wwan = ctxt;
- struct iosm_netdev_priv *priv = netdev_priv(dev);
int if_id = priv->if_id;
if (WARN_ON(if_id < IP_MUX_SESSION_START ||
const char *devname = nla_data(tb[IFLA_PARENT_DEV_NAME]);
struct wwan_device *wwandev = wwan_dev_get_by_name(devname);
struct net_device *dev;
+ unsigned int priv_size;
if (IS_ERR(wwandev))
return ERR_CAST(wwandev);
goto out;
}
- dev = alloc_netdev_mqs(wwandev->ops->priv_size, ifname, name_assign_type,
+ priv_size = sizeof(struct wwan_netdev_priv) + wwandev->ops->priv_size;
+ dev = alloc_netdev_mqs(priv_size, ifname, name_assign_type,
wwandev->ops->setup, num_tx_queues, num_rx_queues);
if (dev) {
{
struct wwan_device *wwandev = wwan_dev_get_by_parent(dev->dev.parent);
u32 link_id = nla_get_u32(data[IFLA_WWAN_LINK_ID]);
+ struct wwan_netdev_priv *priv = netdev_priv(dev);
int ret;
if (IS_ERR(wwandev))
goto out;
}
+ priv->link_id = link_id;
if (wwandev->ops->newlink)
ret = wwandev->ops->newlink(wwandev->ops_ctxt, dev,
link_id, extack);
put_device(&wwandev->dev);
}
+static size_t wwan_rtnl_get_size(const struct net_device *dev)
+{
+ return
+ nla_total_size(4) + /* IFLA_WWAN_LINK_ID */
+ 0;
+}
+
+static int wwan_rtnl_fill_info(struct sk_buff *skb,
+ const struct net_device *dev)
+{
+ struct wwan_netdev_priv *priv = netdev_priv(dev);
+
+ if (nla_put_u32(skb, IFLA_WWAN_LINK_ID, priv->link_id))
+ goto nla_put_failure;
+
+ return 0;
+
+nla_put_failure:
+ return -EMSGSIZE;
+}
+
static const struct nla_policy wwan_rtnl_policy[IFLA_WWAN_MAX + 1] = {
[IFLA_WWAN_LINK_ID] = { .type = NLA_U32 },
};
.validate = wwan_rtnl_validate,
.newlink = wwan_rtnl_newlink,
.dellink = wwan_rtnl_dellink,
+ .get_size = wwan_rtnl_get_size,
+ .fill_info = wwan_rtnl_fill_info,
.policy = wwan_rtnl_policy,
};
#include <linux/poll.h>
#include <linux/skbuff.h>
#include <linux/netlink.h>
+#include <linux/netdevice.h>
/**
* enum wwan_port_type - WWAN port types
*/
void *wwan_port_get_drvdata(struct wwan_port *port);
+/**
+ * struct wwan_netdev_priv - WWAN core network device private data
+ * @link_id: WWAN device data link id
+ * @drv_priv: driver private data area, size is determined in &wwan_ops
+ */
+struct wwan_netdev_priv {
+ u32 link_id;
+
+ /* must be last */
+ u8 drv_priv[] __aligned(sizeof(void *));
+};
+
+static inline void *wwan_netdev_drvpriv(struct net_device *dev)
+{
+ return ((struct wwan_netdev_priv *)netdev_priv(dev))->drv_priv;
+}
+
/*
* Used to indicate that the WWAN core should not create a default network
* link.