From 7e7801e54ee1429d7ec4c87fd12633f86b100f9f Mon Sep 17 00:00:00 2001 From: Russell King Date: Sun, 23 Mar 2014 15:17:13 +0000 Subject: net: fec: use a union for the buffer descriptors Using a union gives clearer C code than the existing solution, and allows the removal of some odd code from the receive path whose purpose was to merely store the enhanced buffer descriptor. Signed-off-by: Russell King --- drivers/net/ethernet/freescale/fec.h | 14 +- drivers/net/ethernet/freescale/fec_main.c | 256 ++++++++++++++---------------- 2 files changed, 130 insertions(+), 140 deletions(-) diff --git a/drivers/net/ethernet/freescale/fec.h b/drivers/net/ethernet/freescale/fec.h index a1caee8fd648..e850e7e5118f 100644 --- a/drivers/net/ethernet/freescale/fec.h +++ b/drivers/net/ethernet/freescale/fec.h @@ -170,6 +170,11 @@ struct bufdesc_ex { unsigned short res0[4]; }; +union bufdesc_u { + struct bufdesc bd; + struct bufdesc_ex ebd; +}; + /* * The following definitions courtesy of commproc.h, which where * Copyright (c) 1997 Dan Malek (dmalek@jlc.net). @@ -288,14 +293,13 @@ struct fec_enet_private { dma_addr_t rx_bd_dma; dma_addr_t tx_bd_dma; /* Address of Rx and Tx buffers */ - struct bufdesc *rx_bd_base; - struct bufdesc *tx_bd_base; + union bufdesc_u *rx_bd_base; + union bufdesc_u *tx_bd_base; /* The next free ring entry */ - struct bufdesc *cur_rx, *cur_tx; + union bufdesc_u *cur_rx, *cur_tx; /* The ring entries to be free()ed */ - struct bufdesc *dirty_tx; + union bufdesc_u *dirty_tx; - unsigned short bufdesc_size; unsigned short tx_ring_size; unsigned short rx_ring_size; unsigned short tx_stop_threshold; diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c index 27ef27f6994f..c49f2e22e6ee 100644 --- a/drivers/net/ethernet/freescale/fec_main.c +++ b/drivers/net/ethernet/freescale/fec_main.c @@ -265,68 +265,73 @@ MODULE_PARM_DESC(macaddr, "FEC Ethernet MAC address"); static int mii_cnt; static inline -struct bufdesc *fec_enet_get_nextdesc(struct bufdesc *bdp, struct fec_enet_private *fep) +union bufdesc_u *fec_enet_get_nextdesc(union bufdesc_u *bdp, struct fec_enet_private *fep) { - struct bufdesc *new_bd = bdp + 1; - struct bufdesc_ex *ex_new_bd = (struct bufdesc_ex *)bdp + 1; - struct bufdesc_ex *ex_base; - struct bufdesc *base; + union bufdesc_u *base; int ring_size; if (bdp >= fep->tx_bd_base) { base = fep->tx_bd_base; ring_size = fep->tx_ring_size; - ex_base = (struct bufdesc_ex *)fep->tx_bd_base; } else { base = fep->rx_bd_base; ring_size = fep->rx_ring_size; - ex_base = (struct bufdesc_ex *)fep->rx_bd_base; } - if (fep->bufdesc_ex) - return (struct bufdesc *)((ex_new_bd >= (ex_base + ring_size)) ? - ex_base : ex_new_bd); - else - return (new_bd >= (base + ring_size)) ? - base : new_bd; + if (fep->bufdesc_ex) { + struct bufdesc_ex *ebd = &bdp->ebd + 1; + return ebd >= (&base->ebd + ring_size) ? + base : (union bufdesc_u *)ebd; + } else { + struct bufdesc *bd = &bdp->bd + 1; + return bd >= (&base->bd + ring_size) ? + base : (union bufdesc_u *)bd; + } } static inline -struct bufdesc *fec_enet_get_prevdesc(struct bufdesc *bdp, struct fec_enet_private *fep) +union bufdesc_u *fec_enet_get_prevdesc(union bufdesc_u *bdp, struct fec_enet_private *fep) { - struct bufdesc *new_bd = bdp - 1; - struct bufdesc_ex *ex_new_bd = (struct bufdesc_ex *)bdp - 1; - struct bufdesc_ex *ex_base; - struct bufdesc *base; + union bufdesc_u *base; int ring_size; if (bdp >= fep->tx_bd_base) { base = fep->tx_bd_base; ring_size = fep->tx_ring_size; - ex_base = (struct bufdesc_ex *)fep->tx_bd_base; } else { base = fep->rx_bd_base; ring_size = fep->rx_ring_size; - ex_base = (struct bufdesc_ex *)fep->rx_bd_base; } - if (fep->bufdesc_ex) - return (struct bufdesc *)((ex_new_bd < ex_base) ? - (ex_new_bd + ring_size) : ex_new_bd); - else - return (new_bd < base) ? (new_bd + ring_size) : new_bd; + if (fep->bufdesc_ex) { + struct bufdesc_ex *ebd = &bdp->ebd - 1; + return (union bufdesc_u *)(ebd < &base->ebd ? + ebd + ring_size : ebd); + } else { + struct bufdesc *bd = &bdp->bd - 1; + return (union bufdesc_u *)(bd < &base->bd ? + bd + ring_size : bd); + } } -static int fec_enet_get_bd_index(struct bufdesc *base, struct bufdesc *bdp, +static int fec_enet_get_bd_index(union bufdesc_u *base, union bufdesc_u *bdp, struct fec_enet_private *fep) { - return ((const char *)bdp - (const char *)base) / fep->bufdesc_size; + if (fep->bufdesc_ex) + return &bdp->ebd - &base->ebd; + else + return &bdp->bd - &base->bd; } static unsigned int fec_enet_get_free_txdesc_num(struct fec_enet_private *fep) { - int num = ((const char *)fep->dirty_tx - - (const char *)fep->cur_tx) / fep->bufdesc_size; + int num; + + if (fep->bufdesc_ex) + num = &fep->dirty_tx->ebd - &fep->cur_tx->ebd; + else + num = &fep->dirty_tx->bd - &fep->cur_tx->bd; + return num < 0 ? num + fep->tx_ring_size : num; } @@ -344,7 +349,7 @@ static void *swap_buffer(void *bufaddr, int len) static void fec_dump(struct net_device *ndev) { struct fec_enet_private *fep = netdev_priv(ndev); - struct bufdesc *bdp = fep->tx_bd_base; + union bufdesc_u *bdp = fep->tx_bd_base; unsigned int index = 0; netdev_info(ndev, "TX ring dump\n"); @@ -355,7 +360,8 @@ static void fec_dump(struct net_device *ndev) index, bdp == fep->cur_tx ? 'S' : ' ', bdp == fep->dirty_tx ? 'H' : ' ', - bdp->cbd_sc, bdp->cbd_bufaddr, bdp->cbd_datlen, + bdp->bd.cbd_sc, bdp->bd.cbd_bufaddr, + bdp->bd.cbd_datlen, fep->tx_skbuff[index]); bdp = fec_enet_get_nextdesc(bdp, fep); index++; @@ -394,10 +400,10 @@ fec_enet_clear_csum(struct sk_buff *skb, struct net_device *ndev) } static void -fec_enet_tx_unmap(struct bufdesc *bdp, struct fec_enet_private *fep) +fec_enet_tx_unmap(union bufdesc_u *bdp, struct fec_enet_private *fep) { - dma_addr_t addr = bdp->cbd_bufaddr; - size_t length = bdp->cbd_datlen; + dma_addr_t addr = bdp->bd.cbd_bufaddr; + size_t length = bdp->bd.cbd_datlen; dma_unmap_single(&fep->pdev->dev, addr, length, DMA_TO_DEVICE); } @@ -408,8 +414,7 @@ fec_enet_txq_submit_frag_skb(struct sk_buff *skb, struct net_device *ndev) struct fec_enet_private *fep = netdev_priv(ndev); const struct platform_device_id *id_entry = platform_get_device_id(fep->pdev); - struct bufdesc *bdp = fep->cur_tx; - struct bufdesc_ex *ebdp; + union bufdesc_u *bdp = fep->cur_tx; int nr_frags = skb_shinfo(skb)->nr_frags; int frag, frag_len; unsigned short status; @@ -423,9 +428,8 @@ fec_enet_txq_submit_frag_skb(struct sk_buff *skb, struct net_device *ndev) for (frag = 0; frag < nr_frags; frag++) { this_frag = &skb_shinfo(skb)->frags[frag]; bdp = fec_enet_get_nextdesc(bdp, fep); - ebdp = (struct bufdesc_ex *)bdp; - status = bdp->cbd_sc; + status = bdp->bd.cbd_sc; status &= ~BD_ENET_TX_STATS; status |= (BD_ENET_TX_TC | BD_ENET_TX_READY); frag_len = skb_shinfo(skb)->frags[frag].size; @@ -444,8 +448,8 @@ fec_enet_txq_submit_frag_skb(struct sk_buff *skb, struct net_device *ndev) if (fep->bufdesc_ex) { if (skb->ip_summed == CHECKSUM_PARTIAL) estatus |= BD_ENET_TX_PINS | BD_ENET_TX_IINS; - ebdp->cbd_bdu = 0; - ebdp->cbd_esc = estatus; + bdp->ebd.cbd_bdu = 0; + bdp->ebd.cbd_esc = estatus; } bufaddr = page_address(this_frag->page.p) + this_frag->page_offset; @@ -469,9 +473,9 @@ fec_enet_txq_submit_frag_skb(struct sk_buff *skb, struct net_device *ndev) goto dma_mapping_error; } - bdp->cbd_bufaddr = addr; - bdp->cbd_datlen = frag_len; - bdp->cbd_sc = status; + bdp->bd.cbd_bufaddr = addr; + bdp->bd.cbd_datlen = frag_len; + bdp->bd.cbd_sc = status; } fep->cur_tx = bdp; @@ -482,8 +486,8 @@ dma_mapping_error: bdp = fep->cur_tx; for (i = 0; i < frag; i++) { bdp = fec_enet_get_nextdesc(bdp, fep); - dma_unmap_single(&fep->pdev->dev, bdp->cbd_bufaddr, - bdp->cbd_datlen, DMA_TO_DEVICE); + dma_unmap_single(&fep->pdev->dev, bdp->bd.cbd_bufaddr, + bdp->bd.cbd_datlen, DMA_TO_DEVICE); } return NETDEV_TX_OK; } @@ -494,7 +498,7 @@ static int fec_enet_txq_submit_skb(struct sk_buff *skb, struct net_device *ndev) const struct platform_device_id *id_entry = platform_get_device_id(fep->pdev); int nr_frags = skb_shinfo(skb)->nr_frags; - struct bufdesc *bdp, *last_bdp; + union bufdesc_u *bdp, *last_bdp; void *bufaddr; dma_addr_t addr; unsigned short status; @@ -518,7 +522,7 @@ static int fec_enet_txq_submit_skb(struct sk_buff *skb, struct net_device *ndev) /* Fill in a Tx ring entry */ bdp = fep->cur_tx; - status = bdp->cbd_sc; + status = bdp->bd.cbd_sc; status &= ~BD_ENET_TX_STATS; /* Set buffer length and buffer pointer */ @@ -559,9 +563,6 @@ static int fec_enet_txq_submit_skb(struct sk_buff *skb, struct net_device *ndev) } if (fep->bufdesc_ex) { - - struct bufdesc_ex *ebdp = (struct bufdesc_ex *)bdp; - if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP && fep->hwts_tx_en)) skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS; @@ -569,8 +570,8 @@ static int fec_enet_txq_submit_skb(struct sk_buff *skb, struct net_device *ndev) if (skb->ip_summed == CHECKSUM_PARTIAL) estatus |= BD_ENET_TX_PINS | BD_ENET_TX_IINS; - ebdp->cbd_bdu = 0; - ebdp->cbd_esc = estatus; + bdp->ebd.cbd_bdu = 0; + bdp->ebd.cbd_esc = estatus; } last_bdp = fep->cur_tx; @@ -578,8 +579,8 @@ static int fec_enet_txq_submit_skb(struct sk_buff *skb, struct net_device *ndev) /* Save skb pointer */ fep->tx_skbuff[index] = skb; - bdp->cbd_datlen = buflen; - bdp->cbd_bufaddr = addr; + bdp->bd.cbd_datlen = buflen; + bdp->bd.cbd_bufaddr = addr; /* * We need the preceding stores to the descriptor to complete @@ -592,7 +593,7 @@ static int fec_enet_txq_submit_skb(struct sk_buff *skb, struct net_device *ndev) * it's the last BD of the frame, and to put the CRC on the end. */ status |= (BD_ENET_TX_READY | BD_ENET_TX_TC); - bdp->cbd_sc = status; + bdp->bd.cbd_sc = status; /* If this was the last BD in the ring, start at the beginning again. */ bdp = fec_enet_get_nextdesc(last_bdp, fep); @@ -611,18 +612,17 @@ static int fec_enet_txq_submit_skb(struct sk_buff *skb, struct net_device *ndev) static int fec_enet_txq_put_data_tso(struct sk_buff *skb, struct net_device *ndev, - struct bufdesc *bdp, int index, char *data, + union bufdesc_u *bdp, int index, char *data, int size, bool last_tcp, bool is_last) { struct fec_enet_private *fep = netdev_priv(ndev); const struct platform_device_id *id_entry = platform_get_device_id(fep->pdev); - struct bufdesc_ex *ebdp = (struct bufdesc_ex *)bdp; unsigned short status; unsigned int estatus = 0; dma_addr_t addr; - status = bdp->cbd_sc; + status = bdp->bd.cbd_sc; status &= ~BD_ENET_TX_STATS; status |= (BD_ENET_TX_TC | BD_ENET_TX_READY); @@ -644,14 +644,14 @@ fec_enet_txq_put_data_tso(struct sk_buff *skb, struct net_device *ndev, return NETDEV_TX_BUSY; } - bdp->cbd_datlen = size; - bdp->cbd_bufaddr = addr; + bdp->bd.cbd_datlen = size; + bdp->bd.cbd_bufaddr = addr; if (fep->bufdesc_ex) { if (skb->ip_summed == CHECKSUM_PARTIAL) estatus |= BD_ENET_TX_PINS | BD_ENET_TX_IINS; - ebdp->cbd_bdu = 0; - ebdp->cbd_esc = estatus; + bdp->ebd.cbd_bdu = 0; + bdp->ebd.cbd_esc = estatus; } /* Handle the last BD specially */ @@ -660,29 +660,28 @@ fec_enet_txq_put_data_tso(struct sk_buff *skb, struct net_device *ndev, if (is_last) { status |= BD_ENET_TX_INTR; if (fep->bufdesc_ex) - ebdp->cbd_esc |= BD_ENET_TX_INT; + bdp->ebd.cbd_esc |= BD_ENET_TX_INT; } - bdp->cbd_sc = status; + bdp->bd.cbd_sc = status; return 0; } static int fec_enet_txq_put_hdr_tso(struct sk_buff *skb, struct net_device *ndev, - struct bufdesc *bdp, int index) + union bufdesc_u *bdp, int index) { struct fec_enet_private *fep = netdev_priv(ndev); const struct platform_device_id *id_entry = platform_get_device_id(fep->pdev); int hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb); - struct bufdesc_ex *ebdp = (struct bufdesc_ex *)bdp; void *bufaddr; unsigned long dmabuf; unsigned short status; unsigned int estatus = 0; - status = bdp->cbd_sc; + status = bdp->bd.cbd_sc; status &= ~BD_ENET_TX_STATS; status |= (BD_ENET_TX_TC | BD_ENET_TX_READY); @@ -706,17 +705,17 @@ fec_enet_txq_put_hdr_tso(struct sk_buff *skb, struct net_device *ndev, } } - bdp->cbd_bufaddr = dmabuf; - bdp->cbd_datlen = hdr_len; + bdp->bd.cbd_bufaddr = dmabuf; + bdp->bd.cbd_datlen = hdr_len; if (fep->bufdesc_ex) { if (skb->ip_summed == CHECKSUM_PARTIAL) estatus |= BD_ENET_TX_PINS | BD_ENET_TX_IINS; - ebdp->cbd_bdu = 0; - ebdp->cbd_esc = estatus; + bdp->ebd.cbd_bdu = 0; + bdp->ebd.cbd_esc = estatus; } - bdp->cbd_sc = status; + bdp->bd.cbd_sc = status; return 0; } @@ -726,7 +725,7 @@ static int fec_enet_txq_submit_tso(struct sk_buff *skb, struct net_device *ndev) struct fec_enet_private *fep = netdev_priv(ndev); int hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb); int total_len, data_left; - struct bufdesc *bdp = fep->cur_tx; + union bufdesc_u *bdp = fep->cur_tx; struct tso_t tso; unsigned int index = 0; int ret; @@ -823,7 +822,7 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *ndev) static void fec_enet_bd_init(struct net_device *dev) { struct fec_enet_private *fep = netdev_priv(dev); - struct bufdesc *bdp; + union bufdesc_u *bdp; unsigned int i; /* Initialize the receive buffer descriptors. */ @@ -831,16 +830,16 @@ static void fec_enet_bd_init(struct net_device *dev) for (i = 0; i < fep->rx_ring_size; i++) { /* Initialize the BD for every fragment in the page. */ - if (bdp->cbd_bufaddr) - bdp->cbd_sc = BD_ENET_RX_EMPTY; + if (bdp->bd.cbd_bufaddr) + bdp->bd.cbd_sc = BD_ENET_RX_EMPTY; else - bdp->cbd_sc = 0; + bdp->bd.cbd_sc = 0; bdp = fec_enet_get_nextdesc(bdp, fep); } /* Set the last buffer to wrap */ bdp = fec_enet_get_prevdesc(bdp, fep); - bdp->cbd_sc |= BD_SC_WRAP; + bdp->bd.cbd_sc |= BD_SC_WRAP; fep->cur_rx = fep->rx_bd_base; @@ -850,10 +849,10 @@ static void fec_enet_bd_init(struct net_device *dev) for (i = 0; i < fep->tx_ring_size; i++) { /* Initialize the BD for every fragment in the page. */ - bdp->cbd_sc = 0; - if (bdp->cbd_bufaddr && !IS_TSO_HEADER(fep, bdp->cbd_bufaddr)) + bdp->bd.cbd_sc = 0; + if (bdp->bd.cbd_bufaddr) fec_enet_tx_unmap(bdp, fep); - bdp->cbd_bufaddr = 0; + bdp->bd.cbd_bufaddr = 0; if (fep->tx_skbuff[i]) { dev_kfree_skb_any(fep->tx_skbuff[i]); fep->tx_skbuff[i] = NULL; @@ -863,7 +862,7 @@ static void fec_enet_bd_init(struct net_device *dev) /* Set the last buffer to wrap */ bdp = fec_enet_get_prevdesc(bdp, fep); - bdp->cbd_sc |= BD_SC_WRAP; + bdp->bd.cbd_sc |= BD_SC_WRAP; fep->dirty_tx = bdp; } @@ -1128,7 +1127,7 @@ static void fec_enet_tx(struct net_device *ndev) { struct fec_enet_private *fep; - struct bufdesc *bdp; + union bufdesc_u *bdp; unsigned short status; struct sk_buff *skb; int index = 0; @@ -1141,7 +1140,7 @@ fec_enet_tx(struct net_device *ndev) bdp = fec_enet_get_nextdesc(bdp, fep); pkts_compl = bytes_compl = 0; - while (((status = bdp->cbd_sc) & BD_ENET_TX_READY) == 0) { + while (((status = bdp->bd.cbd_sc) & BD_ENET_TX_READY) == 0) { /* current queue is empty */ if (bdp == fep->cur_tx) @@ -1151,9 +1150,9 @@ fec_enet_tx(struct net_device *ndev) skb = fep->tx_skbuff[index]; fep->tx_skbuff[index] = NULL; - if (!IS_TSO_HEADER(fep, bdp->cbd_bufaddr)) + if (!IS_TSO_HEADER(fep, bdp->bd.cbd_bufaddr)) fec_enet_tx_unmap(bdp, fep); - bdp->cbd_bufaddr = 0; + bdp->bd.cbd_bufaddr = 0; if (!skb) { bdp = fec_enet_get_nextdesc(bdp, fep); continue; @@ -1182,9 +1181,8 @@ fec_enet_tx(struct net_device *ndev) if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_IN_PROGRESS) && fep->bufdesc_ex) { struct skb_shared_hwtstamps shhwtstamps; - struct bufdesc_ex *ebdp = (struct bufdesc_ex *)bdp; - fec_enet_hwtstamp(fep, ebdp->ts, &shhwtstamps); + fec_enet_hwtstamp(fep, bdp->ebd.ts, &shhwtstamps); skb_tstamp_tx(skb, &shhwtstamps); } @@ -1228,13 +1226,12 @@ fec_enet_rx(struct net_device *ndev, int budget) struct fec_enet_private *fep = netdev_priv(ndev); const struct platform_device_id *id_entry = platform_get_device_id(fep->pdev); - struct bufdesc *bdp; + union bufdesc_u *bdp; unsigned short status; struct sk_buff *skb; ushort pkt_len; __u8 *data; int pkt_received = 0; - struct bufdesc_ex *ebdp = NULL; bool vlan_packet_rcvd = false; u16 vlan_tag; int index = 0; @@ -1248,7 +1245,7 @@ fec_enet_rx(struct net_device *ndev, int budget) */ bdp = fep->cur_rx; - while (!((status = bdp->cbd_sc) & BD_ENET_RX_EMPTY)) { + while (!((status = bdp->bd.cbd_sc) & BD_ENET_RX_EMPTY)) { if (pkt_received >= budget) break; @@ -1297,26 +1294,21 @@ fec_enet_rx(struct net_device *ndev, int budget) /* Process the incoming frame. */ ndev->stats.rx_packets++; - pkt_len = bdp->cbd_datlen; + pkt_len = bdp->bd.cbd_datlen; ndev->stats.rx_bytes += pkt_len; index = fec_enet_get_bd_index(fep->rx_bd_base, bdp, fep); data = fep->rx_skbuff[index]->data; - dma_sync_single_for_cpu(&fep->pdev->dev, bdp->cbd_bufaddr, + dma_sync_single_for_cpu(&fep->pdev->dev, bdp->bd.cbd_bufaddr, FEC_ENET_RX_FRSIZE, DMA_FROM_DEVICE); if (id_entry->driver_data & FEC_QUIRK_SWAP_FRAME) swap_buffer(data, pkt_len); - /* Extract the enhanced buffer descriptor */ - ebdp = NULL; - if (fep->bufdesc_ex) - ebdp = (struct bufdesc_ex *)bdp; - /* If this is a VLAN packet remove the VLAN Tag */ vlan_packet_rcvd = false; if ((ndev->features & NETIF_F_HW_VLAN_CTAG_RX) && - fep->bufdesc_ex && (ebdp->cbd_esc & BD_ENET_RX_VLAN)) { + fep->bufdesc_ex && (bdp->ebd.cbd_esc & BD_ENET_RX_VLAN)) { /* Push and remove the vlan tag */ struct vlan_hdr *vlan_header = (struct vlan_hdr *) (data + ETH_HLEN); @@ -1352,12 +1344,12 @@ fec_enet_rx(struct net_device *ndev, int budget) /* Get receive timestamp from the skb */ if (fep->hwts_rx_en && fep->bufdesc_ex) - fec_enet_hwtstamp(fep, ebdp->ts, + fec_enet_hwtstamp(fep, bdp->ebd.ts, skb_hwtstamps(skb)); if (fep->bufdesc_ex && (fep->csum_flags & FLAG_RX_CSUM_ENABLED)) { - if (!(ebdp->cbd_esc & FLAG_RX_CSUM_ERROR)) { + if (!(bdp->ebd.cbd_esc & FLAG_RX_CSUM_ERROR)) { /* don't check it */ skb->ip_summed = CHECKSUM_UNNECESSARY; } else { @@ -1374,15 +1366,13 @@ fec_enet_rx(struct net_device *ndev, int budget) napi_gro_receive(&fep->napi, skb); } - dma_sync_single_for_device(&fep->pdev->dev, bdp->cbd_bufaddr, + dma_sync_single_for_device(&fep->pdev->dev, bdp->bd.cbd_bufaddr, FEC_ENET_RX_FRSIZE, DMA_FROM_DEVICE); rx_processing_done: if (fep->bufdesc_ex) { - struct bufdesc_ex *ebdp = (struct bufdesc_ex *)bdp; - - ebdp->cbd_esc = BD_ENET_RX_INT; - ebdp->cbd_prot = 0; - ebdp->cbd_bdu = 0; + bdp->ebd.cbd_esc = BD_ENET_RX_INT; + bdp->ebd.cbd_prot = 0; + bdp->ebd.cbd_bdu = 0; } /* @@ -1396,7 +1386,7 @@ rx_processing_done: /* Mark the buffer empty */ status |= BD_ENET_RX_EMPTY; - bdp->cbd_sc = status; + bdp->bd.cbd_sc = status; /* Update BD pointer to next entry */ bdp = fec_enet_get_nextdesc(bdp, fep); @@ -2249,14 +2239,14 @@ static void fec_enet_free_buffers(struct net_device *ndev) struct fec_enet_private *fep = netdev_priv(ndev); unsigned int i; struct sk_buff *skb; - struct bufdesc *bdp; + union bufdesc_u *bdp; bdp = fep->rx_bd_base; for (i = 0; i < fep->rx_ring_size; i++) { skb = fep->rx_skbuff[i]; fep->rx_skbuff[i] = NULL; if (skb) { - dma_unmap_single(&fep->pdev->dev, bdp->cbd_bufaddr, + dma_unmap_single(&fep->pdev->dev, bdp->bd.cbd_bufaddr, FEC_ENET_RX_FRSIZE, DMA_FROM_DEVICE); dev_kfree_skb(skb); } @@ -2265,9 +2255,9 @@ static void fec_enet_free_buffers(struct net_device *ndev) bdp = fep->tx_bd_base; for (i = 0; i < fep->tx_ring_size; i++) { - if (bdp->cbd_bufaddr && !IS_TSO_HEADER(fep, bdp->cbd_bufaddr)) + if (bdp->bd.cbd_bufaddr) fec_enet_tx_unmap(bdp, fep); - bdp->cbd_bufaddr = 0; + bdp->bd.cbd_bufaddr = 0; kfree(fep->tx_bounce[i]); fep->tx_bounce[i] = NULL; skb = fep->tx_skbuff[i]; @@ -2281,7 +2271,7 @@ static int fec_enet_alloc_buffers(struct net_device *ndev) struct fec_enet_private *fep = netdev_priv(ndev); unsigned int i; struct sk_buff *skb; - struct bufdesc *bdp; + union bufdesc_u *bdp; bdp = fep->rx_bd_base; for (i = 0; i < fep->rx_ring_size; i++) { @@ -2301,20 +2291,18 @@ static int fec_enet_alloc_buffers(struct net_device *ndev) } fep->rx_skbuff[i] = skb; - bdp->cbd_bufaddr = addr; - bdp->cbd_sc = BD_ENET_RX_EMPTY; + bdp->bd.cbd_bufaddr = addr; + bdp->bd.cbd_sc = BD_ENET_RX_EMPTY; - if (fep->bufdesc_ex) { - struct bufdesc_ex *ebdp = (struct bufdesc_ex *)bdp; - ebdp->cbd_esc = BD_ENET_RX_INT; - } + if (fep->bufdesc_ex) + bdp->ebd.cbd_esc = BD_ENET_RX_INT; bdp = fec_enet_get_nextdesc(bdp, fep); } /* Set the last buffer to wrap. */ bdp = fec_enet_get_prevdesc(bdp, fep); - bdp->cbd_sc |= BD_SC_WRAP; + bdp->bd.cbd_sc |= BD_SC_WRAP; bdp = fep->tx_bd_base; for (i = 0; i < fep->tx_ring_size; i++) { @@ -2322,20 +2310,18 @@ static int fec_enet_alloc_buffers(struct net_device *ndev) if (!fep->tx_bounce[i]) goto err_alloc; - bdp->cbd_sc = 0; - bdp->cbd_bufaddr = 0; + bdp->bd.cbd_sc = 0; + bdp->bd.cbd_bufaddr = 0; - if (fep->bufdesc_ex) { - struct bufdesc_ex *ebdp = (struct bufdesc_ex *)bdp; - ebdp->cbd_esc = BD_ENET_TX_INT; - } + if (fep->bufdesc_ex) + bdp->ebd.cbd_esc = BD_ENET_TX_INT; bdp = fec_enet_get_nextdesc(bdp, fep); } /* Set the last buffer to wrap. */ bdp = fec_enet_get_prevdesc(bdp, fep); - bdp->cbd_sc |= BD_SC_WRAP; + bdp->bd.cbd_sc |= BD_SC_WRAP; return 0; @@ -2580,7 +2566,7 @@ static int fec_enet_init(struct net_device *ndev) struct fec_enet_private *fep = netdev_priv(ndev); const struct platform_device_id *id_entry = platform_get_device_id(fep->pdev); - struct bufdesc *cbd_base; + union bufdesc_u *cbd_base; dma_addr_t cbd_dma; int bd_size; @@ -2591,12 +2577,11 @@ static int fec_enet_init(struct net_device *ndev) fep->tx_stop_threshold = FEC_MAX_SKB_DESCS; fep->tx_wake_threshold = (fep->tx_ring_size - fep->tx_stop_threshold) / 2; + bd_size = fep->tx_ring_size + fep->rx_ring_size; if (fep->bufdesc_ex) - fep->bufdesc_size = sizeof(struct bufdesc_ex); + bd_size *= sizeof(struct bufdesc_ex); else - fep->bufdesc_size = sizeof(struct bufdesc); - bd_size = (fep->tx_ring_size + fep->rx_ring_size) * - fep->bufdesc_size; + bd_size *= sizeof(struct bufdesc); /* Allocate memory for buffer descriptors. */ cbd_base = dma_alloc_coherent(NULL, bd_size, &cbd_dma, GFP_KERNEL); @@ -2623,12 +2608,13 @@ static int fec_enet_init(struct net_device *ndev) fep->rx_bd_base = cbd_base; fep->rx_bd_dma = cbd_dma; if (fep->bufdesc_ex) { - fep->tx_bd_base = (struct bufdesc *) - (((struct bufdesc_ex *)cbd_base) + fep->rx_ring_size); + fep->tx_bd_base = (union bufdesc_u *) + (&cbd_base->ebd + fep->rx_ring_size); fep->tx_bd_dma = cbd_dma + sizeof(struct bufdesc_ex) * fep->rx_ring_size; } else { - fep->tx_bd_base = cbd_base + fep->rx_ring_size; + fep->tx_bd_base = (union bufdesc_u *) + (&cbd_base->bd + fep->rx_ring_size); fep->tx_bd_dma = cbd_dma + sizeof(struct bufdesc) * fep->rx_ring_size; } -- cgit