Deleted Added
full compact
phyp_llan.c (256778) phyp_llan.c (257292)
1/*-
2 * Copyright 2013 Nathan Whitehorn
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 11 unchanged lines hidden (view full) ---

20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 */
26
27#include <sys/cdefs.h>
1/*-
2 * Copyright 2013 Nathan Whitehorn
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 11 unchanged lines hidden (view full) ---

20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 */
26
27#include <sys/cdefs.h>
28__FBSDID("$FreeBSD: head/sys/powerpc/pseries/phyp_llan.c 256778 2013-10-20 01:31:09Z nwhitehorn $");
28__FBSDID("$FreeBSD: stable/10/sys/powerpc/pseries/phyp_llan.c 257292 2013-10-28 23:47:52Z nwhitehorn $");
29
30#include <sys/param.h>
31#include <sys/systm.h>
32#include <sys/sockio.h>
33#include <sys/endian.h>
34#include <sys/mbuf.h>
35#include <sys/module.h>
36#include <sys/malloc.h>

--- 18 unchanged lines hidden (view full) ---

55#include <sys/rman.h>
56
57#include <powerpc/pseries/phyp-hvcall.h>
58
59#define LLAN_MAX_RX_PACKETS 100
60#define LLAN_MAX_TX_PACKETS 100
61#define LLAN_RX_BUF_LEN 8*PAGE_SIZE
62
29
30#include <sys/param.h>
31#include <sys/systm.h>
32#include <sys/sockio.h>
33#include <sys/endian.h>
34#include <sys/mbuf.h>
35#include <sys/module.h>
36#include <sys/malloc.h>

--- 18 unchanged lines hidden (view full) ---

55#include <sys/rman.h>
56
57#include <powerpc/pseries/phyp-hvcall.h>
58
59#define LLAN_MAX_RX_PACKETS 100
60#define LLAN_MAX_TX_PACKETS 100
61#define LLAN_RX_BUF_LEN 8*PAGE_SIZE
62
63#define LLAN_BUFDESC_VALID (1ULL << 63)
64#define LLAN_ADD_MULTICAST 0x1
65#define LLAN_DEL_MULTICAST 0x2
66#define LLAN_CLEAR_MULTICAST 0x3
67
63struct llan_xfer {
64 struct mbuf *rx_mbuf;
65 bus_dmamap_t rx_dmamap;
66 uint64_t rx_bufdesc;
67};
68
69struct llan_receive_queue_entry { /* PAPR page 539 */
70 uint8_t control;

--- 37 unchanged lines hidden (view full) ---

108static int llan_attach(device_t);
109static void llan_intr(void *xsc);
110static void llan_init(void *xsc);
111static void llan_start(struct ifnet *ifp);
112static int llan_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data);
113static void llan_rx_load_cb(void *xsc, bus_dma_segment_t *segs, int nsegs,
114 int err);
115static int llan_add_rxbuf(struct llan_softc *sc, struct llan_xfer *rx);
68struct llan_xfer {
69 struct mbuf *rx_mbuf;
70 bus_dmamap_t rx_dmamap;
71 uint64_t rx_bufdesc;
72};
73
74struct llan_receive_queue_entry { /* PAPR page 539 */
75 uint8_t control;

--- 37 unchanged lines hidden (view full) ---

113static int llan_attach(device_t);
114static void llan_intr(void *xsc);
115static void llan_init(void *xsc);
116static void llan_start(struct ifnet *ifp);
117static int llan_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data);
118static void llan_rx_load_cb(void *xsc, bus_dma_segment_t *segs, int nsegs,
119 int err);
120static int llan_add_rxbuf(struct llan_softc *sc, struct llan_xfer *rx);
121static int llan_set_multicast(struct llan_softc *sc);
116
117static devclass_t llan_devclass;
118static device_method_t llan_methods[] = {
119 DEVMETHOD(device_probe, llan_probe),
120 DEVMETHOD(device_attach, llan_attach),
121
122 DEVMETHOD_END
123};

--- 120 unchanged lines hidden (view full) ---

244 mtx_lock(&sc->io_lock);
245
246 phyp_hcall(H_FREE_LOGICAL_LAN, sc->unit);
247
248 /* Create buffers (page 539) */
249 sc->rx_dma_slot = 0;
250 sc->rx_valid_val = 1;
251
122
123static devclass_t llan_devclass;
124static device_method_t llan_methods[] = {
125 DEVMETHOD(device_probe, llan_probe),
126 DEVMETHOD(device_attach, llan_attach),
127
128 DEVMETHOD_END
129};

--- 120 unchanged lines hidden (view full) ---

