summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRussell King <rmk+kernel@arm.linux.org.uk>2014-03-23 15:17:13 +0000
committerRussell King <rmk+kernel@arm.linux.org.uk>2014-10-17 14:35:13 +0100
commit7e7801e54ee1429d7ec4c87fd12633f86b100f9f (patch)
tree5dbabe294d992071fc4095ea2808869373c534df
parent9d498e576d9caa2240a2c85d1b664da046c94d08 (diff)
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 <rmk+kernel@arm.linux.org.uk>
-rw-r--r--drivers/net/ethernet/freescale/fec.h14
-rw-r--r--drivers/net/ethernet/freescale/fec_main.c256
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;
}