/** * 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. * @ch_id: IPC channel number for which interface device is created.
*/ struct iosm_netdev_priv { struct iosm_wwan *ipc_wwan; struct net_device *netdev; int if_id; int ch_id;
};
/** * struct iosm_wwan - This structure contains information about WWAN root device * and interface to the IPC layer. * @ipc_imem: Pointer to imem data-struct * @sub_netlist: List of active netdevs * @dev: Pointer device structure
*/ struct iosm_wwan { struct iosm_imem *ipc_imem; struct iosm_netdev_priv __rcu *sub_netlist[IP_MUX_SESSION_END + 1]; struct device *dev;
};
/* Bring-up the wwan net link */ staticint ipc_wwan_link_open(struct net_device *netdev)
{ struct iosm_netdev_priv *priv = wwan_netdev_drvpriv(netdev); struct iosm_wwan *ipc_wwan = priv->ipc_wwan; int if_id = priv->if_id;
if (if_id < IP_MUX_SESSION_START ||
if_id >= ARRAY_SIZE(ipc_wwan->sub_netlist)) return -EINVAL;
/* get channel id */
priv->ch_id = ipc_imem_sys_wwan_open(ipc_wwan->ipc_imem, if_id);
if (priv->ch_id < 0) {
dev_err(ipc_wwan->dev, "cannot connect wwan0 & id %d to the IPC mem layer",
if_id); return -ENODEV;
}
/* enable tx path, DL data may follow */
netif_start_queue(netdev);
dev_dbg(ipc_wwan->dev, "Channel id %d allocated to if_id %d",
priv->ch_id, priv->if_id);
return 0;
}
/* Bring-down the wwan net link */ staticint ipc_wwan_link_stop(struct net_device *netdev)
{ struct iosm_netdev_priv *priv = wwan_netdev_drvpriv(netdev);
/* Transmit a packet */ static netdev_tx_t ipc_wwan_link_transmit(struct sk_buff *skb, struct net_device *netdev)
{ struct iosm_netdev_priv *priv = wwan_netdev_drvpriv(netdev); struct iosm_wwan *ipc_wwan = priv->ipc_wwan; unsignedint len = skb->len; int if_id = priv->if_id; int ret;
/* Interface IDs from 1 to 8 are for IP data * & from 257 to 261 are for non-IP data
*/ if (if_id < IP_MUX_SESSION_START ||
if_id >= ARRAY_SIZE(ipc_wwan->sub_netlist)) return -EINVAL;
/* Send the SKB to device for transmission */
ret = ipc_imem_sys_wwan_transmit(ipc_wwan->ipc_imem,
if_id, priv->ch_id, skb);
/* Return code of zero is success */ if (ret == 0) {
netdev->stats.tx_packets++;
netdev->stats.tx_bytes += len;
ret = NETDEV_TX_OK;
} elseif (ret == -EBUSY) {
ret = NETDEV_TX_BUSY;
dev_err(ipc_wwan->dev, "unable to push packets");
} else { gotoexit;
}
return ret;
exit: /* Log any skb drop */ if (if_id)
dev_dbg(ipc_wwan->dev, "skb dropped. IF_ID: %d, ret: %d", if_id,
ret);
/* Ops structure for wwan net link */ staticconststruct net_device_ops ipc_inm_ops = {
.ndo_open = ipc_wwan_link_open,
.ndo_stop = ipc_wwan_link_stop,
.ndo_start_xmit = ipc_wwan_link_transmit,
};
/* Setup function for creating new net link */ staticvoid ipc_wwan_setup(struct net_device *iosm_dev)
{
iosm_dev->header_ops = NULL;
iosm_dev->hard_header_len = 0;
iosm_dev->tx_queue_len = DEFAULT_TX_QUEUE_LEN;
/* WWAN core will create a netdev for the default IP MUX channel */ if (wwan_register_ops(ipc_wwan->dev, &iosm_wwan_ops, ipc_wwan,
IP_MUX_SESSION_DEFAULT)) {
kfree(ipc_wwan); return NULL;
}
return ipc_wwan;
}
void ipc_wwan_deinit(struct iosm_wwan *ipc_wwan)
{ /* This call will remove all child netdev(s) */
wwan_unregister_ops(ipc_wwan->dev);
kfree(ipc_wwan);
}
Messung V0.5
¤ Dauer der Verarbeitung: 0.1 Sekunden
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.