250 mtx_lock(&sc->io_lock);
251
252 phyp_hcall(H_FREE_LOGICAL_LAN, sc->unit);
253
254 /* Create buffers (page 539) */
255 sc->rx_dma_slot = 0;
256 sc->rx_valid_val = 1;
257
252 rx_buf_desc = (1UL << 63); /* valid */
258 rx_buf_desc = LLAN_BUFDESC_VALID;
253 rx_buf_desc |= (sc->rx_buf_len << 32);
254 rx_buf_desc |= sc->rx_buf_phys;
255 memcpy(&macaddr, sc->mac_address, 8);
256 err = phyp_hcall(H_REGISTER_LOGICAL_LAN, sc->unit, sc->input_buf_phys,
257 rx_buf_desc, sc->filter_buf_phys, macaddr);
258
259 for (i = 0; i < LLAN_MAX_RX_PACKETS; i++)
260 llan_add_rxbuf(sc, &sc->rx_xfer[i]);

--- 41 unchanged lines hidden (view full) ---

302
303 /* If nsegs is wrong then the stack is corrupt. */
304 KASSERT(nsegs == 1,
305 ("%s: too many DMA segments (%d)", __func__, nsegs));
306 rx->rx_mbuf = m;
307
308 bus_dmamap_sync(sc->rxbuf_dma_tag, rx->rx_dmamap, BUS_DMASYNC_PREREAD);
309
259 rx_buf_desc |= (sc->rx_buf_len << 32);
260 rx_buf_desc |= sc->rx_buf_phys;
261 memcpy(&macaddr, sc->mac_address, 8);
262 err = phyp_hcall(H_REGISTER_LOGICAL_LAN, sc->unit, sc->input_buf_phys,
263 rx_buf_desc, sc->filter_buf_phys, macaddr);
264
265 for (i = 0; i < LLAN_MAX_RX_PACKETS; i++)
266 llan_add_rxbuf(sc, &sc->rx_xfer[i]);

--- 41 unchanged lines hidden (view full) ---

308
309 /* If nsegs is wrong then the stack is corrupt. */
310 KASSERT(nsegs == 1,
311 ("%s: too many DMA segments (%d)", __func__, nsegs));
312 rx->rx_mbuf = m;
313
314 bus_dmamap_sync(sc->rxbuf_dma_tag, rx->rx_dmamap, BUS_DMASYNC_PREREAD);
315
310 rx->rx_bufdesc = (1UL << 63); /* valid */
316 rx->rx_bufdesc = LLAN_BUFDESC_VALID;
311 rx->rx_bufdesc |= (((uint64_t)segs[0].ds_len) << 32);
312 rx->rx_bufdesc |= segs[0].ds_addr;
313 error = phyp_hcall(H_ADD_LOGICAL_LAN_BUFFER, sc->unit, rx->rx_bufdesc);
314 if (error != 0) {
315 m_freem(m);
316 rx->rx_mbuf = NULL;
317 return (ENOBUFS);
318 }

--- 52 unchanged lines hidden (view full) ---

