1 /*        $NetBSD: vnet.c,v 1.10 2023/12/14 20:17:18 andvar Exp $     */
2 /*        $OpenBSD: vnet.c,v 1.62 2020/07/10 13:26:36 patrick Exp $   */
3 /*
4  * Copyright (c) 2009, 2015 Mark Kettenis
5  *
6  * Permission to use, copy, modify, and distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  */
18 
19 #include <sys/kmem.h>
20 #include <sys/param.h>
21 #include <sys/atomic.h>
22 #include <sys/callout.h>
23 #include <sys/device.h>
24 #include <sys/malloc.h>
25 #include <sys/pool.h>
26 #include <sys/mbuf.h>
27 #include <sys/socket.h>
28 #include <sys/sockio.h>
29 #include <sys/systm.h>
30 
31 #include <machine/autoconf.h>
32 #include <machine/hypervisor.h>
33 #include <machine/openfirm.h>
34 
35 #include <net/if.h>
36 #include <net/if_media.h>
37 
38 #include <netinet/in.h>
39 #include <net/if_ether.h>
40 
41 #if NBPFILTER > 0
42 #include <net/bpf.h>
43 #endif
44 
45 #include <uvm/uvm_extern.h>
46 
47 #include <sparc64/dev/cbusvar.h>
48 #include <sparc64/dev/ldcvar.h>
49 #include <sparc64/dev/viovar.h>
50 
51 #ifdef VNET_DEBUG
52 #define DPRINTF(x)  printf x
53 #else
54 #define DPRINTF(x)
55 #endif
56 
57 #define VNET_TX_ENTRIES                 32
58 #define VNET_RX_ENTRIES                 32
59 
60 struct vnet_attr_info {
61           struct vio_msg_tag  tag;
62           uint8_t                       xfer_mode;
63           uint8_t                       addr_type;
64           uint16_t            ack_freq;
65           uint32_t            _reserved1;
66           uint64_t            addr;
67           uint64_t            mtu;
68           uint64_t            _reserved2[3];
69 };
70 
71 /* Address types. */
72 #define VNET_ADDR_ETHERMAC    0x01
73 
74 /* Sub-Type envelopes. */
75 #define VNET_MCAST_INFO                 0x0101
76 
77 #define VNET_NUM_MCAST                  7
78 
79 struct vnet_mcast_info {
80           struct vio_msg_tag  tag;
81           uint8_t                       set;
82           uint8_t                       count;
83           uint8_t                       mcast_addr[VNET_NUM_MCAST][ETHER_ADDR_LEN];
84           uint32_t            _reserved;
85 };
86 
87 struct vnet_desc {
88           struct vio_dring_hdr          hdr;
89           uint32_t            nbytes;
90           uint32_t            ncookies;
91           struct ldc_cookie   cookie[2];
92 };
93 
94 struct vnet_desc_msg {
95           struct vio_msg_tag  tag;
96           uint64_t            seq_no;
97           uint64_t            desc_handle;
98           uint32_t            nbytes;
99           uint32_t            ncookies;
100           struct ldc_cookie   cookie[1];
101 };
102 
103 struct vnet_dring {
104           bus_dmamap_t                  vd_map;
105           bus_dma_segment_t   vd_seg;
106           struct vnet_desc    *vd_desc;
107           int                           vd_nentries;
108 };
109 
110 struct vnet_dring *vnet_dring_alloc(bus_dma_tag_t, int);
111 void      vnet_dring_free(bus_dma_tag_t, struct vnet_dring *);
112 
113 /*
114  * For now, we only support vNet 1.0.
115  */
116 #define VNET_MAJOR  1
117 #define VNET_MINOR  0
118 
119 /*
120  * The vNet protocol wants the IP header to be 64-bit aligned, so
121  * define out own variant of ETHER_ALIGN.
122  */
123 #define VNET_ETHER_ALIGN      6
124 
125 struct vnet_soft_desc {
126           int                 vsd_map_idx;
127           unsigned char *vsd_buf;
128 };
129 
130 struct vnet_softc {
131           device_t  sc_dv;
132           bus_space_tag_t     sc_bustag;
133           bus_dma_tag_t       sc_dmatag;
134 
135           uint64_t  sc_tx_ino;
136           uint64_t  sc_rx_ino;
137           void                *sc_tx_ih;
138           void                *sc_rx_ih;
139 
140           struct ldc_conn     sc_lc;
141 
142           uint16_t  sc_vio_state;
143 #define VIO_SND_VER_INFO      0x0001
144 #define VIO_ACK_VER_INFO      0x0002
145 #define VIO_RCV_VER_INFO      0x0004
146 #define VIO_SND_ATTR_INFO     0x0008
147 #define VIO_ACK_ATTR_INFO     0x0010
148 #define VIO_RCV_ATTR_INFO     0x0020
149 #define VIO_SND_DRING_REG     0x0040
150 #define VIO_ACK_DRING_REG     0x0080
151 #define VIO_RCV_DRING_REG     0x0100
152 #define VIO_SND_RDX           0x0200
153 #define VIO_ACK_RDX           0x0400
154 #define VIO_RCV_RDX           0x0800
155 
156           struct callout      sc_handshake_co;
157 
158           uint8_t             sc_xfer_mode;
159 
160           uint32_t  sc_local_sid;
161           uint64_t  sc_dring_ident;
162           uint64_t  sc_seq_no;
163 
164           u_int               sc_tx_prod;
165           u_int               sc_tx_cons;
166 
167           u_int               sc_peer_state;
168 
169           struct ldc_map      *sc_lm;
170           struct vnet_dring *sc_vd;
171           struct vnet_soft_desc *sc_vsd;
172 #define VNET_NUM_SOFT_DESC    128
173 
174           size_t              sc_peer_desc_size;
175           struct ldc_cookie sc_peer_dring_cookie;
176           int                 sc_peer_dring_nentries;
177 
178           struct pool         sc_pool;
179 
180           struct ethercom     sc_ethercom;
181           struct ifmedia      sc_media;
182           u_int8_t sc_macaddr[ETHER_ADDR_LEN];
183 };
184 
185 int vnet_match (device_t, cfdata_t, void *);
186 void vnet_attach (device_t, device_t, void *);
187 
188 CFATTACH_DECL_NEW(vnet, sizeof(struct vnet_softc),
189     vnet_match, vnet_attach, NULL, NULL);
190 
191 int       vnet_tx_intr(void *);
192 int       vnet_rx_intr(void *);
193 void      vnet_handshake(void *);
194 
195 void      vio_rx_data(struct ldc_conn *, struct ldc_pkt *);
196 void      vnet_rx_vio_ctrl(struct vnet_softc *, struct vio_msg *);
197 void      vnet_rx_vio_ver_info(struct vnet_softc *, struct vio_msg_tag *);
198 void      vnet_rx_vio_attr_info(struct vnet_softc *, struct vio_msg_tag *);
199 void      vnet_rx_vio_dring_reg(struct vnet_softc *, struct vio_msg_tag *);
200 void      vnet_rx_vio_rdx(struct vnet_softc *sc, struct vio_msg_tag *);
201 void      vnet_rx_vio_mcast_info(struct vnet_softc *sc, struct vio_msg_tag *);
202 void      vnet_rx_vio_data(struct vnet_softc *sc, struct vio_msg *);
203 void      vnet_rx_vio_desc_data(struct vnet_softc *sc, struct vio_msg_tag *);
204 void      vnet_rx_vio_dring_data(struct vnet_softc *sc, struct vio_msg_tag *);
205 
206 void      vnet_ldc_reset(struct ldc_conn *);
207 void      vnet_ldc_start(struct ldc_conn *);
208 
209 void      vnet_sendmsg(struct vnet_softc *, void *, size_t);
210 void      vnet_send_ver_info(struct vnet_softc *, uint16_t, uint16_t);
211 void      vnet_send_attr_info(struct vnet_softc *);
212 void      vnet_send_dring_reg(struct vnet_softc *);
213 void      vio_send_rdx(struct vnet_softc *);
214 void      vnet_send_dring_data(struct vnet_softc *, uint32_t);
215 
216 void      vnet_start(struct ifnet *);
217 void      vnet_start_desc(struct ifnet *);
218 int                 vnet_ioctl(struct ifnet *, u_long, void *);
219 void      vnet_watchdog(struct ifnet *);
220 
221 int                 vnet_media_change(struct ifnet *);
222 void      vnet_media_status(struct ifnet *, struct ifmediareq *);
223 
224 void      vnet_link_state(struct vnet_softc *sc);
225 
226 void      vnet_setmulti(struct vnet_softc *, int);
227 
228 int                 vnet_init(struct ifnet *);
229 void      vnet_stop(struct ifnet *, int);
230 
vnet_match(device_t parent,cfdata_t match,void * aux)231 int vnet_match(device_t parent, cfdata_t match, void *aux)
232 {
233 
234           struct cbus_attach_args *ca = aux;
235 
236           if (strcmp(ca->ca_name, "network") == 0)
237                     return (1);
238 
239           return (0);
240 }
241 
242 void
vnet_attach(struct device * parent,struct device * self,void * aux)243 vnet_attach(struct device *parent, struct device *self, void *aux)
244 {
245           struct vnet_softc *sc = device_private(self);
246           struct cbus_attach_args *ca = aux;
247           struct ldc_conn *lc;
248           struct ifnet *ifp;
249 
250           sc->sc_dv = self;
251           sc->sc_bustag = ca->ca_bustag;
252           sc->sc_dmatag = ca->ca_dmatag;
253           sc->sc_tx_ino = ca->ca_tx_ino;
254           sc->sc_rx_ino = ca->ca_rx_ino;
255 
256           printf(": ivec 0x%" PRIx64 ", 0x%" PRIx64, sc->sc_tx_ino, sc->sc_rx_ino);
257 
258           /*
259            * Un-configure queues before registering interrupt handlers,
260            * such that we dont get any stale LDC packets or events.
261            */
262           hv_ldc_tx_qconf(ca->ca_id, 0, 0);
263           hv_ldc_rx_qconf(ca->ca_id, 0, 0);
264 
265           sc->sc_tx_ih = bus_intr_establish(ca->ca_bustag, sc->sc_tx_ino,
266               IPL_NET, vnet_tx_intr, sc);
267           sc->sc_rx_ih = bus_intr_establish(ca->ca_bustag, sc->sc_rx_ino,
268               IPL_NET, vnet_rx_intr, sc);
269           if (sc->sc_tx_ih == NULL || sc->sc_rx_ih == NULL) {
270                     printf(", can't establish interrupts\n");
271                     return;
272           }
273 
274           lc = &sc->sc_lc;
275           lc->lc_id = ca->ca_id;
276           lc->lc_sc = sc;
277           lc->lc_reset = vnet_ldc_reset;
278           lc->lc_start = vnet_ldc_start;
279           lc->lc_rx_data = vio_rx_data;
280 
281           callout_init(&sc->sc_handshake_co, 0);
282 
283           sc->sc_peer_state = VIO_DP_STOPPED;
284 
285           lc->lc_txq = ldc_queue_alloc(VNET_TX_ENTRIES);
286           if (lc->lc_txq == NULL) {
287                     printf(", can't allocate tx queue\n");
288                     return;
289           }
290 
291           lc->lc_rxq = ldc_queue_alloc(VNET_RX_ENTRIES);
292           if (lc->lc_rxq == NULL) {
293                     printf(", can't allocate rx queue\n");
294                     goto free_txqueue;
295           }
296 
297           if (OF_getprop(ca->ca_node, "local-mac-address",
298                                            sc->sc_macaddr, ETHER_ADDR_LEN) > 0) {
299                     printf(", address %s", ether_sprintf(sc->sc_macaddr));
300           } else {
301                     printf(", cannot retrieve local mac address\n");
302                     return;
303           }
304 
305           /*
306            * Each interface gets its own pool.
307            */
308           pool_init(&sc->sc_pool, /*size*/2048, /*align*/0, /*align_offset*/0,
309               /*flags*/0, /*wchan*/device_xname(sc->sc_dv), /*palloc*/NULL,
310               IPL_NET);
311 
312           ifp = &sc->sc_ethercom.ec_if;
313           ifp->if_softc = sc;
314           ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
315           ifp->if_init = vnet_init;
316           ifp->if_ioctl = vnet_ioctl;
317           ifp->if_start = vnet_start;
318           ifp->if_stop = vnet_stop;
319           ifp->if_watchdog = vnet_watchdog;
320           strlcpy(ifp->if_xname, device_xname(self), IFNAMSIZ);
321           IFQ_SET_MAXLEN(&ifp->if_snd, 31); /* XXX */
322 
323           ifmedia_init(&sc->sc_media, 0, vnet_media_change, vnet_media_status);
324           ifmedia_add(&sc->sc_media, IFM_ETHER | IFM_AUTO, 0, NULL);
325           ifmedia_set(&sc->sc_media, IFM_ETHER | IFM_AUTO);
326 
327           if_attach(ifp);
328           ether_ifattach(ifp, sc->sc_macaddr);
329 
330           printf("\n");
331           return;
332 free_txqueue:
333           ldc_queue_free(lc->lc_txq);
334 }
335 
336 int
vnet_tx_intr(void * arg)337 vnet_tx_intr(void *arg)
338 {
339           struct vnet_softc *sc = arg;
340           struct ldc_conn *lc = &sc->sc_lc;
341           uint64_t tx_head, tx_tail, tx_state;
342 
343           hv_ldc_tx_get_state(lc->lc_id, &tx_head, &tx_tail, &tx_state);
344           if (tx_state != lc->lc_tx_state) {
345                     switch (tx_state) {
346                     case LDC_CHANNEL_DOWN:
347                               DPRINTF(("%s: Tx link down\n", __func__));
348                               break;
349                     case LDC_CHANNEL_UP:
350                               DPRINTF(("%s: Tx link up\n", __func__));
351                               break;
352                     case LDC_CHANNEL_RESET:
353                               DPRINTF(("%s: Tx link reset\n", __func__));
354                               break;
355                     }
356                     lc->lc_tx_state = tx_state;
357           }
358 
359           return (1);
360 }
361 
362 int
vnet_rx_intr(void * arg)363 vnet_rx_intr(void *arg)
364 {
365           struct vnet_softc *sc = arg;
366           struct ldc_conn *lc = &sc->sc_lc;
367           uint64_t rx_head, rx_tail, rx_state;
368           struct ldc_pkt *lp;
369           int err;
370 
371           err = hv_ldc_rx_get_state(lc->lc_id, &rx_head, &rx_tail, &rx_state);
372           if (err == H_EINVAL) {
373                     printf("hv_ldc_rx_get_state failed\n");
374                     return (0);
375           }
376           if (err != H_EOK) {
377                     printf("hv_ldc_rx_get_state %d\n", err);
378                     return (0);
379           }
380 
381           if (rx_state != lc->lc_rx_state) {
382                     switch (rx_state) {
383                     case LDC_CHANNEL_DOWN:
384                               lc->lc_tx_seqid = 0;
385                               lc->lc_state = 0;
386                               lc->lc_reset(lc);
387                               if (rx_head == rx_tail)
388                                         break;
389                               /* Discard and ack pending I/O. */
390                               DPRINTF(("setting rx qhead to %" PRId64 "\n", rx_tail));
391                               err = hv_ldc_rx_set_qhead(lc->lc_id, rx_tail);
392                               if (err == H_EOK)
393                                         break;
394                               printf("%s: hv_ldc_rx_set_qhead %d\n", __func__, err);
395                               break;
396                     case LDC_CHANNEL_UP:
397                               callout_reset(&sc->sc_handshake_co, hz / 2, vnet_handshake, sc);
398                               break;
399                     case LDC_CHANNEL_RESET:
400                               DPRINTF(("%s: Rx link reset\n", __func__));
401                               lc->lc_tx_seqid = 0;
402                               lc->lc_state = 0;
403                               lc->lc_reset(lc);
404                               callout_reset(&sc->sc_handshake_co, hz / 2, vnet_handshake, sc);
405                               if (rx_head == rx_tail) {
406                                         break;
407                               }
408                               /* Discard and ack pending I/O. */
409                               DPRINTF(("setting rx qhead to %" PRId64 "\n", rx_tail));
410                               err = hv_ldc_rx_set_qhead(lc->lc_id, rx_tail);
411                               if (err == H_EOK)
412                                         break;
413                               printf("%s: hv_ldc_rx_set_qhead %d\n", __func__, err);
414                               break;
415                     default:
416                               DPRINTF(("%s: unhandled rx_state %" PRIx64 "\n", __func__, rx_state));
417                               break;
418                     }
419                     lc->lc_rx_state = rx_state;
420                     return (1);
421           } else {
422           }
423 
424           if (rx_head == rx_tail)
425           {
426                     DPRINTF(("%s: head eq tail\n", __func__));
427                     return (0);
428           }
429           lp = (struct ldc_pkt *)(uintptr_t)(lc->lc_rxq->lq_va + rx_head);
430           switch (lp->type) {
431           case LDC_CTRL:
432                     DPRINTF(("%s: LDC_CTRL\n", __func__));
433                     ldc_rx_ctrl(lc, lp);
434                     break;
435 
436           case LDC_DATA:
437                     DPRINTF(("%s: LDC_DATA\n", __func__));
438                     ldc_rx_data(lc, lp);
439                     break;
440 
441           default:
442                     DPRINTF(("%s: unhandled type %0x02/%0x02/%0x02\n",
443                                          __func__, lp->type, lp->stype, lp->ctrl));
444                     console_debugger();
445                     ldc_reset(lc);
446                     break;
447           }
448 
449           if (lc->lc_state == 0)
450                     return (1);
451 
452           rx_head += sizeof(*lp);
453           rx_head &= ((lc->lc_rxq->lq_nentries * sizeof(*lp)) - 1);
454           err = hv_ldc_rx_set_qhead(lc->lc_id, rx_head);
455           if (err != H_EOK)
456                     printf("%s: hv_ldc_rx_set_qhead %d\n", __func__, err);
457           return (1);
458 }
459 
460 void
vnet_handshake(void * arg)461 vnet_handshake(void *arg)
462 {
463           struct vnet_softc *sc = arg;
464 
465           ldc_send_vers(&sc->sc_lc);
466 }
467 
468 void
vio_rx_data(struct ldc_conn * lc,struct ldc_pkt * lp)469 vio_rx_data(struct ldc_conn *lc, struct ldc_pkt *lp)
470 {
471           struct vio_msg *vm = (struct vio_msg *)lp;
472 
473           switch (vm->type) {
474           case VIO_TYPE_CTRL:
475                     if ((lp->env & LDC_FRAG_START) == 0 &&
476                         (lp->env & LDC_FRAG_STOP) == 0) {
477                               DPRINTF(("%s: FRAG_START==0 and FRAG_STOP==0\n", __func__));
478                               return;
479                     }
480                     vnet_rx_vio_ctrl(lc->lc_sc, vm);
481                     break;
482 
483           case VIO_TYPE_DATA:
484                     if((lp->env & LDC_FRAG_START) == 0) {
485                               DPRINTF(("%s: FRAG_START==0\n", __func__));
486                               return;
487                     }
488                     vnet_rx_vio_data(lc->lc_sc, vm);
489                     break;
490 
491           default:
492                     DPRINTF(("Unhandled packet type 0x%02x\n", vm->type));
493                     ldc_reset(lc);
494                     break;
495           }
496 }
497 
498 void
vnet_rx_vio_ctrl(struct vnet_softc * sc,struct vio_msg * vm)499 vnet_rx_vio_ctrl(struct vnet_softc *sc, struct vio_msg *vm)
500 {
501           struct vio_msg_tag *tag = (struct vio_msg_tag *)&vm->type;
502 
503           switch (tag->stype_env) {
504           case VIO_VER_INFO:
505                     vnet_rx_vio_ver_info(sc, tag);
506                     break;
507           case VIO_ATTR_INFO:
508                     vnet_rx_vio_attr_info(sc, tag);
509                     break;
510           case VIO_DRING_REG:
511                     vnet_rx_vio_dring_reg(sc, tag);
512                     break;
513           case VIO_RDX:
514                     vnet_rx_vio_rdx(sc, tag);
515                     break;
516           case VNET_MCAST_INFO:
517                     vnet_rx_vio_mcast_info(sc, tag);
518                     break;
519           default:
520                     printf("%s: CTRL/0x%02x/0x%04x FIXME\n",
521                                          __func__, tag->stype, tag->stype_env);
522                     break;
523           }
524 }
525 
526 void
vnet_rx_vio_ver_info(struct vnet_softc * sc,struct vio_msg_tag * tag)527 vnet_rx_vio_ver_info(struct vnet_softc *sc, struct vio_msg_tag *tag)
528 {
529           struct vio_ver_info *vi = (struct vio_ver_info *)tag;
530 
531           switch (vi->tag.stype) {
532           case VIO_SUBTYPE_INFO:
533                     DPRINTF(("CTRL/INFO/VER_INFO\n"));
534 
535                     /* Make sure we're talking to a virtual network device. */
536                     if (vi->dev_class != VDEV_NETWORK &&
537                         vi->dev_class != VDEV_NETWORK_SWITCH) {
538                               DPRINTF(("Class is not network or network switch\n"));
539                               /* Huh, we're not talking to a network device? */
540                               printf("Not a network device\n");
541                               vi->tag.stype = VIO_SUBTYPE_NACK;
542                               vnet_sendmsg(sc, vi, sizeof(*vi));
543                               return;
544                     }
545 
546                     if (vi->major != VNET_MAJOR) {
547                               DPRINTF(("Major mismatch %" PRId8 " vs %" PRId8 "\n",
548                                                    vi->major, VNET_MAJOR));
549                               vi->tag.stype = VIO_SUBTYPE_NACK;
550                               vi->major = VNET_MAJOR;
551                               vi->minor = VNET_MINOR;
552                               vnet_sendmsg(sc, vi, sizeof(*vi));
553                               return;
554                     }
555 
556                     vi->tag.stype = VIO_SUBTYPE_ACK;
557                     vi->tag.sid = sc->sc_local_sid;
558                     vi->minor = VNET_MINOR;
559                     vnet_sendmsg(sc, vi, sizeof(*vi));
560                     sc->sc_vio_state |= VIO_RCV_VER_INFO;
561                     break;
562 
563           case VIO_SUBTYPE_ACK:
564                     DPRINTF(("CTRL/ACK/VER_INFO\n"));
565                     if (!ISSET(sc->sc_vio_state, VIO_SND_VER_INFO)) {
566                               ldc_reset(&sc->sc_lc);
567                               break;
568                     }
569                     sc->sc_vio_state |= VIO_ACK_VER_INFO;
570                     break;
571 
572           default:
573                     DPRINTF(("CTRL/0x%02x/VER_INFO\n", vi->tag.stype));
574                     break;
575           }
576 
577           if (ISSET(sc->sc_vio_state, VIO_RCV_VER_INFO) &&
578               ISSET(sc->sc_vio_state, VIO_ACK_VER_INFO))
579                     vnet_send_attr_info(sc);
580 }
581 
582 void
vnet_rx_vio_attr_info(struct vnet_softc * sc,struct vio_msg_tag * tag)583 vnet_rx_vio_attr_info(struct vnet_softc *sc, struct vio_msg_tag *tag)
584 {
585           struct vnet_attr_info *ai = (struct vnet_attr_info *)tag;
586 
587           switch (ai->tag.stype) {
588           case VIO_SUBTYPE_INFO:
589                     DPRINTF(("CTRL/INFO/ATTR_INFO\n"));
590                     sc->sc_xfer_mode = ai->xfer_mode;
591                     ai->tag.stype = VIO_SUBTYPE_ACK;
592                     ai->tag.sid = sc->sc_local_sid;
593                     vnet_sendmsg(sc, ai, sizeof(*ai));
594                     sc->sc_vio_state |= VIO_RCV_ATTR_INFO;
595                     break;
596 
597           case VIO_SUBTYPE_ACK:
598                     DPRINTF(("CTRL/ACK/ATTR_INFO\n"));
599                     if (!ISSET(sc->sc_vio_state, VIO_SND_ATTR_INFO)) {
600                               ldc_reset(&sc->sc_lc);
601                               break;
602                     }
603                     sc->sc_vio_state |= VIO_ACK_ATTR_INFO;
604                     break;
605 
606           default:
607                     DPRINTF(("CTRL/0x%02x/ATTR_INFO\n", ai->tag.stype));
608                     break;
609           }
610 
611           if (ISSET(sc->sc_vio_state, VIO_RCV_ATTR_INFO) &&
612               ISSET(sc->sc_vio_state, VIO_ACK_ATTR_INFO)) {
613                     if (sc->sc_xfer_mode == VIO_DRING_MODE)
614                               vnet_send_dring_reg(sc);
615                     else
616                               vio_send_rdx(sc);
617           }
618 }
619 
620 void
vnet_rx_vio_dring_reg(struct vnet_softc * sc,struct vio_msg_tag * tag)621 vnet_rx_vio_dring_reg(struct vnet_softc *sc, struct vio_msg_tag *tag)
622 {
623           struct vio_dring_reg *dr = (struct vio_dring_reg *)tag;
624 
625           switch (dr->tag.stype) {
626           case VIO_SUBTYPE_INFO:
627                     DPRINTF(("CTRL/INFO/DRING_REG\n"));
628                     sc->sc_peer_dring_nentries = dr->num_descriptors;
629                     sc->sc_peer_desc_size = dr->descriptor_size;
630                     sc->sc_peer_dring_cookie = dr->cookie[0];
631 
632                     dr->tag.stype = VIO_SUBTYPE_ACK;
633                     dr->tag.sid = sc->sc_local_sid;
634                     vnet_sendmsg(sc, dr, sizeof(*dr));
635                     sc->sc_vio_state |= VIO_RCV_DRING_REG;
636                     break;
637 
638           case VIO_SUBTYPE_ACK:
639                     DPRINTF(("CTRL/ACK/DRING_REG\n"));
640                     if (!ISSET(sc->sc_vio_state, VIO_SND_DRING_REG)) {
641                               ldc_reset(&sc->sc_lc);
642                               break;
643                     }
644 
645                     sc->sc_dring_ident = dr->dring_ident;
646                     sc->sc_seq_no = 1;
647 
648                     sc->sc_vio_state |= VIO_ACK_DRING_REG;
649                     break;
650 
651           default:
652                     DPRINTF(("CTRL/0x%02x/DRING_REG\n", dr->tag.stype));
653                     break;
654           }
655 
656           if (ISSET(sc->sc_vio_state, VIO_RCV_DRING_REG) &&
657               ISSET(sc->sc_vio_state, VIO_ACK_DRING_REG))
658                     vio_send_rdx(sc);
659 }
660 
661 void
vnet_rx_vio_rdx(struct vnet_softc * sc,struct vio_msg_tag * tag)662 vnet_rx_vio_rdx(struct vnet_softc *sc, struct vio_msg_tag *tag)
663 {
664           struct ifnet *ifp = &sc->sc_ethercom.ec_if;
665 
666           switch(tag->stype) {
667           case VIO_SUBTYPE_INFO:
668                     DPRINTF(("CTRL/INFO/RDX\n"));
669                     tag->stype = VIO_SUBTYPE_ACK;
670                     tag->sid = sc->sc_local_sid;
671                     vnet_sendmsg(sc, tag, sizeof(*tag));
672                     sc->sc_vio_state |= VIO_RCV_RDX;
673                     break;
674 
675           case VIO_SUBTYPE_ACK:
676                     DPRINTF(("CTRL/ACK/RDX\n"));
677                     if (!ISSET(sc->sc_vio_state, VIO_SND_RDX)) {
678                               ldc_reset(&sc->sc_lc);
679                               break;
680                     }
681                     sc->sc_vio_state |= VIO_ACK_RDX;
682                     break;
683 
684           default:
685                     DPRINTF(("CTRL/0x%02x/RDX (VIO)\n", tag->stype));
686                     break;
687           }
688 
689           if (ISSET(sc->sc_vio_state, VIO_RCV_RDX) &&
690               ISSET(sc->sc_vio_state, VIO_ACK_RDX)) {
691                     /* Link is up! */
692                     vnet_link_state(sc);
693 
694                     /* Configure multicast now that we can. */
695                     vnet_setmulti(sc, 1);
696 
697                     KERNEL_LOCK(1, curlwp);
698                     vnet_start(ifp);
699                     KERNEL_UNLOCK_ONE(curlwp);
700           }
701 }
702 
703 void
vnet_rx_vio_mcast_info(struct vnet_softc * sc,struct vio_msg_tag * tag)704 vnet_rx_vio_mcast_info(struct vnet_softc *sc, struct vio_msg_tag *tag)
705 {
706           switch(tag->stype) {
707 
708                     case VIO_SUBTYPE_INFO:
709                               DPRINTF(("CTRL/INFO/MCAST_INFO\n"));
710                               break;
711 
712                     case VIO_SUBTYPE_ACK:
713                               DPRINTF(("CTRL/ACK/MCAST_INFO\n"));
714                               break;
715 
716                     case VIO_SUBTYPE_NACK:
717                               DPRINTF(("CTRL/NACK/MCAST_INFO\n"));
718                               break;
719 
720                     default:
721                               printf("%s: CTRL/0x%02x/0x%04x\n",
722                                            __func__, tag->stype, tag->stype_env);
723                               break;
724           }
725 }
726 
727 void
vnet_rx_vio_data(struct vnet_softc * sc,struct vio_msg * vm)728 vnet_rx_vio_data(struct vnet_softc *sc, struct vio_msg *vm)
729 {
730           struct vio_msg_tag *tag = (struct vio_msg_tag *)&vm->type;
731 
732           if (!ISSET(sc->sc_vio_state, VIO_RCV_RDX) ||
733               !ISSET(sc->sc_vio_state, VIO_ACK_RDX)) {
734                     DPRINTF(("Spurious DATA/0x%02x/0x%04x\n", tag->stype,
735                         tag->stype_env));
736                     return;
737           }
738 
739           switch(tag->stype_env) {
740           case VIO_DESC_DATA:
741                     vnet_rx_vio_desc_data(sc, tag);
742                     break;
743 
744           case VIO_DRING_DATA:
745                     vnet_rx_vio_dring_data(sc, tag);
746                     break;
747 
748           default:
749                     DPRINTF(("DATA/0x%02x/0x%04x\n", tag->stype, tag->stype_env));
750                     break;
751           }
752 }
753 
754 void
vnet_rx_vio_desc_data(struct vnet_softc * sc,struct vio_msg_tag * tag)755 vnet_rx_vio_desc_data(struct vnet_softc *sc, struct vio_msg_tag *tag)
756 {
757 
758           struct vnet_desc_msg *dm = (struct vnet_desc_msg *)tag;
759           struct ldc_conn *lc = &sc->sc_lc;
760           struct ldc_map *map = sc->sc_lm;
761           struct ifnet *ifp = &sc->sc_ethercom.ec_if;
762           struct mbuf *m;
763           unsigned char *buf;
764           paddr_t pa;
765           psize_t nbytes;
766           u_int cons;
767           int err;
768 
769           switch(tag->stype) {
770           case VIO_SUBTYPE_INFO:
771                     buf = pool_get(&sc->sc_pool, PR_NOWAIT|PR_ZERO);
772                     if (buf == NULL) {
773                               if_statinc(ifp, if_ierrors);
774                               goto skip;
775                     }
776                     nbytes = roundup(dm->nbytes, 8);
777 
778                     if (dm->nbytes > (ETHER_MAX_LEN - ETHER_CRC_LEN)) {
779                               if_statinc(ifp, if_ierrors);
780                               goto skip;
781                     }
782 
783                     pmap_extract(pmap_kernel(), (vaddr_t)buf, &pa);
784                     err = hv_ldc_copy(lc->lc_id, LDC_COPY_IN,
785                         dm->cookie[0].addr, pa, nbytes, &nbytes);
786                     if (err != H_EOK) {
787                               pool_put(&sc->sc_pool, buf);
788                               if_statinc(ifp, if_ierrors);
789                               goto skip;
790                     }
791 
792                     /* Stupid OBP doesn't align properly. */
793                     m = m_devget(buf, dm->nbytes, 0, ifp);
794                     pool_put(&sc->sc_pool, buf);
795                     if (m == NULL) {
796                               if_statinc(ifp, if_ierrors);
797                               goto skip;
798                     }
799 
800                     /* Pass it on. */
801                     if_percpuq_enqueue(ifp->if_percpuq, m);
802           skip:
803                     dm->tag.stype = VIO_SUBTYPE_ACK;
804                     dm->tag.sid = sc->sc_local_sid;
805                     vnet_sendmsg(sc, dm, sizeof(*dm));
806                     break;
807 
808           case VIO_SUBTYPE_ACK:
809                     DPRINTF(("DATA/ACK/DESC_DATA\n"));
810 
811                     if (dm->desc_handle != sc->sc_tx_cons) {
812                               printf("out of order\n");
813                               return;
814                     }
815 
816                     cons = sc->sc_tx_cons & (sc->sc_vd->vd_nentries - 1);
817 
818                     map->lm_slot[sc->sc_vsd[cons].vsd_map_idx].entry = 0;
819                     atomic_dec_32(&map->lm_count);
820 
821                     pool_put(&sc->sc_pool, sc->sc_vsd[cons].vsd_buf);
822                     sc->sc_vsd[cons].vsd_buf = NULL;
823 
824                     sc->sc_tx_cons++;
825                     break;
826 
827           case VIO_SUBTYPE_NACK:
828                     DPRINTF(("DATA/NACK/DESC_DATA\n"));
829                     break;
830 
831           default:
832                     DPRINTF(("DATA/0x%02x/DESC_DATA\n", tag->stype));
833                     break;
834           }
835 }
836 
837 void
vnet_rx_vio_dring_data(struct vnet_softc * sc,struct vio_msg_tag * tag)838 vnet_rx_vio_dring_data(struct vnet_softc *sc, struct vio_msg_tag *tag)
839 {
840           struct vio_dring_msg *dm = (struct vio_dring_msg *)tag;
841           struct ldc_conn *lc = &sc->sc_lc;
842           struct ifnet *ifp = &sc->sc_ethercom.ec_if;
843           struct mbuf *m = NULL;
844           paddr_t pa;
845           psize_t nbytes;
846           int err;
847 
848           switch(tag->stype) {
849           case VIO_SUBTYPE_INFO:
850           {
851                     DPRINTF(("%s: VIO_SUBTYPE_INFO\n", __func__));
852                     struct vnet_desc desc;
853                     uint64_t cookie;
854                     paddr_t desc_pa;
855                     int idx, ack_end_idx = -1;
856 
857                     idx = dm->start_idx;
858                     for (;;) {
859                               cookie = sc->sc_peer_dring_cookie.addr;
860                               cookie += idx * sc->sc_peer_desc_size;
861                               nbytes = sc->sc_peer_desc_size;
862                               pmap_extract(pmap_kernel(), (vaddr_t)&desc, &desc_pa);
863                               err = hv_ldc_copy(lc->lc_id, LDC_COPY_IN, cookie,
864                                   desc_pa, nbytes, &nbytes);
865                               if (err != H_EOK) {
866                                         printf("hv_ldc_copy_in %d\n", err);
867                                         break;
868                               }
869 
870                               if (desc.hdr.dstate != VIO_DESC_READY)
871                                         break;
872 
873                               if (desc.nbytes > (ETHER_MAX_LEN - ETHER_CRC_LEN)) {
874                                         if_statinc(ifp, if_ierrors);
875                                         goto skip;
876                               }
877 
878                               MGETHDR(m, M_DONTWAIT, MT_DATA);
879                               if (m == NULL) {
880                                         DPRINTF(("%s: MGETHDR failed\n", __func__));
881                                         if_statinc(ifp, if_ierrors);
882                                         goto skip;
883                               }
884                               MCLGET(m, M_DONTWAIT);
885                               if ((m->m_flags & M_EXT) == 0)
886                                         break;
887                               m->m_len = m->m_pkthdr.len = desc.nbytes;
888                               nbytes = roundup(desc.nbytes + VNET_ETHER_ALIGN, 8);
889 
890                               pmap_extract(pmap_kernel(), (vaddr_t)m->m_data, &pa);
891                               err = hv_ldc_copy(lc->lc_id, LDC_COPY_IN,
892                                   desc.cookie[0].addr, pa, nbytes, &nbytes);
893                               if (err != H_EOK) {
894                                         m_freem(m);
895                                         goto skip;
896                               }
897                               m->m_data += VNET_ETHER_ALIGN;
898                               m_set_rcvif(m, ifp);
899 
900                               if_percpuq_enqueue(ifp->if_percpuq, m);
901 
902                     skip:
903                               desc.hdr.dstate = VIO_DESC_DONE;
904                               nbytes = sc->sc_peer_desc_size;
905                               err = hv_ldc_copy(lc->lc_id, LDC_COPY_OUT, cookie,
906                                   desc_pa, nbytes, &nbytes);
907                               if (err != H_EOK)
908                                         printf("hv_ldc_copy_out %d\n", err);
909 
910                               ack_end_idx = idx;
911                               if (++idx == sc->sc_peer_dring_nentries)
912                                         idx = 0;
913                     }
914 
915                     if (ack_end_idx == -1) {
916                               dm->tag.stype = VIO_SUBTYPE_NACK;
917                     } else {
918                               dm->tag.stype = VIO_SUBTYPE_ACK;
919                               dm->end_idx = ack_end_idx;
920                     }
921                     dm->tag.sid = sc->sc_local_sid;
922                     dm->proc_state = VIO_DP_STOPPED;
923                     vnet_sendmsg(sc, dm, sizeof(*dm));
924                     break;
925           }
926 
927           case VIO_SUBTYPE_ACK:
928           {
929                     DPRINTF(("%s: VIO_SUBTYPE_ACK\n", __func__));
930                     struct ldc_map *map = sc->sc_lm;
931                     u_int cons, count;
932 
933                     sc->sc_peer_state = dm->proc_state;
934 
935                     cons = sc->sc_tx_cons & (sc->sc_vd->vd_nentries - 1);
936                     while (sc->sc_vd->vd_desc[cons].hdr.dstate == VIO_DESC_DONE) {
937                               map->lm_slot[sc->sc_vsd[cons].vsd_map_idx].entry = 0;
938                               atomic_dec_32(&map->lm_count);
939 
940                               pool_put(&sc->sc_pool, sc->sc_vsd[cons].vsd_buf);
941                               sc->sc_vsd[cons].vsd_buf = NULL;
942 
943                               sc->sc_vd->vd_desc[cons].hdr.dstate = VIO_DESC_FREE;
944                               sc->sc_tx_cons++;
945                               cons = sc->sc_tx_cons & (sc->sc_vd->vd_nentries - 1);
946                     }
947 
948                     count = sc->sc_tx_prod - sc->sc_tx_cons;
949                     if (count > 0 && sc->sc_peer_state != VIO_DP_ACTIVE)
950                               vnet_send_dring_data(sc, cons);
951 
952                     KERNEL_LOCK(1, curlwp);
953                     if (count == 0)
954                               ifp->if_timer = 0;
955 
956                     vnet_start(ifp);
957                     KERNEL_UNLOCK_ONE(curlwp);
958                     break;
959           }
960 
961           case VIO_SUBTYPE_NACK:
962                     DPRINTF(("DATA/NACK/DRING_DATA\n"));
963                     sc->sc_peer_state = VIO_DP_STOPPED;
964                     break;
965 
966           default:
967                     DPRINTF(("DATA/0x%02x/DRING_DATA\n", tag->stype));
968                     break;
969           }
970 }
971 
972 void
vnet_ldc_reset(struct ldc_conn * lc)973 vnet_ldc_reset(struct ldc_conn *lc)
974 {
975 
976           struct vnet_softc *sc = lc->lc_sc;
977           int i;
978 
979           callout_stop(&sc->sc_handshake_co);
980           sc->sc_tx_prod = sc->sc_tx_cons = 0;
981           sc->sc_peer_state = VIO_DP_STOPPED;
982           sc->sc_vio_state = 0;
983           vnet_link_state(sc);
984 
985           sc->sc_lm->lm_next = 1;
986           sc->sc_lm->lm_count = 1;
987           for (i = 1; i < sc->sc_lm->lm_nentries; i++)
988                     sc->sc_lm->lm_slot[i].entry = 0;
989 
990           for (i = 0; i < sc->sc_vd->vd_nentries; i++) {
991                     if (sc->sc_vsd[i].vsd_buf) {
992                               pool_put(&sc->sc_pool, sc->sc_vsd[i].vsd_buf);
993                               sc->sc_vsd[i].vsd_buf = NULL;
994                     }
995                     sc->sc_vd->vd_desc[i].hdr.dstate = VIO_DESC_FREE;
996           }
997 }
998 
999 void
vnet_ldc_start(struct ldc_conn * lc)1000 vnet_ldc_start(struct ldc_conn *lc)
1001 {
1002           struct vnet_softc *sc = lc->lc_sc;
1003           callout_stop(&sc->sc_handshake_co);
1004           vnet_send_ver_info(sc, VNET_MAJOR, VNET_MINOR);
1005 }
1006 
1007 void
vnet_sendmsg(struct vnet_softc * sc,void * msg,size_t len)1008 vnet_sendmsg(struct vnet_softc *sc, void *msg, size_t len)
1009 {
1010           struct ldc_conn *lc = &sc->sc_lc;
1011           int err;
1012 
1013           err = ldc_send_unreliable(lc, msg, len);
1014           if (err)
1015                     printf("%s: ldc_send_unreliable: %d\n", __func__, err);
1016 }
1017 
1018 void
vnet_send_ver_info(struct vnet_softc * sc,uint16_t major,uint16_t minor)1019 vnet_send_ver_info(struct vnet_softc *sc, uint16_t major, uint16_t minor)
1020 {
1021           struct vio_ver_info vi;
1022 
1023           bzero(&vi, sizeof(vi));
1024           vi.tag.type = VIO_TYPE_CTRL;
1025           vi.tag.stype = VIO_SUBTYPE_INFO;
1026           vi.tag.stype_env = VIO_VER_INFO;
1027           vi.tag.sid = sc->sc_local_sid;
1028           vi.major = major;
1029           vi.minor = minor;
1030           vi.dev_class = VDEV_NETWORK;
1031           vnet_sendmsg(sc, &vi, sizeof(vi));
1032 
1033           sc->sc_vio_state |= VIO_SND_VER_INFO;
1034 }
1035 
1036 void
vnet_send_attr_info(struct vnet_softc * sc)1037 vnet_send_attr_info(struct vnet_softc *sc)
1038 {
1039           struct vnet_attr_info ai;
1040           int i;
1041 
1042           bzero(&ai, sizeof(ai));
1043           ai.tag.type = VIO_TYPE_CTRL;
1044           ai.tag.stype = VIO_SUBTYPE_INFO;
1045           ai.tag.stype_env = VIO_ATTR_INFO;
1046           ai.tag.sid = sc->sc_local_sid;
1047           ai.xfer_mode = VIO_DRING_MODE;
1048           ai.addr_type = VNET_ADDR_ETHERMAC;
1049           ai.ack_freq = 0;
1050           ai.addr = 0;
1051           for (i = 0; i < ETHER_ADDR_LEN; i++) {
1052                     ai.addr <<= 8;
1053                     ai.addr |= sc->sc_macaddr[i];
1054           }
1055           ai.mtu = ETHER_MAX_LEN - ETHER_CRC_LEN;
1056           vnet_sendmsg(sc, &ai, sizeof(ai));
1057 
1058           sc->sc_vio_state |= VIO_SND_ATTR_INFO;
1059 }
1060 
1061 void
vnet_send_dring_reg(struct vnet_softc * sc)1062 vnet_send_dring_reg(struct vnet_softc *sc)
1063 {
1064           struct vio_dring_reg dr;
1065 
1066           bzero(&dr, sizeof(dr));
1067           dr.tag.type = VIO_TYPE_CTRL;
1068           dr.tag.stype = VIO_SUBTYPE_INFO;
1069           dr.tag.stype_env = VIO_DRING_REG;
1070           dr.tag.sid = sc->sc_local_sid;
1071           dr.dring_ident = 0;
1072           dr.num_descriptors = sc->sc_vd->vd_nentries;
1073           dr.descriptor_size = sizeof(struct vnet_desc);
1074           dr.options = VIO_TX_RING;
1075           dr.ncookies = 1;
1076           dr.cookie[0].addr = 0;
1077           dr.cookie[0].size = PAGE_SIZE;
1078           vnet_sendmsg(sc, &dr, sizeof(dr));
1079 
1080           sc->sc_vio_state |= VIO_SND_DRING_REG;
1081 };
1082 
1083 void
vio_send_rdx(struct vnet_softc * sc)1084 vio_send_rdx(struct vnet_softc *sc)
1085 {
1086           struct vio_msg_tag tag;
1087 
1088           tag.type = VIO_TYPE_CTRL;
1089           tag.stype = VIO_SUBTYPE_INFO;
1090           tag.stype_env = VIO_RDX;
1091           tag.sid = sc->sc_local_sid;
1092           vnet_sendmsg(sc, &tag, sizeof(tag));
1093 
1094           sc->sc_vio_state |= VIO_SND_RDX;
1095 }
1096 
1097 void
vnet_send_dring_data(struct vnet_softc * sc,uint32_t start_idx)1098 vnet_send_dring_data(struct vnet_softc *sc, uint32_t start_idx)
1099 {
1100           struct vio_dring_msg dm;
1101           u_int peer_state;
1102 
1103           peer_state = atomic_swap_uint(&sc->sc_peer_state, VIO_DP_ACTIVE);
1104           if (peer_state == VIO_DP_ACTIVE) {
1105                     DPRINTF(("%s: peer_state == VIO_DP_ACTIVE\n", __func__));
1106                     return;
1107           }
1108 
1109           bzero(&dm, sizeof(dm));
1110           dm.tag.type = VIO_TYPE_DATA;
1111           dm.tag.stype = VIO_SUBTYPE_INFO;
1112           dm.tag.stype_env = VIO_DRING_DATA;
1113           dm.tag.sid = sc->sc_local_sid;
1114           dm.seq_no = sc->sc_seq_no++;
1115           dm.dring_ident = sc->sc_dring_ident;
1116           dm.start_idx = start_idx;
1117           dm.end_idx = -1;
1118           vnet_sendmsg(sc, &dm, sizeof(dm));
1119 }
1120 
1121 void
vnet_start(struct ifnet * ifp)1122 vnet_start(struct ifnet *ifp)
1123 {
1124           struct vnet_softc *sc = ifp->if_softc;
1125           struct ldc_conn *lc = &sc->sc_lc;
1126           struct ldc_map *map = sc->sc_lm;
1127           struct mbuf *m;
1128           paddr_t pa;
1129           unsigned char *buf;
1130           uint64_t tx_head, tx_tail, tx_state;
1131           u_int start, prod, count;
1132           int err;
1133           if (!(ifp->if_flags & IFF_RUNNING))
1134           {
1135                     DPRINTF(("%s: not in RUNNING state\n", __func__));
1136                     return;
1137           }
1138 
1139           if (IFQ_IS_EMPTY(&ifp->if_snd))
1140           {
1141                     DPRINTF(("%s: queue is empty\n", __func__));
1142                     return;
1143           } else {
1144                     DPRINTF(("%s: queue size %d\n", __func__, ifp->if_snd.ifq_len));
1145           }
1146 
1147           /*
1148            * We cannot transmit packets until a VIO connection has been
1149            * established.
1150            */
1151           if (!ISSET(sc->sc_vio_state, VIO_RCV_RDX) ||
1152               !ISSET(sc->sc_vio_state, VIO_ACK_RDX))
1153           {
1154                     DPRINTF(("%s: vio connection not established yet\n", __func__));
1155                     return;
1156           }
1157 
1158           /*
1159            * Make sure there is room in the LDC transmit queue to send a
1160            * DRING_DATA message.
1161            */
1162           err = hv_ldc_tx_get_state(lc->lc_id, &tx_head, &tx_tail, &tx_state);
1163           if (err != H_EOK) {
1164                     DPRINTF(("%s: no room in ldc transmit queue\n", __func__));
1165                     return;
1166           }
1167           tx_tail += sizeof(struct ldc_pkt);
1168           tx_tail &= ((lc->lc_txq->lq_nentries * sizeof(struct ldc_pkt)) - 1);
1169           if (tx_tail == tx_head) {
1170                     {
1171                               DPRINTF(("%s: tail equals head\n", __func__));
1172                               return;
1173                     }
1174           }
1175 
1176           if (sc->sc_xfer_mode == VIO_DESC_MODE) {
1177                     DPRINTF(("%s: vio_desc_mode\n", __func__));
1178                     vnet_start_desc(ifp);
1179                     return;
1180           }
1181 
1182           start = prod = sc->sc_tx_prod & (sc->sc_vd->vd_nentries - 1);
1183           while (sc->sc_vd->vd_desc[prod].hdr.dstate == VIO_DESC_FREE) {
1184                     count = sc->sc_tx_prod - sc->sc_tx_cons;
1185                     if (count >= (sc->sc_vd->vd_nentries - 1) ||
1186                         map->lm_count >= map->lm_nentries) {
1187                               DPRINTF(("%s: count issue\n", __func__));
1188                               break;
1189                     }
1190 
1191                     buf = pool_get(&sc->sc_pool, PR_NOWAIT|PR_ZERO);
1192                     if (buf == NULL) {
1193                               DPRINTF(("%s: buff is NULL\n", __func__));
1194                               break;
1195                     }
1196                     IFQ_DEQUEUE(&ifp->if_snd, m);
1197                     if (m == NULL) {
1198                               pool_put(&sc->sc_pool, buf);
1199                               break;
1200                     }
1201 
1202                     m_copydata(m, 0, m->m_pkthdr.len, buf + VNET_ETHER_ALIGN);
1203 
1204 #if NBPFILTER > 0
1205                     /*
1206                      * If BPF is listening on this interface, let it see the
1207                      * packet before we commit it to the wire.
1208                      */
1209                     DPRINTF(("%s: before bpf\n", __func__));
1210                     bpf_mtap(ifp, m, BPF_D_OUT);
1211                     DPRINTF(("%s: after bpf\n", __func__));
1212 #endif
1213 
1214                     pmap_extract(pmap_kernel(), (vaddr_t)buf, &pa);
1215                     KASSERT((pa & ~PAGE_MASK) == (pa & LDC_MTE_RA_MASK));
1216                     while (map->lm_slot[map->lm_next].entry != 0) {
1217                               map->lm_next++;
1218                               map->lm_next &= (map->lm_nentries - 1);
1219                     }
1220                     map->lm_slot[map->lm_next].entry = (pa & LDC_MTE_RA_MASK);
1221                     map->lm_slot[map->lm_next].entry |= LDC_MTE_CPR;
1222                     atomic_inc_32(&map->lm_count);
1223                     sc->sc_vd->vd_desc[prod].nbytes = MAX(m->m_pkthdr.len, 60);
1224                     sc->sc_vd->vd_desc[prod].ncookies = 1;
1225                     sc->sc_vd->vd_desc[prod].cookie[0].addr =
1226                         map->lm_next << PAGE_SHIFT | (pa & PAGE_MASK);
1227                     sc->sc_vd->vd_desc[prod].cookie[0].size = 2048;
1228                     membar_producer();
1229                     sc->sc_vd->vd_desc[prod].hdr.dstate = VIO_DESC_READY;
1230 
1231                     sc->sc_vsd[prod].vsd_map_idx = map->lm_next;
1232                     sc->sc_vsd[prod].vsd_buf = buf;
1233 
1234                     sc->sc_tx_prod++;
1235                     prod = sc->sc_tx_prod & (sc->sc_vd->vd_nentries - 1);
1236 
1237                     m_freem(m);
1238           }
1239 
1240           membar_producer();
1241 
1242           if (start != prod && sc->sc_peer_state != VIO_DP_ACTIVE) {
1243                     vnet_send_dring_data(sc, start);
1244                     ifp->if_timer = 5;
1245           }
1246 
1247 }
1248 
1249 void
vnet_start_desc(struct ifnet * ifp)1250 vnet_start_desc(struct ifnet *ifp)
1251 {
1252           struct vnet_softc *sc = ifp->if_softc;
1253           struct ldc_map *map = sc->sc_lm;
1254           struct vnet_desc_msg dm;
1255           struct mbuf *m;
1256           paddr_t pa;
1257           unsigned char *buf;
1258           u_int prod, count;
1259 
1260           for (;;) {
1261                     count = sc->sc_tx_prod - sc->sc_tx_cons;
1262                     if (count >= (sc->sc_vd->vd_nentries - 1) ||
1263                         map->lm_count >= map->lm_nentries) {
1264                               return;
1265                     }
1266 
1267                     buf = pool_get(&sc->sc_pool, PR_NOWAIT|PR_ZERO);
1268                     if (buf == NULL) {
1269                               return;
1270                     }
1271 
1272                     IFQ_DEQUEUE(&ifp->if_snd, m);
1273 
1274                     if (m == NULL) {
1275                               pool_put(&sc->sc_pool, buf);
1276                               return;
1277                     }
1278 
1279                     m_copydata(m, 0, m->m_pkthdr.len, buf);
1280 
1281 #if NBPFILTER > 0
1282                     /*
1283                      * If BPF is listening on this interface, let it see the
1284                      * packet before we commit it to the wire.
1285                      */
1286                     bpf_mtap(ifp, m, BPF_D_OUT);
1287 #endif
1288 
1289                     pmap_extract(pmap_kernel(), (vaddr_t)buf, &pa);
1290                     KASSERT((pa & ~PAGE_MASK) == (pa & LDC_MTE_RA_MASK));
1291                     while (map->lm_slot[map->lm_next].entry != 0) {
1292                               map->lm_next++;
1293                               map->lm_next &= (map->lm_nentries - 1);
1294                     }
1295                     map->lm_slot[map->lm_next].entry = (pa & LDC_MTE_RA_MASK);
1296                     map->lm_slot[map->lm_next].entry |= LDC_MTE_CPR;
1297                     atomic_inc_32(&map->lm_count);
1298 
1299                     prod = sc->sc_tx_prod & (sc->sc_vd->vd_nentries - 1);
1300                     sc->sc_vsd[prod].vsd_map_idx = map->lm_next;
1301                     sc->sc_vsd[prod].vsd_buf = buf;
1302 
1303                     bzero(&dm, sizeof(dm));
1304                     dm.tag.type = VIO_TYPE_DATA;
1305                     dm.tag.stype = VIO_SUBTYPE_INFO;
1306                     dm.tag.stype_env = VIO_DESC_DATA;
1307                     dm.tag.sid = sc->sc_local_sid;
1308                     dm.seq_no = sc->sc_seq_no++;
1309                     dm.desc_handle = sc->sc_tx_prod;
1310                     dm.nbytes = MAX(m->m_pkthdr.len, 60);
1311                     dm.ncookies = 1;
1312                     dm.cookie[0].addr =
1313                               map->lm_next << PAGE_SHIFT | (pa & PAGE_MASK);
1314                     dm.cookie[0].size = 2048;
1315                     vnet_sendmsg(sc, &dm, sizeof(dm));
1316 
1317                     sc->sc_tx_prod++;
1318                     sc->sc_tx_prod &= (sc->sc_vd->vd_nentries - 1);
1319 
1320                     m_freem(m);
1321           }
1322 }
1323 
1324 int
vnet_ioctl(struct ifnet * ifp,u_long cmd,void * data)1325 vnet_ioctl(struct ifnet *ifp, u_long cmd, void* data)
1326 {
1327           struct vnet_softc *sc = ifp->if_softc;
1328           struct ifreq *ifr = (struct ifreq *)data;
1329           int s, error = 0;
1330 
1331           s = splnet();
1332 
1333           switch (cmd) {
1334 
1335                     case SIOCSIFADDR:
1336                               ifp->if_flags |= IFF_UP;
1337                               /* FALLTHROUGH */
1338                     case SIOCSIFFLAGS:
1339                               if (ifp->if_flags & IFF_UP) {
1340                                         if ((ifp->if_flags & IFF_RUNNING) == 0)
1341                                                   vnet_init(ifp);
1342                               } else {
1343                                         if (ifp->if_flags & IFF_RUNNING)
1344                                                   vnet_stop(ifp, 0);
1345                               }
1346                     break;
1347 
1348                     case SIOCGIFMEDIA:
1349                     case SIOCSIFMEDIA:
1350                               error = ifmedia_ioctl(ifp, ifr, &sc->sc_media, cmd);
1351                               break;
1352 
1353                     case SIOCADDMULTI:
1354                     case SIOCDELMULTI:
1355                               /*
1356                                * XXX Removing all multicast addresses and adding
1357                                * most of them back, is somewhat retarded.
1358                                */
1359                               vnet_setmulti(sc, 0);
1360                               error = ether_ioctl(ifp, cmd, data);
1361                               vnet_setmulti(sc, 1);
1362                               if (error == ENETRESET)
1363                                         error = 0;
1364                               break;
1365 
1366                     default:
1367                               error = ether_ioctl(ifp, cmd, data);
1368           }
1369 
1370           splx(s);
1371 
1372           return (error);
1373 }
1374 
1375 void
vnet_watchdog(struct ifnet * ifp)1376 vnet_watchdog(struct ifnet *ifp)
1377 {
1378 
1379           struct vnet_softc *sc = ifp->if_softc;
1380 
1381           printf("%s: watchdog timeout\n", device_xname(sc->sc_dv));
1382 }
1383 
1384 int
vnet_media_change(struct ifnet * ifp)1385 vnet_media_change(struct ifnet *ifp)
1386 {
1387           return (0);
1388 }
1389 
1390 void
vnet_media_status(struct ifnet * ifp,struct ifmediareq * imr)1391 vnet_media_status(struct ifnet *ifp, struct ifmediareq *imr)
1392 {
1393           imr->ifm_active = IFM_ETHER | IFM_AUTO;
1394           imr->ifm_status = IFM_AVALID;
1395           if (ifp->if_link_state == LINK_STATE_UP &&
1396               ifp->if_flags & IFF_UP)
1397                     imr->ifm_status |= IFM_ACTIVE;
1398 }
1399 
1400 void
vnet_link_state(struct vnet_softc * sc)1401 vnet_link_state(struct vnet_softc *sc)
1402 {
1403           struct ifnet *ifp = &sc->sc_ethercom.ec_if;
1404           int link_state = LINK_STATE_DOWN;
1405 
1406           KERNEL_LOCK(1, curlwp);
1407           if (ISSET(sc->sc_vio_state, VIO_RCV_RDX) &&
1408               ISSET(sc->sc_vio_state, VIO_ACK_RDX))
1409                     link_state = LINK_STATE_UP;
1410           if (ifp->if_link_state != link_state) {
1411                     if_link_state_change(ifp, link_state);
1412           }
1413           KERNEL_UNLOCK_ONE(curlwp);
1414 }
1415 
1416 void
vnet_setmulti(struct vnet_softc * sc,int set)1417 vnet_setmulti(struct vnet_softc *sc, int set)
1418 {
1419           struct ethercom *ec = &sc->sc_ethercom;
1420           struct ether_multi *enm;
1421           struct ether_multistep step;
1422           struct vnet_mcast_info mi;
1423           int count = 0;
1424 
1425           if (!ISSET(sc->sc_vio_state, VIO_RCV_RDX) ||
1426               !ISSET(sc->sc_vio_state, VIO_ACK_RDX))
1427                     return;
1428 
1429           bzero(&mi, sizeof(mi));
1430           mi.tag.type = VIO_TYPE_CTRL;
1431           mi.tag.stype = VIO_SUBTYPE_INFO;
1432           mi.tag.stype_env = VNET_MCAST_INFO;
1433           mi.tag.sid = sc->sc_local_sid;
1434           mi.set = set ? 1 : 0;
1435           KERNEL_LOCK(1, curlwp);
1436           ETHER_FIRST_MULTI(step, ec, enm);
1437           while (enm != NULL) {
1438                     /* XXX What about multicast ranges? */
1439                     bcopy(enm->enm_addrlo, mi.mcast_addr[count], ETHER_ADDR_LEN);
1440                     ETHER_NEXT_MULTI(step, enm);
1441 
1442                     count++;
1443                     if (count < VNET_NUM_MCAST)
1444                               continue;
1445 
1446                     mi.count = VNET_NUM_MCAST;
1447                     vnet_sendmsg(sc, &mi, sizeof(mi));
1448                     count = 0;
1449           }
1450 
1451           if (count > 0) {
1452                     mi.count = count;
1453                     vnet_sendmsg(sc, &mi, sizeof(mi));
1454           }
1455           KERNEL_UNLOCK_ONE(curlwp);
1456 }
1457 
1458 
1459 int
vnet_init(struct ifnet * ifp)1460 vnet_init(struct ifnet *ifp)
1461 {
1462           struct vnet_softc *sc = ifp->if_softc;
1463           struct ldc_conn *lc = &sc->sc_lc;
1464           int err;
1465           vaddr_t va;
1466           paddr_t pa;
1467           sc->sc_lm = ldc_map_alloc(2048);
1468           if (sc->sc_lm == NULL)
1469                     return ENOMEM;
1470 
1471           va = (vaddr_t)sc->sc_lm->lm_slot;
1472           pa = 0;
1473           if (pmap_extract(pmap_kernel(), va, &pa) == FALSE)
1474                     panic("pmap_extract failed %lx\n", va);
1475           err = hv_ldc_set_map_table(lc->lc_id, pa, 2048);
1476           if (err != H_EOK) {
1477                     printf("hv_ldc_set_map_table %d\n", err);
1478                     return EINVAL;
1479           }
1480 
1481           sc->sc_vd = vnet_dring_alloc(sc->sc_dmatag, VNET_NUM_SOFT_DESC);
1482           if (sc->sc_vd == NULL)
1483                     return ENOMEM;
1484           sc->sc_vsd = malloc(VNET_NUM_SOFT_DESC * sizeof(*sc->sc_vsd), M_DEVBUF,
1485               M_NOWAIT|M_ZERO);
1486           if (sc->sc_vsd == NULL)
1487                     return ENOMEM;
1488 
1489           va = (vaddr_t)sc->sc_vd->vd_desc;
1490           pa = 0;
1491           if (pmap_extract(pmap_kernel(), va, &pa) == FALSE)
1492                     panic("pmap_extract failed %lx\n", va);
1493           sc->sc_lm->lm_slot[0].entry = pa;
1494           sc->sc_lm->lm_slot[0].entry &= LDC_MTE_RA_MASK;
1495           sc->sc_lm->lm_slot[0].entry |= LDC_MTE_CPR | LDC_MTE_CPW;
1496           sc->sc_lm->lm_next = 1;
1497           sc->sc_lm->lm_count = 1;
1498 
1499           va = lc->lc_txq->lq_va;
1500           pa = 0;
1501           if (pmap_extract(pmap_kernel(), va, &pa) == FALSE)
1502                     panic("pmap_extract failed %lx\n", va);
1503           err = hv_ldc_tx_qconf(lc->lc_id, pa, lc->lc_txq->lq_nentries);
1504           if (err != H_EOK)
1505                     printf("hv_ldc_tx_qconf %d\n", err);
1506 
1507           va = (vaddr_t)lc->lc_rxq->lq_va;
1508           pa = 0;
1509           if (pmap_extract(pmap_kernel(), va, &pa) == FALSE)
1510             panic("pmap_extract failed %lx\n", va);
1511 
1512           err = hv_ldc_rx_qconf(lc->lc_id, pa, lc->lc_rxq->lq_nentries);
1513           if (err != H_EOK)
1514                     printf("hv_ldc_rx_qconf %d\n", err);
1515 
1516           cbus_intr_setenabled(sc->sc_bustag, sc->sc_tx_ino, INTR_ENABLED);
1517           cbus_intr_setenabled(sc->sc_bustag, sc->sc_rx_ino, INTR_ENABLED);
1518 
1519           ldc_send_vers(lc);
1520 
1521           ifp->if_flags |= IFF_RUNNING;
1522 
1523           return 0;
1524 }
1525 
1526 void
vnet_stop(struct ifnet * ifp,int disable)1527 vnet_stop(struct ifnet *ifp, int disable)
1528 
1529 {
1530           struct vnet_softc *sc = ifp->if_softc;
1531           struct ldc_conn *lc = &sc->sc_lc;
1532 
1533           ifp->if_flags &= ~IFF_RUNNING;
1534           ifp->if_timer = 0;
1535 
1536           cbus_intr_setenabled(sc->sc_bustag, sc->sc_tx_ino, INTR_DISABLED);
1537           cbus_intr_setenabled(sc->sc_bustag, sc->sc_rx_ino, INTR_DISABLED);
1538 
1539 #if 0
1540 openbsd XXX
1541           intr_barrier(sc->sc_tx_ih);
1542           intr_barrier(sc->sc_rx_ih);
1543 #else
1544           printf("vnet_stop() intr_barrier() not available\n");
1545 #endif
1546 
1547           hv_ldc_tx_qconf(lc->lc_id, 0, 0);
1548           hv_ldc_rx_qconf(lc->lc_id, 0, 0);
1549           lc->lc_tx_seqid = 0;
1550           lc->lc_state = 0;
1551           lc->lc_tx_state = lc->lc_rx_state = LDC_CHANNEL_DOWN;
1552           vnet_ldc_reset(lc);
1553 
1554           free(sc->sc_vsd, M_DEVBUF);
1555 
1556           vnet_dring_free(sc->sc_dmatag, sc->sc_vd);
1557 
1558           hv_ldc_set_map_table(lc->lc_id, 0, 0);
1559           ldc_map_free(sc->sc_lm);
1560 }
1561 
1562 struct vnet_dring *
vnet_dring_alloc(bus_dma_tag_t t,int nentries)1563 vnet_dring_alloc(bus_dma_tag_t t, int nentries)
1564 {
1565           struct vnet_dring *vd;
1566           bus_size_t size;
1567           vaddr_t va;
1568           int i;
1569 
1570           vd = kmem_zalloc(sizeof(struct vnet_dring), KM_SLEEP);
1571           if (vd == NULL)
1572                     return NULL;
1573 
1574           size = roundup(nentries * sizeof(struct vnet_desc), PAGE_SIZE);
1575 
1576           va = (vaddr_t)kmem_zalloc(size, KM_SLEEP);
1577           vd->vd_desc = (struct vnet_desc *)va;
1578           vd->vd_nentries = nentries;
1579           bzero(vd->vd_desc, nentries * sizeof(struct vnet_desc));
1580           for (i = 0; i < vd->vd_nentries; i++)
1581                     vd->vd_desc[i].hdr.dstate = VIO_DESC_FREE;
1582           return (vd);
1583 
1584           return (NULL);
1585 }
1586 
1587 void
vnet_dring_free(bus_dma_tag_t t,struct vnet_dring * vd)1588 vnet_dring_free(bus_dma_tag_t t, struct vnet_dring *vd)
1589 {
1590 
1591           bus_size_t size;
1592 
1593           size = vd->vd_nentries * sizeof(struct vnet_desc);
1594           size = roundup(size, PAGE_SIZE);
1595 
1596           kmem_free(vd->vd_desc, size);
1597           kmem_free(vd, size);
1598 }
1599 
1600