aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTuomas Tynkkynen2018-10-15 04:21:03 -0500
committerSimon Glass2018-11-14 11:16:27 -0600
commitf371ad3064699f460711523db5e8177a0fc7b22e (patch)
treec6c8578c87e420023bd18a9d88a446dc97ad6f8a /drivers
parentfdc4aca89ecb928d893c8bca4d0de08ebd07686a (diff)
downloadu-boot-f371ad3064699f460711523db5e8177a0fc7b22e.tar.gz
u-boot-f371ad3064699f460711523db5e8177a0fc7b22e.tar.xz
u-boot-f371ad3064699f460711523db5e8177a0fc7b22e.zip
virtio: Add net driver support
This adds virtio net device driver support. Signed-off-by: Tuomas Tynkkynen <tuomas.tynkkynen@iki.fi> Signed-off-by: Bin Meng <bmeng.cn@gmail.com> Reviewed-by: Simon Glass <sjg@chromium.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/virtio/Kconfig7
-rw-r--r--drivers/virtio/Makefile1
-rw-r--r--drivers/virtio/virtio_net.c218
-rw-r--r--drivers/virtio/virtio_net.h268
4 files changed, 494 insertions, 0 deletions
diff --git a/drivers/virtio/Kconfig b/drivers/virtio/Kconfig
index 4f9a11b6ef..e20dd69395 100644
--- a/drivers/virtio/Kconfig
+++ b/drivers/virtio/Kconfig
@@ -29,4 +29,11 @@ config VIRTIO_MMIO
29 This driver provides support for memory mapped virtio 29 This driver provides support for memory mapped virtio
30 platform device driver. 30 platform device driver.
31 31
32config VIRTIO_NET
33 bool "virtio net driver"
34 depends on VIRTIO
35 help
36 This is the virtual net driver for virtio. It can be used with
37 QEMU based targets.
38
32endmenu 39endmenu
diff --git a/drivers/virtio/Makefile b/drivers/virtio/Makefile
index 2e487854a2..b7764f161e 100644
--- a/drivers/virtio/Makefile
+++ b/drivers/virtio/Makefile
@@ -5,3 +5,4 @@
5 5
6obj-y += virtio-uclass.o virtio_ring.o 6obj-y += virtio-uclass.o virtio_ring.o
7obj-$(CONFIG_VIRTIO_MMIO) += virtio_mmio.o 7obj-$(CONFIG_VIRTIO_MMIO) += virtio_mmio.o
8obj-$(CONFIG_VIRTIO_NET) += virtio_net.o
diff --git a/drivers/virtio/virtio_net.c b/drivers/virtio/virtio_net.c
new file mode 100644
index 0000000000..5bb6a9fcc9
--- /dev/null
+++ b/drivers/virtio/virtio_net.c
@@ -0,0 +1,218 @@
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
24struct 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};
36
37/*
38 * For simplicity, the driver only negotiates the VIRTIO_NET_F_MAC feature.
39 * For the VIRTIO_NET_F_STATUS feature, we don't negotiate it, hence per spec
40 * we should assume the link is always active.
41 */
42static const u32 feature[] = {
43 VIRTIO_NET_F_MAC
44};
45
46static const u32 feature_legacy[] = {
47 VIRTIO_NET_F_MAC
48};
49
50static int virtio_net_start(struct udevice *dev)
51{
52 struct virtio_net_priv *priv = dev_get_priv(dev);
53 struct virtio_sg sg;
54 struct virtio_sg *sgs[] = { &sg };
55 int i;
56
57 if (!priv->rx_running) {
58 /* receive buffer length is always 1526 */
59 sg.length = VIRTIO_NET_RX_BUF_SIZE;
60
61 /* setup the receive buffer address */
62 for (i = 0; i < VIRTIO_NET_NUM_RX_BUFS; i++) {
63 sg.addr = priv->rx_buff[i];
64 virtqueue_add(priv->rx_vq, sgs, 0, 1);
65 }
66
67 virtqueue_kick(priv->rx_vq);
68
69 /* setup the receive queue only once */
70 priv->rx_running = true;
71 }
72
73 return 0;
74}
75
76static int virtio_net_send(struct udevice *dev, void *packet, int length)
77{
78 struct virtio_net_priv *priv = dev_get_priv(dev);
79 struct virtio_net_hdr hdr;
80 struct virtio_sg hdr_sg = { &hdr, sizeof(hdr) };
81 struct virtio_sg data_sg = { packet, length };
82 struct virtio_sg *sgs[] = { &hdr_sg, &data_sg };
83 int ret;
84
85 memset(&hdr, 0, sizeof(struct virtio_net_hdr));
86
87 ret = virtqueue_add(priv->tx_vq, sgs, 2, 0);
88 if (ret)
89 return ret;
90
91 virtqueue_kick(priv->tx_vq);
92
93 while (1) {
94 if (virtqueue_get_buf(priv->tx_vq, NULL))
95 break;
96 }
97
98 return 0;
99}
100
101static int virtio_net_recv(struct udevice *dev, int flags, uchar **packetp)
102{
103 struct virtio_net_priv *priv = dev_get_priv(dev);
104 unsigned int len;
105 void *buf;
106
107 buf = virtqueue_get_buf(priv->rx_vq, &len);
108 if (!buf)
109 return -EAGAIN;
110
111 *packetp = buf + sizeof(struct virtio_net_hdr);
112 return len - sizeof(struct virtio_net_hdr);
113}
114
115static int virtio_net_free_pkt(struct udevice *dev, uchar *packet, int length)
116{
117 struct virtio_net_priv *priv = dev_get_priv(dev);
118 void *buf = packet - sizeof(struct virtio_net_hdr);
119 struct virtio_sg sg = { buf, VIRTIO_NET_RX_BUF_SIZE };
120 struct virtio_sg *sgs[] = { &sg };
121
122 /* Put the buffer back to the rx ring */
123 virtqueue_add(priv->rx_vq, sgs, 0, 1);
124
125 return 0;
126}
127
128static void virtio_net_stop(struct udevice *dev)
129{
130 /*
131 * There is no way to stop the queue from running, unless we issue
132 * a reset to the virtio device, and re-do the queue initialization
133 * from the beginning.
134 */
135}
136
137static int virtio_net_write_hwaddr(struct udevice *dev)
138{
139 struct virtio_dev_priv *uc_priv = dev_get_uclass_priv(dev->parent);
140 struct eth_pdata *pdata = dev_get_platdata(dev);
141 int i;
142
143 /*
144 * v1.0 compliant device's MAC address is set through control channel,
145 * which we don't support for now.
146 */
147 if (!uc_priv->legacy)
148 return -ENOSYS;
149
150 for (i = 0; i < sizeof(pdata->enetaddr); i++) {
151 virtio_cwrite8(dev,
152 offsetof(struct virtio_net_config, mac) + i,
153 pdata->enetaddr[i]);
154 }
155
156 return 0;
157}
158
159static int virtio_net_read_rom_hwaddr(struct udevice *dev)
160{
161 struct eth_pdata *pdata = dev_get_platdata(dev);
162
163 if (!pdata)
164 return -ENOSYS;
165
166 if (virtio_has_feature(dev, VIRTIO_NET_F_MAC)) {
167 virtio_cread_bytes(dev,
168 offsetof(struct virtio_net_config, mac),
169 pdata->enetaddr, sizeof(pdata->enetaddr));
170 }
171
172 return 0;
173}
174
175static int virtio_net_bind(struct udevice *dev)
176{
177 struct virtio_dev_priv *uc_priv = dev_get_uclass_priv(dev->parent);
178
179 /* Indicate what driver features we support */
180 virtio_driver_features_init(uc_priv, feature, ARRAY_SIZE(feature),
181 feature_legacy, ARRAY_SIZE(feature_legacy));
182
183 return 0;
184}
185
186static int virtio_net_probe(struct udevice *dev)
187{
188 struct virtio_net_priv *priv = dev_get_priv(dev);
189 int ret;
190
191 ret = virtio_find_vqs(dev, 2, priv->vqs);
192 if (ret < 0)
193 return ret;
194
195 return 0;
196}
197
198static const struct eth_ops virtio_net_ops = {
199 .start = virtio_net_start,
200 .send = virtio_net_send,
201 .recv = virtio_net_recv,
202 .free_pkt = virtio_net_free_pkt,
203 .stop = virtio_net_stop,
204 .write_hwaddr = virtio_net_write_hwaddr,
205 .read_rom_hwaddr = virtio_net_read_rom_hwaddr,
206};
207
208U_BOOT_DRIVER(virtio_net) = {
209 .name = VIRTIO_NET_DRV_NAME,
210 .id = UCLASS_ETH,
211 .bind = virtio_net_bind,
212 .probe = virtio_net_probe,
213 .remove = virtio_reset,
214 .ops = &virtio_net_ops,
215 .priv_auto_alloc_size = sizeof(struct virtio_net_priv),
216 .platdata_auto_alloc_size = sizeof(struct eth_pdata),
217 .flags = DM_FLAG_ACTIVE_DMA,
218};
diff --git a/drivers/virtio/virtio_net.h b/drivers/virtio/virtio_net.h
new file mode 100644
index 0000000000..c92bae5269
--- /dev/null
+++ b/drivers/virtio/virtio_net.h
@@ -0,0 +1,268 @@
1/* SPDX-License-Identifier: BSD-3-Clause */
2/*
3 * Copyright (C) 2018, Tuomas Tynkkynen <tuomas.tynkkynen@iki.fi>
4 * Copyright (C) 2018, Bin Meng <bmeng.cn@gmail.com>
5 *
6 * From Linux kernel include/uapi/linux/virtio_net.h
7 */
8
9#ifndef _LINUX_VIRTIO_NET_H
10#define _LINUX_VIRTIO_NET_H
11
12/* TODO: needs to be removed! */
13#define ETH_ALEN 6
14
15/* The feature bitmap for virtio net */
16
17/* Host handles pkts w/ partial csum */
18#define VIRTIO_NET_F_CSUM 0
19/* Guest handles pkts w/ partial csum */
20#define VIRTIO_NET_F_GUEST_CSUM 1
21/* Dynamic offload configuration */
22#define VIRTIO_NET_F_CTRL_GUEST_OFFLOADS 2
23/* Initial MTU advice */
24#define VIRTIO_NET_F_MTU 3
25/* Host has given MAC address */
26#define VIRTIO_NET_F_MAC 5
27/* Guest can handle TSOv4 in */
28#define VIRTIO_NET_F_GUEST_TSO4 7
29/* Guest can handle TSOv6 in */
30#define VIRTIO_NET_F_GUEST_TSO6 8
31/* Guest can handle TSO[6] w/ ECN in */
32#define VIRTIO_NET_F_GUEST_ECN 9
33/* Guest can handle UFO in */
34#define VIRTIO_NET_F_GUEST_UFO 10
35/* Host can handle TSOv4 in */
36#define VIRTIO_NET_F_HOST_TSO4 11
37/* Host can handle TSOv6 in */
38#define VIRTIO_NET_F_HOST_TSO6 12
39/* Host can handle TSO[6] w/ ECN in */
40#define VIRTIO_NET_F_HOST_ECN 13
41/* Host can handle UFO in */
42#define VIRTIO_NET_F_HOST_UFO 14
43/* Host can merge receive buffers */
44#define VIRTIO_NET_F_MRG_RXBUF 15
45/* virtio_net_config.status available */
46#define VIRTIO_NET_F_STATUS 16
47/* Control channel available */
48#define VIRTIO_NET_F_CTRL_VQ 17
49/* Control channel RX mode support */
50#define VIRTIO_NET_F_CTRL_RX 18
51/* Control channel VLAN filtering */
52#define VIRTIO_NET_F_CTRL_VLAN 19
53/* Extra RX mode control support */
54#define VIRTIO_NET_F_CTRL_RX_EXTRA 20
55/* Guest can announce device on the network */
56#define VIRTIO_NET_F_GUEST_ANNOUNCE 21
57/* Device supports receive flow steering */
58#define VIRTIO_NET_F_MQ 22
59/* Set MAC address */
60#define VIRTIO_NET_F_CTRL_MAC_ADDR 23
61/* Device set linkspeed and duplex */
62#define VIRTIO_NET_F_SPEED_DUPLEX 63
63
64#ifndef VIRTIO_NET_NO_LEGACY
65/* Host handles pkts w/ any GSO type */
66#define VIRTIO_NET_F_GSO 6
67#endif /* VIRTIO_NET_NO_LEGACY */
68
69#define VIRTIO_NET_S_LINK_UP 1 /* Link is up */
70#define VIRTIO_NET_S_ANNOUNCE 2 /* Announcement is needed */
71
72struct __packed virtio_net_config {
73 /* The config defining mac address (if VIRTIO_NET_F_MAC) */
74 __u8 mac[ETH_ALEN];
75 /* See VIRTIO_NET_F_STATUS and VIRTIO_NET_S_* above */
76 __u16 status;
77 /*
78 * Maximum number of each of transmit and receive queues;
79 * see VIRTIO_NET_F_MQ and VIRTIO_NET_CTRL_MQ.
80 * Legal values are between 1 and 0x8000
81 */
82 __u16 max_virtqueue_pairs;
83 /* Default maximum transmit unit advice */
84 __u16 mtu;
85 /*
86 * speed, in units of 1Mb. All values 0 to INT_MAX are legal.
87 * Any other value stands for unknown.
88 */
89 __u32 speed;
90 /*
91 * 0x00 - half duplex
92 * 0x01 - full duplex
93 * Any other value stands for unknown.
94 */
95 __u8 duplex;
96};
97
98/*
99 * This header comes first in the scatter-gather list. If you don't
100 * specify GSO or CSUM features, you can simply ignore the header.
101 *
102 * This is bitwise-equivalent to the legacy struct virtio_net_hdr_mrg_rxbuf,
103 * only flattened.
104 */
105struct virtio_net_hdr_v1 {
106#define VIRTIO_NET_HDR_F_NEEDS_CSUM 0x01 /* Use csum_start, csum_offset */
107#define VIRTIO_NET_HDR_F_DATA_VALID 0x02 /* Csum is valid */
108 __u8 flags;
109#define VIRTIO_NET_HDR_GSO_NONE 0x00 /* Not a GSO frame */
110#define VIRTIO_NET_HDR_GSO_TCPV4 0x01 /* GSO frame, IPv4 TCP (TSO) */
111#define VIRTIO_NET_HDR_GSO_UDP 0x03 /* GSO frame, IPv4 UDP (UFO) */
112#define VIRTIO_NET_HDR_GSO_TCPV6 0x04 /* GSO frame, IPv6 TCP */
113#define VIRTIO_NET_HDR_GSO_ECN 0x80 /* TCP has ECN set */
114 __u8 gso_type;
115 __virtio16 hdr_len; /* Ethernet + IP + tcp/udp hdrs */
116 __virtio16 gso_size; /* Bytes to append to hdr_len per frame */
117 __virtio16 csum_start; /* Position to start checksumming from */
118 __virtio16 csum_offset; /* Offset after that to place checksum */
119 __virtio16 num_buffers; /* Number of merged rx buffers */
120};
121
122#ifndef VIRTIO_NET_NO_LEGACY
123/*
124 * This header comes first in the scatter-gather list.
125 *
126 * For legacy virtio, if VIRTIO_F_ANY_LAYOUT is not negotiated, it must
127 * be the first element of the scatter-gather list. If you don't
128 * specify GSO or CSUM features, you can simply ignore the header.
129 */
130struct virtio_net_hdr {
131 /* See VIRTIO_NET_HDR_F_* */
132 __u8 flags;
133 /* See VIRTIO_NET_HDR_GSO_* */
134 __u8 gso_type;
135 __virtio16 hdr_len; /* Ethernet + IP + tcp/udp hdrs */
136 __virtio16 gso_size; /* Bytes to append to hdr_len per frame */
137 __virtio16 csum_start; /* Position to start checksumming from */
138 __virtio16 csum_offset; /* Offset after that to place checksum */
139};
140
141/*
142 * This is the version of the header to use when the MRG_RXBUF
143 * feature has been negotiated.
144 */
145struct virtio_net_hdr_mrg_rxbuf {
146 struct virtio_net_hdr hdr;
147 __virtio16 num_buffers; /* Number of merged rx buffers */
148};
149#endif /* ...VIRTIO_NET_NO_LEGACY */
150
151/*
152 * Control virtqueue data structures
153 *
154 * The control virtqueue expects a header in the first sg entry
155 * and an ack/status response in the last entry. Data for the
156 * command goes in between.
157 */
158struct __packed virtio_net_ctrl_hdr {
159 __u8 class;
160 __u8 cmd;
161};
162
163typedef __u8 virtio_net_ctrl_ack;
164
165#define VIRTIO_NET_OK 0
166#define VIRTIO_NET_ERR 1
167
168/*
169 * Control the RX mode, ie. promisucous, allmulti, etc...
170 *
171 * All commands require an "out" sg entry containing a 1 byte state value,
172 * zero = disable, non-zero = enable.
173 *
174 * Commands 0 and 1 are supported with the VIRTIO_NET_F_CTRL_RX feature.
175 * Commands 2-5 are added with VIRTIO_NET_F_CTRL_RX_EXTRA.
176 */
177#define VIRTIO_NET_CTRL_RX 0
178#define VIRTIO_NET_CTRL_RX_PROMISC 0
179#define VIRTIO_NET_CTRL_RX_ALLMULTI 1
180#define VIRTIO_NET_CTRL_RX_ALLUNI 2
181#define VIRTIO_NET_CTRL_RX_NOMULTI 3
182#define VIRTIO_NET_CTRL_RX_NOUNI 4
183#define VIRTIO_NET_CTRL_RX_NOBCAST 5
184
185/*
186 * Control the MAC
187 *
188 * The MAC filter table is managed by the hypervisor, the guest should assume
189 * the size is infinite. Filtering should be considered non-perfect, ie. based
190 * on hypervisor resources, the guest may received packets from sources not
191 * specified in the filter list.
192 *
193 * In addition to the class/cmd header, the TABLE_SET command requires two
194 * out scatterlists. Each contains a 4 byte count of entries followed by a
195 * concatenated byte stream of the ETH_ALEN MAC addresses. The first sg list
196 * contains unicast addresses, the second is for multicast. This functionality
197 * is present if the VIRTIO_NET_F_CTRL_RX feature is available.
198 *
199 * The ADDR_SET command requests one out scatterlist, it contains a 6 bytes MAC
200 * address. This functionality is present if the VIRTIO_NET_F_CTRL_MAC_ADDR
201 * feature is available.
202 */
203struct __packed virtio_net_ctrl_mac {
204 __virtio32 entries;
205 __u8 macs[][ETH_ALEN];
206};
207
208#define VIRTIO_NET_CTRL_MAC 1
209#define VIRTIO_NET_CTRL_MAC_TABLE_SET 0
210#define VIRTIO_NET_CTRL_MAC_ADDR_SET 1
211
212/*
213 * Control VLAN filtering
214 *
215 * The VLAN filter table is controlled via a simple ADD/DEL interface. VLAN IDs
216 * not added may be filterd by the hypervisor. Del is the opposite of add. Both
217 * commands expect an out entry containing a 2 byte VLAN ID. VLAN filterting is
218 * available with the VIRTIO_NET_F_CTRL_VLAN feature bit.
219 */
220#define VIRTIO_NET_CTRL_VLAN 2
221#define VIRTIO_NET_CTRL_VLAN_ADD 0
222#define VIRTIO_NET_CTRL_VLAN_DEL 1
223
224/*
225 * Control link announce acknowledgment
226 *
227 * The command VIRTIO_NET_CTRL_ANNOUNCE_ACK is used to indicate that driver has
228 * recevied the notification; device would clear the VIRTIO_NET_S_ANNOUNCE bit
229 * in the status field after it receives this command.
230 */
231#define VIRTIO_NET_CTRL_ANNOUNCE 3
232#define VIRTIO_NET_CTRL_ANNOUNCE_ACK 0
233
234/*
235 * Control receive flow steering
236 *
237 * The command VIRTIO_NET_CTRL_MQ_VQ_PAIRS_SET enables receive flow steering,
238 * specifying the number of the transmit and receive queues that will be used.
239 * After the command is consumed and acked by the device, the device will not
240 * steer new packets on receive virtqueues other than specified nor read from
241 * transmit virtqueues other than specified. Accordingly, driver should not
242 * transmit new packets on virtqueues other than specified.
243 */
244struct virtio_net_ctrl_mq {
245 __virtio16 virtqueue_pairs;
246};
247
248#define VIRTIO_NET_CTRL_MQ 4
249#define VIRTIO_NET_CTRL_MQ_VQ_PAIRS_SET 0
250#define VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MIN 1
251#define VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MAX 0x8000
252
253/*
254 * Control network offloads
255 *
256 * Reconfigures the network offloads that guest can handle.
257 *
258 * Available with the VIRTIO_NET_F_CTRL_GUEST_OFFLOADS feature bit.
259 *
260 * Command data format matches the feature bit mask exactly.
261 *
262 * See VIRTIO_NET_F_GUEST_* for the list of offloads
263 * that can be enabled/disabled.
264 */
265#define VIRTIO_NET_CTRL_GUEST_OFFLOADS 5
266#define VIRTIO_NET_CTRL_GUEST_OFFLOADS_SET 0
267
268#endif /* _LINUX_VIRTIO_NET_H */