// SPDX-License-Identifier: GPL-2.0-only /* * Copyright (C) ST-Ericsson AB 2013 * Authors: Vicram Arv * Dmitry Tarnyagin <[email protected]> * Sjur Brendeland */ #include <linux/module.h> #include <linux/if_arp.h> #include <linux/virtio.h> #include <linux/vringh.h> #include <linux/debugfs.h> #include <linux/spinlock.h> #include <linux/genalloc.h> #include <linux/interrupt.h> #include <linux/netdevice.h> #include <linux/rtnetlink.h> #include <linux/virtio_ids.h> #include <linux/virtio_caif.h> #include <linux/virtio_ring.h> #include <linux/dma-mapping.h> #include <net/caif/caif_dev.h> #include <linux/virtio_config.h> MODULE_LICENSE(…) …; MODULE_AUTHOR(…) …; MODULE_AUTHOR(…) …; MODULE_DESCRIPTION(…) …; /* NAPI schedule quota */ #define CFV_DEFAULT_QUOTA … /* Defaults used if virtio config space is unavailable */ #define CFV_DEF_MTU_SIZE … #define CFV_DEF_HEADROOM … #define CFV_DEF_TAILROOM … /* Required IP header alignment */ #define IP_HDR_ALIGN … /* struct cfv_napi_contxt - NAPI context info * @riov: IOV holding data read from the ring. Note that riov may * still hold data when cfv_rx_poll() returns. * @head: Last descriptor ID we received from vringh_getdesc_kern. * We use this to put descriptor back on the used ring. USHRT_MAX is * used to indicate invalid head-id. */ struct cfv_napi_context { … }; /* struct cfv_stats - statistics for debugfs * @rx_napi_complete: Number of NAPI completions (RX) * @rx_napi_resched: Number of calls where the full quota was used (RX) * @rx_nomem: Number of SKB alloc failures (RX) * @rx_kicks: Number of RX kicks * @tx_full_ring: Number times TX ring was full * @tx_no_mem: Number of times TX went out of memory * @tx_flow_on: Number of flow on (TX) * @tx_kicks: Number of TX kicks */ struct cfv_stats { … }; /* struct cfv_info - Caif Virtio control structure * @cfdev: caif common header * @vdev: Associated virtio device * @vr_rx: rx/downlink host vring * @vq_tx: tx/uplink virtqueue * @ndev: CAIF link layer device * @watermark_tx: indicates number of free descriptors we need * to reopen the tx-queues after overload. * @tx_lock: protects vq_tx from concurrent use * @tx_release_tasklet: Tasklet for freeing consumed TX buffers * @napi: Napi context used in cfv_rx_poll() * @ctx: Context data used in cfv_rx_poll() * @tx_hr: transmit headroom * @rx_hr: receive headroom * @tx_tr: transmit tail room * @rx_tr: receive tail room * @mtu: transmit max size * @mru: receive max size * @allocsz: size of dma memory reserved for TX buffers * @alloc_addr: virtual address to dma memory for TX buffers * @alloc_dma: dma address to dma memory for TX buffers * @genpool: Gen Pool used for allocating TX buffers * @reserved_mem: Pointer to memory reserve allocated from genpool * @reserved_size: Size of memory reserve allocated from genpool * @stats: Statistics exposed in sysfs * @debugfs: Debugfs dentry for statistic counters */ struct cfv_info { … }; /* struct buf_info - maintains transmit buffer data handle * @size: size of transmit buffer * @dma_handle: handle to allocated dma device memory area * @vaddr: virtual address mapping to allocated memory area */ struct buf_info { … }; /* Called from virtio device, in IRQ context */ static void cfv_release_cb(struct virtqueue *vq_tx) { … } static void free_buf_info(struct cfv_info *cfv, struct buf_info *buf_info) { … } /* This is invoked whenever the remote processor completed processing * a TX msg we just sent, and the buffer is put back to the used ring. */ static void cfv_release_used_buf(struct virtqueue *vq_tx) { … } /* Allocate a SKB and copy packet data to it */ static struct sk_buff *cfv_alloc_and_copy_skb(int *err, struct cfv_info *cfv, u8 *frm, u32 frm_len) { … } /* Get packets from the host vring */ static int cfv_rx_poll(struct napi_struct *napi, int quota) { … } static void cfv_recv(struct virtio_device *vdev, struct vringh *vr_rx) { … } static void cfv_destroy_genpool(struct cfv_info *cfv) { … } static int cfv_create_genpool(struct cfv_info *cfv) { … } /* Enable the CAIF interface and allocate the memory-pool */ static int cfv_netdev_open(struct net_device *netdev) { … } /* Disable the CAIF interface and free the memory-pool */ static int cfv_netdev_close(struct net_device *netdev) { … } /* Allocate a buffer in dma-memory and copy skb to it */ static struct buf_info *cfv_alloc_and_copy_to_shm(struct cfv_info *cfv, struct sk_buff *skb, struct scatterlist *sg) { … } /* Put the CAIF packet on the virtio ring and kick the receiver */ static netdev_tx_t cfv_netdev_tx(struct sk_buff *skb, struct net_device *netdev) { … } static void cfv_tx_release_tasklet(struct tasklet_struct *t) { … } static const struct net_device_ops cfv_netdev_ops = …; static void cfv_netdev_setup(struct net_device *netdev) { … } /* Create debugfs counters for the device */ static inline void debugfs_init(struct cfv_info *cfv) { … } /* Setup CAIF for the a virtio device */ static int cfv_probe(struct virtio_device *vdev) { … } static void cfv_remove(struct virtio_device *vdev) { … } static struct virtio_device_id id_table[] = …; static unsigned int features[] = …; static struct virtio_driver caif_virtio_driver = …; module_virtio_driver(…) …; MODULE_DEVICE_TABLE(virtio, id_table);