Pull virtio updates from Michael Tsirkin: - new virtio CAN driver - support for LoongArch architecture in fw_cfg - support for firmware notifications in vdpa/octeon_ep - support for VFs in virtio core - fixes, cleanups all over the place, notably: - vhost: fix vhost_get_avail_idx for a non empty ring fixing an significant old perf regression - READ_ONCE() annotations mean virtio ring is now free of KCSAN warnings * tag 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mst/vhost: (37 commits) can: virtio: Fix comment in UAPI header can: virtio: Add virtio CAN driver virtio: add num_vf callback to virtio_bus fw_cfg: Add support for LoongArch architecture vdpa/octeon_ep: fix IRQ-to-ring mapping in interrupt handler vdpa/octeon_ep: Add vDPA device event handling for firmware notifications vdpa/octeon_ep: Use 4 bytes for mailbox signature vdpa/octeon_ep: Fix PF->VF mailbox data address calculation vhost_task_create: kill unnecessary .exit_signal initialization vhost: remove unnecessary module_init/exit functions vdpa/mlx5: Use kvzalloc_flex() for MTT command memory vdpa_sim_net: switch to dynamic root device vdpa_sim_blk: switch to dynamic root device virtio-mem: Destroy mutex before freeing virtio_mem virtio-balloon: Destroy mutex before freeing virtio_balloon tools/virtio: fix build for kmalloc_obj API and missing stubs virtio_ring: Add READ_ONCE annotations for device-writable fields vduse: fix compat handling for VDUSE_IOTLB_GET_FD/VDUSE_VQ_GET_INFO tools/virtio: check mmap return value in vringh_test vhost/net: complete zerocopy ubufs only once ...
Unified · Split
| @@ -28326,6 +28326,15 @@ F: drivers/scsi/virtio_scsi.c · 28325 unmodified lines | |||
| 28326 | F: include/uapi/linux/virtio_blk.h | 28326 | F: include/uapi/linux/virtio_blk.h |
| 28327 | F: include/uapi/linux/virtio_scsi.h | 28327 | F: include/uapi/linux/virtio_scsi.h |
| 28328 | 28328 | ||
| 28329 | VIRTIO CAN DRIVER | ||
| 28330 | M: "Harald Mommer" <harald.mommer@oss.qualcomm.com> | ||
| 28331 | M: "Matias Ezequiel Vara Larsen" <mvaralar@redhat.com> | ||
| 28332 | L: virtualization@lists.linux.dev | ||
| 28333 | L: linux-can@vger.kernel.org | ||
| 28334 | S: Maintained | ||
| 28335 | F: drivers/net/can/virtio_can.c | ||
| 28336 | F: include/uapi/linux/virtio_can.h | ||
| 28337 | |||
| 28329 | VIRTIO CONSOLE DRIVER | 28338 | VIRTIO CONSOLE DRIVER |
| 28330 | M: Amit Shah <amit@kernel.org> | 28339 | M: Amit Shah <amit@kernel.org> |
| 28331 | L: virtualization@lists.linux.dev | 28340 | L: virtualization@lists.linux.dev |
| @@ -7,6 +7,7 @@ · 6 unmodified lines | |||
| 7 | #include <asm/barrier.h> | 7 | #include <asm/barrier.h> |
| 8 | #include <linux/err.h> | 8 | #include <linux/err.h> |
| 9 | #include <linux/hw_random.h> | 9 | #include <linux/hw_random.h> |
| 10 | #include <linux/nospec.h> | ||
| 10 | #include <linux/scatterlist.h> | 11 | #include <linux/scatterlist.h> |
| 11 | #include <linux/spinlock.h> | 12 | #include <linux/spinlock.h> |
| 12 | #include <linux/virtio.h> | 13 | #include <linux/virtio.h> |
| @@ -69,8 +70,26 @@ static void request_entropy(struct virtrng_info *vi) · 56 unmodified lines | |||
| 69 | static unsigned int copy_data(struct virtrng_info *vi, void *buf, | 70 | static unsigned int copy_data(struct virtrng_info *vi, void *buf, |
| 70 | unsigned int size) | 71 | unsigned int size) |
| 71 | { | 72 | { |
| 72 | size = min_t(unsigned int, size, vi->data_avail); | 73 | unsigned int idx, avail; |
| 73 | memcpy(buf, vi->data + vi->data_idx, size); | 74 | |
| 75 | /* | ||
| 76 | * vi->data_avail was set from the device-reported used.len and | ||
| 77 | * vi->data_idx was advanced by previous copy_data() calls. A | ||
| 78 | * malicious or buggy virtio-rng backend can drive either past | ||
| 79 | * sizeof(vi->data). Clamp at point of use and harden the index | ||
| 80 | * with array_index_nospec() so the memcpy() below cannot be | ||
| 81 | * steered into adjacent slab memory, including under | ||
| 82 | * speculation. | ||
| 83 | */ | ||
| 84 | avail = min_t(unsigned int, vi->data_avail, sizeof(vi->data)); | ||
| 85 | if (vi->data_idx >= avail) { | ||
| 86 | vi->data_avail = 0; | ||
| 87 | request_entropy(vi); | ||
| 88 | return 0; | ||
| 89 | } | ||
| 90 | size = min_t(unsigned int, size, avail - vi->data_idx); | ||
| 91 | idx = array_index_nospec(vi->data_idx, sizeof(vi->data)); | ||
| 92 | memcpy(buf, vi->data + idx, size); | ||
| 74 | vi->data_idx += size; | 93 | vi->data_idx += size; |
| 75 | vi->data_avail -= size; | 94 | vi->data_avail -= size; |
| 76 | if (vi->data_avail == 0) | 95 | if (vi->data_avail == 0) |
| @@ -1771,32 +1771,40 @@ static void config_intr(struct virtio_device *vdev) · 1770 unmodified lines | |||
| 1771 | schedule_work(&portdev->config_work); | 1771 | schedule_work(&portdev->config_work); |
| 1772 | } | 1772 | } |
| 1773 | 1773 | ||
| 1774 | static void config_work_handler(struct work_struct *work) | 1774 | static void update_size_from_config(struct ports_device *portdev) |
| 1775 | { | 1775 | { |
| 1776 | struct ports_device *portdev; | 1776 | struct virtio_device *vdev; |
| 1777 | struct port *port; | ||
| 1778 | u16 rows, cols; | ||
| 1777 | 1779 | ||
| 1778 | portdev = container_of(work, struct ports_device, config_work); | 1780 | vdev = portdev->vdev; |
| 1779 | if (!use_multiport(portdev)) { | ||
| 1780 | struct virtio_device *vdev; | ||
| 1781 | struct port *port; | ||
| 1782 | u16 rows, cols; | ||
| 1783 | 1781 | ||
| 1784 | vdev = portdev->vdev; | 1782 | /* |
| 1785 | virtio_cread(vdev, struct virtio_console_config, cols, &cols); | 1783 | * We'll use this way of resizing only for legacy support. |
| 1786 | virtio_cread(vdev, struct virtio_console_config, rows, &rows); | 1784 | * For multiport devices, use control messages to indicate |
| 1785 | * console size changes so that it can be done per-port. | ||
| 1786 | * | ||
| 1787 | * Don't test F_SIZE at all if we're rproc: not a valid feature. | ||
| 1788 | */ | ||
| 1789 | if (is_rproc_serial(vdev) || | ||
| 1790 | use_multiport(portdev) || | ||
| 1791 | !virtio_has_feature(vdev, VIRTIO_CONSOLE_F_SIZE)) | ||
| 1792 | return; | ||
| 1787 | 1793 | ||
| 1788 | port = find_port_by_id(portdev, 0); | 1794 | virtio_cread(vdev, struct virtio_console_config, cols, &cols); |
| 1789 | set_console_size(port, rows, cols); | 1795 | virtio_cread(vdev, struct virtio_console_config, rows, &rows); |
| 1790 | 1796 | ||
| 1791 | /* | 1797 | port = find_port_by_id(portdev, 0); |
| 1792 | * We'll use this way of resizing only for legacy | 1798 | set_console_size(port, rows, cols); |
| 1793 | * support. For newer userspace | 1799 | resize_console(port); |
| 1794 | * (VIRTIO_CONSOLE_F_MULTPORT+), use control messages | 1800 | } |
| 1795 | * to indicate console size changes so that it can be | 1801 | |
| 1796 | * done per-port. | 1802 | static void config_work_handler(struct work_struct *work) |
| 1797 | */ | 1803 | { |
| 1798 | resize_console(port); | 1804 | struct ports_device *portdev; |
| 1799 | } | 1805 | |
| 1806 | portdev = container_of(work, struct ports_device, config_work); | ||
| 1807 | update_size_from_config(portdev); | ||
| 1800 | } | 1808 | } |
| 1801 | 1809 | ||
| 1802 | static int init_vqs(struct ports_device *portdev) | 1810 | static int init_vqs(struct ports_device *portdev) |
| @@ -2052,6 +2060,8 @@ static int virtcons_probe(struct virtio_device *vdev) · 249 unmodified lines | |||
| 2052 | __send_control_msg(portdev, VIRTIO_CONSOLE_BAD_ID, | 2060 | __send_control_msg(portdev, VIRTIO_CONSOLE_BAD_ID, |
| 2053 | VIRTIO_CONSOLE_DEVICE_READY, 1); | 2061 | VIRTIO_CONSOLE_DEVICE_READY, 1); |
| 2054 | 2062 | ||
| 2063 | update_size_from_config(portdev); | ||
| 2064 | |||
| 2055 | return 0; | 2065 | return 0; |
| 2056 | 2066 | ||
| 2057 | free_chrdev: | 2067 | free_chrdev: |
| @@ -124,7 +124,7 @@ config RASPBERRYPI_FIRMWARE · 123 unmodified lines | |||
| 124 | 124 | ||
| 125 | config FW_CFG_SYSFS | 125 | config FW_CFG_SYSFS |
| 126 | tristate "QEMU fw_cfg device support in sysfs" | 126 | tristate "QEMU fw_cfg device support in sysfs" |
| 127 | depends on SYSFS && (ARM || ARM64 || PARISC || PPC_PMAC || RISCV || SPARC || X86) | 127 | depends on SYSFS && (ARM || ARM64 || LOONGARCH || PARISC || PPC_PMAC || RISCV || SPARC || X86) |
| 128 | depends on HAS_IOPORT_MAP | 128 | depends on HAS_IOPORT_MAP |
| 129 | default n | 129 | default n |
| 130 | help | 130 | help |
| @@ -211,7 +211,7 @@ static void fw_cfg_io_cleanup(void) · 210 unmodified lines | |||
| 211 | 211 | ||
| 212 | /* arch-specific ctrl & data register offsets are not available in ACPI, DT */ | 212 | /* arch-specific ctrl & data register offsets are not available in ACPI, DT */ |
| 213 | #if !(defined(FW_CFG_CTRL_OFF) && defined(FW_CFG_DATA_OFF)) | 213 | #if !(defined(FW_CFG_CTRL_OFF) && defined(FW_CFG_DATA_OFF)) |
| 214 | # if (defined(CONFIG_ARM) || defined(CONFIG_ARM64) || defined(CONFIG_RISCV)) | 214 | # if (defined(CONFIG_ARM) || defined(CONFIG_ARM64) || defined(CONFIG_LOONGARCH) || defined(CONFIG_RISCV)) |
| 215 | # define FW_CFG_CTRL_OFF 0x08 | 215 | # define FW_CFG_CTRL_OFF 0x08 |
| 216 | # define FW_CFG_DATA_OFF 0x00 | 216 | # define FW_CFG_DATA_OFF 0x00 |
| 217 | # define FW_CFG_DMA_OFF 0x10 | 217 | # define FW_CFG_DMA_OFF 0x10 |
| @@ -226,6 +226,18 @@ config CAN_TI_HECC · 225 unmodified lines | |||
| 226 | Driver for TI HECC (High End CAN Controller) module found on many | 226 | Driver for TI HECC (High End CAN Controller) module found on many |
| 227 | TI devices. The device specifications are available from www.ti.com | 227 | TI devices. The device specifications are available from www.ti.com |
| 228 | 228 | ||
| 229 | config CAN_VIRTIO_CAN | ||
| 230 | depends on VIRTIO | ||
| 231 | tristate "Virtio CAN device support" | ||
| 232 | default n | ||
| 233 | help | ||
| 234 | Say Y here if you want to support for Virtio CAN. | ||
| 235 | |||
| 236 | To compile this driver as a module, choose M here: the | ||
| 237 | module will be called virtio-can. | ||
| 238 | |||
| 239 | If unsure, say N. | ||
| 240 | |||
| 229 | config CAN_XILINXCAN | 241 | config CAN_XILINXCAN |
| 230 | tristate "Xilinx CAN" | 242 | tristate "Xilinx CAN" |
| 231 | depends on ARCH_ZYNQ || ARM64 || MICROBLAZE || COMPILE_TEST | 243 | depends on ARCH_ZYNQ || ARM64 || MICROBLAZE || COMPILE_TEST |
| @@ -33,6 +33,7 @@ obj-$(CONFIG_CAN_PEAK_PCIEFD) += peak_canfd/ · 32 unmodified lines | |||
| 33 | obj-$(CONFIG_CAN_SJA1000) += sja1000/ | 33 | obj-$(CONFIG_CAN_SJA1000) += sja1000/ |
| 34 | obj-$(CONFIG_CAN_SUN4I) += sun4i_can.o | 34 | obj-$(CONFIG_CAN_SUN4I) += sun4i_can.o |
| 35 | obj-$(CONFIG_CAN_TI_HECC) += ti_hecc.o | 35 | obj-$(CONFIG_CAN_TI_HECC) += ti_hecc.o |
| 36 | obj-$(CONFIG_CAN_VIRTIO_CAN) += virtio_can.o | ||
| 36 | obj-$(CONFIG_CAN_XILINXCAN) += xilinx_can.o | 37 | obj-$(CONFIG_CAN_XILINXCAN) += xilinx_can.o |
| 37 | 38 | ||
| 38 | subdir-ccflags-$(CONFIG_CAN_DEBUG_DEVICES) += -DDEBUG | 39 | subdir-ccflags-$(CONFIG_CAN_DEBUG_DEVICES) += -DDEBUG |
| @@ -0,0 +1,1022 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0-only | ||
| 2 | /* | ||
| 3 | * CAN bus driver for the Virtio CAN controller | ||
| 4 | * | ||
| 5 | * Copyright (C) 2021-2023 OpenSynergy GmbH | ||
| 6 | * Copyright Red Hat, Inc. 2025 | ||
| 7 | */ | ||
| 8 | |||
| 9 | #include <linux/atomic.h> | ||
| 10 | #include <linux/idr.h> | ||
| 11 | #include <linux/interrupt.h> | ||
| 12 | #include <linux/io.h> | ||
| 13 | #include <linux/kernel.h> | ||
| 14 | #include <linux/module.h> | ||
| 15 | #include <linux/mutex.h> | ||
| 16 | #include <linux/netdevice.h> | ||
| 17 | #include <linux/stddef.h> | ||
| 18 | #include <linux/can/dev.h> | ||
| 19 | #include <linux/virtio.h> | ||
| 20 | #include <linux/virtio_ring.h> | ||
| 21 | #include <linux/virtio_can.h> | ||
| 22 | |||
| 23 | /* CAN device queues */ | ||
| 24 | #define VIRTIO_CAN_QUEUE_TX 0 | ||
| 25 | #define VIRTIO_CAN_QUEUE_RX 1 | ||
| 26 | #define VIRTIO_CAN_QUEUE_CONTROL 2 | ||
| 27 | #define VIRTIO_CAN_QUEUE_COUNT 3 | ||
| 28 | |||
| 29 | #define CAN_KNOWN_FLAGS \ | ||
| 30 | (VIRTIO_CAN_FLAGS_EXTENDED |\ | ||
| 31 | VIRTIO_CAN_FLAGS_FD |\ | ||
| 32 | VIRTIO_CAN_FLAGS_RTR) | ||
| 33 | |||
| 34 | /* Max. number of in flight TX messages */ | ||
| 35 | #define VIRTIO_CAN_ECHO_SKB_MAX 128 | ||
| 36 | |||
| 37 | struct virtio_can_tx { | ||
| 38 | unsigned int putidx; | ||
| 39 | struct virtio_can_tx_in tx_in; | ||
| 40 | /* Keep virtio_can_tx_out at the end of the structure due to flex array */ | ||
| 41 | struct virtio_can_tx_out tx_out; | ||
| 42 | }; | ||
| 43 | |||
| 44 | struct virtio_can_control { | ||
| 45 | struct virtio_can_control_out cpkt_out; | ||
| 46 | struct virtio_can_control_in cpkt_in; | ||
| 47 | }; | ||
| 48 | |||
| 49 | /* virtio_can private data structure */ | ||
| 50 | struct virtio_can_priv { | ||
| 51 | struct can_priv can; /* must be the first member */ | ||
| 52 | /* NAPI for RX messages */ | ||
| 53 | struct napi_struct napi; | ||
| 54 | /* NAPI for TX messages */ | ||
| 55 | struct napi_struct napi_tx; | ||
| 56 | /* The network device we're associated with */ | ||
| 57 | struct net_device *dev; | ||
| 58 | /* The virtio device we're associated with */ | ||
| 59 | struct virtio_device *vdev; | ||
| 60 | /* The virtqueues */ | ||
| 61 | struct virtqueue *vqs[VIRTIO_CAN_QUEUE_COUNT]; | ||
| 62 | /* Lock for TX operations */ | ||
| 63 | spinlock_t tx_lock; | ||
| 64 | /* Control queue lock */ | ||
| 65 | struct mutex ctrl_lock; | ||
| 66 | /* Wait for control queue processing without polling */ | ||
| 67 | struct completion ctrl_done; | ||
| 68 | /* Array of receive queue messages */ | ||
| 69 | struct virtio_can_rx *rpkt; | ||
| 70 | struct virtio_can_control can_ctr_msg; | ||
| 71 | /* Data to get and maintain the putidx for local TX echo */ | ||
| 72 | struct ida tx_putidx_ida; | ||
| 73 | /* In flight TX messages */ | ||
| 74 | atomic_t tx_inflight; | ||
| 75 | /* Packet length */ | ||
| 76 | int rpkt_len; | ||
| 77 | /* BusOff pending. Reset after successful indication to upper layer */ | ||
| 78 | bool busoff_pending; | ||
| 79 | /* Tracks whether NAPI instances are currently enabled */ | ||
| 80 | bool napi_active; | ||
| 81 | }; | ||
| 82 | |||
| 83 | static void virtqueue_napi_schedule(struct napi_struct *napi, | ||
| 84 | struct virtqueue *vq) | ||
| 85 | { | ||
| 86 | if (napi_schedule_prep(napi)) { | ||
| 87 | virtqueue_disable_cb(vq); | ||
| 88 | __napi_schedule(napi); | ||
| 89 | } | ||
| 90 | } | ||
| 91 | |||
| 92 | static void virtqueue_napi_complete(struct napi_struct *napi, | ||
| 93 | struct virtqueue *vq, int processed) | ||
| 94 | { | ||
| 95 | int opaque; | ||
| 96 | |||
| 97 | opaque = virtqueue_enable_cb_prepare(vq); | ||
| 98 | if (napi_complete_done(napi, processed)) { | ||
| 99 | if (unlikely(virtqueue_poll(vq, opaque))) | ||
| 100 | virtqueue_napi_schedule(napi, vq); | ||
| 101 | } else { | ||
| 102 | virtqueue_disable_cb(vq); | ||
| 103 | } | ||
| 104 | } | ||
| 105 | |||
| 106 | static void virtio_can_free_candev(struct net_device *ndev) | ||
| 107 | { | ||
| 108 | struct virtio_can_priv *priv = netdev_priv(ndev); | ||
| 109 | |||
| 110 | ida_destroy(&priv->tx_putidx_ida); | ||
| 111 | free_candev(ndev); | ||
| 112 | } | ||
| 113 | |||
| 114 | static void virtio_can_napi_enable(struct virtio_can_priv *priv) | ||
| 115 | { | ||
| 116 | if (!priv->napi_active) { | ||
| 117 | napi_enable(&priv->napi); | ||
| 118 | napi_enable(&priv->napi_tx); | ||
| 119 | priv->napi_active = true; | ||
| 120 | } | ||
| 121 | } | ||
| 122 | |||
| 123 | static void virtio_can_napi_disable(struct virtio_can_priv *priv) | ||
| 124 | { | ||
| 125 | if (priv->napi_active) { | ||
| 126 | napi_disable(&priv->napi_tx); | ||
| 127 | napi_disable(&priv->napi); | ||
| 128 | priv->napi_active = false; | ||
| 129 | } | ||
| 130 | } | ||
| 131 | |||
| 132 | static int virtio_can_alloc_tx_idx(struct virtio_can_priv *priv) | ||
| 133 | { | ||
| 134 | int tx_idx; | ||
| 135 | |||
| 136 | tx_idx = ida_alloc_max(&priv->tx_putidx_ida, | ||
| 137 | priv->can.echo_skb_max - 1, GFP_ATOMIC); | ||
| 138 | if (tx_idx >= 0) | ||
| 139 | atomic_inc(&priv->tx_inflight); | ||
| 140 | |||
| 141 | return tx_idx; | ||
| 142 | } | ||
| 143 | |||
| 144 | static void virtio_can_free_tx_idx(struct virtio_can_priv *priv, | ||
| 145 | unsigned int idx) | ||
| 146 | { | ||
| 147 | ida_free(&priv->tx_putidx_ida, idx); | ||
| 148 | atomic_dec(&priv->tx_inflight); | ||
| 149 | } | ||
| 150 | |||
| 151 | /* Create a scatter-gather list representing our input buffer and put | ||
| 152 | * it in the queue. | ||
| 153 | * | ||
| 154 | * Callers should take appropriate locks. | ||
| 155 | */ | ||
| 156 | static int virtio_can_add_inbuf(struct virtqueue *vq, void *buf, | ||
| 157 | unsigned int size) | ||
| 158 | { | ||
| 159 | struct scatterlist sg[1]; | ||
| 160 | int ret; | ||
| 161 | |||
| 162 | sg_init_one(sg, buf, size); | ||
| 163 | |||
| 164 | ret = virtqueue_add_inbuf(vq, sg, 1, buf, GFP_ATOMIC); | ||
| 165 | |||
| 166 | return ret; | ||
| 167 | } | ||
| 168 | |||
| 169 | /* Send a control message with message type either | ||
| 170 | * | ||
| 171 | * - VIRTIO_CAN_SET_CTRL_MODE_START or | ||
| 172 | * - VIRTIO_CAN_SET_CTRL_MODE_STOP. | ||
| 173 | * | ||
| 174 | */ | ||
| 175 | static u8 virtio_can_send_ctrl_msg(struct net_device *ndev, u16 msg_type) | ||
| 176 | { | ||
| 177 | struct scatterlist sg_out, sg_in, *sgs[2] = { &sg_out, &sg_in }; | ||
| 178 | struct virtio_can_priv *priv = netdev_priv(ndev); | ||
| 179 | struct virtqueue *vq = priv->vqs[VIRTIO_CAN_QUEUE_CONTROL]; | ||
| 180 | struct device *dev = &priv->vdev->dev; | ||
| 181 | unsigned int len; | ||
| 182 | int err; | ||
| 183 | |||
| 184 | if (!vq) | ||
| 185 | return VIRTIO_CAN_RESULT_NOT_OK; | ||
| 186 | |||
| 187 | guard(mutex)(&priv->ctrl_lock); | ||
| 188 | |||
| 189 | priv->can_ctr_msg.cpkt_out.msg_type = cpu_to_le16(msg_type); | ||
| 190 | sg_init_one(&sg_out, &priv->can_ctr_msg.cpkt_out, | ||
| 191 | sizeof(priv->can_ctr_msg.cpkt_out)); | ||
| 192 | sg_init_one(&sg_in, &priv->can_ctr_msg.cpkt_in, sizeof(priv->can_ctr_msg.cpkt_in)); | ||
| 193 | |||
| 194 | reinit_completion(&priv->ctrl_done); | ||
| 195 | |||
| 196 | err = virtqueue_add_sgs(vq, sgs, 1u, 1u, priv, GFP_ATOMIC); | ||
| 197 | if (err != 0) { | ||
| 198 | dev_err(dev, "%s(): virtqueue_add_sgs() failed\n", __func__); | ||
| 199 | return VIRTIO_CAN_RESULT_NOT_OK; | ||
| 200 | } | ||
| 201 | |||
| 202 | if (!virtqueue_kick(vq)) { | ||
| 203 | dev_err(dev, "%s(): Kick failed\n", __func__); | ||
| 204 | return VIRTIO_CAN_RESULT_NOT_OK; | ||
| 205 | } | ||
| 206 | |||
| 207 | while (!virtqueue_get_buf(vq, &len) && !virtqueue_is_broken(vq)) | ||
| 208 | wait_for_completion(&priv->ctrl_done); | ||
| 209 | |||
| 210 | return priv->can_ctr_msg.cpkt_in.result; | ||
| 211 | } | ||
| 212 | |||
| 213 | static int virtio_can_start(struct net_device *ndev) | ||
| 214 | { | ||
| 215 | struct virtio_can_priv *priv = netdev_priv(ndev); | ||
| 216 | u8 result; | ||
| 217 | |||
| 218 | result = virtio_can_send_ctrl_msg(ndev, VIRTIO_CAN_SET_CTRL_MODE_START); | ||
| 219 | if (result != VIRTIO_CAN_RESULT_OK) { | ||
| 220 | netdev_err(ndev, "CAN controller start failed\n"); | ||
| 221 | return -EIO; | ||
| 222 | } | ||
| 223 | |||
| 224 | priv->busoff_pending = false; | ||
| 225 | priv->can.state = CAN_STATE_ERROR_ACTIVE; | ||
| 226 | |||
| 227 | return 0; | ||
| 228 | } | ||
| 229 | |||
| 230 | static int virtio_can_set_mode(struct net_device *dev, enum can_mode mode) | ||
| 231 | { | ||
| 232 | int err; | ||
| 233 | |||
| 234 | switch (mode) { | ||
| 235 | case CAN_MODE_START: | ||
| 236 | err = virtio_can_start(dev); | ||
| 237 | if (err) | ||
| 238 | return err; | ||
| 239 | netif_wake_queue(dev); | ||
| 240 | break; | ||
| 241 | default: | ||
| 242 | return -EOPNOTSUPP; | ||
| 243 | } | ||
| 244 | |||
| 245 | return 0; | ||
| 246 | } | ||
| 247 | |||
| 248 | static int virtio_can_open(struct net_device *ndev) | ||
| 249 | { | ||
| 250 | struct virtio_can_priv *priv = netdev_priv(ndev); | ||
| 251 | int err; | ||
| 252 | |||
| 253 | err = open_candev(ndev); | ||
| 254 | if (err) | ||
| 255 | return err; | ||
| 256 | |||
| 257 | err = virtio_can_start(ndev); | ||
| 258 | if (err) { | ||
| 259 | close_candev(ndev); | ||
| 260 | return err; | ||
| 261 | } | ||
| 262 | |||
| 263 | virtio_can_napi_enable(priv); | ||
| 264 | netif_start_queue(ndev); | ||
| 265 | |||
| 266 | return 0; | ||
| 267 | } | ||
| 268 | |||
| 269 | static int virtio_can_stop(struct net_device *ndev) | ||
| 270 | { | ||
| 271 | struct virtio_can_priv *priv = netdev_priv(ndev); | ||
| 272 | struct device *dev = &priv->vdev->dev; | ||
| 273 | u8 result; | ||
| 274 | |||
| 275 | result = virtio_can_send_ctrl_msg(ndev, VIRTIO_CAN_SET_CTRL_MODE_STOP); | ||
| 276 | if (result != VIRTIO_CAN_RESULT_OK) { | ||
| 277 | dev_err(dev, "CAN controller stop failed\n"); | ||
| 278 | return -EIO; | ||
| 279 | } | ||
| 280 | |||
| 281 | priv->busoff_pending = false; | ||
| 282 | priv->can.state = CAN_STATE_STOPPED; | ||
| 283 | |||
| 284 | /* Switch carrier off if device was connected to the bus */ | ||
| 285 | if (netif_carrier_ok(ndev)) | ||
| 286 | netif_carrier_off(ndev); | ||
| 287 | |||
| 288 | return 0; | ||
| 289 | } | ||
| 290 | |||
| 291 | static int virtio_can_close(struct net_device *dev) | ||
| 292 | { | ||
| 293 | struct virtio_can_priv *priv = netdev_priv(dev); | ||
| 294 | |||
| 295 | netif_stop_queue(dev); | ||
| 296 | /* Ignore stop error: ndo_stop must always complete cleanup regardless. | ||
| 297 | * virtio_can_stop() already logs the error if it fails. | ||
| 298 | */ | ||
| 299 | virtio_can_stop(dev); | ||
| 300 | virtio_can_napi_disable(priv); | ||
| 301 | close_candev(dev); | ||
| 302 | |||
| 303 | return 0; | ||
| 304 | } | ||
| 305 | |||
| 306 | static netdev_tx_t virtio_can_start_xmit(struct sk_buff *skb, | ||
| 307 | struct net_device *dev) | ||
| 308 | { | ||
| 309 | struct scatterlist sg_out, sg_in, *sgs[2] = { &sg_out, &sg_in }; | ||
| 310 | const unsigned int hdr_size = sizeof(struct virtio_can_tx_out); | ||
| 311 | struct canfd_frame *cf = (struct canfd_frame *)skb->data; | ||
| 312 | struct virtio_can_priv *priv = netdev_priv(dev); | ||
| 313 | struct virtqueue *vq = priv->vqs[VIRTIO_CAN_QUEUE_TX]; | ||
| 314 | netdev_tx_t xmit_ret = NETDEV_TX_OK; | ||
| 315 | struct virtio_can_tx *can_tx_msg; | ||
| 316 | u32 can_flags; | ||
| 317 | int putidx; | ||
| 318 | int err; | ||
| 319 | |||
| 320 | if (can_dev_dropped_skb(dev, skb)) | ||
| 321 | goto kick; /* No way to return NET_XMIT_DROP here */ | ||
| 322 | |||
| 323 | /* No local check for CAN_RTR_FLAG or FD frame against negotiated | ||
| 324 | * features. The device will reject those anyway if not supported. | ||
| 325 | */ | ||
| 326 | |||
| 327 | can_tx_msg = kzalloc(sizeof(*can_tx_msg) + cf->len, GFP_ATOMIC); | ||
| 328 | if (!can_tx_msg) { | ||
| 329 | kfree_skb(skb); | ||
| 330 | dev->stats.tx_dropped++; | ||
| 331 | goto kick; /* No way to return NET_XMIT_DROP here */ | ||
| 332 | } | ||
| 333 | |||
| 334 | can_tx_msg->tx_out.msg_type = cpu_to_le16(VIRTIO_CAN_TX); | ||
| 335 | can_tx_msg->tx_out.length = cpu_to_le16(cf->len); | ||
| 336 | can_flags = 0; | ||
| 337 | |||
| 338 | if (cf->can_id & CAN_EFF_FLAG) { | ||
| 339 | can_flags |= VIRTIO_CAN_FLAGS_EXTENDED; | ||
| 340 | can_tx_msg->tx_out.can_id = cpu_to_le32(cf->can_id & CAN_EFF_MASK); | ||
| 341 | } else { | ||
| 342 | can_tx_msg->tx_out.can_id = cpu_to_le32(cf->can_id & CAN_SFF_MASK); | ||
| 343 | } | ||
| 344 | if (cf->can_id & CAN_RTR_FLAG) | ||
| 345 | can_flags |= VIRTIO_CAN_FLAGS_RTR; | ||
| 346 | else | ||
| 347 | memcpy(can_tx_msg->tx_out.sdu, cf->data, cf->len); | ||
| 348 | if (can_is_canfd_skb(skb)) | ||
| 349 | can_flags |= VIRTIO_CAN_FLAGS_FD; | ||
| 350 | |||
| 351 | can_tx_msg->tx_out.flags = cpu_to_le32(can_flags); | ||
| 352 | |||
| 353 | sg_init_one(&sg_out, &can_tx_msg->tx_out, hdr_size + cf->len); | ||
| 354 | sg_init_one(&sg_in, &can_tx_msg->tx_in, sizeof(can_tx_msg->tx_in)); | ||
| 355 | |||
| 356 | putidx = virtio_can_alloc_tx_idx(priv); | ||
| 357 | |||
| 358 | if (unlikely(putidx < 0)) { | ||
| 359 | /* -ENOMEM or -ENOSPC here. -ENOSPC should not be possible as | ||
| 360 | * tx_inflight >= can.echo_skb_max is checked in flow control | ||
| 361 | */ | ||
| 362 | WARN_ON_ONCE(putidx == -ENOSPC); | ||
| 363 | kfree(can_tx_msg); | ||
| 364 | kfree_skb(skb); | ||
| 365 | dev->stats.tx_dropped++; | ||
| 366 | goto kick; /* No way to return NET_XMIT_DROP here */ | ||
| 367 | } | ||
| 368 | |||
| 369 | can_tx_msg->putidx = (unsigned int)putidx; | ||
| 370 | |||
| 371 | /* Push loopback echo. Will be looped back on TX interrupt/TX NAPI */ | ||
| 372 | err = can_put_echo_skb(skb, dev, can_tx_msg->putidx, 0); | ||
| 373 | if (unlikely(err)) { | ||
| 374 | /* skb was already freed by can_put_echo_skb() on error */ | ||
| 375 | virtio_can_free_tx_idx(priv, can_tx_msg->putidx); | ||
| 376 | kfree(can_tx_msg); | ||
| 377 | dev->stats.tx_dropped++; | ||
| 378 | goto kick; | ||
| 379 | } | ||
| 380 | |||
| 381 | /* Protect queue and list operations */ | ||
| 382 | scoped_guard(spinlock_irqsave, &priv->tx_lock) | ||
| 383 | err = virtqueue_add_sgs(vq, sgs, 1u, 1u, can_tx_msg, GFP_ATOMIC); | ||
| 384 | |||
| 385 | if (unlikely(err)) { | ||
| 386 | /* | ||
| 387 | * can_put_echo_skb() already consumed skb via consume_skb(), | ||
| 388 | * so returning NETDEV_TX_BUSY would cause the stack to requeue | ||
| 389 | * a freed pointer. Drop the frame and return OK instead. | ||
| 390 | */ | ||
| 391 | can_free_echo_skb(dev, can_tx_msg->putidx, NULL); | ||
| 392 | virtio_can_free_tx_idx(priv, can_tx_msg->putidx); | ||
| 393 | netif_stop_queue(dev); | ||
| 394 | kfree(can_tx_msg); | ||
| 395 | dev->stats.tx_dropped++; | ||
| 396 | /* Expected never to be seen */ | ||
| 397 | netdev_warn(dev, "TX: Stop queue, err = %d\n", err); | ||
| 398 | goto kick; | ||
| 399 | } | ||
| 400 | |||
| 401 | /* Normal flow control: stop queue when no transmission slots left */ | ||
| 402 | if (atomic_read(&priv->tx_inflight) >= priv->can.echo_skb_max || | ||
| 403 | vq->num_free == 0 || (vq->num_free < ARRAY_SIZE(sgs) && | ||
| 404 | !virtio_has_feature(vq->vdev, VIRTIO_RING_F_INDIRECT_DESC))) { | ||
| 405 | netif_stop_queue(dev); | ||
| 406 | netdev_dbg(dev, "TX: Normal stop queue\n"); | ||
| 407 | } | ||
| 408 | |||
| 409 | kick: | ||
| 410 | if (netif_queue_stopped(dev) || !netdev_xmit_more()) { | ||
| 411 | scoped_guard(spinlock_irqsave, &priv->tx_lock) { | ||
| 412 | if (!virtqueue_kick(vq)) | ||
| 413 | netdev_err(dev, "%s(): Kick failed\n", __func__); | ||
| 414 | } | ||
| 415 | } | ||
| 416 | |||
| 417 | return xmit_ret; | ||
| 418 | } | ||
| 419 | |||
| 420 | static const struct net_device_ops virtio_can_netdev_ops = { | ||
| 421 | .ndo_open = virtio_can_open, | ||
| 422 | .ndo_stop = virtio_can_close, | ||
| 423 | .ndo_start_xmit = virtio_can_start_xmit, | ||
| 424 | }; | ||
| 425 | |||
| 426 | static int register_virtio_can_dev(struct net_device *dev) | ||
| 427 | { | ||
| 428 | dev->flags |= IFF_ECHO; /* we support local echo */ | ||
| 429 | dev->netdev_ops = &virtio_can_netdev_ops; | ||
| 430 | |||
| 431 | return register_candev(dev); | ||
| 432 | } | ||
| 433 | |||
| 434 | static int virtio_can_read_tx_queue(struct virtqueue *vq) | ||
| 435 | { | ||
| 436 | struct virtio_can_priv *can_priv = vq->vdev->priv; | ||
| 437 | struct net_device *dev = can_priv->dev; | ||
| 438 | struct virtio_can_tx *can_tx_msg; | ||
| 439 | struct net_device_stats *stats; | ||
| 440 | unsigned int len; | ||
| 441 | u8 result; | ||
| 442 | |||
| 443 | stats = &dev->stats; | ||
| 444 | |||
| 445 | scoped_guard(spinlock_irqsave, &can_priv->tx_lock) | ||
| 446 | can_tx_msg = virtqueue_get_buf(vq, &len); | ||
| 447 | |||
| 448 | if (!can_tx_msg) | ||
| 449 | return 0; | ||
| 450 | |||
| 451 | if (unlikely(len < sizeof(struct virtio_can_tx_in))) { | ||
| 452 | netdev_err(dev, "TX ACK: Device sent no result code\n"); | ||
| 453 | result = VIRTIO_CAN_RESULT_NOT_OK; /* Keep things going */ | ||
| 454 | } else { | ||
| 455 | result = can_tx_msg->tx_in.result; | ||
| 456 | } | ||
| 457 | |||
| 458 | if (can_priv->can.state < CAN_STATE_BUS_OFF) { | ||
| 459 | if (result != VIRTIO_CAN_RESULT_OK) { | ||
| 460 | struct can_frame *skb_cf; | ||
| 461 | struct sk_buff *skb = alloc_can_err_skb(dev, &skb_cf); | ||
| 462 | |||
| 463 | if (skb) { | ||
| 464 | skb_cf->can_id |= CAN_ERR_CRTL; | ||
| 465 | skb_cf->data[1] |= CAN_ERR_CRTL_UNSPEC; | ||
| 466 | netif_rx(skb); | ||
| 467 | } | ||
| 468 | netdev_warn(dev, "TX ACK: Result = %u\n", result); | ||
| 469 | can_free_echo_skb(dev, can_tx_msg->putidx, NULL); | ||
| 470 | stats->tx_dropped++; | ||
| 471 | } else { | ||
| 472 | stats->tx_bytes += can_get_echo_skb(dev, can_tx_msg->putidx, | ||
| 473 | NULL); | ||
| 474 | stats->tx_packets++; | ||
| 475 | } | ||
| 476 | } else { | ||
| 477 | netdev_dbg(dev, "TX ACK: Controller inactive, drop echo\n"); | ||
| 478 | can_free_echo_skb(dev, can_tx_msg->putidx, NULL); | ||
| 479 | stats->tx_dropped++; | ||
| 480 | } | ||
| 481 | |||
| 482 | virtio_can_free_tx_idx(can_priv, can_tx_msg->putidx); | ||
| 483 | |||
| 484 | /* Flow control */ | ||
| 485 | if (netif_queue_stopped(dev)) { | ||
| 486 | netdev_dbg(dev, "TX ACK: Wake up stopped queue\n"); | ||
| 487 | netif_wake_queue(dev); | ||
| 488 | } | ||
| 489 | |||
| 490 | kfree(can_tx_msg); | ||
| 491 | |||
| 492 | return 1; /* Queue was not empty so there may be more data */ | ||
| 493 | } | ||
| 494 | |||
| 495 | static int virtio_can_tx_poll(struct napi_struct *napi, int quota) | ||
| 496 | { | ||
| 497 | struct net_device *dev = napi->dev; | ||
| 498 | struct virtio_can_priv *priv = netdev_priv(dev); | ||
| 499 | struct virtqueue *vq = priv->vqs[VIRTIO_CAN_QUEUE_TX]; | ||
| 500 | int work_done = 0; | ||
| 501 | |||
| 502 | while (work_done < quota && virtio_can_read_tx_queue(vq) != 0) | ||
| 503 | work_done++; | ||
| 504 | |||
| 505 | if (work_done < quota) | ||
| 506 | virtqueue_napi_complete(napi, vq, work_done); | ||
| 507 | |||
| 508 | return work_done; | ||
| 509 | } | ||
| 510 | |||
| 511 | static void virtio_can_tx_intr(struct virtqueue *vq) | ||
| 512 | { | ||
| 513 | struct virtio_can_priv *can_priv = vq->vdev->priv; | ||
| 514 | |||
| 515 | virtqueue_disable_cb(vq); | ||
| 516 | napi_schedule(&can_priv->napi_tx); | ||
| 517 | } | ||
| 518 | |||
| 519 | /* This function is the NAPI RX poll function and NAPI guarantees that this | ||
| 520 | * function is not invoked simultaneously on multiple processors. | ||
| 521 | * Read a RX message from the used queue and sends it to the upper layer. | ||
| 522 | */ | ||
| 523 | static int virtio_can_read_rx_queue(struct virtqueue *vq) | ||
| 524 | { | ||
| 525 | const unsigned int header_size = sizeof(struct virtio_can_rx); | ||
| 526 | struct virtio_can_priv *priv = vq->vdev->priv; | ||
| 527 | struct net_device *dev = priv->dev; | ||
| 528 | struct net_device_stats *stats; | ||
| 529 | struct virtio_can_rx *can_rx; | ||
| 530 | unsigned int transport_len; | ||
| 531 | struct canfd_frame *cf; | ||
| 532 | struct sk_buff *skb; | ||
| 533 | unsigned int len; | ||
| 534 | u32 can_flags; | ||
| 535 | u16 msg_type; | ||
| 536 | u32 can_id; | ||
| 537 | int ret; | ||
| 538 | |||
| 539 | stats = &dev->stats; | ||
| 540 | |||
| 541 | can_rx = virtqueue_get_buf(vq, &transport_len); | ||
| 542 | if (!can_rx) | ||
| 543 | return 0; /* No more data */ | ||
| 544 | |||
| 545 | if (transport_len < header_size) { | ||
| 546 | netdev_warn(dev, "RX: Message too small\n"); | ||
| 547 | goto putback; | ||
| 548 | } | ||
| 549 | |||
| 550 | if (priv->can.state >= CAN_STATE_ERROR_PASSIVE) { | ||
| 551 | netdev_dbg(dev, "%s(): Controller not active\n", __func__); | ||
| 552 | goto putback; | ||
| 553 | } | ||
| 554 | |||
| 555 | msg_type = le16_to_cpu(can_rx->msg_type); | ||
| 556 | if (msg_type != VIRTIO_CAN_RX) { | ||
| 557 | netdev_warn(dev, "RX: Got unknown msg_type %04x\n", msg_type); | ||
| 558 | goto putback; | ||
| 559 | } | ||
| 560 | |||
| 561 | len = le16_to_cpu(can_rx->length); | ||
| 562 | can_flags = le32_to_cpu(can_rx->flags); | ||
| 563 | can_id = le32_to_cpu(can_rx->can_id); | ||
| 564 | |||
| 565 | if (can_flags & ~CAN_KNOWN_FLAGS) { | ||
| 566 | stats->rx_dropped++; | ||
| 567 | netdev_warn(dev, "RX: CAN Id 0x%08x: Invalid flags 0x%x\n", | ||
| 568 | can_id, can_flags); | ||
| 569 | goto putback; | ||
| 570 | } | ||
| 571 | |||
| 572 | if (can_flags & VIRTIO_CAN_FLAGS_EXTENDED) { | ||
| 573 | can_id &= CAN_EFF_MASK; | ||
| 574 | can_id |= CAN_EFF_FLAG; | ||
| 575 | } else { | ||
| 576 | can_id &= CAN_SFF_MASK; | ||
| 577 | } | ||
| 578 | |||
| 579 | if (can_flags & VIRTIO_CAN_FLAGS_RTR) { | ||
| 580 | if (!virtio_has_feature(vq->vdev, VIRTIO_CAN_F_RTR_FRAMES)) { | ||
| 581 | stats->rx_dropped++; | ||
| 582 | netdev_warn(dev, "RX: CAN Id 0x%08x: RTR not negotiated\n", | ||
| 583 | can_id); | ||
| 584 | goto putback; | ||
| 585 | } | ||
| 586 | if (can_flags & VIRTIO_CAN_FLAGS_FD) { | ||
| 587 | stats->rx_dropped++; | ||
| 588 | netdev_warn(dev, "RX: CAN Id 0x%08x: RTR with FD not possible\n", | ||
| 589 | can_id); | ||
| 590 | goto putback; | ||
| 591 | } | ||
| 592 | |||
| 593 | if (len > 0xF) { | ||
| 594 | stats->rx_dropped++; | ||
| 595 | netdev_warn(dev, "RX: CAN Id 0x%08x: RTR with DLC > 0xF\n", | ||
| 596 | can_id); | ||
| 597 | goto putback; | ||
| 598 | } | ||
| 599 | |||
| 600 | if (len > 0x8) | ||
| 601 | len = 0x8; | ||
| 602 | |||
| 603 | can_id |= CAN_RTR_FLAG; | ||
| 604 | } | ||
| 605 | |||
| 606 | if (transport_len < header_size + len) { | ||
| 607 | netdev_warn(dev, "RX: Message too small for payload\n"); | ||
| 608 | goto putback; | ||
| 609 | } | ||
| 610 | |||
| 611 | if (can_flags & VIRTIO_CAN_FLAGS_FD) { | ||
| 612 | if (!virtio_has_feature(vq->vdev, VIRTIO_CAN_F_CAN_FD)) { | ||
| 613 | stats->rx_dropped++; | ||
| 614 | netdev_warn(dev, "RX: CAN Id 0x%08x: FD not negotiated\n", | ||
| 615 | can_id); | ||
| 616 | goto putback; | ||
| 617 | } | ||
| 618 | |||
| 619 | if (len > CANFD_MAX_DLEN) | ||
| 620 | len = CANFD_MAX_DLEN; | ||
| 621 | |||
| 622 | skb = alloc_canfd_skb(priv->dev, &cf); | ||
| 623 | } else { | ||
| 624 | if (!virtio_has_feature(vq->vdev, VIRTIO_CAN_F_CAN_CLASSIC)) { | ||
| 625 | stats->rx_dropped++; | ||
| 626 | netdev_warn(dev, "RX: CAN Id 0x%08x: classic not negotiated\n", | ||
| 627 | can_id); | ||
| 628 | goto putback; | ||
| 629 | } | ||
| 630 | |||
| 631 | if (len > CAN_MAX_DLEN) | ||
| 632 | len = CAN_MAX_DLEN; | ||
| 633 | |||
| 634 | skb = alloc_can_skb(priv->dev, (struct can_frame **)&cf); | ||
| 635 | } | ||
| 636 | if (!skb) { | ||
| 637 | stats->rx_dropped++; | ||
| 638 | netdev_warn(dev, "RX: No skb available\n"); | ||
| 639 | goto putback; | ||
| 640 | } | ||
| 641 | |||
| 642 | cf->can_id = can_id; | ||
| 643 | cf->len = len; | ||
| 644 | if (!(can_flags & VIRTIO_CAN_FLAGS_RTR)) { | ||
| 645 | /* RTR frames have a DLC but no payload */ | ||
| 646 | memcpy(cf->data, can_rx->sdu, len); | ||
| 647 | } | ||
| 648 | |||
| 649 | if (netif_receive_skb(skb) == NET_RX_SUCCESS) { | ||
| 650 | stats->rx_packets++; | ||
| 651 | if (!(can_flags & VIRTIO_CAN_FLAGS_RTR)) | ||
| 652 | stats->rx_bytes += len; | ||
| 653 | } | ||
| 654 | |||
| 655 | putback: | ||
| 656 | /* Put processed RX buffer back into avail queue */ | ||
| 657 | ret = virtio_can_add_inbuf(vq, can_rx, | ||
| 658 | priv->rpkt_len); | ||
| 659 | if (!ret) | ||
| 660 | virtqueue_kick(vq); | ||
| 661 | return 1; /* Queue was not empty so there may be more data */ | ||
| 662 | } | ||
| 663 | |||
| 664 | static int virtio_can_handle_busoff(struct net_device *dev) | ||
| 665 | { | ||
| 666 | struct virtio_can_priv *priv = netdev_priv(dev); | ||
| 667 | struct can_frame *cf; | ||
| 668 | struct sk_buff *skb; | ||
| 669 | |||
| 670 | if (!priv->busoff_pending) | ||
| 671 | return 0; | ||
| 672 | |||
| 673 | if (priv->can.state < CAN_STATE_BUS_OFF) { | ||
| 674 | netdev_dbg(dev, "entered error bus off state\n"); | ||
| 675 | |||
| 676 | /* bus-off state */ | ||
| 677 | priv->can.state = CAN_STATE_BUS_OFF; | ||
| 678 | priv->can.can_stats.bus_off++; | ||
| 679 | can_bus_off(dev); | ||
| 680 | } | ||
| 681 | |||
| 682 | /* propagate the error condition to the CAN stack */ | ||
| 683 | skb = alloc_can_err_skb(dev, &cf); | ||
| 684 | if (unlikely(!skb)) | ||
| 685 | return 0; | ||
| 686 | |||
| 687 | /* bus-off state */ | ||
| 688 | cf->can_id |= CAN_ERR_BUSOFF; | ||
| 689 | |||
| 690 | /* Ensure that the BusOff indication does not get lost */ | ||
| 691 | if (netif_receive_skb(skb) == NET_RX_SUCCESS) | ||
| 692 | priv->busoff_pending = false; | ||
| 693 | |||
| 694 | return 1; | ||
| 695 | } | ||
| 696 | |||
| 697 | static int virtio_can_rx_poll(struct napi_struct *napi, int quota) | ||
| 698 | { | ||
| 699 | struct net_device *dev = napi->dev; | ||
| 700 | struct virtio_can_priv *priv = netdev_priv(dev); | ||
| 701 | struct virtqueue *vq = priv->vqs[VIRTIO_CAN_QUEUE_RX]; | ||
| 702 | int work_done = 0; | ||
| 703 | |||
| 704 | work_done += virtio_can_handle_busoff(dev); | ||
| 705 | |||
| 706 | while (work_done < quota && virtio_can_read_rx_queue(vq) != 0) | ||
| 707 | work_done++; | ||
| 708 | |||
| 709 | if (work_done < quota) | ||
| 710 | virtqueue_napi_complete(napi, vq, work_done); | ||
| 711 | |||
| 712 | return work_done; | ||
| 713 | } | ||
| 714 | |||
| 715 | static void virtio_can_rx_intr(struct virtqueue *vq) | ||
| 716 | { | ||
| 717 | struct virtio_can_priv *can_priv = vq->vdev->priv; | ||
| 718 | |||
| 719 | virtqueue_disable_cb(vq); | ||
| 720 | napi_schedule(&can_priv->napi); | ||
| 721 | } | ||
| 722 | |||
| 723 | static void virtio_can_control_intr(struct virtqueue *vq) | ||
| 724 | { | ||
| 725 | struct virtio_can_priv *can_priv = vq->vdev->priv; | ||
| 726 | |||
| 727 | complete(&can_priv->ctrl_done); | ||
| 728 | } | ||
| 729 | |||
| 730 | static void virtio_can_config_changed(struct virtio_device *vdev) | ||
| 731 | { | ||
| 732 | struct virtio_can_priv *can_priv = vdev->priv; | ||
| 733 | u16 status; | ||
| 734 | |||
| 735 | status = virtio_cread16(vdev, offsetof(struct virtio_can_config, | ||
| 736 | status)); | ||
| 737 | |||
| 738 | if (!(status & VIRTIO_CAN_S_CTRL_BUSOFF)) | ||
| 739 | return; | ||
| 740 | |||
| 741 | if (!can_priv->busoff_pending && | ||
| 742 | can_priv->can.state < CAN_STATE_BUS_OFF) { | ||
| 743 | can_priv->busoff_pending = true; | ||
| 744 | napi_schedule(&can_priv->napi); | ||
| 745 | } | ||
| 746 | } | ||
| 747 | |||
| 748 | static void virtio_can_populate_rx_vq(struct virtio_device *vdev) | ||
| 749 | { | ||
| 750 | struct virtio_can_priv *priv = vdev->priv; | ||
| 751 | struct virtqueue *vq = priv->vqs[VIRTIO_CAN_QUEUE_RX]; | ||
| 752 | unsigned int buf_size = priv->rpkt_len; | ||
| 753 | int num_elements = vq->num_free; | ||
| 754 | u8 *buf = (u8 *)priv->rpkt; | ||
| 755 | unsigned int idx; | ||
| 756 | int ret = 0; | ||
| 757 | |||
| 758 | for (idx = 0; idx < num_elements; idx++) { | ||
| 759 | ret = virtio_can_add_inbuf(vq, buf, buf_size); | ||
| 760 | if (ret < 0) { | ||
| 761 | dev_dbg(&vdev->dev, "rpkt fill: ret=%d, idx=%u, size=%u\n", | ||
| 762 | ret, idx, buf_size); | ||
| 763 | break; | ||
| 764 | } | ||
| 765 | buf += buf_size; | ||
| 766 | } | ||
| 767 | |||
| 768 | if (idx > 0) | ||
| 769 | virtqueue_kick(vq); | ||
| 770 | |||
| 771 | dev_dbg(&vdev->dev, "%u rpkt added\n", idx); | ||
| 772 | } | ||
| 773 | |||
| 774 | static int virtio_can_find_vqs(struct virtio_can_priv *priv) | ||
| 775 | { | ||
| 776 | struct virtqueue_info vqs_info[] = { | ||
| 777 | { "can-tx", virtio_can_tx_intr }, | ||
| 778 | { "can-rx", virtio_can_rx_intr }, | ||
| 779 | { "can-state-ctrl", virtio_can_control_intr }, | ||
| 780 | }; | ||
| 781 | |||
| 782 | /* Find the queues. */ | ||
| 783 | return virtio_find_vqs(priv->vdev, VIRTIO_CAN_QUEUE_COUNT, priv->vqs, | ||
| 784 | vqs_info, NULL); | ||
| 785 | } | ||
| 786 | |||
| 787 | /* Function must not be called before virtio_can_find_vqs() has been run */ | ||
| 788 | static void virtio_can_del_vq(struct virtio_device *vdev) | ||
| 789 | { | ||
| 790 | struct virtio_can_priv *priv = vdev->priv; | ||
| 791 | struct virtqueue *vq = priv->vqs[VIRTIO_CAN_QUEUE_TX]; | ||
| 792 | struct virtio_can_tx *can_tx_msg; | ||
| 793 | int q; | ||
| 794 | |||
| 795 | if (!vq) | ||
| 796 | return; | ||
| 797 | |||
| 798 | /* Reset the device */ | ||
| 799 | virtio_reset_device(vdev); | ||
| 800 | |||
| 801 | /* From here we have dead silence from the device side so no locks | ||
| 802 | * are needed to protect against device side events. | ||
| 803 | */ | ||
| 804 | |||
| 805 | /* Free pending TX buffers which were allocated in virtio_can_start_xmit() */ | ||
| 806 | while ((can_tx_msg = virtqueue_detach_unused_buf(vq))) { | ||
| 807 | can_free_echo_skb(priv->dev, can_tx_msg->putidx, NULL); | ||
| 808 | virtio_can_free_tx_idx(priv, can_tx_msg->putidx); | ||
| 809 | kfree(can_tx_msg); | ||
| 810 | } | ||
| 811 | |||
| 812 | /* RX and control queue buffers are managed elsewhere, just detach */ | ||
| 813 | for (q = VIRTIO_CAN_QUEUE_RX; q < VIRTIO_CAN_QUEUE_COUNT; q++) | ||
| 814 | while (virtqueue_detach_unused_buf(priv->vqs[q])) | ||
| 815 | ; | ||
| 816 | |||
| 817 | if (vdev->config->del_vqs) | ||
| 818 | vdev->config->del_vqs(vdev); | ||
| 819 | |||
| 820 | memset(priv->vqs, 0, sizeof(priv->vqs)); | ||
| 821 | } | ||
| 822 | |||
| 823 | static void virtio_can_remove(struct virtio_device *vdev) | ||
| 824 | { | ||
| 825 | struct virtio_can_priv *priv = vdev->priv; | ||
| 826 | struct net_device *dev = priv->dev; | ||
| 827 | |||
| 828 | unregister_candev(dev); | ||
| 829 | |||
| 830 | virtio_can_del_vq(vdev); | ||
| 831 | |||
| 832 | virtio_can_free_candev(dev); | ||
| 833 | } | ||
| 834 | |||
| 835 | static int virtio_can_validate(struct virtio_device *vdev) | ||
| 836 | { | ||
| 837 | /* CAN needs always access to the config space. | ||
| 838 | * Check that the driver can access the config space | ||
| 839 | */ | ||
| 840 | if (!vdev->config->get) { | ||
| 841 | dev_err(&vdev->dev, "%s failure: config access disabled\n", | ||
| 842 | __func__); | ||
| 843 | return -EINVAL; | ||
| 844 | } | ||
| 845 | |||
| 846 | if (!virtio_has_feature(vdev, VIRTIO_F_VERSION_1)) { | ||
| 847 | dev_err(&vdev->dev, | ||
| 848 | "device does not comply with spec version 1.x\n"); | ||
| 849 | return -EINVAL; | ||
| 850 | } | ||
| 851 | |||
| 852 | return 0; | ||
| 853 | } | ||
| 854 | |||
| 855 | static int virtio_can_probe(struct virtio_device *vdev) | ||
| 856 | { | ||
| 857 | struct virtio_can_priv *priv; | ||
| 858 | struct net_device *dev; | ||
| 859 | size_t size; | ||
| 860 | int err; | ||
| 861 | |||
| 862 | dev = alloc_candev(sizeof(struct virtio_can_priv), | ||
| 863 | VIRTIO_CAN_ECHO_SKB_MAX); | ||
| 864 | if (!dev) | ||
| 865 | return -ENOMEM; | ||
| 866 | |||
| 867 | priv = netdev_priv(dev); | ||
| 868 | |||
| 869 | ida_init(&priv->tx_putidx_ida); | ||
| 870 | |||
| 871 | netif_napi_add(dev, &priv->napi, virtio_can_rx_poll); | ||
| 872 | netif_napi_add(dev, &priv->napi_tx, virtio_can_tx_poll); | ||
| 873 | |||
| 874 | SET_NETDEV_DEV(dev, &vdev->dev); | ||
| 875 | |||
| 876 | priv->dev = dev; | ||
| 877 | priv->vdev = vdev; | ||
| 878 | vdev->priv = priv; | ||
| 879 | |||
| 880 | priv->can.do_set_mode = virtio_can_set_mode; | ||
| 881 | priv->can.bittiming.bitrate = CAN_BITRATE_UNKNOWN; | ||
| 882 | /* Set Virtio CAN supported operations */ | ||
| 883 | priv->can.ctrlmode_supported = CAN_CTRLMODE_BERR_REPORTING; | ||
| 884 | if (virtio_has_feature(vdev, VIRTIO_CAN_F_CAN_FD)) { | ||
| 885 | priv->can.fd.data_bittiming.bitrate = CAN_BITRATE_UNKNOWN; | ||
| 886 | err = can_set_static_ctrlmode(dev, CAN_CTRLMODE_FD); | ||
| 887 | if (err != 0) | ||
| 888 | goto on_failure; | ||
| 889 | } | ||
| 890 | |||
| 891 | /* Initialize virtqueues */ | ||
| 892 | err = virtio_can_find_vqs(priv); | ||
| 893 | if (err != 0) | ||
| 894 | goto on_failure; | ||
| 895 | |||
| 896 | spin_lock_init(&priv->tx_lock); | ||
| 897 | mutex_init(&priv->ctrl_lock); | ||
| 898 | |||
| 899 | init_completion(&priv->ctrl_done); | ||
| 900 | |||
| 901 | priv->rpkt_len = sizeof(struct virtio_can_rx); | ||
| 902 | |||
| 903 | if (virtio_has_feature(vdev, VIRTIO_CAN_F_CAN_FD)) | ||
| 904 | priv->rpkt_len += CANFD_MAX_DLEN; | ||
| 905 | else | ||
| 906 | priv->rpkt_len += CAN_MAX_DLEN; | ||
| 907 | |||
| 908 | size = priv->rpkt_len * priv->vqs[VIRTIO_CAN_QUEUE_RX]->num_free; | ||
| 909 | priv->rpkt = devm_kzalloc(&vdev->dev, size, GFP_KERNEL); | ||
| 910 | if (!priv->rpkt) { | ||
| 911 | virtio_can_del_vq(vdev); | ||
| 912 | err = -ENOMEM; | ||
| 913 | goto on_failure; | ||
| 914 | } | ||
| 915 | virtio_can_populate_rx_vq(vdev); | ||
| 916 | |||
| 917 | err = register_virtio_can_dev(dev); | ||
| 918 | if (err) { | ||
| 919 | virtio_can_del_vq(vdev); | ||
| 920 | goto on_failure; | ||
| 921 | } | ||
| 922 | |||
| 923 | return 0; | ||
| 924 | |||
| 925 | on_failure: | ||
| 926 | virtio_can_free_candev(dev); | ||
| 927 | return err; | ||
| 928 | } | ||
| 929 | |||
| 930 | static int __maybe_unused virtio_can_freeze(struct virtio_device *vdev) | ||
| 931 | { | ||
| 932 | struct virtio_can_priv *priv = vdev->priv; | ||
| 933 | struct net_device *ndev = priv->dev; | ||
| 934 | |||
| 935 | if (netif_running(ndev)) { | ||
| 936 | /* virtio_can_close() calls netif_stop_queue(), virtio_can_stop(), | ||
| 937 | * napi_disable() and close_candev(). Call it directly (not via | ||
| 938 | * dev_close()) to preserve IFF_UP so that netif_running() returns | ||
| 939 | * true in virtio_can_restore() and the device is brought back up. | ||
| 940 | */ | ||
| 941 | virtio_can_close(ndev); | ||
| 942 | netif_device_detach(ndev); | ||
| 943 | } | ||
| 944 | |||
| 945 | priv->can.state = CAN_STATE_SLEEPING; | ||
| 946 | |||
| 947 | virtio_can_del_vq(vdev); | ||
| 948 | |||
| 949 | return 0; | ||
| 950 | } | ||
| 951 | |||
| 952 | static int __maybe_unused virtio_can_restore(struct virtio_device *vdev) | ||
| 953 | { | ||
| 954 | struct virtio_can_priv *priv = vdev->priv; | ||
| 955 | struct net_device *ndev = priv->dev; | ||
| 956 | size_t size; | ||
| 957 | int err; | ||
| 958 | |||
| 959 | err = virtio_can_find_vqs(priv); | ||
| 960 | if (err != 0) | ||
| 961 | return err; | ||
| 962 | |||
| 963 | size = priv->rpkt_len * priv->vqs[VIRTIO_CAN_QUEUE_RX]->num_free; | ||
| 964 | priv->rpkt = devm_krealloc(&vdev->dev, priv->rpkt, size, GFP_KERNEL | __GFP_ZERO); | ||
| 965 | if (!priv->rpkt) { | ||
| 966 | virtio_can_del_vq(vdev); | ||
| 967 | return -ENOMEM; | ||
| 968 | } | ||
| 969 | virtio_can_populate_rx_vq(vdev); | ||
| 970 | |||
| 971 | if (netif_running(ndev)) { | ||
| 972 | /* virtio_can_open() calls open_candev(), virtio_can_start(), | ||
| 973 | * napi_enable() and netif_start_queue(). Call it directly (not | ||
| 974 | * via dev_open()) since IFF_UP is still set from before freeze. | ||
| 975 | */ | ||
| 976 | err = virtio_can_open(ndev); | ||
| 977 | if (err) { | ||
| 978 | virtio_can_del_vq(vdev); | ||
| 979 | return err; | ||
| 980 | } | ||
| 981 | netif_device_attach(ndev); | ||
| 982 | } else { | ||
| 983 | priv->can.state = CAN_STATE_STOPPED; | ||
| 984 | } | ||
| 985 | |||
| 986 | return 0; | ||
| 987 | } | ||
| 988 | |||
| 989 | static struct virtio_device_id virtio_can_id_table[] = { | ||
| 990 | { VIRTIO_ID_CAN, VIRTIO_DEV_ANY_ID }, | ||
| 991 | { 0 }, | ||
| 992 | }; | ||
| 993 | |||
| 994 | static unsigned int features[] = { | ||
| 995 | VIRTIO_CAN_F_CAN_CLASSIC, | ||
| 996 | VIRTIO_CAN_F_CAN_FD, | ||
| 997 | VIRTIO_CAN_F_LATE_TX_ACK, | ||
| 998 | VIRTIO_CAN_F_RTR_FRAMES, | ||
| 999 | }; | ||
| 1000 | |||
| 1001 | static struct virtio_driver virtio_can_driver = { | ||
| 1002 | .feature_table = features, | ||
| 1003 | .feature_table_size = ARRAY_SIZE(features), | ||
| 1004 | .driver.name = KBUILD_MODNAME, | ||
| 1005 | .driver.owner = THIS_MODULE, | ||
| 1006 | .id_table = virtio_can_id_table, | ||
| 1007 | .validate = virtio_can_validate, | ||
| 1008 | .probe = virtio_can_probe, | ||
| 1009 | .remove = virtio_can_remove, | ||
| 1010 | .config_changed = virtio_can_config_changed, | ||
| 1011 | #ifdef CONFIG_PM_SLEEP | ||
| 1012 | .freeze = virtio_can_freeze, | ||
| 1013 | .restore = virtio_can_restore, | ||
| 1014 | #endif | ||
| 1015 | }; | ||
| 1016 | |||
| 1017 | module_virtio_driver(virtio_can_driver); | ||
| 1018 | MODULE_DEVICE_TABLE(virtio, virtio_can_id_table); | ||
| 1019 | |||
| 1020 | MODULE_AUTHOR("OpenSynergy GmbH"); | ||
| 1021 | MODULE_LICENSE("GPL"); | ||
| 1022 | MODULE_DESCRIPTION("CAN bus driver for Virtio CAN controller"); | ||
| @@ -734,15 +734,22 @@ static int ifcvf_vdpa_dev_add(struct vdpa_mgmt_dev *mdev, const char *name, · 733 unmodified lines | |||
| 734 | ret = dev_set_name(&vdpa_dev->dev, "%s", name); | 734 | ret = dev_set_name(&vdpa_dev->dev, "%s", name); |
| 735 | else | 735 | else |
| 736 | ret = dev_set_name(&vdpa_dev->dev, "vdpa%u", vdpa_dev->index); | 736 | ret = dev_set_name(&vdpa_dev->dev, "vdpa%u", vdpa_dev->index); |
| 737 | if (ret) { | ||
| 738 | IFCVF_ERR(pdev, "Failed to set device name"); | ||
| 739 | goto err; | ||
| 740 | } | ||
| 737 | 741 | ||
| 738 | ret = _vdpa_register_device(&adapter->vdpa, vf->nr_vring); | 742 | ret = _vdpa_register_device(&adapter->vdpa, vf->nr_vring); |
| 739 | if (ret) { | 743 | if (ret) { |
| 740 | put_device(&adapter->vdpa.dev); | ||
| 741 | IFCVF_ERR(pdev, "Failed to register to vDPA bus"); | 744 | IFCVF_ERR(pdev, "Failed to register to vDPA bus"); |
| 742 | return ret; | 745 | goto err; |
| 743 | } | 746 | } |
| 744 | 747 | ||
| 745 | return 0; | 748 | return 0; |
| 749 | |||
| 750 | err: | ||
| 751 | put_device(&adapter->vdpa.dev); | ||
| 752 | return ret; | ||
| 746 | } | 753 | } |
| 747 | 754 | ||
| 748 | static void ifcvf_vdpa_dev_del(struct vdpa_mgmt_dev *mdev, struct vdpa_device *dev) | 755 | static void ifcvf_vdpa_dev_del(struct vdpa_mgmt_dev *mdev, struct vdpa_device *dev) |
| @@ -221,11 +221,10 @@ static int create_direct_keys(struct mlx5_vdpa_dev *mvdev, struct mlx5_vdpa_mr * · 220 unmodified lines | |||
| 221 | 221 | ||
| 222 | list_for_each_entry(dmr, &mr->head, list) { | 222 | list_for_each_entry(dmr, &mr->head, list) { |
| 223 | struct mlx5_create_mkey_mem *cmd_mem; | 223 | struct mlx5_create_mkey_mem *cmd_mem; |
| 224 | int mttlen, mttcount; | 224 | int mttcount; |
| 225 | 225 | ||
| 226 | mttlen = roundup(MLX5_ST_SZ_BYTES(mtt) * dmr->nsg, MLX5_VDPA_MTT_ALIGN); | 226 | mttcount = ALIGN(dmr->nsg, MLX5_VDPA_MTT_ALIGN / sizeof(cmd_mem->mtt[0])); |
| 227 | mttcount = mttlen / sizeof(cmd_mem->mtt[0]); | 227 | cmd_mem = kvzalloc_flex(*cmd_mem, mtt, mttcount); |
| 228 | cmd_mem = kvcalloc(1, struct_size(cmd_mem, mtt, mttcount), GFP_KERNEL); | ||
| 229 | if (!cmd_mem) { | 228 | if (!cmd_mem) { |
| 230 | err = -ENOMEM; | 229 | err = -ENOMEM; |
| 231 | goto done; | 230 | goto done; |
| @@ -30,8 +30,10 @@ · 29 unmodified lines | |||
| 30 | #define OCTEP_EPF_RINFO(x) (0x000209f0 | ((x) << 25)) | 30 | #define OCTEP_EPF_RINFO(x) (0x000209f0 | ((x) << 25)) |
| 31 | #define OCTEP_VF_MBOX_DATA(x) (0x00010210 | ((x) << 17)) | 31 | #define OCTEP_VF_MBOX_DATA(x) (0x00010210 | ((x) << 17)) |
| 32 | #define OCTEP_PF_MBOX_DATA(x) (0x00022000 | ((x) << 4)) | 32 | #define OCTEP_PF_MBOX_DATA(x) (0x00022000 | ((x) << 4)) |
| 33 | #define OCTEP_VF_EVENT_STATE(x) (0x00010030 | ((x) << 17)) | ||
| 34 | #define OCTEP_VF_EVENT_REG(x) (0x00010060 | ((x) << 17)) | ||
| 33 | #define OCTEP_VF_IN_CTRL(x) (0x00010000 | ((x) << 17)) | 35 | #define OCTEP_VF_IN_CTRL(x) (0x00010000 | ((x) << 17)) |
| 34 | #define OCTEP_VF_IN_CTRL_RPVF(val) (((val) >> 48) & 0xF) | 36 | #define OCTEP_VF_IN_CTRL_RPVF(val) (FIELD_GET(GENMASK_ULL(51, 48), val)) |
| 35 | 37 | ||
| 36 | #define OCTEP_FW_READY_SIGNATURE0 0xFEEDFEED | 38 | #define OCTEP_FW_READY_SIGNATURE0 0xFEEDFEED |
| 37 | #define OCTEP_FW_READY_SIGNATURE1 0x3355ffaa | 39 | #define OCTEP_FW_READY_SIGNATURE1 0x3355ffaa |
| @@ -43,9 +45,26 @@ enum octep_vdpa_dev_status { · 5 unmodified lines | |||
| 43 | OCTEP_VDPA_DEV_STATUS_WAIT_FOR_BAR_INIT, | 45 | OCTEP_VDPA_DEV_STATUS_WAIT_FOR_BAR_INIT, |
| 44 | OCTEP_VDPA_DEV_STATUS_INIT, | 46 | OCTEP_VDPA_DEV_STATUS_INIT, |
| 45 | OCTEP_VDPA_DEV_STATUS_READY, | 47 | OCTEP_VDPA_DEV_STATUS_READY, |
| 48 | OCTEP_VDPA_DEV_STATUS_ADDED, | ||
| 49 | OCTEP_VDPA_DEV_STATUS_REMOVED, | ||
| 46 | OCTEP_VDPA_DEV_STATUS_UNINIT | 50 | OCTEP_VDPA_DEV_STATUS_UNINIT |
| 47 | }; | 51 | }; |
| 48 | 52 | ||
| 53 | enum octep_vdpa_dev_event_state { | ||
| 54 | OCTEP_VDPA_DEV_NO_EVENT, | ||
| 55 | OCTEP_VDPA_DEV_NEW_EVENT, | ||
| 56 | OCTEP_VDPA_DEV_EVENT_ACTIVE, | ||
| 57 | OCTEP_VDPA_DEV_EVENT_DONE, | ||
| 58 | }; | ||
| 59 | |||
| 60 | enum octep_vdpa_dev_event { | ||
| 61 | OCTEP_VDPA_DEV_EVENT_NONE, | ||
| 62 | OCTEP_VDPA_DEV_EVENT_ACK, | ||
| 63 | OCTEP_VDPA_DEV_EVENT_NACK, | ||
| 64 | OCTEP_VDPA_DEV_ADD_EVENT, | ||
| 65 | OCTEP_VDPA_DEV_DEL_EVENT, | ||
| 66 | }; | ||
| 67 | |||
| 49 | struct octep_vring_info { | 68 | struct octep_vring_info { |
| 50 | struct vdpa_callback cb; | 69 | struct vdpa_callback cb; |
| 51 | void __iomem *notify_addr; | 70 | void __iomem *notify_addr; |
| @@ -86,6 +105,7 @@ struct octep_hw { · 34 unmodified lines | |||
| 86 | u64 features; | 105 | u64 features; |
| 87 | u16 nr_vring; | 106 | u16 nr_vring; |
| 88 | u32 config_size; | 107 | u32 config_size; |
| 108 | int requested_irqs; | ||
| 89 | int nb_irqs; | 109 | int nb_irqs; |
| 90 | int *irqs; | 110 | int *irqs; |
| 91 | u8 dev_id; | 111 | u8 dev_id; |
| @@ -1,6 +1,7 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0-only | 1 | // SPDX-License-Identifier: GPL-2.0-only |
| 2 | /* Copyright (C) 2024 Marvell. */ | 2 | /* Copyright (C) 2024 Marvell. */ |
| 3 | 3 | ||
| 4 | #include <linux/bitfield.h> | ||
| 4 | #include <linux/interrupt.h> | 5 | #include <linux/interrupt.h> |
| 5 | #include <linux/io-64-nonatomic-lo-hi.h> | 6 | #include <linux/io-64-nonatomic-lo-hi.h> |
| 6 | #include <linux/module.h> | 7 | #include <linux/module.h> |
| @@ -8,6 +9,7 @@ · 1 unmodified line | |||
| 8 | #include "octep_vdpa.h" | 9 | #include "octep_vdpa.h" |
| 9 | 10 | ||
| 10 | #define OCTEP_VDPA_DRIVER_NAME "octep_vdpa" | 11 | #define OCTEP_VDPA_DRIVER_NAME "octep_vdpa" |
| 12 | #define OCTEP_VDPA_NAME_BUFSIZE 16 | ||
| 11 | 13 | ||
| 12 | struct octep_pf { | 14 | struct octep_pf { |
| 13 | u8 __iomem *base[PCI_STD_NUM_BARS]; | 15 | u8 __iomem *base[PCI_STD_NUM_BARS]; |
| @@ -19,6 +21,11 @@ struct octep_pf { · 5 unmodified lines | |||
| 19 | u16 vf_devid; | 21 | u16 vf_devid; |
| 20 | }; | 22 | }; |
| 21 | 23 | ||
| 24 | struct octep_vdpa_event_wk { | ||
| 25 | struct work_struct work; | ||
| 26 | void *ctxptr; | ||
| 27 | }; | ||
| 28 | |||
| 22 | struct octep_vdpa { | 29 | struct octep_vdpa { |
| 23 | struct vdpa_device vdpa; | 30 | struct vdpa_device vdpa; |
| 24 | struct octep_hw *oct_hw; | 31 | struct octep_hw *oct_hw; |
| @@ -33,6 +40,8 @@ struct octep_vdpa_mgmt_dev { · 8 unmodified lines | |||
| 33 | struct work_struct setup_task; | 40 | struct work_struct setup_task; |
| 34 | /* Device status */ | 41 | /* Device status */ |
| 35 | atomic_t status; | 42 | atomic_t status; |
| 43 | struct octep_vdpa *oct_vdpa; | ||
| 44 | struct octep_vdpa_event_wk event_wk; | ||
| 36 | }; | 45 | }; |
| 37 | 46 | ||
| 38 | static struct octep_hw *vdpa_to_octep_hw(struct vdpa_device *vdpa_dev) | 47 | static struct octep_hw *vdpa_to_octep_hw(struct vdpa_device *vdpa_dev) |
| @@ -44,10 +53,31 @@ static struct octep_hw *vdpa_to_octep_hw(struct vdpa_device *vdpa_dev) · 5 unmodified lines | |||
| 44 | return oct_vdpa->oct_hw; | 53 | return oct_vdpa->oct_hw; |
| 45 | } | 54 | } |
| 46 | 55 | ||
| 56 | static inline void octep_vdpa_dev_event_schedule(struct octep_hw *oct_hw) | ||
| 57 | { | ||
| 58 | u8 __iomem *addr = oct_hw->base[OCTEP_HW_MBOX_BAR]; | ||
| 59 | struct octep_vdpa_mgmt_dev *mgmt_dev; | ||
| 60 | |||
| 61 | mgmt_dev = container_of(oct_hw, struct octep_vdpa_mgmt_dev, oct_hw); | ||
| 62 | writeb(OCTEP_VDPA_DEV_EVENT_ACTIVE, addr + OCTEP_VF_EVENT_STATE(0)); | ||
| 63 | schedule_work(&mgmt_dev->event_wk.work); | ||
| 64 | } | ||
| 65 | |||
| 66 | static irqreturn_t octep_vdpa_dev_event_handler(int irq, void *data) | ||
| 67 | { | ||
| 68 | struct octep_hw *oct_hw = data; | ||
| 69 | |||
| 70 | if (readb(oct_hw->base[OCTEP_HW_MBOX_BAR] + OCTEP_VF_EVENT_STATE(0)) == | ||
| 71 | OCTEP_VDPA_DEV_NEW_EVENT) | ||
| 72 | octep_vdpa_dev_event_schedule(oct_hw); | ||
| 73 | |||
| 74 | return IRQ_HANDLED; | ||
| 75 | } | ||
| 76 | |||
| 47 | static irqreturn_t octep_vdpa_intr_handler(int irq, void *data) | 77 | static irqreturn_t octep_vdpa_intr_handler(int irq, void *data) |
| 48 | { | 78 | { |
| 49 | struct octep_hw *oct_hw = data; | 79 | struct octep_hw *oct_hw = data; |
| 50 | int i; | 80 | int i, start_ring_idx = -1; |
| 51 | 81 | ||
| 52 | /* Each device has multiple interrupts (nb_irqs) shared among rings | 82 | /* Each device has multiple interrupts (nb_irqs) shared among rings |
| 53 | * (nr_vring). Device interrupts are mapped to the rings in a | 83 | * (nr_vring). Device interrupts are mapped to the rings in a |
| @@ -60,7 +90,16 @@ static irqreturn_t octep_vdpa_intr_handler(int irq, void *data) · 6 unmodified lines | |||
| 60 | * 7 -> 7, 15, 23, 31, 39, 47, 55, 63; | 90 | * 7 -> 7, 15, 23, 31, 39, 47, 55, 63; |
| 61 | */ | 91 | */ |
| 62 | 92 | ||
| 63 | for (i = irq - oct_hw->irqs[0]; i < oct_hw->nr_vring; i += oct_hw->nb_irqs) { | 93 | for (i = 0; i < oct_hw->nb_irqs; i++) { |
| 94 | if (oct_hw->irqs[i] == irq) { | ||
| 95 | start_ring_idx = i; | ||
| 96 | break; | ||
| 97 | } | ||
| 98 | } | ||
| 99 | if (start_ring_idx == -1) | ||
| 100 | return IRQ_NONE; | ||
| 101 | |||
| 102 | for (i = start_ring_idx; i < oct_hw->nr_vring; i += oct_hw->nb_irqs) { | ||
| 64 | if (ioread8(oct_hw->vqs[i].cb_notify_addr)) { | 103 | if (ioread8(oct_hw->vqs[i].cb_notify_addr)) { |
| 65 | /* Acknowledge the per ring notification to the device */ | 104 | /* Acknowledge the per ring notification to the device */ |
| 66 | iowrite8(0, oct_hw->vqs[i].cb_notify_addr); | 105 | iowrite8(0, oct_hw->vqs[i].cb_notify_addr); |
| @@ -72,11 +111,14 @@ static irqreturn_t octep_vdpa_intr_handler(int irq, void *data) · 5 unmodified lines | |||
| 72 | } | 111 | } |
| 73 | 112 | ||
| 74 | /* Check for config interrupt. Config uses the first interrupt */ | 113 | /* Check for config interrupt. Config uses the first interrupt */ |
| 75 | if (unlikely(irq == oct_hw->irqs[0] && ioread8(oct_hw->isr))) { | 114 | if (unlikely(irq == oct_hw->irqs[0])) { |
| 76 | iowrite8(0, oct_hw->isr); | 115 | if (ioread8(oct_hw->isr)) { |
| 116 | iowrite8(0, oct_hw->isr); | ||
| 77 | 117 | ||
| 78 | if (oct_hw->config_cb.callback) | 118 | if (oct_hw->config_cb.callback) |
| 79 | oct_hw->config_cb.callback(oct_hw->config_cb.private); | 119 | oct_hw->config_cb.callback(oct_hw->config_cb.private); |
| 120 | } | ||
| 121 | octep_vdpa_dev_event_handler(irq, data); | ||
| 80 | } | 122 | } |
| 81 | 123 | ||
| 82 | return IRQ_HANDLED; | 124 | return IRQ_HANDLED; |
| @@ -100,33 +142,41 @@ static void octep_free_irqs(struct octep_hw *oct_hw) · 17 unmodified lines | |||
| 100 | pci_free_irq_vectors(pdev); | 142 | pci_free_irq_vectors(pdev); |
| 101 | devm_kfree(&pdev->dev, oct_hw->irqs); | 143 | devm_kfree(&pdev->dev, oct_hw->irqs); |
| 102 | oct_hw->irqs = NULL; | 144 | oct_hw->irqs = NULL; |
| 145 | oct_hw->requested_irqs = 0; | ||
| 103 | } | 146 | } |
| 104 | 147 | ||
| 105 | static int octep_request_irqs(struct octep_hw *oct_hw) | 148 | static int octep_request_irqs(struct octep_hw *oct_hw, irqreturn_t (*irq_handler)(int, void *), |
| 149 | int nb_irqs) | ||
| 106 | { | 150 | { |
| 107 | struct pci_dev *pdev = oct_hw->pdev; | 151 | struct pci_dev *pdev = oct_hw->pdev; |
| 108 | int ret, irq, idx; | 152 | int ret, irq, idx; |
| 109 | 153 | ||
| 110 | oct_hw->irqs = devm_kcalloc(&pdev->dev, oct_hw->nb_irqs, sizeof(int), GFP_KERNEL); | 154 | if ((oct_hw->requested_irqs != nb_irqs) || (nb_irqs == 1)) |
| 155 | octep_free_irqs(oct_hw); | ||
| 156 | else | ||
| 157 | return 0; | ||
| 158 | |||
| 159 | oct_hw->irqs = devm_kcalloc(&pdev->dev, nb_irqs, sizeof(int), GFP_KERNEL); | ||
| 111 | if (!oct_hw->irqs) | 160 | if (!oct_hw->irqs) |
| 112 | return -ENOMEM; | 161 | return -ENOMEM; |
| 113 | 162 | ||
| 114 | ret = pci_alloc_irq_vectors(pdev, 1, oct_hw->nb_irqs, PCI_IRQ_MSIX); | 163 | ret = pci_alloc_irq_vectors(pdev, 1, nb_irqs, PCI_IRQ_MSIX); |
| 115 | if (ret < 0) { | 164 | if (ret < 0) { |
| 116 | dev_err(&pdev->dev, "Failed to alloc msix vector"); | 165 | dev_err(&pdev->dev, "Failed to alloc msix vector"); |
| 117 | return ret; | 166 | return ret; |
| 118 | } | 167 | } |
| 119 | 168 | ||
| 120 | for (idx = 0; idx < oct_hw->nb_irqs; idx++) { | 169 | for (idx = 0; idx < nb_irqs; idx++) { |
| 121 | irq = pci_irq_vector(pdev, idx); | 170 | irq = pci_irq_vector(pdev, idx); |
| 122 | ret = devm_request_irq(&pdev->dev, irq, octep_vdpa_intr_handler, 0, | 171 | ret = devm_request_irq(&pdev->dev, irq, irq_handler, 0, dev_name(&pdev->dev), |
| 123 | dev_name(&pdev->dev), oct_hw); | 172 | oct_hw); |
| 124 | if (ret) { | 173 | if (ret) { |
| 125 | dev_err(&pdev->dev, "Failed to register interrupt handler\n"); | 174 | dev_err(&pdev->dev, "Failed to register interrupt handler\n"); |
| 126 | goto free_irqs; | 175 | goto free_irqs; |
| 127 | } | 176 | } |
| 128 | oct_hw->irqs[idx] = irq; | 177 | oct_hw->irqs[idx] = irq; |
| 129 | } | 178 | } |
| 179 | oct_hw->requested_irqs = nb_irqs; | ||
| 130 | 180 | ||
| 131 | return 0; | 181 | return 0; |
| 132 | 182 | ||
| @@ -188,7 +238,7 @@ static void octep_vdpa_set_status(struct vdpa_device *vdpa_dev, u8 status) · 55 unmodified lines | |||
| 188 | 238 | ||
| 189 | if ((status & VIRTIO_CONFIG_S_DRIVER_OK) && | 239 | if ((status & VIRTIO_CONFIG_S_DRIVER_OK) && |
| 190 | !(status_old & VIRTIO_CONFIG_S_DRIVER_OK)) { | 240 | !(status_old & VIRTIO_CONFIG_S_DRIVER_OK)) { |
| 191 | if (octep_request_irqs(oct_hw)) | 241 | if (octep_request_irqs(oct_hw, octep_vdpa_intr_handler, oct_hw->nb_irqs)) |
| 192 | status = status_old | VIRTIO_CONFIG_S_FAILED; | 242 | status = status_old | VIRTIO_CONFIG_S_FAILED; |
| 193 | } | 243 | } |
| 194 | octep_hw_set_status(oct_hw, status); | 244 | octep_hw_set_status(oct_hw, status); |
| @@ -211,8 +261,10 @@ static int octep_vdpa_reset(struct vdpa_device *vdpa_dev) · 16 unmodified lines | |||
| 211 | } | 261 | } |
| 212 | octep_hw_reset(oct_hw); | 262 | octep_hw_reset(oct_hw); |
| 213 | 263 | ||
| 214 | if (status & VIRTIO_CONFIG_S_DRIVER_OK) | 264 | if (status & VIRTIO_CONFIG_S_DRIVER_OK) { |
| 215 | octep_free_irqs(oct_hw); | 265 | octep_free_irqs(oct_hw); |
| 266 | octep_request_irqs(oct_hw, octep_vdpa_dev_event_handler, 1); | ||
| 267 | } | ||
| 216 | 268 | ||
| 217 | return 0; | 269 | return 0; |
| 218 | } | 270 | } |
| @@ -477,7 +529,8 @@ static void octep_vdpa_remove_vf(struct pci_dev *pdev) · 258 unmodified lines | |||
| 477 | atomic_set(&mgmt_dev->status, OCTEP_VDPA_DEV_STATUS_UNINIT); | 529 | atomic_set(&mgmt_dev->status, OCTEP_VDPA_DEV_STATUS_UNINIT); |
| 478 | 530 | ||
| 479 | cancel_work_sync(&mgmt_dev->setup_task); | 531 | cancel_work_sync(&mgmt_dev->setup_task); |
| 480 | if (status == OCTEP_VDPA_DEV_STATUS_READY) | 532 | if ((status == OCTEP_VDPA_DEV_STATUS_READY) || (status == OCTEP_VDPA_DEV_STATUS_ADDED) || |
| 533 | (status == OCTEP_VDPA_DEV_STATUS_REMOVED)) | ||
| 481 | vdpa_mgmtdev_unregister(&mgmt_dev->mdev); | 534 | vdpa_mgmtdev_unregister(&mgmt_dev->mdev); |
| 482 | 535 | ||
| 483 | if (oct_hw->base[OCTEP_HW_CAPS_BAR]) | 536 | if (oct_hw->base[OCTEP_HW_CAPS_BAR]) |
| @@ -487,6 +540,7 @@ static void octep_vdpa_remove_vf(struct pci_dev *pdev) · 3 unmodified lines | |||
| 487 | octep_iounmap_region(pdev, oct_hw->base, OCTEP_HW_MBOX_BAR); | 540 | octep_iounmap_region(pdev, oct_hw->base, OCTEP_HW_MBOX_BAR); |
| 488 | 541 | ||
| 489 | octep_vdpa_vf_bar_shrink(pdev); | 542 | octep_vdpa_vf_bar_shrink(pdev); |
| 543 | octep_free_irqs(oct_hw); | ||
| 490 | } | 544 | } |
| 491 | 545 | ||
| 492 | static void octep_vdpa_remove(struct pci_dev *pdev) | 546 | static void octep_vdpa_remove(struct pci_dev *pdev) |
| @@ -520,6 +574,7 @@ static int octep_vdpa_dev_add(struct vdpa_mgmt_dev *mdev, const char *name, · 27 unmodified lines | |||
| 520 | oct_vdpa->vdpa.mdev = mdev; | 574 | oct_vdpa->vdpa.mdev = mdev; |
| 521 | oct_vdpa->oct_hw = oct_hw; | 575 | oct_vdpa->oct_hw = oct_hw; |
| 522 | vdpa_dev = &oct_vdpa->vdpa; | 576 | vdpa_dev = &oct_vdpa->vdpa; |
| 577 | mgmt_dev->oct_vdpa = oct_vdpa; | ||
| 523 | 578 | ||
| 524 | device_features = oct_hw->features; | 579 | device_features = oct_hw->features; |
| 525 | if (config->mask & BIT_ULL(VDPA_ATTR_DEV_FEATURES)) { | 580 | if (config->mask & BIT_ULL(VDPA_ATTR_DEV_FEATURES)) { |
| @@ -553,6 +608,7 @@ static int octep_vdpa_dev_add(struct vdpa_mgmt_dev *mdev, const char *name, · 27 unmodified lines | |||
| 553 | dev_err(&pdev->dev, "Failed to register to vDPA bus"); | 608 | dev_err(&pdev->dev, "Failed to register to vDPA bus"); |
| 554 | goto vdpa_dev_put; | 609 | goto vdpa_dev_put; |
| 555 | } | 610 | } |
| 611 | atomic_set(&mgmt_dev->status, OCTEP_VDPA_DEV_STATUS_ADDED); | ||
| 556 | return 0; | 612 | return 0; |
| 557 | 613 | ||
| 558 | vdpa_dev_put: | 614 | vdpa_dev_put: |
| @@ -562,7 +618,9 @@ vdpa_dev_put: · 3 unmodified lines | |||
| 562 | 618 | ||
| 563 | static void octep_vdpa_dev_del(struct vdpa_mgmt_dev *mdev, struct vdpa_device *vdpa_dev) | 619 | static void octep_vdpa_dev_del(struct vdpa_mgmt_dev *mdev, struct vdpa_device *vdpa_dev) |
| 564 | { | 620 | { |
| 621 | struct octep_vdpa_mgmt_dev *mgmt_dev = container_of(mdev, struct octep_vdpa_mgmt_dev, mdev); | ||
| 565 | _vdpa_unregister_device(vdpa_dev); | 622 | _vdpa_unregister_device(vdpa_dev); |
| 623 | atomic_set(&mgmt_dev->status, OCTEP_VDPA_DEV_STATUS_REMOVED); | ||
| 566 | } | 624 | } |
| 567 | 625 | ||
| 568 | static const struct vdpa_mgmtdev_ops octep_vdpa_mgmt_dev_ops = { | 626 | static const struct vdpa_mgmtdev_ops octep_vdpa_mgmt_dev_ops = { |
| @@ -572,10 +630,10 @@ static const struct vdpa_mgmtdev_ops octep_vdpa_mgmt_dev_ops = { · 3 unmodified lines | |||
| 572 | 630 | ||
| 573 | static bool get_device_ready_status(u8 __iomem *addr) | 631 | static bool get_device_ready_status(u8 __iomem *addr) |
| 574 | { | 632 | { |
| 575 | u64 signature = readq(addr + OCTEP_VF_MBOX_DATA(0)); | 633 | u32 signature = readl(addr + OCTEP_VF_MBOX_DATA(0)); |
| 576 | 634 | ||
| 577 | if (signature == OCTEP_DEV_READY_SIGNATURE) { | 635 | if (signature == OCTEP_DEV_READY_SIGNATURE) { |
| 578 | writeq(0, addr + OCTEP_VF_MBOX_DATA(0)); | 636 | writel(0, addr + OCTEP_VF_MBOX_DATA(0)); |
| 579 | return true; | 637 | return true; |
| 580 | } | 638 | } |
| 581 | 639 | ||
| @@ -587,6 +645,36 @@ static struct virtio_device_id id_table[] = { · 5 unmodified lines | |||
| 587 | { 0 }, | 645 | { 0 }, |
| 588 | }; | 646 | }; |
| 589 | 647 | ||
| 648 | static void octep_event_work(struct work_struct *work) | ||
| 649 | { | ||
| 650 | struct octep_vdpa_event_wk *wk = container_of(work, struct octep_vdpa_event_wk, work); | ||
| 651 | struct octep_vdpa_mgmt_dev *mgmt_dev = (struct octep_vdpa_mgmt_dev *)wk->ctxptr; | ||
| 652 | u8 __iomem *addr = mgmt_dev->oct_hw.base[OCTEP_HW_MBOX_BAR]; | ||
| 653 | u8 event = readb(addr + OCTEP_VF_EVENT_REG(0)); | ||
| 654 | struct vdpa_dev_set_config config = {0}; | ||
| 655 | char name[OCTEP_VDPA_NAME_BUFSIZE]; | ||
| 656 | int ret = 0; | ||
| 657 | |||
| 658 | switch (event) { | ||
| 659 | case OCTEP_VDPA_DEV_ADD_EVENT: | ||
| 660 | if (atomic_read(&mgmt_dev->status) != OCTEP_VDPA_DEV_STATUS_ADDED) { | ||
| 661 | snprintf(name, sizeof(name), "%s-%x", "vdpa", mgmt_dev->pdev->devfn); | ||
| 662 | ret = octep_vdpa_dev_add(&mgmt_dev->mdev, name, &config); | ||
| 663 | } | ||
| 664 | break; | ||
| 665 | case OCTEP_VDPA_DEV_DEL_EVENT: | ||
| 666 | if (atomic_read(&mgmt_dev->status) == OCTEP_VDPA_DEV_STATUS_ADDED) | ||
| 667 | octep_vdpa_dev_del(&mgmt_dev->mdev, &mgmt_dev->oct_vdpa->vdpa); | ||
| 668 | break; | ||
| 669 | default: | ||
| 670 | break; | ||
| 671 | } | ||
| 672 | |||
| 673 | event = ret ? OCTEP_VDPA_DEV_EVENT_NACK : OCTEP_VDPA_DEV_EVENT_ACK; | ||
| 674 | writeb(event, addr + OCTEP_VF_EVENT_REG(0)); | ||
| 675 | writeb(OCTEP_VDPA_DEV_EVENT_DONE, addr + OCTEP_VF_EVENT_STATE(0)); | ||
| 676 | } | ||
| 677 | |||
| 590 | static void octep_vdpa_setup_task(struct work_struct *work) | 678 | static void octep_vdpa_setup_task(struct work_struct *work) |
| 591 | { | 679 | { |
| 592 | struct octep_vdpa_mgmt_dev *mgmt_dev = container_of(work, struct octep_vdpa_mgmt_dev, | 680 | struct octep_vdpa_mgmt_dev *mgmt_dev = container_of(work, struct octep_vdpa_mgmt_dev, |
| @@ -652,6 +740,9 @@ static void octep_vdpa_setup_task(struct work_struct *work) · 59 unmodified lines | |||
| 652 | } | 740 | } |
| 653 | 741 | ||
| 654 | atomic_set(&mgmt_dev->status, OCTEP_VDPA_DEV_STATUS_READY); | 742 | atomic_set(&mgmt_dev->status, OCTEP_VDPA_DEV_STATUS_READY); |
| 743 | INIT_WORK(&mgmt_dev->event_wk.work, octep_event_work); | ||
| 744 | mgmt_dev->event_wk.ctxptr = mgmt_dev; | ||
| 745 | octep_request_irqs(&mgmt_dev->oct_hw, octep_vdpa_dev_event_handler, 1); | ||
| 655 | 746 | ||
| 656 | return; | 747 | return; |
| 657 | 748 | ||
| @@ -722,6 +813,8 @@ static int octep_sriov_enable(struct pci_dev *pdev, int num_vfs) · 64 unmodified lines | |||
| 722 | bool done = false; | 813 | bool done = false; |
| 723 | int index = 0; | 814 | int index = 0; |
| 724 | int ret, i; | 815 | int ret, i; |
| 816 | u8 rpvf; | ||
| 817 | u64 val; | ||
| 725 | 818 | ||
| 726 | ret = pci_enable_sriov(pdev, num_vfs); | 819 | ret = pci_enable_sriov(pdev, num_vfs); |
| 727 | if (ret) | 820 | if (ret) |
| @@ -741,9 +834,11 @@ static int octep_sriov_enable(struct pci_dev *pdev, int num_vfs) · 13 unmodified lines | |||
| 741 | } | 834 | } |
| 742 | } | 835 | } |
| 743 | 836 | ||
| 837 | val = readq(addr + OCTEP_EPF_RINFO(0)); | ||
| 838 | rpvf = FIELD_GET(GENMASK_ULL(35, 32), val); | ||
| 744 | if (done) { | 839 | if (done) { |
| 745 | for (i = 0; i < pf->enabled_vfs; i++) | 840 | for (i = 0; i < pf->enabled_vfs; i++) |
| 746 | writeq(OCTEP_DEV_READY_SIGNATURE, addr + OCTEP_PF_MBOX_DATA(i)); | 841 | writel(OCTEP_DEV_READY_SIGNATURE, addr + OCTEP_PF_MBOX_DATA(i * rpvf)); |
| 747 | } | 842 | } |
| 748 | 843 | ||
| 749 | return num_vfs; | 844 | return num_vfs; |
| @@ -397,14 +397,7 @@ static void vdpasim_blk_free(struct vdpasim *vdpasim) · 396 unmodified lines | |||
| 397 | kvfree(blk->buffer); | 397 | kvfree(blk->buffer); |
| 398 | } | 398 | } |
| 399 | 399 | ||
| 400 | static void vdpasim_blk_mgmtdev_release(struct device *dev) | 400 | static struct device *vdpasim_blk_mgmtdev; |
| 401 | { | ||
| 402 | } | ||
| 403 | |||
| 404 | static struct device vdpasim_blk_mgmtdev = { | ||
| 405 | .init_name = "vdpasim_blk", | ||
| 406 | .release = vdpasim_blk_mgmtdev_release, | ||
| 407 | }; | ||
| 408 | 401 | ||
| 409 | static int vdpasim_blk_dev_add(struct vdpa_mgmt_dev *mdev, const char *name, | 402 | static int vdpasim_blk_dev_add(struct vdpa_mgmt_dev *mdev, const char *name, |
| 410 | const struct vdpa_dev_set_config *config) | 403 | const struct vdpa_dev_set_config *config) |
| @@ -475,7 +468,6 @@ static struct virtio_device_id id_table[] = { · 64 unmodified lines | |||
| 475 | }; | 468 | }; |
| 476 | 469 | ||
| 477 | static struct vdpa_mgmt_dev mgmt_dev = { | 470 | static struct vdpa_mgmt_dev mgmt_dev = { |
| 478 | .device = &vdpasim_blk_mgmtdev, | ||
| 479 | .id_table = id_table, | 471 | .id_table = id_table, |
| 480 | .ops = &vdpasim_blk_mgmtdev_ops, | 472 | .ops = &vdpasim_blk_mgmtdev_ops, |
| 481 | }; | 473 | }; |
| @@ -484,12 +476,11 @@ static int __init vdpasim_blk_init(void) · 2 unmodified lines | |||
| 484 | { | 476 | { |
| 485 | int ret; | 477 | int ret; |
| 486 | 478 | ||
| 487 | ret = device_register(&vdpasim_blk_mgmtdev); | 479 | vdpasim_blk_mgmtdev = root_device_register("vdpasim_blk"); |
| 488 | if (ret) { | 480 | if (IS_ERR(vdpasim_blk_mgmtdev)) |
| 489 | put_device(&vdpasim_blk_mgmtdev); | 481 | return PTR_ERR(vdpasim_blk_mgmtdev); |
| 490 | return ret; | ||
| 491 | } | ||
| 492 | 482 | ||
| 483 | mgmt_dev.device = vdpasim_blk_mgmtdev; | ||
| 493 | ret = vdpa_mgmtdev_register(&mgmt_dev); | 484 | ret = vdpa_mgmtdev_register(&mgmt_dev); |
| 494 | if (ret) | 485 | if (ret) |
| 495 | goto parent_err; | 486 | goto parent_err; |
| @@ -507,7 +498,8 @@ static int __init vdpasim_blk_init(void) · 11 unmodified lines | |||
| 507 | mgmt_dev_err: | 498 | mgmt_dev_err: |
| 508 | vdpa_mgmtdev_unregister(&mgmt_dev); | 499 | vdpa_mgmtdev_unregister(&mgmt_dev); |
| 509 | parent_err: | 500 | parent_err: |
| 510 | device_unregister(&vdpasim_blk_mgmtdev); | 501 | root_device_unregister(vdpasim_blk_mgmtdev); |
| 502 | |||
| 511 | return ret; | 503 | return ret; |
| 512 | } | 504 | } |
| 513 | 505 | ||
| @@ -515,7 +507,7 @@ static void __exit vdpasim_blk_exit(void) · 1 unmodified line | |||
| 515 | { | 507 | { |
| 516 | kvfree(shared_buffer); | 508 | kvfree(shared_buffer); |
| 517 | vdpa_mgmtdev_unregister(&mgmt_dev); | 509 | vdpa_mgmtdev_unregister(&mgmt_dev); |
| 518 | device_unregister(&vdpasim_blk_mgmtdev); | 510 | root_device_unregister(vdpasim_blk_mgmtdev); |
| 519 | } | 511 | } |
| 520 | 512 | ||
| 521 | module_init(vdpasim_blk_init) | 513 | module_init(vdpasim_blk_init) |
| @@ -453,14 +453,7 @@ static void vdpasim_net_free(struct vdpasim *vdpasim) · 452 unmodified lines | |||
| 453 | kvfree(net->buffer); | 453 | kvfree(net->buffer); |
| 454 | } | 454 | } |
| 455 | 455 | ||
| 456 | static void vdpasim_net_mgmtdev_release(struct device *dev) | 456 | static struct device *vdpasim_net_mgmtdev; |
| 457 | { | ||
| 458 | } | ||
| 459 | |||
| 460 | static struct device vdpasim_net_mgmtdev = { | ||
| 461 | .init_name = "vdpasim_net", | ||
| 462 | .release = vdpasim_net_mgmtdev_release, | ||
| 463 | }; | ||
| 464 | 457 | ||
| 465 | static int vdpasim_net_dev_add(struct vdpa_mgmt_dev *mdev, const char *name, | 458 | static int vdpasim_net_dev_add(struct vdpa_mgmt_dev *mdev, const char *name, |
| 466 | const struct vdpa_dev_set_config *config) | 459 | const struct vdpa_dev_set_config *config) |
| @@ -538,7 +531,6 @@ static struct virtio_device_id id_table[] = { · 71 unmodified lines | |||
| 538 | }; | 531 | }; |
| 539 | 532 | ||
| 540 | static struct vdpa_mgmt_dev mgmt_dev = { | 533 | static struct vdpa_mgmt_dev mgmt_dev = { |
| 541 | .device = &vdpasim_net_mgmtdev, | ||
| 542 | .id_table = id_table, | 534 | .id_table = id_table, |
| 543 | .ops = &vdpasim_net_mgmtdev_ops, | 535 | .ops = &vdpasim_net_mgmtdev_ops, |
| 544 | .config_attr_mask = (1 << VDPA_ATTR_DEV_NET_CFG_MACADDR | | 536 | .config_attr_mask = (1 << VDPA_ATTR_DEV_NET_CFG_MACADDR | |
| @@ -552,26 +544,25 @@ static int __init vdpasim_net_init(void) · 7 unmodified lines | |||
| 552 | { | 544 | { |
| 553 | int ret; | 545 | int ret; |
| 554 | 546 | ||
| 555 | ret = device_register(&vdpasim_net_mgmtdev); | 547 | vdpasim_net_mgmtdev = root_device_register("vdpasim_net"); |
| 556 | if (ret) { | 548 | if (IS_ERR(vdpasim_net_mgmtdev)) |
| 557 | put_device(&vdpasim_net_mgmtdev); | 549 | return PTR_ERR(vdpasim_net_mgmtdev); |
| 558 | return ret; | ||
| 559 | } | ||
| 560 | 550 | ||
| 551 | mgmt_dev.device = vdpasim_net_mgmtdev; | ||
| 561 | ret = vdpa_mgmtdev_register(&mgmt_dev); | 552 | ret = vdpa_mgmtdev_register(&mgmt_dev); |
| 562 | if (ret) | 553 | if (ret) |
| 563 | goto parent_err; | 554 | goto parent_err; |
| 564 | return 0; | 555 | return 0; |
| 565 | 556 | ||
| 566 | parent_err: | 557 | parent_err: |
| 567 | device_unregister(&vdpasim_net_mgmtdev); | 558 | root_device_unregister(vdpasim_net_mgmtdev); |
| 568 | return ret; | 559 | return ret; |
| 569 | } | 560 | } |
| 570 | 561 | ||
| 571 | static void __exit vdpasim_net_exit(void) | 562 | static void __exit vdpasim_net_exit(void) |
| 572 | { | 563 | { |
| 573 | vdpa_mgmtdev_unregister(&mgmt_dev); | 564 | vdpa_mgmtdev_unregister(&mgmt_dev); |
| 574 | device_unregister(&vdpasim_net_mgmtdev); | 565 | root_device_unregister(vdpasim_net_mgmtdev); |
| 575 | } | 566 | } |
| 576 | 567 | ||
| 577 | module_init(vdpasim_net_init); | 568 | module_init(vdpasim_net_init); |
| @@ -124,7 +124,7 @@ static int vduse_domain_map_bounce_page(struct vduse_iova_domain *domain, · 123 unmodified lines | |||
| 124 | if (!map->bounce_page) { | 124 | if (!map->bounce_page) { |
| 125 | head_map = &domain->bounce_maps[(iova & PAGE_MASK) >> BOUNCE_MAP_SHIFT]; | 125 | head_map = &domain->bounce_maps[(iova & PAGE_MASK) >> BOUNCE_MAP_SHIFT]; |
| 126 | if (!head_map->bounce_page) { | 126 | if (!head_map->bounce_page) { |
| 127 | tmp_page = alloc_page(GFP_ATOMIC); | 127 | tmp_page = alloc_page(GFP_ATOMIC | __GFP_ZERO); |
| 128 | if (!tmp_page) | 128 | if (!tmp_page) |
| 129 | return -ENOMEM; | 129 | return -ENOMEM; |
| 130 | if (cmpxchg(&head_map->bounce_page, NULL, tmp_page)) | 130 | if (cmpxchg(&head_map->bounce_page, NULL, tmp_page)) |
| @@ -221,6 +221,12 @@ static void vduse_enqueue_msg(struct list_head *head, · 220 unmodified lines | |||
| 221 | list_add_tail(&msg->list, head); | 221 | list_add_tail(&msg->list, head); |
| 222 | } | 222 | } |
| 223 | 223 | ||
| 224 | static void vduse_enqueue_msg_head(struct list_head *head, | ||
| 225 | struct vduse_dev_msg *msg) | ||
| 226 | { | ||
| 227 | list_add(&msg->list, head); | ||
| 228 | } | ||
| 229 | |||
| 224 | static void vduse_dev_broken(struct vduse_dev *dev) | 230 | static void vduse_dev_broken(struct vduse_dev *dev) |
| 225 | { | 231 | { |
| 226 | struct vduse_dev_msg *msg, *tmp; | 232 | struct vduse_dev_msg *msg, *tmp; |
| @@ -358,6 +364,7 @@ static ssize_t vduse_dev_read_iter(struct kiocb *iocb, struct iov_iter *to) · 131 unmodified lines | |||
| 358 | struct file *file = iocb->ki_filp; | 364 | struct file *file = iocb->ki_filp; |
| 359 | struct vduse_dev *dev = file->private_data; | 365 | struct vduse_dev *dev = file->private_data; |
| 360 | struct vduse_dev_msg *msg; | 366 | struct vduse_dev_msg *msg; |
| 367 | struct vduse_dev_request req; | ||
| 361 | int size = sizeof(struct vduse_dev_request); | 368 | int size = sizeof(struct vduse_dev_request); |
| 362 | ssize_t ret; | 369 | ssize_t ret; |
| 363 | 370 | ||
| @@ -369,12 +376,11 @@ static ssize_t vduse_dev_read_iter(struct kiocb *iocb, struct iov_iter *to) · 5 unmodified lines | |||
| 369 | msg = vduse_dequeue_msg(&dev->send_list); | 376 | msg = vduse_dequeue_msg(&dev->send_list); |
| 370 | if (msg) | 377 | if (msg) |
| 371 | break; | 378 | break; |
| 379 | spin_unlock(&dev->msg_lock); | ||
| 372 | 380 | ||
| 373 | ret = -EAGAIN; | ||
| 374 | if (file->f_flags & O_NONBLOCK) | 381 | if (file->f_flags & O_NONBLOCK) |
| 375 | goto unlock; | 382 | return -EAGAIN; |
| 376 | 383 | ||
| 377 | spin_unlock(&dev->msg_lock); | ||
| 378 | ret = wait_event_interruptible_exclusive(dev->waitq, | 384 | ret = wait_event_interruptible_exclusive(dev->waitq, |
| 379 | !list_empty(&dev->send_list)); | 385 | !list_empty(&dev->send_list)); |
| 380 | if (ret) | 386 | if (ret) |
| @@ -382,17 +388,34 @@ static ssize_t vduse_dev_read_iter(struct kiocb *iocb, struct iov_iter *to) · 1 unmodified line | |||
| 382 | 388 | ||
| 383 | spin_lock(&dev->msg_lock); | 389 | spin_lock(&dev->msg_lock); |
| 384 | } | 390 | } |
| 391 | |||
| 392 | memcpy(&req, &msg->req, sizeof(req)); | ||
| 393 | /* | ||
| 394 | * We must ensure vduse_msg is on send_list or recv_list before unlock | ||
| 395 | * dev->msg_lock. Because vduse_dev_msg_sync() may be timeout when we | ||
| 396 | * copy data to userspace, and will call list_del() for this msg. | ||
| 397 | */ | ||
| 398 | vduse_enqueue_msg(&dev->recv_list, msg); | ||
| 385 | spin_unlock(&dev->msg_lock); | 399 | spin_unlock(&dev->msg_lock); |
| 386 | ret = copy_to_iter(&msg->req, size, to); | 400 | |
| 387 | spin_lock(&dev->msg_lock); | 401 | ret = copy_to_iter(&req, size, to); |
| 388 | if (ret != size) { | 402 | if (ret != size) { |
| 403 | /* | ||
| 404 | * Roll back: move msg back to send_list if still pending. | ||
| 405 | * | ||
| 406 | * NOTE: | ||
| 407 | * vduse_find_msg() must use req.request_id instead of `msg`. | ||
| 408 | * A malicious userspace may reply to this request, and wake up | ||
| 409 | * the caller, after which `msg` will have already been freed. | ||
| 410 | * And here vduse_find_msg() will return NULL then do nothing. | ||
| 411 | */ | ||
| 412 | spin_lock(&dev->msg_lock); | ||
| 413 | msg = vduse_find_msg(&dev->recv_list, req.request_id); | ||
| 414 | if (msg) | ||
| 415 | vduse_enqueue_msg_head(&dev->send_list, msg); | ||
| 416 | spin_unlock(&dev->msg_lock); | ||
| 389 | ret = -EFAULT; | 417 | ret = -EFAULT; |
| 390 | vduse_enqueue_msg(&dev->send_list, msg); | ||
| 391 | goto unlock; | ||
| 392 | } | 418 | } |
| 393 | vduse_enqueue_msg(&dev->recv_list, msg); | ||
| 394 | unlock: | ||
| 395 | spin_unlock(&dev->msg_lock); | ||
| 396 | 419 | ||
| 397 | return ret; | 420 | return ret; |
| 398 | } | 421 | } |
| @@ -976,7 +999,7 @@ static void *vduse_dev_alloc_coherent(union virtio_map token, size_t size, · 577 unmodified lines | |||
| 976 | if (!token.group) | 999 | if (!token.group) |
| 977 | return NULL; | 1000 | return NULL; |
| 978 | 1001 | ||
| 979 | addr = alloc_pages_exact(size, flag); | 1002 | addr = alloc_pages_exact(size, flag | __GFP_ZERO); |
| 980 | if (!addr) | 1003 | if (!addr) |
| 981 | return NULL; | 1004 | return NULL; |
| 982 | 1005 | ||
| @@ -1618,6 +1641,127 @@ static long vduse_dev_ioctl(struct file *file, unsigned int cmd, · 635 unmodified lines | |||
| 1618 | return ret; | 1641 | return ret; |
| 1619 | } | 1642 | } |
| 1620 | 1643 | ||
| 1644 | #ifdef CONFIG_COMPAT_FOR_U64_ALIGNMENT | ||
| 1645 | /* | ||
| 1646 | * i386 has different alignment constraints than x86_64, | ||
| 1647 | * so there are only 3 bytes of padding instead of 7. | ||
| 1648 | */ | ||
| 1649 | struct compat_vduse_iotlb_entry { | ||
| 1650 | compat_u64 offset; | ||
| 1651 | compat_u64 start; | ||
| 1652 | compat_u64 last; | ||
| 1653 | __u8 perm; | ||
| 1654 | __u8 padding[3]; | ||
| 1655 | }; | ||
| 1656 | #define COMPAT_VDUSE_IOTLB_GET_FD _IOWR(VDUSE_BASE, 0x10, struct compat_vduse_iotlb_entry) | ||
| 1657 | |||
| 1658 | struct compat_vduse_vq_info { | ||
| 1659 | __u32 index; | ||
| 1660 | __u32 num; | ||
| 1661 | compat_u64 desc_addr; | ||
| 1662 | compat_u64 driver_addr; | ||
| 1663 | compat_u64 device_addr; | ||
| 1664 | union { | ||
| 1665 | struct vduse_vq_state_split split; | ||
| 1666 | struct vduse_vq_state_packed packed; | ||
| 1667 | }; | ||
| 1668 | __u8 ready; | ||
| 1669 | __u8 padding[3]; | ||
| 1670 | }; | ||
| 1671 | #define COMPAT_VDUSE_VQ_GET_INFO _IOWR(VDUSE_BASE, 0x15, struct compat_vduse_vq_info) | ||
| 1672 | |||
| 1673 | static long vduse_dev_compat_ioctl(struct file *file, unsigned int cmd, | ||
| 1674 | unsigned long arg) | ||
| 1675 | { | ||
| 1676 | struct vduse_dev *dev = file->private_data; | ||
| 1677 | void __user *argp = (void __user *)arg; | ||
| 1678 | int ret; | ||
| 1679 | |||
| 1680 | if (unlikely(dev->broken)) | ||
| 1681 | return -EPERM; | ||
| 1682 | |||
| 1683 | switch (cmd) { | ||
| 1684 | case COMPAT_VDUSE_IOTLB_GET_FD: { | ||
| 1685 | struct vduse_iotlb_entry_v2 entry = {0}; | ||
| 1686 | struct file *f = NULL; | ||
| 1687 | |||
| 1688 | ret = -EFAULT; | ||
| 1689 | if (copy_from_user(&entry, argp, _IOC_SIZE(cmd))) | ||
| 1690 | break; | ||
| 1691 | |||
| 1692 | ret = vduse_dev_iotlb_entry(dev, &entry, &f, NULL); | ||
| 1693 | if (ret) | ||
| 1694 | break; | ||
| 1695 | |||
| 1696 | ret = -EINVAL; | ||
| 1697 | if (!f) | ||
| 1698 | break; | ||
| 1699 | |||
| 1700 | ret = copy_to_user(argp, &entry, _IOC_SIZE(cmd)); | ||
| 1701 | if (ret) { | ||
| 1702 | ret = -EFAULT; | ||
| 1703 | fput(f); | ||
| 1704 | break; | ||
| 1705 | } | ||
| 1706 | ret = receive_fd(f, NULL, perm_to_file_flags(entry.perm)); | ||
| 1707 | fput(f); | ||
| 1708 | break; | ||
| 1709 | } | ||
| 1710 | case COMPAT_VDUSE_VQ_GET_INFO: { | ||
| 1711 | struct vduse_vq_info vq_info = {}; | ||
| 1712 | struct vduse_virtqueue *vq; | ||
| 1713 | u32 index; | ||
| 1714 | |||
| 1715 | ret = -EFAULT; | ||
| 1716 | if (copy_from_user(&vq_info, argp, | ||
| 1717 | sizeof(struct compat_vduse_vq_info))) | ||
| 1718 | break; | ||
| 1719 | |||
| 1720 | ret = -EINVAL; | ||
| 1721 | if (vq_info.index >= dev->vq_num) | ||
| 1722 | break; | ||
| 1723 | |||
| 1724 | index = array_index_nospec(vq_info.index, dev->vq_num); | ||
| 1725 | vq = dev->vqs[index]; | ||
| 1726 | vq_info.desc_addr = vq->desc_addr; | ||
| 1727 | vq_info.driver_addr = vq->driver_addr; | ||
| 1728 | vq_info.device_addr = vq->device_addr; | ||
| 1729 | vq_info.num = vq->num; | ||
| 1730 | |||
| 1731 | if (dev->driver_features & BIT_ULL(VIRTIO_F_RING_PACKED)) { | ||
| 1732 | vq_info.packed.last_avail_counter = | ||
| 1733 | vq->state.packed.last_avail_counter; | ||
| 1734 | vq_info.packed.last_avail_idx = | ||
| 1735 | vq->state.packed.last_avail_idx; | ||
| 1736 | vq_info.packed.last_used_counter = | ||
| 1737 | vq->state.packed.last_used_counter; | ||
| 1738 | vq_info.packed.last_used_idx = | ||
| 1739 | vq->state.packed.last_used_idx; | ||
| 1740 | } else | ||
| 1741 | vq_info.split.avail_index = | ||
| 1742 | vq->state.split.avail_index; | ||
| 1743 | |||
| 1744 | vq_info.ready = vq->ready; | ||
| 1745 | |||
| 1746 | ret = -EFAULT; | ||
| 1747 | if (copy_to_user(argp, &vq_info, | ||
| 1748 | sizeof(struct compat_vduse_vq_info))) | ||
| 1749 | break; | ||
| 1750 | |||
| 1751 | ret = 0; | ||
| 1752 | break; | ||
| 1753 | } | ||
| 1754 | default: | ||
| 1755 | ret = -ENOIOCTLCMD; | ||
| 1756 | break; | ||
| 1757 | } | ||
| 1758 | |||
| 1759 | return vduse_dev_ioctl(file, cmd, (unsigned long)compat_ptr(arg)); | ||
| 1760 | } | ||
| 1761 | #else | ||
| 1762 | #define vduse_dev_compat_ioctl compat_ptr_ioctl | ||
| 1763 | #endif | ||
| 1764 | |||
| 1621 | static int vduse_dev_release(struct inode *inode, struct file *file) | 1765 | static int vduse_dev_release(struct inode *inode, struct file *file) |
| 1622 | { | 1766 | { |
| 1623 | struct vduse_dev *dev = file->private_data; | 1767 | struct vduse_dev *dev = file->private_data; |
| @@ -1637,26 +1781,18 @@ static int vduse_dev_release(struct inode *inode, struct file *file) · 13 unmodified lines | |||
| 1637 | return 0; | 1781 | return 0; |
| 1638 | } | 1782 | } |
| 1639 | 1783 | ||
| 1640 | static struct vduse_dev *vduse_dev_get_from_minor(int minor) | 1784 | static int vduse_dev_open(struct inode *inode, struct file *file) |
| 1641 | { | 1785 | { |
| 1786 | int ret = -EBUSY; | ||
| 1642 | struct vduse_dev *dev; | 1787 | struct vduse_dev *dev; |
| 1643 | 1788 | ||
| 1644 | mutex_lock(&vduse_lock); | 1789 | mutex_lock(&vduse_lock); |
| 1645 | dev = idr_find(&vduse_idr, minor); | 1790 | dev = idr_find(&vduse_idr, iminor(inode)); |
| 1646 | mutex_unlock(&vduse_lock); | 1791 | if (!dev) { |
| 1647 | 1792 | mutex_unlock(&vduse_lock); | |
| 1648 | return dev; | ||
| 1649 | } | ||
| 1650 | |||
| 1651 | static int vduse_dev_open(struct inode *inode, struct file *file) | ||
| 1652 | { | ||
| 1653 | int ret; | ||
| 1654 | struct vduse_dev *dev = vduse_dev_get_from_minor(iminor(inode)); | ||
| 1655 | |||
| 1656 | if (!dev) | ||
| 1657 | return -ENODEV; | 1793 | return -ENODEV; |
| 1794 | } | ||
| 1658 | 1795 | ||
| 1659 | ret = -EBUSY; | ||
| 1660 | mutex_lock(&dev->lock); | 1796 | mutex_lock(&dev->lock); |
| 1661 | if (dev->connected) | 1797 | if (dev->connected) |
| 1662 | goto unlock; | 1798 | goto unlock; |
| @@ -1666,6 +1802,7 @@ static int vduse_dev_open(struct inode *inode, struct file *file) · 3 unmodified lines | |||
| 1666 | file->private_data = dev; | 1802 | file->private_data = dev; |
| 1667 | unlock: | 1803 | unlock: |
| 1668 | mutex_unlock(&dev->lock); | 1804 | mutex_unlock(&dev->lock); |
| 1805 | mutex_unlock(&vduse_lock); | ||
| 1669 | 1806 | ||
| 1670 | return ret; | 1807 | return ret; |
| 1671 | } | 1808 | } |
| @@ -1678,7 +1815,7 @@ static const struct file_operations vduse_dev_fops = { · 6 unmodified lines | |||
| 1678 | .write_iter = vduse_dev_write_iter, | 1815 | .write_iter = vduse_dev_write_iter, |
| 1679 | .poll = vduse_dev_poll, | 1816 | .poll = vduse_dev_poll, |
| 1680 | .unlocked_ioctl = vduse_dev_ioctl, | 1817 | .unlocked_ioctl = vduse_dev_ioctl, |
| 1681 | .compat_ioctl = compat_ptr_ioctl, | 1818 | .compat_ioctl = vduse_dev_compat_ioctl, |
| 1682 | .llseek = noop_llseek, | 1819 | .llseek = noop_llseek, |
| 1683 | }; | 1820 | }; |
| 1684 | 1821 | ||
| @@ -399,13 +399,20 @@ static void vhost_zerocopy_signal_used(struct vhost_net *net, · 398 unmodified lines | |||
| 399 | static void vhost_zerocopy_complete(struct sk_buff *skb, | 399 | static void vhost_zerocopy_complete(struct sk_buff *skb, |
| 400 | struct ubuf_info *ubuf_base, bool success) | 400 | struct ubuf_info *ubuf_base, bool success) |
| 401 | { | 401 | { |
| 402 | struct ubuf_info_msgzc *ubuf = uarg_to_msgzc(ubuf_base); | 402 | struct ubuf_info_msgzc *ubuf; |
| 403 | struct vhost_net_ubuf_ref *ubufs = ubuf->ctx; | 403 | struct vhost_net_ubuf_ref *ubufs; |
| 404 | struct vhost_virtqueue *vq = ubufs->vq; | 404 | struct vhost_virtqueue *vq; |
| 405 | int cnt; | 405 | int cnt; |
| 406 | 406 | ||
| 407 | rcu_read_lock_bh(); | 407 | /* Only the final cloned skb reference completes the vhost descriptor. */ |
| 408 | if (!refcount_dec_and_test(&ubuf_base->refcnt)) | ||
| 409 | return; | ||
| 410 | |||
| 411 | ubuf = uarg_to_msgzc(ubuf_base); | ||
| 412 | ubufs = ubuf->ctx; | ||
| 413 | vq = ubufs->vq; | ||
| 408 | 414 | ||
| 415 | rcu_read_lock_bh(); | ||
| 409 | /* set len to mark this desc buffers done DMA */ | 416 | /* set len to mark this desc buffers done DMA */ |
| 410 | vq->heads[ubuf->desc].len = success ? | 417 | vq->heads[ubuf->desc].len = success ? |
| 411 | VHOST_DMA_DONE_LEN : VHOST_DMA_FAILED_LEN; | 418 | VHOST_DMA_DONE_LEN : VHOST_DMA_FAILED_LEN; |
| @@ -1482,16 +1482,32 @@ static int vhost_vdpa_release(struct inode *inode, struct file *filep) · 1481 unmodified lines | |||
| 1482 | } | 1482 | } |
| 1483 | 1483 | ||
| 1484 | #ifdef CONFIG_MMU | 1484 | #ifdef CONFIG_MMU |
| 1485 | static vm_fault_t vhost_vdpa_fault(struct vm_fault *vmf) | 1485 | static int |
| 1486 | vhost_vdpa_get_vq_notification(struct vhost_vdpa *v, unsigned long index, | ||
| 1487 | struct vdpa_notification_area *notify) | ||
| 1486 | { | 1488 | { |
| 1487 | struct vhost_vdpa *v = vmf->vma->vm_file->private_data; | ||
| 1488 | struct vdpa_device *vdpa = v->vdpa; | 1489 | struct vdpa_device *vdpa = v->vdpa; |
| 1489 | const struct vdpa_config_ops *ops = vdpa->config; | 1490 | const struct vdpa_config_ops *ops = vdpa->config; |
| 1491 | |||
| 1492 | if (index > 65535 || index >= v->nvqs) | ||
| 1493 | return -EINVAL; | ||
| 1494 | |||
| 1495 | index = array_index_nospec(index, v->nvqs); | ||
| 1496 | |||
| 1497 | *notify = ops->get_vq_notification(vdpa, index); | ||
| 1498 | |||
| 1499 | return 0; | ||
| 1500 | } | ||
| 1501 | |||
| 1502 | static vm_fault_t vhost_vdpa_fault(struct vm_fault *vmf) | ||
| 1503 | { | ||
| 1504 | struct vhost_vdpa *v = vmf->vma->vm_file->private_data; | ||
| 1490 | struct vdpa_notification_area notify; | 1505 | struct vdpa_notification_area notify; |
| 1491 | struct vm_area_struct *vma = vmf->vma; | 1506 | struct vm_area_struct *vma = vmf->vma; |
| 1492 | u16 index = vma->vm_pgoff; | 1507 | unsigned long index = vma->vm_pgoff; |
| 1493 | 1508 | ||
| 1494 | notify = ops->get_vq_notification(vdpa, index); | 1509 | if (vhost_vdpa_get_vq_notification(v, index, ¬ify)) |
| 1510 | return VM_FAULT_SIGBUS; | ||
| 1495 | 1511 | ||
| 1496 | return vmf_insert_pfn(vma, vmf->address & PAGE_MASK, PFN_DOWN(notify.addr)); | 1512 | return vmf_insert_pfn(vma, vmf->address & PAGE_MASK, PFN_DOWN(notify.addr)); |
| 1497 | } | 1513 | } |
| @@ -1514,8 +1530,6 @@ static int vhost_vdpa_mmap(struct file *file, struct vm_area_struct *vma) · 16 unmodified lines | |||
| 1514 | return -EINVAL; | 1530 | return -EINVAL; |
| 1515 | if (vma->vm_flags & VM_READ) | 1531 | if (vma->vm_flags & VM_READ) |
| 1516 | return -EINVAL; | 1532 | return -EINVAL; |
| 1517 | if (index > 65535) | ||
| 1518 | return -EINVAL; | ||
| 1519 | if (!ops->get_vq_notification) | 1533 | if (!ops->get_vq_notification) |
| 1520 | return -ENOTSUPP; | 1534 | return -ENOTSUPP; |
| 1521 | 1535 | ||
| @@ -1523,7 +1537,8 @@ static int vhost_vdpa_mmap(struct file *file, struct vm_area_struct *vma) · 1 unmodified line | |||
| 1523 | * support the doorbell which sits on the page boundary and | 1537 | * support the doorbell which sits on the page boundary and |
| 1524 | * does not share the page with other registers. | 1538 | * does not share the page with other registers. |
| 1525 | */ | 1539 | */ |
| 1526 | notify = ops->get_vq_notification(vdpa, index); | 1540 | if (vhost_vdpa_get_vq_notification(v, index, ¬ify)) |
| 1541 | return -EINVAL; | ||
| 1527 | if (notify.addr & (PAGE_SIZE - 1)) | 1542 | if (notify.addr & (PAGE_SIZE - 1)) |
| 1528 | return -EINVAL; | 1543 | return -EINVAL; |
| 1529 | if (vma->vm_end - vma->vm_start != notify.size) | 1544 | if (vma->vm_end - vma->vm_start != notify.size) |
| @@ -1522,6 +1522,7 @@ static void vhost_dev_unlock_vqs(struct vhost_dev *d) · 1521 unmodified lines | |||
| 1522 | static inline int vhost_get_avail_idx(struct vhost_virtqueue *vq) | 1522 | static inline int vhost_get_avail_idx(struct vhost_virtqueue *vq) |
| 1523 | { | 1523 | { |
| 1524 | __virtio16 idx; | 1524 | __virtio16 idx; |
| 1525 | u16 avail_idx; | ||
| 1525 | int r; | 1526 | int r; |
| 1526 | 1527 | ||
| 1527 | r = vhost_get_avail(vq, idx, &vq->avail->idx); | 1528 | r = vhost_get_avail(vq, idx, &vq->avail->idx); |
| @@ -1532,17 +1533,19 @@ static inline int vhost_get_avail_idx(struct vhost_virtqueue *vq) · 4 unmodified lines | |||
| 1532 | } | 1533 | } |
| 1533 | 1534 | ||
| 1534 | /* Check it isn't doing very strange thing with available indexes */ | 1535 | /* Check it isn't doing very strange thing with available indexes */ |
| 1535 | vq->avail_idx = vhost16_to_cpu(vq, idx); | 1536 | avail_idx = vhost16_to_cpu(vq, idx); |
| 1536 | if (unlikely((u16)(vq->avail_idx - vq->last_avail_idx) > vq->num)) { | 1537 | if (unlikely((u16)(avail_idx - vq->last_avail_idx) > vq->num)) { |
| 1537 | vq_err(vq, "Invalid available index change from %u to %u", | 1538 | vq_err(vq, "Invalid available index change from %u to %u", |
| 1538 | vq->last_avail_idx, vq->avail_idx); | 1539 | vq->last_avail_idx, avail_idx); |
| 1539 | return -EINVAL; | 1540 | return -EINVAL; |
| 1540 | } | 1541 | } |
| 1541 | 1542 | ||
| 1542 | /* We're done if there is nothing new */ | 1543 | /* We're done if there is nothing new */ |
| 1543 | if (vq->avail_idx == vq->last_avail_idx) | 1544 | if (avail_idx == vq->avail_idx) |
| 1544 | return 0; | 1545 | return 0; |
| 1545 | 1546 | ||
| 1547 | vq->avail_idx = avail_idx; | ||
| 1548 | |||
| 1546 | /* | 1549 | /* |
| 1547 | * We updated vq->avail_idx so we need a memory barrier between | 1550 | * We updated vq->avail_idx so we need a memory barrier between |
| 1548 | * the index read above and the caller reading avail ring entries. | 1551 | * the index read above and the caller reading avail ring entries. |
| @@ -3321,18 +3324,6 @@ void vhost_set_backend_features(struct vhost_dev *dev, u64 features) · 1772 unmodified lines | |||
| 3321 | } | 3324 | } |
| 3322 | EXPORT_SYMBOL_GPL(vhost_set_backend_features); | 3325 | EXPORT_SYMBOL_GPL(vhost_set_backend_features); |
| 3323 | 3326 | ||
| 3324 | static int __init vhost_init(void) | ||
| 3325 | { | ||
| 3326 | return 0; | ||
| 3327 | } | ||
| 3328 | |||
| 3329 | static void __exit vhost_exit(void) | ||
| 3330 | { | ||
| 3331 | } | ||
| 3332 | |||
| 3333 | module_init(vhost_init); | ||
| 3334 | module_exit(vhost_exit); | ||
| 3335 | |||
| 3336 | MODULE_VERSION("0.0.1"); | 3327 | MODULE_VERSION("0.0.1"); |
| 3337 | MODULE_LICENSE("GPL v2"); | 3328 | MODULE_LICENSE("GPL v2"); |
| 3338 | MODULE_AUTHOR("Michael S. Tsirkin"); | 3329 | MODULE_AUTHOR("Michael S. Tsirkin"); |
| @@ -302,6 +302,22 @@ vhost_transport_send_pkt(struct sk_buff *skb, struct net *net) · 301 unmodified lines | |||
| 302 | return -ENODEV; | 302 | return -ENODEV; |
| 303 | } | 303 | } |
| 304 | 304 | ||
| 305 | /* Fast-fail if the guest hasn't enabled the RX vq yet. Queuing the packet | ||
| 306 | * and making the caller wait is pointless: even if the guest manages to init | ||
| 307 | * within the timeout, it'll immediately reply with RST, because there's no | ||
| 308 | * listener on the port yet. | ||
| 309 | * | ||
| 310 | * vhost_vq_get_backend() without vq->mutex is acceptable here: locking | ||
| 311 | * the mutex would be too expensive in this hot path, and we already have | ||
| 312 | * all the outcomes covered: if the backend becomes NULL right after the check, | ||
| 313 | * vhost_transport_do_send_pkt() will check it under the mutex anyway. | ||
| 314 | */ | ||
| 315 | if (unlikely(!data_race(vhost_vq_get_backend(&vsock->vqs[VSOCK_VQ_RX])))) { | ||
| 316 | rcu_read_unlock(); | ||
| 317 | kfree_skb(skb); | ||
| 318 | return -EHOSTUNREACH; | ||
| 319 | } | ||
| 320 | |||
| 305 | if (virtio_vsock_skb_reply(skb)) | 321 | if (virtio_vsock_skb_reply(skb)) |
| 306 | atomic_inc(&vsock->queued_replies); | 322 | atomic_inc(&vsock->queued_replies); |
| 307 | 323 | ||
| @@ -435,6 +435,14 @@ static void virtio_dev_shutdown(struct device *_d) · 434 unmodified lines | |||
| 435 | dev->config->reset(dev); | 435 | dev->config->reset(dev); |
| 436 | } | 436 | } |
| 437 | 437 | ||
| 438 | static int virtio_dev_num_vf(struct device *dev) | ||
| 439 | { | ||
| 440 | struct virtio_device *vdev = dev_to_virtio(dev); | ||
| 441 | |||
| 442 | return dev_num_vf(vdev->dev.parent); | ||
| 443 | } | ||
| 444 | |||
| 445 | |||
| 438 | static const struct bus_type virtio_bus = { | 446 | static const struct bus_type virtio_bus = { |
| 439 | .name = "virtio", | 447 | .name = "virtio", |
| 440 | .match = virtio_dev_match, | 448 | .match = virtio_dev_match, |
| @@ -444,6 +452,7 @@ static const struct bus_type virtio_bus = { · 3 unmodified lines | |||
| 444 | .remove = virtio_dev_remove, | 452 | .remove = virtio_dev_remove, |
| 445 | .irq_get_affinity = virtio_irq_get_affinity, | 453 | .irq_get_affinity = virtio_irq_get_affinity, |
| 446 | .shutdown = virtio_dev_shutdown, | 454 | .shutdown = virtio_dev_shutdown, |
| 455 | .num_vf = virtio_dev_num_vf, | ||
| 447 | }; | 456 | }; |
| 448 | 457 | ||
| 449 | int __register_virtio_driver(struct virtio_driver *driver, struct module *owner) | 458 | int __register_virtio_driver(struct virtio_driver *driver, struct module *owner) |
| @@ -1075,6 +1075,7 @@ out_del_balloon_wq: · 1074 unmodified lines | |||
| 1075 | out_del_vqs: | 1075 | out_del_vqs: |
| 1076 | vdev->config->del_vqs(vdev); | 1076 | vdev->config->del_vqs(vdev); |
| 1077 | out_free_vb: | 1077 | out_free_vb: |
| 1078 | mutex_destroy(&vb->balloon_lock); | ||
| 1078 | kfree(vb); | 1079 | kfree(vb); |
| 1079 | out: | 1080 | out: |
| 1080 | return err; | 1081 | return err; |
| @@ -1119,6 +1120,7 @@ static void virtballoon_remove(struct virtio_device *vdev) · 38 unmodified lines | |||
| 1119 | } | 1120 | } |
| 1120 | 1121 | ||
| 1121 | remove_common(vb); | 1122 | remove_common(vb); |
| 1123 | mutex_destroy(&vb->balloon_lock); | ||
| 1122 | kfree(vb); | 1124 | kfree(vb); |
| 1123 | } | 1125 | } |
| 1124 | 1126 | ||
| @@ -2975,6 +2975,7 @@ static int virtio_mem_probe(struct virtio_device *vdev) · 2974 unmodified lines | |||
| 2975 | out_del_vq: | 2975 | out_del_vq: |
| 2976 | vdev->config->del_vqs(vdev); | 2976 | vdev->config->del_vqs(vdev); |
| 2977 | out_free_vm: | 2977 | out_free_vm: |
| 2978 | mutex_destroy(&vm->hotplug_mutex); | ||
| 2978 | kfree(vm); | 2979 | kfree(vm); |
| 2979 | vdev->priv = NULL; | 2980 | vdev->priv = NULL; |
| 2980 | 2981 | ||
| @@ -3067,6 +3068,7 @@ static void virtio_mem_remove(struct virtio_device *vdev) · 86 unmodified lines | |||
| 3067 | virtio_reset_device(vdev); | 3068 | virtio_reset_device(vdev); |
| 3068 | vdev->config->del_vqs(vdev); | 3069 | vdev->config->del_vqs(vdev); |
| 3069 | 3070 | ||
| 3071 | mutex_destroy(&vm->hotplug_mutex); | ||
| 3070 | kfree(vm); | 3072 | kfree(vm); |
| 3071 | vdev->priv = NULL; | 3073 | vdev->priv = NULL; |
| 3072 | } | 3074 | } |
| @@ -662,9 +662,7 @@ static void virtio_mmio_remove(struct platform_device *pdev) · 661 unmodified lines | |||
| 662 | 662 | ||
| 663 | #if defined(CONFIG_VIRTIO_MMIO_CMDLINE_DEVICES) | 663 | #if defined(CONFIG_VIRTIO_MMIO_CMDLINE_DEVICES) |
| 664 | 664 | ||
| 665 | static struct device vm_cmdline_parent = { | 665 | static struct device *vm_cmdline_parent; |
| 666 | .init_name = "virtio-mmio-cmdline", | ||
| 667 | }; | ||
| 668 | 666 | ||
| 669 | static int vm_cmdline_parent_registered; | 667 | static int vm_cmdline_parent_registered; |
| 670 | static int vm_cmdline_id; | 668 | static int vm_cmdline_id; |
| @@ -672,7 +670,6 @@ static int vm_cmdline_id; · 1 unmodified line | |||
| 672 | static int vm_cmdline_set(const char *device, | 670 | static int vm_cmdline_set(const char *device, |
| 673 | const struct kernel_param *kp) | 671 | const struct kernel_param *kp) |
| 674 | { | 672 | { |
| 675 | int err; | ||
| 676 | struct resource resources[2] = {}; | 673 | struct resource resources[2] = {}; |
| 677 | char *str; | 674 | char *str; |
| 678 | long long base, size; | 675 | long long base, size; |
| @@ -704,11 +701,10 @@ static int vm_cmdline_set(const char *device, · 25 unmodified lines | |||
| 704 | resources[1].start = resources[1].end = irq; | 701 | resources[1].start = resources[1].end = irq; |
| 705 | 702 | ||
| 706 | if (!vm_cmdline_parent_registered) { | 703 | if (!vm_cmdline_parent_registered) { |
| 707 | err = device_register(&vm_cmdline_parent); | 704 | vm_cmdline_parent = __root_device_register("virtio-mmio-cmdline", NULL); |
| 708 | if (err) { | 705 | if (IS_ERR(vm_cmdline_parent)) { |
| 709 | put_device(&vm_cmdline_parent); | ||
| 710 | pr_err("Failed to register parent device!\n"); | 706 | pr_err("Failed to register parent device!\n"); |
| 711 | return err; | 707 | return PTR_ERR(vm_cmdline_parent); |
| 712 | } | 708 | } |
| 713 | vm_cmdline_parent_registered = 1; | 709 | vm_cmdline_parent_registered = 1; |
| 714 | } | 710 | } |
| @@ -719,7 +715,7 @@ static int vm_cmdline_set(const char *device, · 4 unmodified lines | |||
| 719 | (unsigned long long)resources[0].end, | 715 | (unsigned long long)resources[0].end, |
| 720 | (int)resources[1].start); | 716 | (int)resources[1].start); |
| 721 | 717 | ||
| 722 | pdev = platform_device_register_resndata(&vm_cmdline_parent, | 718 | pdev = platform_device_register_resndata(vm_cmdline_parent, |
| 723 | "virtio-mmio", vm_cmdline_id++, | 719 | "virtio-mmio", vm_cmdline_id++, |
| 724 | resources, ARRAY_SIZE(resources), NULL, 0); | 720 | resources, ARRAY_SIZE(resources), NULL, 0); |
| 725 | 721 | ||
| @@ -743,8 +739,12 @@ static int vm_cmdline_get_device(struct device *dev, void *data) · 17 unmodified lines | |||
| 743 | static int vm_cmdline_get(char *buffer, const struct kernel_param *kp) | 739 | static int vm_cmdline_get(char *buffer, const struct kernel_param *kp) |
| 744 | { | 740 | { |
| 745 | buffer[0] = '\0'; | 741 | buffer[0] = '\0'; |
| 746 | device_for_each_child(&vm_cmdline_parent, buffer, | 742 | |
| 747 | vm_cmdline_get_device); | 743 | if (vm_cmdline_parent_registered) { |
| 744 | device_for_each_child(vm_cmdline_parent, buffer, | ||
| 745 | vm_cmdline_get_device); | ||
| 746 | } | ||
| 747 | |||
| 748 | return strlen(buffer) + 1; | 748 | return strlen(buffer) + 1; |
| 749 | } | 749 | } |
| 750 | 750 | ||
| @@ -766,9 +766,9 @@ static int vm_unregister_cmdline_device(struct device *dev, · 15 unmodified lines | |||
| 766 | static void vm_unregister_cmdline_devices(void) | 766 | static void vm_unregister_cmdline_devices(void) |
| 767 | { | 767 | { |
| 768 | if (vm_cmdline_parent_registered) { | 768 | if (vm_cmdline_parent_registered) { |
| 769 | device_for_each_child(&vm_cmdline_parent, NULL, | 769 | device_for_each_child(vm_cmdline_parent, NULL, |
| 770 | vm_unregister_cmdline_device); | 770 | vm_unregister_cmdline_device); |
| 771 | device_unregister(&vm_cmdline_parent); | 771 | root_device_unregister(vm_cmdline_parent); |
| 772 | vm_cmdline_parent_registered = 0; | 772 | vm_cmdline_parent_registered = 0; |
| 773 | } | 773 | } |
| 774 | } | 774 | } |
| @@ -423,10 +423,11 @@ static int vp_find_vqs_msix(struct virtio_device *vdev, unsigned int nvqs, · 422 unmodified lines | |||
| 423 | vqs[i] = NULL; | 423 | vqs[i] = NULL; |
| 424 | continue; | 424 | continue; |
| 425 | } | 425 | } |
| 426 | vqs[i] = vp_find_one_vq_msix(vdev, queue_idx++, vqi->callback, | 426 | vqs[i] = vp_find_one_vq_msix(vdev, queue_idx, vqi->callback, |
| 427 | vqi->name, vqi->ctx, false, | 427 | vqi->name, vqi->ctx, false, |
| 428 | &allocated_vectors, vector_policy, | 428 | &allocated_vectors, vector_policy, |
| 429 | &vp_dev->vqs[i]); | 429 | &vp_dev->vqs[queue_idx]); |
| 430 | queue_idx++; | ||
| 430 | if (IS_ERR(vqs[i])) { | 431 | if (IS_ERR(vqs[i])) { |
| 431 | err = PTR_ERR(vqs[i]); | 432 | err = PTR_ERR(vqs[i]); |
| 432 | goto error_find; | 433 | goto error_find; |
| @@ -485,9 +486,10 @@ static int vp_find_vqs_intx(struct virtio_device *vdev, unsigned int nvqs, · 52 unmodified lines | |||
| 485 | vqs[i] = NULL; | 486 | vqs[i] = NULL; |
| 486 | continue; | 487 | continue; |
| 487 | } | 488 | } |
| 488 | vqs[i] = vp_setup_vq(vdev, queue_idx++, vqi->callback, | 489 | vqs[i] = vp_setup_vq(vdev, queue_idx, vqi->callback, |
| 489 | vqi->name, vqi->ctx, | 490 | vqi->name, vqi->ctx, |
| 490 | VIRTIO_MSI_NO_VECTOR, &vp_dev->vqs[i]); | 491 | VIRTIO_MSI_NO_VECTOR, &vp_dev->vqs[queue_idx]); |
| 492 | queue_idx++; | ||
| 491 | if (IS_ERR(vqs[i])) { | 493 | if (IS_ERR(vqs[i])) { |
| 492 | err = PTR_ERR(vqs[i]); | 494 | err = PTR_ERR(vqs[i]); |
| 493 | goto out_del_vqs; | 495 | goto out_del_vqs; |
| @@ -272,6 +272,55 @@ struct vring_virtqueue { · 271 unmodified lines | |||
| 272 | #endif | 272 | #endif |
| 273 | }; | 273 | }; |
| 274 | 274 | ||
| 275 | /* | ||
| 276 | * Accessors for device-writable fields in virtio rings. | ||
| 277 | * These fields are concurrently written by the device and read by the driver. | ||
| 278 | * Use READ_ONCE() to prevent compiler optimizations, document the | ||
| 279 | * intentional data race and prevent KCSAN warnings. | ||
| 280 | */ | ||
| 281 | static inline u16 vring_read_split_used_idx(const struct vring_virtqueue *vq) | ||
| 282 | { | ||
| 283 | return virtio16_to_cpu(vq->vq.vdev, | ||
| 284 | READ_ONCE(vq->split.vring.used->idx)); | ||
| 285 | } | ||
| 286 | |||
| 287 | static inline u32 vring_read_split_used_id(const struct vring_virtqueue *vq, | ||
| 288 | u16 idx) | ||
| 289 | { | ||
| 290 | return virtio32_to_cpu(vq->vq.vdev, | ||
| 291 | READ_ONCE(vq->split.vring.used->ring[idx].id)); | ||
| 292 | } | ||
| 293 | |||
| 294 | static inline u32 vring_read_split_used_len(const struct vring_virtqueue *vq, u16 idx) | ||
| 295 | { | ||
| 296 | return virtio32_to_cpu(vq->vq.vdev, | ||
| 297 | READ_ONCE(vq->split.vring.used->ring[idx].len)); | ||
| 298 | } | ||
| 299 | |||
| 300 | static inline u16 vring_read_split_avail_event(const struct vring_virtqueue *vq) | ||
| 301 | { | ||
| 302 | return virtio16_to_cpu(vq->vq.vdev, | ||
| 303 | READ_ONCE(vring_avail_event(&vq->split.vring))); | ||
| 304 | } | ||
| 305 | |||
| 306 | static inline u16 vring_read_packed_desc_flags(const struct vring_virtqueue *vq, | ||
| 307 | u16 idx) | ||
| 308 | { | ||
| 309 | return le16_to_cpu(READ_ONCE(vq->packed.vring.desc[idx].flags)); | ||
| 310 | } | ||
| 311 | |||
| 312 | static inline u16 vring_read_packed_desc_id(const struct vring_virtqueue *vq, | ||
| 313 | u16 idx) | ||
| 314 | { | ||
| 315 | return le16_to_cpu(READ_ONCE(vq->packed.vring.desc[idx].id)); | ||
| 316 | } | ||
| 317 | |||
| 318 | static inline u32 vring_read_packed_desc_len(const struct vring_virtqueue *vq, | ||
| 319 | u16 idx) | ||
| 320 | { | ||
| 321 | return le32_to_cpu(READ_ONCE(vq->packed.vring.desc[idx].len)); | ||
| 322 | } | ||
| 323 | |||
| 275 | static struct vring_desc_extra *vring_alloc_desc_extra(unsigned int num); | 324 | static struct vring_desc_extra *vring_alloc_desc_extra(unsigned int num); |
| 276 | static void vring_free(struct virtqueue *_vq); | 325 | static void vring_free(struct virtqueue *_vq); |
| 277 | 326 | ||
| @@ -809,8 +858,7 @@ static bool virtqueue_kick_prepare_split(struct vring_virtqueue *vq) · 531 unmodified lines | |||
| 809 | LAST_ADD_TIME_INVALID(vq); | 858 | LAST_ADD_TIME_INVALID(vq); |
| 810 | 859 | ||
| 811 | if (vq->event) { | 860 | if (vq->event) { |
| 812 | needs_kick = vring_need_event(virtio16_to_cpu(vq->vq.vdev, | 861 | needs_kick = vring_need_event(vring_read_split_avail_event(vq), |
| 813 | vring_avail_event(&vq->split.vring)), | ||
| 814 | new, old); | 862 | new, old); |
| 815 | } else { | 863 | } else { |
| 816 | needs_kick = !(vq->split.vring.used->flags & | 864 | needs_kick = !(vq->split.vring.used->flags & |
| @@ -897,8 +945,7 @@ static void detach_buf_split(struct vring_virtqueue *vq, unsigned int head, · 80 unmodified lines | |||
| 897 | static bool virtqueue_poll_split(const struct vring_virtqueue *vq, | 945 | static bool virtqueue_poll_split(const struct vring_virtqueue *vq, |
| 898 | unsigned int last_used_idx) | 946 | unsigned int last_used_idx) |
| 899 | { | 947 | { |
| 900 | return (u16)last_used_idx != virtio16_to_cpu(vq->vq.vdev, | 948 | return (u16)last_used_idx != vring_read_split_used_idx(vq); |
| 901 | vq->split.vring.used->idx); | ||
| 902 | } | 949 | } |
| 903 | 950 | ||
| 904 | static bool more_used_split(const struct vring_virtqueue *vq) | 951 | static bool more_used_split(const struct vring_virtqueue *vq) |
| @@ -939,10 +986,8 @@ static void *virtqueue_get_buf_ctx_split(struct vring_virtqueue *vq, · 34 unmodified lines | |||
| 939 | virtio_rmb(vq->weak_barriers); | 986 | virtio_rmb(vq->weak_barriers); |
| 940 | 987 | ||
| 941 | last_used = (vq->last_used_idx & (vq->split.vring.num - 1)); | 988 | last_used = (vq->last_used_idx & (vq->split.vring.num - 1)); |
| 942 | i = virtio32_to_cpu(vq->vq.vdev, | 989 | i = vring_read_split_used_id(vq, last_used); |
| 943 | vq->split.vring.used->ring[last_used].id); | 990 | *len = vring_read_split_used_len(vq, last_used); |
| 944 | *len = virtio32_to_cpu(vq->vq.vdev, | ||
| 945 | vq->split.vring.used->ring[last_used].len); | ||
| 946 | 991 | ||
| 947 | if (unlikely(i >= vq->split.vring.num)) { | 992 | if (unlikely(i >= vq->split.vring.num)) { |
| 948 | BAD_RING(vq, "id %u out of range\n", i); | 993 | BAD_RING(vq, "id %u out of range\n", i); |
| @@ -1003,10 +1048,8 @@ static void *virtqueue_get_buf_ctx_split_in_order(struct vring_virtqueue *vq, · 54 unmodified lines | |||
| 1003 | */ | 1048 | */ |
| 1004 | virtio_rmb(vq->weak_barriers); | 1049 | virtio_rmb(vq->weak_barriers); |
| 1005 | 1050 | ||
| 1006 | vq->batch_last.id = virtio32_to_cpu(vq->vq.vdev, | 1051 | vq->batch_last.id = vring_read_split_used_id(vq, last_used_idx); |
| 1007 | vq->split.vring.used->ring[last_used_idx].id); | 1052 | vq->batch_last.len = vring_read_split_used_len(vq, last_used_idx); |
| 1008 | vq->batch_last.len = virtio32_to_cpu(vq->vq.vdev, | ||
| 1009 | vq->split.vring.used->ring[last_used_idx].len); | ||
| 1010 | } | 1053 | } |
| 1011 | 1054 | ||
| 1012 | if (vq->batch_last.id == last_used) { | 1055 | if (vq->batch_last.id == last_used) { |
| @@ -1112,7 +1155,7 @@ static bool virtqueue_enable_cb_delayed_split(struct vring_virtqueue *vq) · 99 unmodified lines | |||
| 1112 | &vring_used_event(&vq->split.vring), | 1155 | &vring_used_event(&vq->split.vring), |
| 1113 | cpu_to_virtio16(vq->vq.vdev, vq->last_used_idx + bufs)); | 1156 | cpu_to_virtio16(vq->vq.vdev, vq->last_used_idx + bufs)); |
| 1114 | 1157 | ||
| 1115 | if (unlikely((u16)(virtio16_to_cpu(vq->vq.vdev, vq->split.vring.used->idx) | 1158 | if (unlikely((u16)(vring_read_split_used_idx(vq) |
| 1116 | - vq->last_used_idx) > bufs)) { | 1159 | - vq->last_used_idx) > bufs)) { |
| 1117 | END_USE(vq); | 1160 | END_USE(vq); |
| 1118 | return false; | 1161 | return false; |
| @@ -2036,10 +2079,10 @@ static void detach_buf_packed(struct vring_virtqueue *vq, · 917 unmodified lines | |||
| 2036 | static inline bool is_used_desc_packed(const struct vring_virtqueue *vq, | 2079 | static inline bool is_used_desc_packed(const struct vring_virtqueue *vq, |
| 2037 | u16 idx, bool used_wrap_counter) | 2080 | u16 idx, bool used_wrap_counter) |
| 2038 | { | 2081 | { |
| 2039 | bool avail, used; | ||
| 2040 | u16 flags; | 2082 | u16 flags; |
| 2083 | bool avail, used; | ||
| 2041 | 2084 | ||
| 2042 | flags = le16_to_cpu(vq->packed.vring.desc[idx].flags); | 2085 | flags = vring_read_packed_desc_flags(vq, idx); |
| 2043 | avail = !!(flags & (1 << VRING_PACKED_DESC_F_AVAIL)); | 2086 | avail = !!(flags & (1 << VRING_PACKED_DESC_F_AVAIL)); |
| 2044 | used = !!(flags & (1 << VRING_PACKED_DESC_F_USED)); | 2087 | used = !!(flags & (1 << VRING_PACKED_DESC_F_USED)); |
| 2045 | 2088 | ||
| @@ -2186,8 +2229,8 @@ static void *virtqueue_get_buf_ctx_packed(struct vring_virtqueue *vq, · 140 unmodified lines | |||
| 2186 | last_used_idx = READ_ONCE(vq->last_used_idx); | 2229 | last_used_idx = READ_ONCE(vq->last_used_idx); |
| 2187 | used_wrap_counter = packed_used_wrap_counter(last_used_idx); | 2230 | used_wrap_counter = packed_used_wrap_counter(last_used_idx); |
| 2188 | last_used = packed_last_used(last_used_idx); | 2231 | last_used = packed_last_used(last_used_idx); |
| 2189 | id = le16_to_cpu(vq->packed.vring.desc[last_used].id); | 2232 | id = vring_read_packed_desc_id(vq, last_used); |
| 2190 | *len = le32_to_cpu(vq->packed.vring.desc[last_used].len); | 2233 | *len = vring_read_packed_desc_len(vq, last_used); |
| 2191 | 2234 | ||
| 2192 | if (unlikely(id >= num)) { | 2235 | if (unlikely(id >= num)) { |
| 2193 | BAD_RING(vq, "id %u out of range\n", id); | 2236 | BAD_RING(vq, "id %u out of range\n", id); |
| @@ -1257,6 +1257,15 @@ static int viortc_init_vqs(struct viortc_dev *viortc) · 1256 unmodified lines | |||
| 1257 | return 0; | 1257 | return 0; |
| 1258 | } | 1258 | } |
| 1259 | 1259 | ||
| 1260 | static void __viortc_remove(struct viortc_dev *viortc) | ||
| 1261 | { | ||
| 1262 | struct virtio_device *vdev = viortc->vdev; | ||
| 1263 | |||
| 1264 | viortc_clocks_deinit(viortc); | ||
| 1265 | virtio_reset_device(vdev); | ||
| 1266 | vdev->config->del_vqs(vdev); | ||
| 1267 | } | ||
| 1268 | |||
| 1260 | /** | 1269 | /** |
| 1261 | * viortc_probe() - probe a virtio_rtc virtio device | 1270 | * viortc_probe() - probe a virtio_rtc virtio device |
| 1262 | * @vdev: virtio device | 1271 | * @vdev: virtio device |
| @@ -1282,7 +1291,7 @@ static int viortc_probe(struct virtio_device *vdev) · 19 unmodified lines | |||
| 1282 | 1291 | ||
| 1283 | ret = viortc_init_vqs(viortc); | 1292 | ret = viortc_init_vqs(viortc); |
| 1284 | if (ret) | 1293 | if (ret) |
| 1285 | return ret; | 1294 | goto err_reset_vdev; |
| 1286 | 1295 | ||
| 1287 | virtio_device_ready(vdev); | 1296 | virtio_device_ready(vdev); |
| 1288 | 1297 | ||
| @@ -1329,10 +1338,7 @@ static void viortc_remove(struct virtio_device *vdev) · 40 unmodified lines | |||
| 1329 | { | 1338 | { |
| 1330 | struct viortc_dev *viortc = vdev->priv; | 1339 | struct viortc_dev *viortc = vdev->priv; |
| 1331 | 1340 | ||
| 1332 | viortc_clocks_deinit(viortc); | 1341 | __viortc_remove(viortc); |
| 1333 | |||
| 1334 | virtio_reset_device(vdev); | ||
| 1335 | vdev->config->del_vqs(vdev); | ||
| 1336 | } | 1342 | } |
| 1337 | 1343 | ||
| 1338 | static int viortc_freeze(struct virtio_device *dev) | 1344 | static int viortc_freeze(struct virtio_device *dev) |
| @@ -1353,9 +1359,11 @@ static int viortc_restore(struct virtio_device *dev) · 14 unmodified lines | |||
| 1353 | bool notify = false; | 1359 | bool notify = false; |
| 1354 | int ret; | 1360 | int ret; |
| 1355 | 1361 | ||
| 1362 | dev->config->del_vqs(dev); | ||
| 1363 | |||
| 1356 | ret = viortc_init_vqs(viortc); | 1364 | ret = viortc_init_vqs(viortc); |
| 1357 | if (ret) | 1365 | if (ret) |
| 1358 | return ret; | 1366 | goto err_remove; |
| 1359 | 1367 | ||
| 1360 | alarm_viortc_vq = &viortc->vqs[VIORTC_ALARMQ]; | 1368 | alarm_viortc_vq = &viortc->vqs[VIORTC_ALARMQ]; |
| 1361 | alarm_vq = alarm_viortc_vq->vq; | 1369 | alarm_vq = alarm_viortc_vq->vq; |
| @@ -1364,7 +1372,7 @@ static int viortc_restore(struct virtio_device *dev) · 2 unmodified lines | |||
| 1364 | ret = viortc_populate_vq(viortc, alarm_viortc_vq, | 1372 | ret = viortc_populate_vq(viortc, alarm_viortc_vq, |
| 1365 | VIORTC_ALARMQ_BUF_CAP, false); | 1373 | VIORTC_ALARMQ_BUF_CAP, false); |
| 1366 | if (ret) | 1374 | if (ret) |
| 1367 | return ret; | 1375 | goto err_remove; |
| 1368 | 1376 | ||
| 1369 | notify = virtqueue_kick_prepare(alarm_vq); | 1377 | notify = virtqueue_kick_prepare(alarm_vq); |
| 1370 | } | 1378 | } |
| @@ -1372,8 +1380,12 @@ static int viortc_restore(struct virtio_device *dev) · 1 unmodified line | |||
| 1372 | virtio_device_ready(dev); | 1380 | virtio_device_ready(dev); |
| 1373 | 1381 | ||
| 1374 | if (notify && !virtqueue_notify(alarm_vq)) | 1382 | if (notify && !virtqueue_notify(alarm_vq)) |
| 1375 | ret = -EIO; | 1383 | return -EIO; |
| 1384 | |||
| 1385 | return 0; | ||
| 1376 | 1386 | ||
| 1387 | err_remove: | ||
| 1388 | __viortc_remove(viortc); | ||
| 1377 | return ret; | 1389 | return ret; |
| 1378 | } | 1390 | } |
| 1379 | 1391 | ||
| @@ -157,11 +157,13 @@ struct virtio_admin_cmd { · 156 unmodified lines | |||
| 157 | * @id: the device type identification (used to match it with a driver). | 157 | * @id: the device type identification (used to match it with a driver). |
| 158 | * @config: the configuration ops for this device. | 158 | * @config: the configuration ops for this device. |
| 159 | * @vringh_config: configuration ops for host vrings. | 159 | * @vringh_config: configuration ops for host vrings. |
| 160 | * @map: the map operations for mapping virtio device memory. | ||
| 160 | * @vqs: the list of virtqueues for this device. | 161 | * @vqs: the list of virtqueues for this device. |
| 161 | * @features: the 64 lower features supported by both driver and device. | 162 | * @features: the 64 lower features supported by both driver and device. |
| 162 | * @features_array: the full features space supported by both driver and | 163 | * @features_array: the full features space supported by both driver and |
| 163 | * device. | 164 | * device. |
| 164 | * @priv: private pointer for the driver's use. | 165 | * @priv: private pointer for the driver's use. |
| 166 | * @vmap: the map container with transport- or device-specific metadata. | ||
| 165 | * @debugfs_dir: debugfs directory entry. | 167 | * @debugfs_dir: debugfs directory entry. |
| 166 | * @debugfs_filter_features: features to be filtered set by debugfs. | 168 | * @debugfs_filter_features: features to be filtered set by debugfs. |
| 167 | */ | 169 | */ |
| @@ -0,0 +1,78 @@ | |||
| 1 | /* SPDX-License-Identifier: BSD-3-Clause */ | ||
| 2 | /* | ||
| 3 | * Copyright (C) 2021-2023 OpenSynergy GmbH | ||
| 4 | * Copyright Red Hat, Inc. 2025 | ||
| 5 | */ | ||
| 6 | #ifndef _LINUX_VIRTIO_VIRTIO_CAN_H | ||
| 7 | #define _LINUX_VIRTIO_VIRTIO_CAN_H | ||
| 8 | |||
| 9 | #include <linux/types.h> | ||
| 10 | #include <linux/virtio_types.h> | ||
| 11 | #include <linux/virtio_ids.h> | ||
| 12 | #include <linux/virtio_config.h> | ||
| 13 | |||
| 14 | /* Feature bit numbers */ | ||
| 15 | #define VIRTIO_CAN_F_CAN_CLASSIC 0 | ||
| 16 | #define VIRTIO_CAN_F_CAN_FD 1 | ||
| 17 | #define VIRTIO_CAN_F_RTR_FRAMES 2 | ||
| 18 | #define VIRTIO_CAN_F_LATE_TX_ACK 3 | ||
| 19 | |||
| 20 | /* CAN Result Types */ | ||
| 21 | #define VIRTIO_CAN_RESULT_OK 0 | ||
| 22 | #define VIRTIO_CAN_RESULT_NOT_OK 1 | ||
| 23 | |||
| 24 | /* CAN flags to determine type of CAN Id */ | ||
| 25 | #define VIRTIO_CAN_FLAGS_EXTENDED 0x8000 | ||
| 26 | #define VIRTIO_CAN_FLAGS_FD 0x4000 | ||
| 27 | #define VIRTIO_CAN_FLAGS_RTR 0x2000 | ||
| 28 | |||
| 29 | #define VIRTIO_CAN_MAX_DLEN 64 /* this is like CANFD_MAX_DLEN */ | ||
| 30 | |||
| 31 | struct virtio_can_config { | ||
| 32 | #define VIRTIO_CAN_S_CTRL_BUSOFF (1u << 0) /* Controller BusOff */ | ||
| 33 | /* CAN controller status */ | ||
| 34 | __le16 status; | ||
| 35 | }; | ||
| 36 | |||
| 37 | /* TX queue message types */ | ||
| 38 | struct virtio_can_tx_out { | ||
| 39 | #define VIRTIO_CAN_TX 0x0001 | ||
| 40 | __le16 msg_type; | ||
| 41 | __le16 length; /* 0..8 CC, 0..64 CAN-FD, 0..2048 CAN-XL, 12 bits */ | ||
| 42 | __u8 reserved_classic_dlc; /* If CAN classic length = 8 then DLC can be 8..15 */ | ||
| 43 | __u8 padding; | ||
| 44 | __le16 reserved_xl_priority; /* May be needed for CAN XL priority */ | ||
| 45 | __le32 flags; | ||
| 46 | __le32 can_id; | ||
| 47 | __u8 sdu[] __counted_by_le(length); | ||
| 48 | }; | ||
| 49 | |||
| 50 | struct virtio_can_tx_in { | ||
| 51 | __u8 result; | ||
| 52 | }; | ||
| 53 | |||
| 54 | /* RX queue message types */ | ||
| 55 | struct virtio_can_rx { | ||
| 56 | #define VIRTIO_CAN_RX 0x0101 | ||
| 57 | __le16 msg_type; | ||
| 58 | __le16 length; /* 0..8 CC, 0..64 CAN-FD, 0..2048 CAN-XL, 12 bits */ | ||
| 59 | __u8 reserved_classic_dlc; /* If CAN classic length = 8 then DLC can be 8..15 */ | ||
| 60 | __u8 padding; | ||
| 61 | __le16 reserved_xl_priority; /* May be needed for CAN XL priority */ | ||
| 62 | __le32 flags; | ||
| 63 | __le32 can_id; | ||
| 64 | __u8 sdu[] __counted_by_le(length); | ||
| 65 | }; | ||
| 66 | |||
| 67 | /* Control queue message types */ | ||
| 68 | struct virtio_can_control_out { | ||
| 69 | #define VIRTIO_CAN_SET_CTRL_MODE_START 0x0201 | ||
| 70 | #define VIRTIO_CAN_SET_CTRL_MODE_STOP 0x0202 | ||
| 71 | __le16 msg_type; | ||
| 72 | }; | ||
| 73 | |||
| 74 | struct virtio_can_control_in { | ||
| 75 | __u8 result; | ||
| 76 | }; | ||
| 77 | |||
| 78 | #endif /* #ifndef _LINUX_VIRTIO_VIRTIO_CAN_H */ | ||
| @@ -44,7 +44,7 @@ · 43 unmodified lines | |||
| 44 | #define VIRTIO_CONSOLE_BAD_ID (~(__u32)0) | 44 | #define VIRTIO_CONSOLE_BAD_ID (~(__u32)0) |
| 45 | 45 | ||
| 46 | struct virtio_console_config { | 46 | struct virtio_console_config { |
| 47 | /* colums of the screens */ | 47 | /* columns of the screens */ |
| 48 | __virtio16 cols; | 48 | __virtio16 cols; |
| 49 | /* rows of the screens */ | 49 | /* rows of the screens */ |
| 50 | __virtio16 rows; | 50 | __virtio16 rows; |
| @@ -123,7 +123,6 @@ struct vhost_task *vhost_task_create(bool (*fn)(void *), · 122 unmodified lines | |||
| 123 | struct kernel_clone_args args = { | 123 | struct kernel_clone_args args = { |
| 124 | .flags = CLONE_FS | CLONE_UNTRACED | CLONE_VM | | 124 | .flags = CLONE_FS | CLONE_UNTRACED | CLONE_VM | |
| 125 | CLONE_THREAD | CLONE_SIGHAND, | 125 | CLONE_THREAD | CLONE_SIGHAND, |
| 126 | .exit_signal = 0, | ||
| 127 | .fn = vhost_task_fn, | 126 | .fn = vhost_task_fn, |
| 128 | .name = name, | 127 | .name = name, |
| 129 | .user_worker = 1, | 128 | .user_worker = 1, |
| @@ -60,4 +60,6 @@ enum dma_data_direction { · 59 unmodified lines | |||
| 60 | */ | 60 | */ |
| 61 | #define DMA_MAPPING_ERROR (~(dma_addr_t)0) | 61 | #define DMA_MAPPING_ERROR (~(dma_addr_t)0) |
| 62 | 62 | ||
| 63 | #define DMA_ATTR_CPU_CACHE_CLEAN (1UL << 11) | ||
| 64 | |||
| 63 | #endif | 65 | #endif |
| @@ -1,6 +1,7 @@ | |||
| 1 | /* SPDX-License-Identifier: GPL-2.0 */ | 1 | /* SPDX-License-Identifier: GPL-2.0 */ |
| 2 | #ifndef ERR_H | 2 | #ifndef ERR_H |
| 3 | #define ERR_H | 3 | #define ERR_H |
| 4 | #include <linux/kernel.h> | ||
| 4 | #define MAX_ERRNO 4095 | 5 | #define MAX_ERRNO 4095 |
| 5 | 6 | ||
| 6 | #define IS_ERR_VALUE(x) unlikely((x) >= (unsigned long)-MAX_ERRNO) | 7 | #define IS_ERR_VALUE(x) unlikely((x) >= (unsigned long)-MAX_ERRNO) |
| @@ -65,6 +65,12 @@ static inline void *kmalloc_array(unsigned n, size_t s, gfp_t gfp) · 64 unmodified lines | |||
| 65 | return kmalloc(n * s, gfp); | 65 | return kmalloc(n * s, gfp); |
| 66 | } | 66 | } |
| 67 | 67 | ||
| 68 | #define kmalloc_obj(VAR_OR_TYPE, ...) \ | ||
| 69 | ((typeof(VAR_OR_TYPE) *)kmalloc(sizeof(typeof(VAR_OR_TYPE)), 0)) | ||
| 70 | |||
| 71 | #define kmalloc_objs(VAR_OR_TYPE, COUNT, ...) \ | ||
| 72 | ((typeof(VAR_OR_TYPE) *)kmalloc(sizeof(typeof(VAR_OR_TYPE)) * (COUNT), 0)) | ||
| 73 | |||
| 68 | static inline void *kzalloc(size_t s, gfp_t gfp) | 74 | static inline void *kzalloc(size_t s, gfp_t gfp) |
| 69 | { | 75 | { |
| 70 | void *p = kmalloc(s, gfp); | 76 | void *p = kmalloc(s, gfp); |
| @@ -159,7 +159,12 @@ static int parallel_test(u64 features, · 158 unmodified lines | |||
| 159 | 159 | ||
| 160 | /* Parent and child use separate addresses, to check our mapping logic! */ | 160 | /* Parent and child use separate addresses, to check our mapping logic! */ |
| 161 | host_map = mmap(NULL, mapsize, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); | 161 | host_map = mmap(NULL, mapsize, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); |
| 162 | if (host_map == MAP_FAILED) | ||
| 163 | err(1, "mmap host_map"); | ||
| 164 | |||
| 162 | guest_map = mmap(NULL, mapsize, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); | 165 | guest_map = mmap(NULL, mapsize, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); |
| 166 | if (guest_map == MAP_FAILED) | ||
| 167 | err(1, "mmap guest_map"); | ||
| 163 | 168 | ||
| 164 | pipe_ret = pipe(to_guest); | 169 | pipe_ret = pipe(to_guest); |
| 165 | assert(!pipe_ret); | 170 | assert(!pipe_ret); |