Split common TX/RX descriptor DMA tag to TX and RX DMA tags
respectively and fix all bus_dma(9) issues seen when bounce buffers are used. o Setup frame handling had no bus_dmamap_sync(9) which prevented driver from configuring RX filter. Add missing bus_dmamap_sync(9) in both dc_setfilt_21143()/dc_setfilt_xircom() and dc_txeof(). o Use bus_addr_t for DMA segment instead of using u_int32_t. o Introduce dc_dma_alloc()/dc_dma_free() functions to allocate/free DMA'able memory. o Create two DMA descriptor list for each TX/RX lists. This change will minimize the size of bounce buffers that would be used in each TX/RX path. Previously driver had to copy both TX/RX lists when bounce buffer is active. o 21143 data sheet says descriptor list requires 4 bytes alignment. Remove PAGE_SIZE alignment restriction and use sizeof(struct dc_dec). o Setup frame requires 4 bytes alignment. Remove PAGE_SIZE alignment restriction and use sizeof(struct dc_dec). o Add missing DMA map unload for both setup frame and TX/RX descriptor list. o Overhaul RX handling logic such that make driver always allocate new RX buffer with dc_newbuf(). Previously driver allowed to copy received frame with m_devget(9) after passing the descriptor ownership to controller. This can lead to passing wrong frame to upper stack. o Introduce dc_discard_rxbuf() which will discard received frame and reuse loaded DMA map and RX mbuf. o Correct several wrong bus_dmamap_sync(9) usage in dc_rxeof and dc_txeof. The TX/RX descriptor lists are updated by both driver and HW so READ/WRITE semantics should be used. o If driver failed to allocate new RX buffer, update if_iqdrops counter instead of if_ierrors since driver received the frame without errors. o Make sure to unload loaded setup frame DMA map in dc_txeof and clear the mark of setup frame of the TX descriptor in dc_txeof(). o Add check for possible TX descriptor overruns in dc_encap() and move check for free buffer to caller, dc_start_locked(). o Swap the loaded DMA map and the last DMA map for multi-segmented frames. Since dc_txeof() assumes the last descriptor of the frame has the DMA map, driver should swap the first and the last DMA map in dc_encap(). Previously driver tried to unload not-yet-loaded DMA map such that the loaded DMA map was not unloaded at all for multi-segmented frames. o Rewrite DC_RXDESC/DC_TXDESC macro to simpler one. o Remove definition of ETHER_ALIGN, it's already defined in ethernet.h. With this changes, dc(4) works with bounce buffers and it shall also fix issues which might have shown in PAE environments. Tested by: marius
This commit is contained in:
parent
a84b4e80ca
commit
5f14ee2363
File diff suppressed because it is too large
Load Diff
@ -471,11 +471,15 @@ struct dc_desc {
|
||||
|
||||
#define DC_INC(x, y) (x) = (x + 1) % y
|
||||
|
||||
#define DC_LIST_ALIGN (sizeof(struct dc_desc))
|
||||
#define DC_RXBUF_ALIGN 4
|
||||
|
||||
/* Macros to easily get the DMA address of a descriptor. */
|
||||
#define DC_RXDESC(sc, i) (sc->dc_laddr + \
|
||||
(uintptr_t)(sc->dc_ldata->dc_rx_list + i) - (uintptr_t)sc->dc_ldata)
|
||||
#define DC_TXDESC(sc, i) (sc->dc_laddr + \
|
||||
(uintptr_t)(sc->dc_ldata->dc_tx_list + i) - (uintptr_t)sc->dc_ldata)
|
||||
#define DC_ADDR_LO(x) ((uint64_t)(x) & 0xFFFFFFFF)
|
||||
#define DC_RXDESC(sc, i) \
|
||||
(DC_ADDR_LO(sc->dc_ldata.dc_rx_list_paddr + (sizeof(struct dc_desc) * i)))
|
||||
#define DC_TXDESC(sc, i) \
|
||||
(DC_ADDR_LO(sc->dc_ldata.dc_tx_list_paddr + (sizeof(struct dc_desc) * i)))
|
||||
|
||||
#if BYTE_ORDER == BIG_ENDIAN
|
||||
#define DC_SP_MAC(x) ((x) << 16)
|
||||
@ -484,10 +488,15 @@ struct dc_desc {
|
||||
#endif
|
||||
|
||||
struct dc_list_data {
|
||||
struct dc_desc dc_rx_list[DC_RX_LIST_CNT];
|
||||
struct dc_desc dc_tx_list[DC_TX_LIST_CNT];
|
||||
struct dc_desc *dc_rx_list;
|
||||
bus_addr_t dc_rx_list_paddr;
|
||||
struct dc_desc *dc_tx_list;
|
||||
bus_addr_t dc_tx_list_paddr;
|
||||
};
|
||||
|
||||
#define DC_RX_LIST_SZ ((sizeof(struct dc_desc) * DC_RX_LIST_CNT))
|
||||
#define DC_TX_LIST_SZ ((sizeof(struct dc_desc) * DC_TX_LIST_CNT))
|
||||
|
||||
struct dc_chain_data {
|
||||
struct mbuf *dc_rx_chain[DC_RX_LIST_CNT];
|
||||
struct mbuf *dc_tx_chain[DC_TX_LIST_CNT];
|
||||
@ -722,14 +731,17 @@ struct dc_softc {
|
||||
device_t dc_dev; /* device info */
|
||||
bus_space_handle_t dc_bhandle; /* bus space handle */
|
||||
bus_space_tag_t dc_btag; /* bus space tag */
|
||||
bus_dma_tag_t dc_ltag; /* tag for descriptor ring */
|
||||
bus_dmamap_t dc_lmap; /* map for descriptor ring */
|
||||
u_int32_t dc_laddr; /* DMA address of dc_ldata */
|
||||
bus_dma_tag_t dc_mtag; /* tag for mbufs */
|
||||
bus_dma_tag_t dc_ptag; /* parent DMA tag */
|
||||
bus_dmamap_t dc_sparemap;
|
||||
bus_dma_tag_t dc_rx_ltag; /* tag for RX descriptors */
|
||||
bus_dmamap_t dc_rx_lmap;
|
||||
bus_dma_tag_t dc_tx_ltag; /* tag for TX descriptors */
|
||||
bus_dmamap_t dc_tx_lmap;
|
||||
bus_dma_tag_t dc_stag; /* tag for the setup frame */
|
||||
bus_dmamap_t dc_smap; /* map for the setup frame */
|
||||
u_int32_t dc_saddr; /* DMA address of setup frame */
|
||||
bus_addr_t dc_saddr; /* DMA address of setup frame */
|
||||
bus_dma_tag_t dc_rx_mtag; /* tag for RX mbufs */
|
||||
bus_dma_tag_t dc_tx_mtag; /* tag for TX mbufs */
|
||||
void *dc_intrhand;
|
||||
struct resource *dc_irq;
|
||||
struct resource *dc_res;
|
||||
@ -749,7 +761,7 @@ struct dc_softc {
|
||||
u_int32_t dc_eaddr[2];
|
||||
u_int8_t *dc_srom;
|
||||
struct dc_mediainfo *dc_mi;
|
||||
struct dc_list_data *dc_ldata;
|
||||
struct dc_list_data dc_ldata;
|
||||
struct dc_chain_data dc_cdata;
|
||||
struct callout dc_stat_ch;
|
||||
struct callout dc_wdog_ch;
|
||||
@ -796,7 +808,6 @@ struct dc_softc {
|
||||
bus_space_barrier(sc->dc_btag, sc->dc_bhandle, reg, 4, flags)
|
||||
|
||||
#define DC_TIMEOUT 1000
|
||||
#define ETHER_ALIGN 2
|
||||
|
||||
/*
|
||||
* General constants that are fun to know.
|
||||
|
Loading…
Reference in New Issue
Block a user