371{
372 struct llan_softc *sc = xsc;
373 uint64_t bufdescs[6];
374 int i;
375
376 bzero(bufdescs, sizeof(bufdescs));
377
378 for (i = 0; i < nsegs; i++) {
317 rx->rx_bufdesc |= (((uint64_t)segs[0].ds_len) << 32);
318 rx->rx_bufdesc |= segs[0].ds_addr;
319 error = phyp_hcall(H_ADD_LOGICAL_LAN_BUFFER, sc->unit, rx->rx_bufdesc);
320 if (error != 0) {
321 m_freem(m);
322 rx->rx_mbuf = NULL;
323 return (ENOBUFS);
324 }

--- 52 unchanged lines hidden (view full) ---

377{
378 struct llan_softc *sc = xsc;
379 uint64_t bufdescs[6];
380 int i;
381
382 bzero(bufdescs, sizeof(bufdescs));
383
384 for (i = 0; i < nsegs; i++) {
379 bufdescs[i] = (1UL << 63); /* valid */
385 bufdescs[i] = LLAN_BUFDESC_VALID;
380 bufdescs[i] |= (((uint64_t)segs[i].ds_len) << 32);
381 bufdescs[i] |= segs[i].ds_addr;
382 }
383
386 bufdescs[i] |= (((uint64_t)segs[i].ds_len) << 32);
387 bufdescs[i] |= segs[i].ds_addr;
388 }
389
384 error = phyp_hcall(H_SEND_LOGICAL_LAN, sc->unit, bufdescs[0],
390 phyp_hcall(H_SEND_LOGICAL_LAN, sc->unit, bufdescs[0],
385 bufdescs[1], bufdescs[2], bufdescs[3], bufdescs[4], bufdescs[5], 0);
391 bufdescs[1], bufdescs[2], bufdescs[3], bufdescs[4], bufdescs[5], 0);
386#if 0
387 if (error)
388 sc->ifp->if_drv_flags |= IFF_DRV_OACTIVE;
389
390 /* XXX: handle H_BUSY? */
391 /* H_SEND_LOGICAL_LAN returning 0 implies completion of the send op */
392#endif
392 /*
393 * The hypercall returning implies completion -- or that the call will
394 * not complete. In principle, we should try a few times if we get back
395 * H_BUSY based on the continuation token in R4. For now, just drop
396 * the packet in such cases.
397 */
393}
394
395static void
396llan_start_locked(struct ifnet *ifp)
397{
398 struct llan_softc *sc = ifp->if_softc;
399 bus_addr_t first;
400 int nsegs;

--- 19 unchanged lines hidden (view full) ---

420 if (nsegs > 6) {
421 m = m_collapse(mb_head, M_NOWAIT, 6);
422 if (m == NULL) {
423 m_freem(mb_head);
424 continue;
425 }
426 }
427
398}
399
400static void
401llan_start_locked(struct ifnet *ifp)
402{
403 struct llan_softc *sc = ifp->if_softc;
404 bus_addr_t first;
405 int nsegs;

--- 19 unchanged lines hidden (view full) ---

425 if (nsegs > 6) {
426 m = m_collapse(mb_head, M_NOWAIT, 6);
427 if (m == NULL) {
428 m_freem(mb_head);
429 continue;
430 }
431 }
432
428 bus_dmamap_load_mbuf(sc->tx_dma_tag, sc->tx_dma_map, //xfer->dmamap,
433 bus_dmamap_load_mbuf(sc->tx_dma_tag, sc->tx_dma_map,
429 mb_head, llan_send_packet, sc, 0);
434 mb_head, llan_send_packet, sc, 0);
430 bus_dmamap_unload(sc->tx_dma_tag, sc->tx_dma_map); // XXX
435 bus_dmamap_unload(sc->tx_dma_tag, sc->tx_dma_map);
431 m_freem(mb_head);
432 }
433}
434
435static void
436llan_start(struct ifnet *ifp)
437{
438 struct llan_softc *sc = ifp->if_softc;
439
440 mtx_lock(&sc->io_lock);
441 llan_start_locked(ifp);
442 mtx_unlock(&sc->io_lock);
443}
444
445static int
436 m_freem(mb_head);
437 }
438}
439
440static void
441llan_start(struct ifnet *ifp)
442{
443 struct llan_softc *sc = ifp->if_softc;
444
445 mtx_lock(&sc->io_lock);
446 llan_start_locked(ifp);
447 mtx_unlock(&sc->io_lock);
448}
449
450static int
451llan_set_multicast(struct llan_softc *sc)
452{
453 struct ifnet *ifp = sc->ifp;
454 struct ifmultiaddr *inm;
455 uint64_t macaddr;
456
457 mtx_assert(&sc->io_lock, MA_OWNED);
458
459 phyp_hcall(H_MULTICAST_CTRL, sc->unit, LLAN_CLEAR_MULTICAST, 0);
460
461 if_maddr_rlock(ifp);
462 TAILQ_FOREACH(inm, &ifp->if_multiaddrs, ifma_link) {
463 if (inm->ifma_addr->sa_family != AF_LINK)
464 continue;
465
466 memcpy((uint8_t *)&macaddr + 2,
467 LLADDR((struct sockaddr_dl *)inm->ifma_addr), 6);
468 phyp_hcall(H_MULTICAST_CTRL, sc->unit, LLAN_ADD_MULTICAST,
469 macaddr);
470 }
471 if_maddr_runlock(ifp);
472
473 return (0);
474}
475
476static int
446llan_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
447{
477llan_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
478{
448 int err;
479 int err = 0;
480 struct llan_softc *sc = ifp->if_softc;
449
481
450 err = ether_ioctl(ifp, cmd, data);
482 switch (cmd) {
483 case SIOCADDMULTI:
484 case SIOCDELMULTI:
485 mtx_lock(&sc->io_lock);
486 if ((sc->ifp->if_drv_flags & IFF_DRV_RUNNING) != 0)
487 llan_set_multicast(sc);
488 mtx_unlock(&sc->io_lock);
489 break;
490 case SIOCSIFFLAGS:
491 default:
492 err = ether_ioctl(ifp, cmd, data);
493 break;
494 }
451
452 return (err);
453}
454
495
496 return (err);
497}
498