{
        struct gfar_private *priv = netdev_priv(dev);
        struct txfcb *fcb = NULL;
-       struct txbd8 *txbdp;
+       struct txbd8 *txbdp, *base;
        u16 status;
        unsigned long flags;
 
 
        /* Point at the first free tx descriptor */
        txbdp = priv->cur_tx;
+       base = priv->tx_bd_base;
 
        /* Clear all but the WRAP status flags */
        status = txbdp->status & TXBD_WRAP;
        eieio();
        txbdp->status = status;
 
-       /* If this was the last BD in the ring, the next one */
-       /* is at the beginning of the ring */
-       if (txbdp->status & TXBD_WRAP)
-               txbdp = priv->tx_bd_base;
-       else
-               txbdp++;
+       txbdp = next_bd(txbdp, base, priv->tx_ring_size);
 
        /* If the next BD still needs to be cleaned up, then the bds
           are full.  We need to tell the kernel to stop sending us stuff. */
 /* Interrupt Handler for Transmit complete */
 static int gfar_clean_tx_ring(struct net_device *dev)
 {
-       struct txbd8 *bdp;
+       struct txbd8 *bdp, *base;
        struct gfar_private *priv = netdev_priv(dev);
        int howmany = 0;
 
        bdp = priv->dirty_tx;
+       base = priv->tx_bd_base;
        while ((bdp->status & TXBD_READY) == 0) {
                /* If dirty_tx and cur_tx are the same, then either the */
                /* ring is empty or full now (it could only be full in the beginning, */
                /* Clean BD length for empty detection */
                bdp->length = 0;
 
-               /* update bdp to point at next bd in the ring (wrapping if necessary) */
-               if (bdp->status & TXBD_WRAP)
-                       bdp = priv->tx_bd_base;
-               else
-                       bdp++;
+               bdp = next_bd(bdp, base, priv->tx_ring_size);
 
                /* Move dirty_tx to be the next bd */
                priv->dirty_tx = bdp;
  */
 int gfar_clean_rx_ring(struct net_device *dev, int rx_work_limit)
 {
-       struct rxbd8 *bdp;
+       struct rxbd8 *bdp, *base;
        struct sk_buff *skb;
        int pkt_len;
        int amount_pull;
 
        /* Get the first full descriptor */
        bdp = priv->cur_rx;
+       base = priv->rx_bd_base;
 
        amount_pull = (gfar_uses_fcb(priv) ? GMAC_FCB_LEN : 0) +
                priv->padding;
                gfar_new_rxbdp(dev, bdp, newskb);
 
                /* Update to the next pointer */
-               if (bdp->status & RXBD_WRAP)
-                       bdp = priv->rx_bd_base;
-               else
-                       bdp++;
+               bdp = next_bd(bdp, base, priv->rx_ring_size);
 
                /* update to point at the next skb */
                priv->skb_currx =
 
 #define DEFAULT_TXIC mk_ic_value(DEFAULT_TXCOUNT, DEFAULT_TXTIME)
 #define DEFAULT_RXIC mk_ic_value(DEFAULT_RXCOUNT, DEFAULT_RXTIME)
 
+#define skip_bd(bdp, stride, base, ring_size) ({ \
+       typeof(bdp) new_bd = (bdp) + (stride); \
+       (new_bd >= (base) + (ring_size)) ? (new_bd - (ring_size)) : new_bd; })
+
+#define next_bd(bdp, base, ring_size) skip_bd(bdp, 1, base, ring_size)
+
 #define RCTRL_PAL_MASK         0x001f0000
 #define RCTRL_VLEX             0x00002000
 #define RCTRL_FILREN           0x00001000