[U-Boot] [PATCH 7/9] net: tsec: Use portable types and accessors for BDs

Claudiu Manoil
2013-09-30T09:44:45Z

Currently, the buffer descriptor (BD) fields cannot be
correctly accessed by a little endian processor. This
patch fixes the issue by making the access of BDs to be
portable among different cpu architectures.

Use portable data types for the Rx/Tx buffer descriptor
fields. Add macro accessors to insure that the big endian
buffer descriptors are correctly accessed by the little
endian cpus too. Sparse tool was also used to verify the
correctness of these conversion macros.

Signed-off-by: Claudiu Manoil <claudiu.manoil@freescale.com>
---
drivers/net/tsec.c | 89 ++++++++++++++++++++++++++++++++----------------------
include/tsec.h | 22 ++++++--------
2 files changed, 63 insertions(+), 48 deletions(-)

diff --git a/drivers/net/tsec.c b/drivers/net/tsec.c
index 289229a..cf99546 100644
--- a/drivers/net/tsec.c
+++ b/drivers/net/tsec.c
@@ -29,12 +29,20 @@ static uint rx_idx; /* index of the current RX buffer */
static uint tx_idx; /* index of the current TX buffer */

typedef volatile struct rtxbd {
- txbd8_t txbd[TX_BUF_CNT];
- rxbd8_t rxbd[PKTBUFSRX];
+ struct txbd8 txbd[TX_BUF_CNT];
+ struct rxbd8 rxbd[PKTBUFSRX];
} RTXBD;

#ifdef __GNUC__
-static RTXBD rtx __attribute__ ((aligned(8)));
+static RTXBD rtx __aligned(8);
+#define RXBD(i) rtx.rxbd[i]
+#define TXBD(i) rtx.txbd[i]
+#define GET_BD_STAT(T, i) be16_to_cpu((__force __be16)T##BD(i).status)
+#define SET_BD_STAT(T, i, v) T##BD(i).status = (__force __u16)cpu_to_be16(v)
+#define GET_BD_BLEN(T, i) be16_to_cpu((__force __be16)T##BD(i).length)
+#define SET_BD_BLEN(T, i, v) T##BD(i).length = (__force __u16)cpu_to_be16(v)
+#define GET_BD_BPTR(T, i) be32_to_cpu((__force __be32)T##BD(i).bufptr)
+#define SET_BD_BPTR(T, i, v) T##BD(i).bufptr = (__force __u32)cpu_to_be32(v)
#else
#error "rtx must be 64-bit aligned"
#endif
@@ -275,10 +283,11 @@ void redundant_init(struct eth_device *dev)
clrbits_be32(&regs->dmactrl, DMACTRL_GRS | DMACTRL_GTS);

