if_arge.c (289476) | if_arge.c (289671) |
---|---|
1/*- 2 * Copyright (c) 2009, Oleksandr Tymoshenko 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 --- 12 unchanged lines hidden (view full) --- 21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 */ 27 28#include <sys/cdefs.h> | 1/*- 2 * Copyright (c) 2009, Oleksandr Tymoshenko 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 --- 12 unchanged lines hidden (view full) --- 21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 */ 27 28#include <sys/cdefs.h> |
29__FBSDID("$FreeBSD: head/sys/mips/atheros/if_arge.c 289476 2015-10-18 00:59:28Z adrian $"); | 29__FBSDID("$FreeBSD: head/sys/mips/atheros/if_arge.c 289671 2015-10-21 01:41:18Z adrian $"); |
30 31/* 32 * AR71XX gigabit ethernet driver 33 */ 34#ifdef HAVE_KERNEL_OPTION_HEADERS 35#include "opt_device_polling.h" 36#endif 37 --- 2122 unchanged lines hidden (view full) --- 2160{ 2161 struct arge_desc *desc; 2162 struct arge_rxdesc *rxd; 2163 struct mbuf *m; 2164 bus_dma_segment_t segs[1]; 2165 bus_dmamap_t map; 2166 int nsegs; 2167 | 30 31/* 32 * AR71XX gigabit ethernet driver 33 */ 34#ifdef HAVE_KERNEL_OPTION_HEADERS 35#include "opt_device_polling.h" 36#endif 37 --- 2122 unchanged lines hidden (view full) --- 2160{ 2161 struct arge_desc *desc; 2162 struct arge_rxdesc *rxd; 2163 struct mbuf *m; 2164 bus_dma_segment_t segs[1]; 2165 bus_dmamap_t map; 2166 int nsegs; 2167 |
2168 /* XXX TODO: should just allocate an explicit 2KiB buffer */ |
|
2168 m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR); 2169 if (m == NULL) 2170 return (ENOBUFS); 2171 m->m_len = m->m_pkthdr.len = MCLBYTES; 2172 2173 /* 2174 * Add extra space to "adjust" (copy) the packet back to be aligned 2175 * for purposes of IPv4/IPv6 header contents. 2176 */ | 2169 m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR); 2170 if (m == NULL) 2171 return (ENOBUFS); 2172 m->m_len = m->m_pkthdr.len = MCLBYTES; 2173 2174 /* 2175 * Add extra space to "adjust" (copy) the packet back to be aligned 2176 * for purposes of IPv4/IPv6 header contents. 2177 */ |
2177 m_adj(m, sizeof(uint64_t)); | 2178 if (sc->arge_hw_flags & ARGE_HW_FLG_RX_DESC_ALIGN_4BYTE) 2179 m_adj(m, sizeof(uint64_t)); 2180 /* 2181 * If it's a 1-byte aligned buffer, then just offset it two bytes 2182 * and that will give us a hopefully correctly DWORD aligned 2183 * L3 payload - and we won't have to undo it afterwards. 2184 */ 2185 else if (sc->arge_hw_flags & ARGE_HW_FLG_RX_DESC_ALIGN_1BYTE) 2186 m_adj(m, sizeof(uint16_t)); |
2178 2179 if (bus_dmamap_load_mbuf_sg(sc->arge_cdata.arge_rx_tag, 2180 sc->arge_cdata.arge_rx_sparemap, m, segs, &nsegs, 0) != 0) { 2181 m_freem(m); 2182 return (ENOBUFS); 2183 } 2184 KASSERT(nsegs == 1, ("%s: %d segments returned!", __func__, nsegs)); 2185 2186 rxd = &sc->arge_cdata.arge_rxdesc[idx]; 2187 if (rxd->rx_m != NULL) { 2188 bus_dmamap_unload(sc->arge_cdata.arge_rx_tag, rxd->rx_dmamap); | 2187 2188 if (bus_dmamap_load_mbuf_sg(sc->arge_cdata.arge_rx_tag, 2189 sc->arge_cdata.arge_rx_sparemap, m, segs, &nsegs, 0) != 0) { 2190 m_freem(m); 2191 return (ENOBUFS); 2192 } 2193 KASSERT(nsegs == 1, ("%s: %d segments returned!", __func__, nsegs)); 2194 2195 rxd = &sc->arge_cdata.arge_rxdesc[idx]; 2196 if (rxd->rx_m != NULL) { 2197 bus_dmamap_unload(sc->arge_cdata.arge_rx_tag, rxd->rx_dmamap); |
2198 /* XXX TODO: free rx_m? */ 2199 device_printf(sc->arge_dev, 2200 "%s: ring[%d] rx_m wasn't free?\n", 2201 __func__, 2202 idx); |
|
2189 } 2190 map = rxd->rx_dmamap; 2191 rxd->rx_dmamap = sc->arge_cdata.arge_rx_sparemap; 2192 sc->arge_cdata.arge_rx_sparemap = map; 2193 rxd->rx_m = m; 2194 desc = rxd->desc; 2195 if ((sc->arge_hw_flags & ARGE_HW_FLG_RX_DESC_ALIGN_4BYTE) && 2196 segs[0].ds_addr & 3) 2197 panic("RX packet address unaligned"); 2198 desc->packet_addr = segs[0].ds_addr; 2199 desc->packet_ctrl = ARGE_DESC_EMPTY | ARGE_DMASIZE(segs[0].ds_len); 2200 2201 bus_dmamap_sync(sc->arge_cdata.arge_rx_ring_tag, 2202 sc->arge_cdata.arge_rx_ring_map, 2203 BUS_DMASYNC_PREWRITE); 2204 2205 return (0); 2206} 2207 | 2203 } 2204 map = rxd->rx_dmamap; 2205 rxd->rx_dmamap = sc->arge_cdata.arge_rx_sparemap; 2206 sc->arge_cdata.arge_rx_sparemap = map; 2207 rxd->rx_m = m; 2208 desc = rxd->desc; 2209 if ((sc->arge_hw_flags & ARGE_HW_FLG_RX_DESC_ALIGN_4BYTE) && 2210 segs[0].ds_addr & 3) 2211 panic("RX packet address unaligned"); 2212 desc->packet_addr = segs[0].ds_addr; 2213 desc->packet_ctrl = ARGE_DESC_EMPTY | ARGE_DMASIZE(segs[0].ds_len); 2214 2215 bus_dmamap_sync(sc->arge_cdata.arge_rx_ring_tag, 2216 sc->arge_cdata.arge_rx_ring_map, 2217 BUS_DMASYNC_PREWRITE); 2218 2219 return (0); 2220} 2221 |
2222/* 2223 * Move the data backwards 16 bits to (hopefully!) ensure the 2224 * IPv4/IPv6 payload is aligned. 2225 * 2226 * This is required for earlier hardware where the RX path 2227 * requires DWORD aligned buffers. 2228 */ |
|
2208static __inline void 2209arge_fixup_rx(struct mbuf *m) 2210{ 2211 int i; 2212 uint16_t *src, *dst; 2213 2214 src = mtod(m, uint16_t *); 2215 dst = src - 1; --- 123 unchanged lines hidden (view full) --- 2339 2340 prog++; 2341 2342 packet_len = ARGE_DMASIZE(cur_rx->packet_ctrl); 2343 bus_dmamap_sync(sc->arge_cdata.arge_rx_tag, rxd->rx_dmamap, 2344 BUS_DMASYNC_POSTREAD); 2345 m = rxd->rx_m; 2346 | 2229static __inline void 2230arge_fixup_rx(struct mbuf *m) 2231{ 2232 int i; 2233 uint16_t *src, *dst; 2234 2235 src = mtod(m, uint16_t *); 2236 dst = src - 1; --- 123 unchanged lines hidden (view full) --- 2360 2361 prog++; 2362 2363 packet_len = ARGE_DMASIZE(cur_rx->packet_ctrl); 2364 bus_dmamap_sync(sc->arge_cdata.arge_rx_tag, rxd->rx_dmamap, 2365 BUS_DMASYNC_POSTREAD); 2366 m = rxd->rx_m; 2367 |
2347 arge_fixup_rx(m); | 2368 /* 2369 * If the MAC requires 4 byte alignment then the RX setup 2370 * routine will have pre-offset things; so un-offset it here. 2371 */ 2372 if (sc->arge_hw_flags & ARGE_HW_FLG_RX_DESC_ALIGN_4BYTE) 2373 arge_fixup_rx(m); 2374 |
2348 m->m_pkthdr.rcvif = ifp; 2349 /* Skip 4 bytes of CRC */ 2350 m->m_pkthdr.len = m->m_len = packet_len - ETHER_CRC_LEN; 2351 if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1); 2352 rx_npkts++; 2353 2354 ARGE_UNLOCK(sc); 2355 (*ifp->if_input)(ifp, m); --- 246 unchanged lines hidden --- | 2375 m->m_pkthdr.rcvif = ifp; 2376 /* Skip 4 bytes of CRC */ 2377 m->m_pkthdr.len = m->m_len = packet_len - ETHER_CRC_LEN; 2378 if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1); 2379 rx_npkts++; 2380 2381 ARGE_UNLOCK(sc); 2382 (*ifp->if_input)(ifp, m); --- 246 unchanged lines hidden --- |