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 |