do {
+ uint16_t status;
tsec_send(dev, (void *)pkt, sizeof(pkt));

/* Wait for buffer to be received */
- for (t = 0; rtx.rxbd[rx_idx].status & RXBD_EMPTY; t++) {
+ for (t = 0; GET_BD_STAT(RX, rx_idx) & RXBD_EMPTY; t++) {
if (t >= 10 * TOUT_LOOP) {
printf("%s: tsec: rx error\n", dev->name);
break;
@@ -288,9 +297,11 @@ void redundant_init(struct eth_device *dev)
if (!memcmp(pkt, (void *)NetRxPackets[rx_idx], sizeof(pkt)))
fail = 0;

- rtx.rxbd[rx_idx].length = 0;
- rtx.rxbd[rx_idx].status =
- RXBD_EMPTY | (((rx_idx + 1) == PKTBUFSRX) ? RXBD_WRAP : 0);
+ SET_BD_BLEN(RX, rx_idx, 0);
+ status = RXBD_EMPTY;
+ if ((rx_idx + 1) == PKTBUFSRX)
+ status |= RXBD_WRAP;
+ SET_BD_STAT(RX, rx_idx, status);
rx_idx = (rx_idx + 1) % PKTBUFSRX;

if (in_be32(&regs->ievent) & IEVENT_BSY) {
@@ -319,9 +330,10 @@ void redundant_init(struct eth_device *dev)
*/
static void startup_tsec(struct eth_device *dev)
{
- int i;
struct tsec_private *priv = (struct tsec_private *)dev->priv;
struct tsec __iomem *regs = priv->regs;
+ uint16_t status;
+ int i;

/* reset the indices to zero */
rx_idx = 0;
@@ -331,24 +343,26 @@ static void startup_tsec(struct eth_device *dev)
#endif

/* Point to the buffer descriptors */
- out_be32(&regs->tbase, (unsigned int)(&rtx.txbd[tx_idx]));
- out_be32(&regs->rbase, (unsigned int)(&rtx.rxbd[rx_idx]));
+ out_be32(&regs->tbase, (u32)&TXBD(0));
+ out_be32(&regs->rbase, (u32)&RXBD(0));

/* Initialize the Rx Buffer descriptors */
for (i = 0; i < PKTBUFSRX; i++) {
- rtx.rxbd[i].status = RXBD_EMPTY;
- rtx.rxbd[i].length = 0;
- rtx.rxbd[i].bufptr = (uint) NetRxPackets[i];
+ SET_BD_STAT(RX, i, RXBD_EMPTY);
+ SET_BD_BLEN(RX, i, 0);
+ SET_BD_BPTR(RX, i, (u32)NetRxPackets[i]);
}
- rtx.rxbd[PKTBUFSRX - 1].status |= RXBD_WRAP;
+ status = GET_BD_STAT(RX, PKTBUFSRX - 1);
+ SET_BD_STAT(RX, PKTBUFSRX - 1, status | RXBD_WRAP);

/* Initialize the TX Buffer Descriptors */
for (i = 0; i < TX_BUF_CNT; i++) {
- rtx.txbd[i].status = 0;
- rtx.txbd[i].length = 0;
- rtx.txbd[i].bufptr = 0;
+ SET_BD_STAT(TX, i, 0);
+ SET_BD_BLEN(TX, i, 0);
+ SET_BD_BPTR(TX, i, 0);
}
- rtx.txbd[TX_BUF_CNT - 1].status |= TXBD_WRAP;
+ status = GET_BD_STAT(TX, TX_BUF_CNT - 1);
+ SET_BD_STAT(TX, TX_BUF_CNT - 1, status | TXBD_WRAP);

#ifdef CONFIG_SYS_FSL_ERRATUM_NMG_ETSEC129
svr = get_svr();
@@ -372,29 +386,31 @@ static void startup_tsec(struct eth_device *dev)
*/
static int tsec_send(struct eth_device *dev, void *packet, int length)
{
- int i;
- int result = 0;
struct tsec_private *priv = (struct tsec_private *)dev->priv;
struct tsec __iomem *regs = priv->regs;
+ uint16_t status;
+ int result = 0;
+ int i;

/* Find an empty buffer descriptor */
- for (i = 0; rtx.txbd[tx_idx].status & TXBD_READY; i++) {
+ for (i = 0; GET_BD_STAT(TX, tx_idx) & TXBD_READY; i++) {
if (i >= TOUT_LOOP) {
debug("%s: tsec: tx buffers full\n", dev->name);
return result;
}
}

- rtx.txbd[tx_idx].bufptr = (uint) packet;
- rtx.txbd[tx_idx].length = length;
- rtx.txbd[tx_idx].status |=
- (TXBD_READY | TXBD_LAST | TXBD_CRC | TXBD_INTERRUPT);
+ SET_BD_BPTR(TX, tx_idx, (u32)packet);
+ SET_BD_BLEN(TX, tx_idx, length);
+ status = GET_BD_STAT(TX, tx_idx);
+ SET_BD_STAT(TX, tx_idx, status |
+ (TXBD_READY | TXBD_LAST | TXBD_CRC | TXBD_INTERRUPT));

/* Tell the DMA to go */
out_be32(&regs->tstat, TSTAT_CLEAR_THALT);

/* Wait for buffer to be transmitted */
- for (i = 0; rtx.txbd[tx_idx].status & TXBD_READY; i++) {
+ for (i = 0; GET_BD_STAT(TX, tx_idx) & TXBD_READY; i++) {
if (i >= TOUT_LOOP) {
debug("%s: tsec: tx error\n", dev->name);
return result;
@@ -402,34 +418,35 @@ static int tsec_send(struct eth_device *dev, void *packet, int length)
}

tx_idx = (tx_idx + 1) % TX_BUF_CNT;
- result = rtx.txbd[tx_idx].status & TXBD_STATS;
+ result = GET_BD_STAT(TX, tx_idx) & TXBD_STATS;

return result;
}

static int tsec_recv(struct eth_device *dev)
{
- int length;
struct tsec_private *priv = (struct tsec_private *)dev->priv;
struct tsec __iomem *regs = priv->regs;

- while (!(rtx.rxbd[rx_idx].status & RXBD_EMPTY)) {
-
- length = rtx.rxbd[rx_idx].length;
+ while (!(GET_BD_STAT(RX, rx_idx) & RXBD_EMPTY)) {
+ int length = GET_BD_BLEN(RX, rx_idx);
+ uint16_t status;

/* Send the packet up if there were no errors */
- if (!(rtx.rxbd[rx_idx].status & RXBD_STATS)) {
+ if (!(GET_BD_STAT(RX, rx_idx) & RXBD_STATS)) {
NetReceive(NetRxPackets[rx_idx], length - 4);
} else {
printf("Got error %x\n",
- (rtx.rxbd[rx_idx].status & RXBD_STATS));
+ (GET_BD_STAT(RX, rx_idx) & RXBD_STATS));
}

- rtx.rxbd[rx_idx].length = 0;
+ SET_BD_BLEN(RX, rx_idx, 0);

+ status = RXBD_EMPTY;
/* Set the wrap bit if this is the last element in the list */
- rtx.rxbd[rx_idx].status =
- RXBD_EMPTY | (((rx_idx + 1) == PKTBUFSRX) ? RXBD_WRAP : 0);
+ if ((rx_idx + 1) == PKTBUFSRX)
+ status |= RXBD_WRAP;
+ SET_BD_STAT(RX, rx_idx, status);

rx_idx = (rx_idx + 1) % PKTBUFSRX;
}
diff --git a/include/tsec.h b/include/tsec.h
index 6bc43ef..95054be 100644
--- a/include/tsec.h
+++ b/include/tsec.h
@@ -198,19 +198,17 @@
#define RXBD_TRUNCATED 0x0001
#define RXBD_STATS 0x003f

-typedef struct txbd8
-{
- ushort status; /* Status Fields */
- ushort length; /* Buffer length */
- uint bufptr; /* Buffer Pointer */
-} txbd8_t;
+struct txbd8 {
+ uint16_t status; /* Status Fields */
+ uint16_t length; /* Buffer length */
+ uint32_t bufptr; /* Buffer Pointer */
+};

-typedef struct rxbd8
-{
- ushort status; /* Status Fields */
- ushort length; /* Buffer Length */
- uint bufptr; /* Buffer Pointer */
-} rxbd8_t;
+struct rxbd8 {
+ uint16_t status; /* Status Fields */
+ uint16_t length; /* Buffer Length */
+ uint32_t bufptr; /* Buffer Pointer */
+};

typedef struct rmon_mib
{
--
1.7.11.7