1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * Copyright (C) 2018, Tuomas Tynkkynen <tuomas.tynkkynen@iki.fi> 4 * Copyright (C) 2018, Bin Meng <bmeng.cn@gmail.com> 5 */ 6 7 #include <common.h> 8 #include <dm.h> 9 #include <net.h> 10 #include <virtio_types.h> 11 #include <virtio.h> 12 #include <virtio_ring.h> 13 #include "virtio_net.h" 14 15 /* Amount of buffers to keep in the RX virtqueue */ 16 #define VIRTIO_NET_NUM_RX_BUFS 32 17 18 /* 19 * This value comes from the VirtIO spec: 1500 for maximum packet size, 20 * 14 for the Ethernet header, 12 for virtio_net_hdr. In total 1526 bytes. 21 */ 22 #define VIRTIO_NET_RX_BUF_SIZE 1526 23 24 struct virtio_net_priv { 25 union { 26 struct virtqueue *vqs[2]; 27 struct { 28 struct virtqueue *rx_vq; 29 struct virtqueue *tx_vq; 30 }; 31 }; 32 33 char rx_buff[VIRTIO_NET_NUM_RX_BUFS][VIRTIO_NET_RX_BUF_SIZE]; 34 bool rx_running; 35 int net_hdr_len; 36 }; 37 38 /* 39 * For simplicity, the driver only negotiates the VIRTIO_NET_F_MAC feature. 40 * For the VIRTIO_NET_F_STATUS feature, we don't negotiate it, hence per spec 41 * we should assume the link is always active. 42 */ 43 static const u32 feature[] = { 44 VIRTIO_NET_F_MAC 45 }; 46 47 static const u32 feature_legacy[] = { 48 VIRTIO_NET_F_MAC 49 }; 50 51 static int virtio_net_start(struct udevice *dev) 52 { 53 struct virtio_net_priv *priv = dev_get_priv(dev); 54 struct virtio_sg sg; 55 struct virtio_sg *sgs[] = { &sg }; 56 int i; 57 58 if (!priv->rx_running) { 59 /* receive buffer length is always 1526 */ 60 sg.length = VIRTIO_NET_RX_BUF_SIZE; 61 62 /* setup the receive buffer address */ 63 for (i = 0; i < VIRTIO_NET_NUM_RX_BUFS; i++) { 64 sg.addr = priv->rx_buff[i]; 65 virtqueue_add(priv->rx_vq, sgs, 0, 1); 66 } 67 68 virtqueue_kick(priv->rx_vq); 69 70 /* setup the receive queue only once */ 71 priv->rx_running = true; 72 } 73 74 return 0; 75 } 76 77 static int virtio_net_send(struct udevice *dev, void *packet, int length) 78 { 79 struct virtio_net_priv *priv = dev_get_priv(dev); 80 struct virtio_net_hdr hdr; 81 struct virtio_net_hdr_v1 hdr_v1; 82 struct virtio_sg hdr_sg; 83 struct virtio_sg data_sg = { packet, length }; 84 struct virtio_sg *sgs[] = { &hdr_sg, &data_sg }; 85 int ret; 86 87 if (priv->net_hdr_len == sizeof(struct virtio_net_hdr)) 88 hdr_sg.addr = &hdr; 89 else 90 hdr_sg.addr = &hdr_v1; 91 hdr_sg.length = priv->net_hdr_len; 92 93 memset(hdr_sg.addr, 0, priv->net_hdr_len); 94 95 ret = virtqueue_add(priv->tx_vq, sgs, 2, 0); 96 if (ret) 97 return ret; 98 99 virtqueue_kick(priv->tx_vq); 100 101 while (1) { 102 if (virtqueue_get_buf(priv->tx_vq, NULL)) 103 break; 104 } 105 106 return 0; 107 } 108 109 static int virtio_net_recv(struct udevice *dev, int flags, uchar **packetp) 110 { 111 struct virtio_net_priv *priv = dev_get_priv(dev); 112 unsigned int len; 113 void *buf; 114 115 buf = virtqueue_get_buf(priv->rx_vq, &len); 116 if (!buf) 117 return -EAGAIN; 118 119 *packetp = buf + priv->net_hdr_len; 120 return len - priv->net_hdr_len; 121 } 122 123 static int virtio_net_free_pkt(struct udevice *dev, uchar *packet, int length) 124 { 125 struct virtio_net_priv *priv = dev_get_priv(dev); 126 void *buf = packet - priv->net_hdr_len; 127 struct virtio_sg sg = { buf, VIRTIO_NET_RX_BUF_SIZE }; 128 struct virtio_sg *sgs[] = { &sg }; 129 130 /* Put the buffer back to the rx ring */ 131 virtqueue_add(priv->rx_vq, sgs, 0, 1); 132 133 return 0; 134 } 135 136 static void virtio_net_stop(struct udevice *dev) 137 { 138 /* 139 * There is no way to stop the queue from running, unless we issue 140 * a reset to the virtio device, and re-do the queue initialization 141 * from the beginning. 142 */ 143 } 144 145 static int virtio_net_write_hwaddr(struct udevice *dev) 146 { 147 struct virtio_dev_priv *uc_priv = dev_get_uclass_priv(dev->parent); 148 struct eth_pdata *pdata = dev_get_platdata(dev); 149 int i; 150 151 /* 152 * v1.0 compliant device's MAC address is set through control channel, 153 * which we don't support for now. 154 */ 155 if (!uc_priv->legacy) 156 return -ENOSYS; 157 158 for (i = 0; i < sizeof(pdata->enetaddr); i++) { 159 virtio_cwrite8(dev, 160 offsetof(struct virtio_net_config, mac) + i, 161 pdata->enetaddr[i]); 162 } 163 164 return 0; 165 } 166 167 static int virtio_net_read_rom_hwaddr(struct udevice *dev) 168 { 169 struct eth_pdata *pdata = dev_get_platdata(dev); 170 171 if (!pdata) 172 return -ENOSYS; 173 174 if (virtio_has_feature(dev, VIRTIO_NET_F_MAC)) { 175 virtio_cread_bytes(dev, 176 offsetof(struct virtio_net_config, mac), 177 pdata->enetaddr, sizeof(pdata->enetaddr)); 178 } 179 180 return 0; 181 } 182 183 static int virtio_net_bind(struct udevice *dev) 184 { 185 struct virtio_dev_priv *uc_priv = dev_get_uclass_priv(dev->parent); 186 187 /* Indicate what driver features we support */ 188 virtio_driver_features_init(uc_priv, feature, ARRAY_SIZE(feature), 189 feature_legacy, ARRAY_SIZE(feature_legacy)); 190 191 return 0; 192 } 193 194 static int virtio_net_probe(struct udevice *dev) 195 { 196 struct virtio_net_priv *priv = dev_get_priv(dev); 197 struct virtio_dev_priv *uc_priv = dev_get_uclass_priv(dev->parent); 198 int ret; 199 200 ret = virtio_find_vqs(dev, 2, priv->vqs); 201 if (ret < 0) 202 return ret; 203 204 /* 205 * For v1.0 compliant device, it always assumes the member 206 * 'num_buffers' exists in the struct virtio_net_hdr while 207 * the legacy driver only presented 'num_buffers' when 208 * VIRTIO_NET_F_MRG_RXBUF was negotiated. Without that feature 209 * the structure was 2 bytes shorter. 210 */ 211 if (uc_priv->legacy) 212 priv->net_hdr_len = sizeof(struct virtio_net_hdr); 213 else 214 priv->net_hdr_len = sizeof(struct virtio_net_hdr_v1); 215 216 return 0; 217 } 218 219 static const struct eth_ops virtio_net_ops = { 220 .start = virtio_net_start, 221 .send = virtio_net_send, 222 .recv = virtio_net_recv, 223 .free_pkt = virtio_net_free_pkt, 224 .stop = virtio_net_stop, 225 .write_hwaddr = virtio_net_write_hwaddr, 226 .read_rom_hwaddr = virtio_net_read_rom_hwaddr, 227 }; 228 229 U_BOOT_DRIVER(virtio_net) = { 230 .name = VIRTIO_NET_DRV_NAME, 231 .id = UCLASS_ETH, 232 .bind = virtio_net_bind, 233 .probe = virtio_net_probe, 234 .remove = virtio_reset, 235 .ops = &virtio_net_ops, 236 .priv_auto_alloc_size = sizeof(struct virtio_net_priv), 237 .platdata_auto_alloc_size = sizeof(struct eth_pdata), 238 .flags = DM_FLAG_ACTIVE_DMA, 239 }; 240