diff options
Diffstat (limited to 'drivers/virtio/virtio_net.c')
-rw-r--r-- | drivers/virtio/virtio_net.c | 31 |
1 files changed, 26 insertions, 5 deletions
diff --git a/drivers/virtio/virtio_net.c b/drivers/virtio/virtio_net.c index 5bb6a9fcc9..0dbbd78023 100644 --- a/drivers/virtio/virtio_net.c +++ b/drivers/virtio/virtio_net.c | |||
@@ -32,6 +32,7 @@ struct virtio_net_priv { | |||
32 | 32 | ||
33 | char rx_buff[VIRTIO_NET_NUM_RX_BUFS][VIRTIO_NET_RX_BUF_SIZE]; | 33 | char rx_buff[VIRTIO_NET_NUM_RX_BUFS][VIRTIO_NET_RX_BUF_SIZE]; |
34 | bool rx_running; | 34 | bool rx_running; |
35 | int net_hdr_len; | ||
35 | }; | 36 | }; |
36 | 37 | ||
37 | /* | 38 | /* |
@@ -77,12 +78,19 @@ static int virtio_net_send(struct udevice *dev, void *packet, int length) | |||
77 | { | 78 | { |
78 | struct virtio_net_priv *priv = dev_get_priv(dev); | 79 | struct virtio_net_priv *priv = dev_get_priv(dev); |
79 | struct virtio_net_hdr hdr; | 80 | struct virtio_net_hdr hdr; |
80 | struct virtio_sg hdr_sg = { &hdr, sizeof(hdr) }; | 81 | struct virtio_net_hdr_v1 hdr_v1; |
82 | struct virtio_sg hdr_sg; | ||
81 | struct virtio_sg data_sg = { packet, length }; | 83 | struct virtio_sg data_sg = { packet, length }; |
82 | struct virtio_sg *sgs[] = { &hdr_sg, &data_sg }; | 84 | struct virtio_sg *sgs[] = { &hdr_sg, &data_sg }; |
83 | int ret; | 85 | int ret; |
84 | 86 | ||
85 | memset(&hdr, 0, sizeof(struct virtio_net_hdr)); | 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); | ||
86 | 94 | ||
87 | ret = virtqueue_add(priv->tx_vq, sgs, 2, 0); | 95 | ret = virtqueue_add(priv->tx_vq, sgs, 2, 0); |
88 | if (ret) | 96 | if (ret) |
@@ -108,14 +116,14 @@ static int virtio_net_recv(struct udevice *dev, int flags, uchar **packetp) | |||
108 | if (!buf) | 116 | if (!buf) |
109 | return -EAGAIN; | 117 | return -EAGAIN; |
110 | 118 | ||
111 | *packetp = buf + sizeof(struct virtio_net_hdr); | 119 | *packetp = buf + priv->net_hdr_len; |
112 | return len - sizeof(struct virtio_net_hdr); | 120 | return len - priv->net_hdr_len; |
113 | } | 121 | } |
114 | 122 | ||
115 | static int virtio_net_free_pkt(struct udevice *dev, uchar *packet, int length) | 123 | static int virtio_net_free_pkt(struct udevice *dev, uchar *packet, int length) |
116 | { | 124 | { |
117 | struct virtio_net_priv *priv = dev_get_priv(dev); | 125 | struct virtio_net_priv *priv = dev_get_priv(dev); |
118 | void *buf = packet - sizeof(struct virtio_net_hdr); | 126 | void *buf = packet - priv->net_hdr_len; |
119 | struct virtio_sg sg = { buf, VIRTIO_NET_RX_BUF_SIZE }; | 127 | struct virtio_sg sg = { buf, VIRTIO_NET_RX_BUF_SIZE }; |
120 | struct virtio_sg *sgs[] = { &sg }; | 128 | struct virtio_sg *sgs[] = { &sg }; |
121 | 129 | ||
@@ -186,12 +194,25 @@ static int virtio_net_bind(struct udevice *dev) | |||
186 | static int virtio_net_probe(struct udevice *dev) | 194 | static int virtio_net_probe(struct udevice *dev) |
187 | { | 195 | { |
188 | struct virtio_net_priv *priv = dev_get_priv(dev); | 196 | struct virtio_net_priv *priv = dev_get_priv(dev); |
197 | struct virtio_dev_priv *uc_priv = dev_get_uclass_priv(dev->parent); | ||
189 | int ret; | 198 | int ret; |
190 | 199 | ||
191 | ret = virtio_find_vqs(dev, 2, priv->vqs); | 200 | ret = virtio_find_vqs(dev, 2, priv->vqs); |
192 | if (ret < 0) | 201 | if (ret < 0) |
193 | return ret; | 202 | return ret; |
194 | 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 | |||
195 | return 0; | 216 | return 0; |
196 | } | 217 | } |
197 | 218 | ||