Date: Sat, 24 Apr 2010 22:09:13 +0000 (UTC) From: Juli Mallett <jmallett@FreeBSD.org> To: src-committers@freebsd.org, svn-src-user@freebsd.org Subject: svn commit: r207165 - user/jmallett/octeon/sys/mips/cavium/octe Message-ID: <201004242209.o3OM9D7F060513@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: jmallett Date: Sat Apr 24 22:09:13 2010 New Revision: 207165 URL: http://svn.freebsd.org/changeset/base/207165 Log: o) Disable REUSE_MBUFS_WITHOUT_FREE rather than commenting out the implementation. o) Basic transmit support. Enough to send a DHCP request and get a response and go on a bit before panicking. Modified: user/jmallett/octeon/sys/mips/cavium/octe/cavium-ethernet.h user/jmallett/octeon/sys/mips/cavium/octe/ethernet-common.c user/jmallett/octeon/sys/mips/cavium/octe/ethernet-defines.h user/jmallett/octeon/sys/mips/cavium/octe/ethernet-tx.c user/jmallett/octeon/sys/mips/cavium/octe/ethernet.c user/jmallett/octeon/sys/mips/cavium/octe/octe.c Modified: user/jmallett/octeon/sys/mips/cavium/octe/cavium-ethernet.h ============================================================================== --- user/jmallett/octeon/sys/mips/cavium/octe/cavium-ethernet.h Sat Apr 24 22:01:15 2010 (r207164) +++ user/jmallett/octeon/sys/mips/cavium/octe/cavium-ethernet.h Sat Apr 24 22:09:13 2010 (r207165) @@ -92,12 +92,10 @@ typedef struct { int queue; /* PKO hardware queue for the port */ int fau; /* Hardware fetch and add to count outstanding tx buffers */ int imode; /* Type of port. This is one of the enums in cvmx_helper_interface_mode_t */ - struct mbuf *tx_free_list[16];/* List of outstanding tx buffers per queue */ /* Keeping intercept_cb close the the part of stats that is most often modified helps throughput. */ cvm_oct_callback_t intercept_cb; /* Optional intecept callback defined above */ #if 0 struct ifnet_stats stats; /* Device statistics */ - struct mii_if_info mii_info; /* Generic MII info structure */ #endif uint64_t link_info; /* Last negotiated link state */ void (*poll)(struct ifnet *ifp); /* Called periodically to check link status */ @@ -117,6 +115,8 @@ typedef struct { uint8_t mac[6]; int phy_id; + struct ifqueue tx_free_queue[16]; + struct ifmedia media; int if_flags; } cvm_oct_private_t; Modified: user/jmallett/octeon/sys/mips/cavium/octe/ethernet-common.c ============================================================================== --- user/jmallett/octeon/sys/mips/cavium/octe/ethernet-common.c Sat Apr 24 22:01:15 2010 (r207164) +++ user/jmallett/octeon/sys/mips/cavium/octe/ethernet-common.c Sat Apr 24 22:09:13 2010 (r207165) @@ -253,11 +253,9 @@ int cvm_oct_common_init(struct ifnet *if #if 0 if (priv->queue != -1) { - ifp->hard_start_xmit = cvm_oct_xmit; if (USE_HW_TCPUDP_CHECKSUM) ifp->features |= NETIF_F_IP_CSUM; - } else - ifp->hard_start_xmit = cvm_oct_xmit_pow; + } #endif count++; Modified: user/jmallett/octeon/sys/mips/cavium/octe/ethernet-defines.h ============================================================================== --- user/jmallett/octeon/sys/mips/cavium/octe/ethernet-defines.h Sat Apr 24 22:01:15 2010 (r207164) +++ user/jmallett/octeon/sys/mips/cavium/octe/ethernet-defines.h Sat Apr 24 22:09:13 2010 (r207165) @@ -76,11 +76,15 @@ AND WITH ALL FAULTS AND CAVIUM NETWORKS #else #define USE_32BIT_SHARED 0 #define USE_MBUFS_IN_HW 1 +#if 0 #ifdef CONFIG_NETFILTER #define REUSE_MBUFS_WITHOUT_FREE 0 #else #define REUSE_MBUFS_WITHOUT_FREE 1 #endif +#else + #define REUSE_MBUFS_WITHOUT_FREE 0 +#endif #endif #define INTERRUPT_LIMIT 10000 /* Max interrupts per second per core */ Modified: user/jmallett/octeon/sys/mips/cavium/octe/ethernet-tx.c ============================================================================== --- user/jmallett/octeon/sys/mips/cavium/octe/ethernet-tx.c Sat Apr 24 22:01:15 2010 (r207164) +++ user/jmallett/octeon/sys/mips/cavium/octe/ethernet-tx.c Sat Apr 24 22:09:13 2010 (r207165) @@ -72,10 +72,8 @@ int cvm_oct_xmit(struct mbuf *m, struct int32_t in_use; int32_t buffers_to_free; #if REUSE_MBUFS_WITHOUT_FREE -#if 0 unsigned char *fpa_head; #endif -#endif /* Prefetch the private data structure. It is larger that one cache line */ @@ -115,7 +113,7 @@ int cvm_oct_xmit(struct mbuf *m, struct 68 bytes whenever we are in half duplex mode. We don't handle the case of having a small packet but no room to add the padding. The kernel should always give us at least a cache line */ - if ((m->m_pkthdr.len < 64) && OCTEON_IS_MODEL(OCTEON_CN3XXX)) { + if (__predict_false(m->m_pkthdr.len < 64) && OCTEON_IS_MODEL(OCTEON_CN3XXX)) { cvmx_gmxx_prtx_cfg_t gmx_prt_cfg; int interface = INTERFACE(priv->port); int index = INDEX(priv->port); @@ -124,27 +122,25 @@ int cvm_oct_xmit(struct mbuf *m, struct /* We only need to pad packet in half duplex mode */ gmx_prt_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(index, interface)); if (gmx_prt_cfg.s.duplex == 0) { - panic("%s: small packet padding not yet implemented.", __func__); -#if 0 - int add_bytes = 64 - m->len; - if ((m_tail_pointer(m) + add_bytes) <= m_end_pointer(m)) - memset(__m_put(m, add_bytes), 0, add_bytes); -#endif + static uint8_t pad[64]; + + if (!m_append(m, sizeof pad - m->m_pkthdr.len, pad)) + printf("%s: unable to padd small packet.", __func__); } } } /* Build the PKO buffer pointer */ - /* - * XXX/juli - * Implement mbuf loading. - */ -#if 0 + if (m->m_pkthdr.len != m->m_len) { + m = m_defrag(m, M_DONTWAIT); + if (m->m_pkthdr.len != m->m_len) + panic("%s: need to load multiple segments.", __func__); + } + hw_buffer.u64 = 0; hw_buffer.s.addr = cvmx_ptr_to_phys(m->m_data); hw_buffer.s.pool = 0; - hw_buffer.s.size = (unsigned long)m_end_pointer(m) - (unsigned long)m->head; -#endif + hw_buffer.s.size = m->m_len; /* Build the PKO command */ pko_command.u64 = 0; @@ -164,7 +160,6 @@ int cvm_oct_xmit(struct mbuf *m, struct the define REUSE_MBUFS_WITHOUT_FREE. The reuse of buffers has shown a 25% increase in performance under some loads */ #if REUSE_MBUFS_WITHOUT_FREE -#if 0 fpa_head = m->head + 128 - ((unsigned long)m->head&0x7f); if (__predict_false(m->data < fpa_head)) { /* @@ -248,9 +243,6 @@ int cvm_oct_xmit(struct mbuf *m, struct #endif /* CONFIG_NET_SCHED */ dont_put_mbuf_in_hw: -#else -#endif - panic("%s: not ready for REUSE_MBUFS_WITHOUT_FREE yet.", __func__); #endif /* REUSE_MBUFS_WITHOUT_FREE */ /* Check if we can use the hardware checksumming */ @@ -285,19 +277,12 @@ dont_put_mbuf_in_hw: cvmx_pko_send_packet_prepare(priv->port, priv->queue + qos, CVMX_PKO_LOCK_CMD_QUEUE); /* Drop this packet if we have too many already queued to the HW */ -#if 0 - if ((m_queue_len(&priv->tx_free_list[qos]) >= MAX_OUT_QUEUE_DEPTH)) { - /* - DEBUGPRINT("%s: Tx dropped. Too many queued\n", if_name(ifp)); - */ + if (_IF_QFULL(&priv->tx_free_queue[qos])) { dropped = 1; } /* Send the packet to the output queue */ else -#else - panic("%s: free queues really not implemented.", __func__); -#endif - if ((cvmx_pko_send_packet_finish(priv->port, priv->queue + qos, pko_command, hw_buffer, CVMX_PKO_LOCK_CMD_QUEUE))) { + if (__predict_false(cvmx_pko_send_packet_finish(priv->port, priv->queue + qos, pko_command, hw_buffer, CVMX_PKO_LOCK_CMD_QUEUE))) { DEBUGPRINT("%s: Failed to send the packet\n", if_name(ifp)); dropped = 1; } @@ -308,7 +293,7 @@ dont_put_mbuf_in_hw: cvmx_scratch_write64(CVMX_SCR_SCRATCH+8, old_scratch2); } - if ((dropped)) { + if (__predict_false(dropped)) { m_freem(m); cvmx_fau_atomic_add32(priv->fau+qos*4, -1); ifp->if_oerrors++; @@ -316,30 +301,26 @@ dont_put_mbuf_in_hw: if (USE_MBUFS_IN_HW) { /* Put this packet on the queue to be freed later */ if (pko_command.s.dontfree) - panic("%s: need to queue mbuf to free it later.", __func__); + IF_ENQUEUE(&priv->tx_free_queue[qos], m); else { cvmx_fau_atomic_add32(FAU_NUM_PACKET_BUFFERS_TO_FREE, -1); cvmx_fau_atomic_add32(priv->fau+qos*4, -1); } } else { /* Put this packet on the queue to be freed later */ - panic("%s: need to queue mbuf to free it later. (2)", __func__); + IF_ENQUEUE(&priv->tx_free_queue[qos], m); } } - /* Free mbufs not in use by the hardware, possibly two at a time */ - panic("%s: need to free queued mbufs.", __func__); -#if 0 - if (m_queue_len(&priv->tx_free_list[qos]) > in_use) { - spin_lock(&priv->tx_free_list[qos].lock); - /* Check again now that we have the lock. It might have changed */ - if (m_queue_len(&priv->tx_free_list[qos]) > in_use) - dev_kfree_m(__m_dequeue(&priv->tx_free_list[qos])); - if (m_queue_len(&priv->tx_free_list[qos]) > in_use) - dev_kfree_m(__m_dequeue(&priv->tx_free_list[qos])); - spin_unlock(&priv->tx_free_list[qos].lock); + /* Free mbufs not in use by the hardware */ + if (_IF_QLEN(&priv->tx_free_queue[qos]) > in_use) { + IF_LOCK(&priv->tx_free_queue[qos]); + while (_IF_QLEN(&priv->tx_free_queue[qos]) > in_use) { + _IF_DEQUEUE(&priv->tx_free_queue[qos], m); + m_freem(m); + } + IF_UNLOCK(&priv->tx_free_queue[qos]); } -#endif return 0; } @@ -360,7 +341,7 @@ int cvm_oct_xmit_pow(struct mbuf *m, str /* Get a work queue entry */ cvmx_wqe_t *work = cvmx_fpa_alloc(CVMX_FPA_WQE_POOL); - if ((work == NULL)) { + if (__predict_false(work == NULL)) { DEBUGPRINT("%s: Failed to allocate a work queue entry\n", if_name(ifp)); ifp->if_oerrors++; m_freem(m); @@ -369,7 +350,7 @@ int cvm_oct_xmit_pow(struct mbuf *m, str /* Get a packet buffer */ packet_buffer = cvmx_fpa_alloc(CVMX_FPA_PACKET_POOL); - if ((packet_buffer == NULL)) { + if (__predict_false(packet_buffer == NULL)) { DEBUGPRINT("%s: Failed to allocate a packet buffer\n", if_name(ifp)); cvmx_fpa_free(work, CVMX_FPA_WQE_POOL, DONT_WRITEBACK(1)); @@ -389,11 +370,7 @@ int cvm_oct_xmit_pow(struct mbuf *m, str /* We have to copy the packet since whoever processes this packet will free it to a hardware pool. We can't use the trick of counting outstanding packets like in cvm_oct_xmit */ -#if 0 - memcpy(copy_location, m->data, m->len); -#else - panic("%s: need to implement mbuf loading.", __func__); -#endif + m_copydata(m, 0, m->m_pkthdr.len, copy_location); /* Fill in some of the work queue fields. We may need to add more if the software at the other end needs them */ @@ -414,6 +391,7 @@ int cvm_oct_xmit_pow(struct mbuf *m, str work->packet_ptr.s.size = CVMX_FPA_PACKET_POOL_SIZE; work->packet_ptr.s.back = (copy_location - packet_buffer)>>7; + panic("%s: POW transmit not quite implemented yet.", __func__); #if 0 if (m->protocol == htons(ETH_P_IP)) { work->word2.s.ip_offset = 14; @@ -540,19 +518,19 @@ int cvm_oct_transmit_qos(struct ifnet *i pko_command.s.total_bytes = work->len; /* Check if we can use the hardware checksumming */ - if ((work->word2.s.not_IP || work->word2.s.IP_exc)) + if (__predict_false(work->word2.s.not_IP || work->word2.s.IP_exc)) pko_command.s.ipoffp1 = 0; else pko_command.s.ipoffp1 = ETHER_HDR_LEN + 1; /* Send the packet to the output queue */ - if ((cvmx_pko_send_packet_finish(priv->port, priv->queue + qos, pko_command, hw_buffer, CVMX_PKO_LOCK_CMD_QUEUE))) { + if (__predict_false(cvmx_pko_send_packet_finish(priv->port, priv->queue + qos, pko_command, hw_buffer, CVMX_PKO_LOCK_CMD_QUEUE))) { DEBUGPRINT("%s: Failed to send the packet\n", if_name(ifp)); dropped = -1; } critical_exit(); - if ((dropped)) { + if (__predict_false(dropped)) { if (do_free) cvm_oct_free_work(work); ifp->if_oerrors++; @@ -571,18 +549,10 @@ int cvm_oct_transmit_qos(struct ifnet *i */ void cvm_oct_tx_shutdown(struct ifnet *ifp) { -#if 0 cvm_oct_private_t *priv = (cvm_oct_private_t *)ifp->if_softc; - unsigned long flags; int qos; for (qos = 0; qos < 16; qos++) { - spin_lock_irqsave(&priv->tx_free_list[qos].lock, flags); - while (m_queue_len(&priv->tx_free_list[qos])) - dev_kfree_m_any(__m_dequeue(&priv->tx_free_list[qos])); - spin_unlock_irqrestore(&priv->tx_free_list[qos].lock, flags); + IF_DRAIN(&priv->tx_free_queue[qos]); } -#else - panic("%s: not yet implemented.", __func__); -#endif } Modified: user/jmallett/octeon/sys/mips/cavium/octe/ethernet.c ============================================================================== --- user/jmallett/octeon/sys/mips/cavium/octe/ethernet.c Sat Apr 24 22:01:15 2010 (r207164) +++ user/jmallett/octeon/sys/mips/cavium/octe/ethernet.c Sat Apr 24 22:09:13 2010 (r207165) @@ -396,12 +396,7 @@ int cvm_oct_init_module(device_t bus) priv->port = CVMX_PIP_NUM_INPUT_PORTS; priv->queue = -1; - if_initname(ifp, "pow", 0); device_set_desc(dev, "Cavium Octeon POW Ethernet\n"); -#if 0 - for (qos = 0; qos < 16; qos++) - m_queue_head_init(&priv->tx_free_list[qos]); -#endif ifp->if_softc = priv; @@ -452,10 +447,6 @@ int cvm_oct_init_module(device_t bus) priv->queue = cvmx_pko_get_base_queue(priv->port); priv->intercept_cb = NULL; priv->fau = fau - cvmx_pko_get_num_queues(port) * 4; -#if 0 - for (qos = 0; qos < 16; qos++) - m_queue_head_init(&priv->tx_free_list[qos]); -#endif for (qos = 0; qos < cvmx_pko_get_num_queues(port); qos++) cvmx_fau_atomic_write32(priv->fau+qos*4, 0); Modified: user/jmallett/octeon/sys/mips/cavium/octe/octe.c ============================================================================== --- user/jmallett/octeon/sys/mips/cavium/octe/octe.c Sat Apr 24 22:01:15 2010 (r207164) +++ user/jmallett/octeon/sys/mips/cavium/octe/octe.c Sat Apr 24 22:09:13 2010 (r207165) @@ -48,6 +48,7 @@ #include <sys/sockio.h> #include <sys/sysctl.h> +#include <net/bpf.h> #include <net/ethernet.h> #include <net/if.h> #include <net/if_media.h> @@ -60,7 +61,9 @@ #include "cavium-ethernet.h" #include "ethernet-common.h" +#include "ethernet-defines.h" #include "ethernet-mdio.h" +#include "ethernet-tx.h" #include "miibus_if.h" @@ -74,6 +77,7 @@ static int octe_miibus_writereg(device_ static void octe_init(void *); static void octe_stop(void *); +static void octe_start(struct ifnet *); static int octe_mii_medchange(struct ifnet *); static void octe_mii_medstat(struct ifnet *, struct ifmediareq *); @@ -129,6 +133,7 @@ octe_attach(device_t dev) { struct ifnet *ifp; cvm_oct_private_t *priv; + unsigned qos; int error; priv = device_get_softc(dev); @@ -153,11 +158,21 @@ octe_attach(device_t dev) ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; ifp->if_init = octe_init; ifp->if_ioctl = octe_ioctl; + ifp->if_start = octe_start; priv->if_flags = ifp->if_flags; + for (qos = 0; qos < 16; qos++) { + mtx_init(&priv->tx_free_queue[qos].ifq_mtx, ifp->if_xname, "octe tx free queue", MTX_DEF); + IFQ_SET_MAXLEN(&priv->tx_free_queue[qos], MAX_OUT_QUEUE_DEPTH); + } + ether_ifattach(ifp, priv->mac); + IFQ_SET_MAXLEN(&ifp->if_snd, 16); + ifp->if_snd.ifq_drv_maxlen = 16; /* XXX */ + IFQ_SET_READY(&ifp->if_snd); + return (0); } @@ -211,6 +226,9 @@ octe_init(void *arg) if (priv->miibus != NULL) mii_mediachg(device_get_softc(priv->miibus)); + + ifp->if_drv_flags |= IFF_DRV_RUNNING; + ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; } static void @@ -224,6 +242,46 @@ octe_stop(void *arg) if (priv->stop != NULL) priv->stop(ifp); + + ifp->if_drv_flags &= ~IFF_DRV_RUNNING; +} + +static void +octe_start(struct ifnet *ifp) +{ + cvm_oct_private_t *priv; + struct mbuf *m; + int error; + + priv = ifp->if_softc; + + if ((ifp->if_drv_flags & (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)) != IFF_DRV_RUNNING) + return; + + while (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) { + IFQ_DRV_DEQUEUE(&ifp->if_snd, m); + + if (priv->queue != -1) { + error = cvm_oct_xmit(m, ifp); + } else { + error = cvm_oct_xmit_pow(m, ifp); + } + + if (error != 0) { + /* + * XXX + * Need to implement freeing and clearing of + * OACTIVE at some point. + * + * XXX + * Incremenet errors? Maybe make xmit functions + * not free the packets? + */ + ifp->if_drv_flags |= IFF_DRV_OACTIVE; + } + + BPF_MTAP(ifp, m); + } } static int @@ -283,7 +341,7 @@ octe_medstat(struct ifnet *ifp, struct i link_info.u64 = priv->link_info; - if (!link_info.s.link_up) + if (!link_info.s.link_up) return; ifm->ifm_status |= IFM_ACTIVE;
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201004242209.o3OM9D7F060513>