f9feada9b047368ad319332870fd88c4ac2bbc59
[dpdk.git] / drivers / bus / vmbus / vmbus_channel.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright (c) 2018, Microsoft Corporation.
3  * All Rights Reserved.
4  */
5
6 #include <unistd.h>
7 #include <stdint.h>
8 #include <string.h>
9 #include <sys/uio.h>
10
11 #include <rte_eal.h>
12 #include <rte_tailq.h>
13 #include <rte_log.h>
14 #include <rte_malloc.h>
15 #include <rte_bus.h>
16 #include <rte_atomic.h>
17 #include <rte_memory.h>
18 #include <rte_bus_vmbus.h>
19
20 #include "private.h"
21
22 static inline void
23 vmbus_sync_set_bit(volatile uint32_t *addr, uint32_t mask)
24 {
25         /* Use GCC builtin which atomic does atomic OR operation */
26         __sync_or_and_fetch(addr, mask);
27 }
28
29 static inline void
30 vmbus_send_interrupt(const struct rte_vmbus_device *dev, uint32_t relid)
31 {
32         uint32_t *int_addr;
33         uint32_t int_mask;
34
35         int_addr = dev->int_page + relid / 32;
36         int_mask = 1u << (relid % 32);
37
38         vmbus_sync_set_bit(int_addr, int_mask);
39 }
40
41 static inline void
42 vmbus_set_monitor(const struct rte_vmbus_device *dev, uint32_t monitor_id)
43 {
44         uint32_t *monitor_addr, monitor_mask;
45         unsigned int trigger_index;
46
47         trigger_index = monitor_id / HV_MON_TRIG_LEN;
48         monitor_mask = 1u << (monitor_id % HV_MON_TRIG_LEN);
49
50         monitor_addr = &dev->monitor_page->trigs[trigger_index].pending;
51         vmbus_sync_set_bit(monitor_addr, monitor_mask);
52 }
53
54 static void
55 vmbus_set_event(const struct rte_vmbus_device *dev,
56                 const struct vmbus_channel *chan)
57 {
58         vmbus_send_interrupt(dev, chan->relid);
59         vmbus_set_monitor(dev, chan->monitor_id);
60 }
61
62 /*
63  * Notify host that there are data pending on our TX bufring.
64  *
65  * Since this in userspace, rely on the monitor page.
66  * Can't do a hypercall from userspace.
67  */
68 void
69 rte_vmbus_chan_signal_tx(const struct vmbus_channel *chan)
70 {
71         const struct rte_vmbus_device *dev = chan->device;
72         const struct vmbus_br *tbr = &chan->txbr;
73
74         /* Make sure all updates are done before signaling host */
75         rte_smp_wmb();
76
77         /* If host is ignoring interrupts? */
78         if (tbr->vbr->imask)
79                 return;
80
81         vmbus_set_event(dev, chan);
82 }
83
84
85 /* Do a simple send directly using transmit ring. */
86 int rte_vmbus_chan_send(struct vmbus_channel *chan, uint16_t type,
87                         void *data, uint32_t dlen,
88                         uint64_t xactid, uint32_t flags, bool *need_sig)
89 {
90         struct vmbus_chanpkt pkt;
91         unsigned int pktlen, pad_pktlen;
92         const uint32_t hlen = sizeof(pkt);
93         bool send_evt = false;
94         uint64_t pad = 0;
95         struct iovec iov[3];
96         int error;
97
98         pktlen = hlen + dlen;
99         pad_pktlen = RTE_ALIGN(pktlen, sizeof(uint64_t));
100
101         pkt.hdr.type = type;
102         pkt.hdr.flags = flags;
103         pkt.hdr.hlen = hlen >> VMBUS_CHANPKT_SIZE_SHIFT;
104         pkt.hdr.tlen = pad_pktlen >> VMBUS_CHANPKT_SIZE_SHIFT;
105         pkt.hdr.xactid = xactid;
106
107         iov[0].iov_base = &pkt;
108         iov[0].iov_len = hlen;
109         iov[1].iov_base = data;
110         iov[1].iov_len = dlen;
111         iov[2].iov_base = &pad;
112         iov[2].iov_len = pad_pktlen - pktlen;
113
114         error = vmbus_txbr_write(&chan->txbr, iov, 3, &send_evt);
115
116         /*
117          * caller sets need_sig to non-NULL if it will handle
118          * signaling if required later.
119          * if need_sig is NULL, signal now if needed.
120          */
121         if (need_sig)
122                 *need_sig |= send_evt;
123         else if (error == 0 && send_evt)
124                 rte_vmbus_chan_signal_tx(chan);
125         return error;
126 }
127
128 /* Do a scatter/gather send where the descriptor points to data. */
129 int rte_vmbus_chan_send_sglist(struct vmbus_channel *chan,
130                                struct vmbus_gpa sg[], uint32_t sglen,
131                                void *data, uint32_t dlen,
132                                uint64_t xactid, bool *need_sig)
133 {
134         struct vmbus_chanpkt_sglist pkt;
135         unsigned int pktlen, pad_pktlen, hlen;
136         bool send_evt = false;
137         struct iovec iov[4];
138         uint64_t pad = 0;
139         int error;
140
141         hlen = offsetof(struct vmbus_chanpkt_sglist, gpa[sglen]);
142         pktlen = hlen + dlen;
143         pad_pktlen = RTE_ALIGN(pktlen, sizeof(uint64_t));
144
145         pkt.hdr.type = VMBUS_CHANPKT_TYPE_GPA;
146         pkt.hdr.flags = VMBUS_CHANPKT_FLAG_RC;
147         pkt.hdr.hlen = hlen >> VMBUS_CHANPKT_SIZE_SHIFT;
148         pkt.hdr.tlen = pad_pktlen >> VMBUS_CHANPKT_SIZE_SHIFT;
149         pkt.hdr.xactid = xactid;
150         pkt.rsvd = 0;
151         pkt.gpa_cnt = sglen;
152
153         iov[0].iov_base = &pkt;
154         iov[0].iov_len = sizeof(pkt);
155         iov[1].iov_base = sg;
156         iov[1].iov_len = sizeof(struct vmbus_gpa) * sglen;
157         iov[2].iov_base = data;
158         iov[2].iov_len = dlen;
159         iov[3].iov_base = &pad;
160         iov[3].iov_len = pad_pktlen - pktlen;
161
162         error = vmbus_txbr_write(&chan->txbr, iov, 4, &send_evt);
163
164         /* if caller is batching, just propagate the status */
165         if (need_sig)
166                 *need_sig |= send_evt;
167         else if (error == 0 && send_evt)
168                 rte_vmbus_chan_signal_tx(chan);
169         return error;
170 }
171
172 bool rte_vmbus_chan_rx_empty(const struct vmbus_channel *channel)
173 {
174         const struct vmbus_br *br = &channel->rxbr;
175
176         return br->vbr->rindex == br->vbr->windex;
177 }
178
179 static int vmbus_read_and_signal(struct vmbus_channel *chan,
180                                  void *data, size_t dlen, size_t skip)
181 {
182         struct vmbus_br *rbr = &chan->rxbr;
183         uint32_t write_sz, pending_sz, bytes_read;
184         int error;
185
186         /* Record where host was when we started read (for debug) */
187         rbr->windex = rbr->vbr->windex;
188
189         /* Read data and skip packet header */
190         error = vmbus_rxbr_read(rbr, data, dlen, skip);
191         if (error)
192                 return error;
193
194         /* No need for signaling on older versions */
195         if (!rbr->vbr->feature_bits.feat_pending_send_sz)
196                 return 0;
197
198         /* Make sure reading of pending happens after new read index */
199         rte_mb();
200
201         pending_sz = rbr->vbr->pending_send;
202         if (!pending_sz)
203                 return 0;
204
205         rte_smp_rmb();
206         write_sz = vmbus_br_availwrite(rbr, rbr->vbr->windex);
207         bytes_read = dlen + skip + sizeof(uint64_t);
208
209         /* If there was space before then host was not blocked */
210         if (write_sz - bytes_read > pending_sz)
211                 return 0;
212
213         /* If pending write will not fit */
214         if (write_sz <= pending_sz)
215                 return 0;
216
217         vmbus_set_event(chan->device, chan);
218         return 0;
219 }
220
221 /* TODO: replace this with inplace ring buffer (no copy) */
222 int rte_vmbus_chan_recv(struct vmbus_channel *chan, void *data, uint32_t *len,
223                         uint64_t *request_id)
224 {
225         struct vmbus_chanpkt_hdr pkt;
226         uint32_t dlen, hlen, bufferlen = *len;
227         int error;
228
229         *len = 0;
230
231         error = vmbus_rxbr_peek(&chan->rxbr, &pkt, sizeof(pkt));
232         if (error)
233                 return error;
234
235         if (unlikely(pkt.hlen < VMBUS_CHANPKT_HLEN_MIN)) {
236                 VMBUS_LOG(ERR, "VMBUS recv, invalid hlen %u", pkt.hlen);
237                 /* XXX this channel is dead actually. */
238                 return -EIO;
239         }
240
241         if (unlikely(pkt.hlen > pkt.tlen)) {
242                 VMBUS_LOG(ERR, "VMBUS recv,invalid hlen %u and tlen %u",
243                           pkt.hlen, pkt.tlen);
244                 return -EIO;
245         }
246
247         /* Length are in quad words */
248         hlen = pkt.hlen << VMBUS_CHANPKT_SIZE_SHIFT;
249         dlen = (pkt.tlen << VMBUS_CHANPKT_SIZE_SHIFT) - hlen;
250         *len = dlen;
251
252         /* If caller buffer is not large enough */
253         if (unlikely(dlen > bufferlen))
254                 return -ENOBUFS;
255
256         if (request_id)
257                 *request_id = pkt.xactid;
258
259         /* Read data and skip the header */
260         return vmbus_read_and_signal(chan, data, dlen, hlen);
261 }
262
263 int rte_vmbus_chan_recv_raw(struct vmbus_channel *chan,
264                             void *data, uint32_t *len)
265 {
266         struct vmbus_chanpkt_hdr pkt;
267         uint32_t dlen, bufferlen = *len;
268         int error;
269
270         error = vmbus_rxbr_peek(&chan->rxbr, &pkt, sizeof(pkt));
271         if (error)
272                 return error;
273
274         if (unlikely(pkt.hlen < VMBUS_CHANPKT_HLEN_MIN)) {
275                 VMBUS_LOG(ERR, "VMBUS recv, invalid hlen %u", pkt.hlen);
276                 /* XXX this channel is dead actually. */
277                 return -EIO;
278         }
279
280         if (unlikely(pkt.hlen > pkt.tlen)) {
281                 VMBUS_LOG(ERR, "VMBUS recv,invalid hlen %u and tlen %u",
282                         pkt.hlen, pkt.tlen);
283                 return -EIO;
284         }
285
286         /* Length are in quad words */
287         dlen = pkt.tlen << VMBUS_CHANPKT_SIZE_SHIFT;
288         *len = dlen;
289
290         /* If caller buffer is not large enough */
291         if (unlikely(dlen > bufferlen))
292                 return -ENOBUFS;
293
294         /* Put packet header in data buffer */
295         return vmbus_read_and_signal(chan, data, dlen, 0);
296 }
297
298 int vmbus_chan_create(const struct rte_vmbus_device *device,
299                       uint16_t relid, uint16_t subid, uint8_t monitor_id,
300                       struct vmbus_channel **new_chan)
301 {
302         struct vmbus_channel *chan;
303         int err;
304
305         chan = rte_zmalloc_socket("VMBUS", sizeof(*chan), RTE_CACHE_LINE_SIZE,
306                                   device->device.numa_node);
307         if (!chan)
308                 return -ENOMEM;
309
310         STAILQ_INIT(&chan->subchannel_list);
311         chan->device = device;
312         chan->subchannel_id = subid;
313         chan->relid = relid;
314         chan->monitor_id = monitor_id;
315         *new_chan = chan;
316
317         err = vmbus_uio_map_rings(chan);
318         if (err) {
319                 rte_free(chan);
320                 return err;
321         }
322
323         return 0;
324 }
325
326 /* Setup the primary channel */
327 int rte_vmbus_chan_open(struct rte_vmbus_device *device,
328                         struct vmbus_channel **new_chan)
329 {
330         int err;
331
332         err = vmbus_chan_create(device, device->relid, 0,
333                                 device->monitor_id, new_chan);
334         if (!err)
335                 device->primary = *new_chan;
336
337         return err;
338 }
339
340 int rte_vmbus_max_channels(const struct rte_vmbus_device *device)
341 {
342         if (vmbus_uio_subchannels_supported(device, device->primary))
343                 return VMBUS_MAX_CHANNELS;
344         else
345                 return 1;
346 }
347
348 /* Setup secondary channel */
349 int rte_vmbus_subchan_open(struct vmbus_channel *primary,
350                            struct vmbus_channel **new_chan)
351 {
352         struct vmbus_channel *chan;
353         int err;
354
355         err = vmbus_uio_get_subchan(primary, &chan);
356         if (err)
357                 return err;
358
359         STAILQ_INSERT_TAIL(&primary->subchannel_list, chan, next);
360         *new_chan = chan;
361         return 0;
362 }
363
364 uint16_t rte_vmbus_sub_channel_index(const struct vmbus_channel *chan)
365 {
366         return chan->subchannel_id;
367 }
368
369 void rte_vmbus_chan_close(struct vmbus_channel *chan)
370 {
371         const struct rte_vmbus_device *device = chan->device;
372         struct vmbus_channel *primary = device->primary;
373
374         if (chan != primary)
375                 STAILQ_REMOVE(&primary->subchannel_list, chan,
376                               vmbus_channel, next);
377
378         rte_free(chan);
379 }
380
381 static void vmbus_dump_ring(FILE *f, const char *id, const struct vmbus_br *br)
382 {
383         const struct vmbus_bufring *vbr = br->vbr;
384         struct vmbus_chanpkt_hdr pkt;
385
386         fprintf(f, "%s windex=%u rindex=%u mask=%u pending=%u feature=%#x\n",
387                 id, vbr->windex, vbr->rindex, vbr->imask,
388                 vbr->pending_send, vbr->feature_bits.value);
389         fprintf(f, " size=%u avail write=%u read=%u\n",
390                 br->dsize, vmbus_br_availwrite(br, vbr->windex),
391                 vmbus_br_availread(br));
392
393         if (vmbus_rxbr_peek(br, &pkt, sizeof(pkt)) == 0)
394                 fprintf(f, "  pkt type %#x len %u flags %#x xactid %#"PRIx64"\n",
395                         pkt.type,
396                         pkt.tlen << VMBUS_CHANPKT_SIZE_SHIFT,
397                         pkt.flags, pkt.xactid);
398 }
399
400 void rte_vmbus_chan_dump(FILE *f, const struct vmbus_channel *chan)
401 {
402         fprintf(f, "channel[%u] relid=%u monitor=%u\n",
403                 chan->subchannel_id, chan->relid, chan->monitor_id);
404         vmbus_dump_ring(f, "rxbr", &chan->rxbr);
405         vmbus_dump_ring(f, "txbr", &chan->txbr);
406 }