summaryrefslogtreecommitdiff
path: root/drivers/net/ethernet/freescale/gianfar.h
diff options
context:
space:
mode:
authorAlok Makhariya <B46187@freescale.com>2014-03-28 11:49:18 (GMT)
committerJose Rivera <German.Rivera@freescale.com>2014-03-28 14:16:51 (GMT)
commit14bc1055d1415408999b4ac1660a261daddd3b55 (patch)
treef1e8fb79b0fb2c2e0af086819e48cf6c867acd6c /drivers/net/ethernet/freescale/gianfar.h
parent5e8ab76d971d561480bed27078a06cfbbe759442 (diff)
downloadlinux-fsl-qoriq-14bc1055d1415408999b4ac1660a261daddd3b55.tar.xz
gianfar: Moving inline static function to gianfar.h
Static inline function used by ASF moved to gianfar.h CQ ID : ENGR00304852 Signed-off-by: Alok Makhariya <B46187@freescale.com> Change-Id: Iafbc62267be60064625305c97dbee1fc8d15a4ec Reviewed-on: http://git.am.freescale.net:8181/10477 Tested-by: Review Code-CDREVIEW <CDREVIEW@freescale.com> Reviewed-by: Claudiu Manoil <claudiu.manoil@freescale.com> Reviewed-by: Jose Rivera <German.Rivera@freescale.com>
Diffstat (limited to 'drivers/net/ethernet/freescale/gianfar.h')
-rw-r--r--drivers/net/ethernet/freescale/gianfar.h152
1 files changed, 152 insertions, 0 deletions
diff --git a/drivers/net/ethernet/freescale/gianfar.h b/drivers/net/ethernet/freescale/gianfar.h
index 4ec37d4..34e5693 100644
--- a/drivers/net/ethernet/freescale/gianfar.h
+++ b/drivers/net/ethernet/freescale/gianfar.h
@@ -38,6 +38,10 @@
#include <linux/mm.h>
#include <linux/mii.h>
#include <linux/phy.h>
+#include <linux/ip.h>
+#include <linux/tcp.h>
+#include <linux/udp.h>
+
#include <asm/io.h>
#include <asm/irq.h>
@@ -1463,4 +1467,152 @@ struct filer_table {
/* The gianfar_ptp module will set this variable */
extern int gfar_phc_index;
+static inline struct txbd8 *skip_txbd(struct txbd8 *bdp, int stride,
+ struct txbd8 *base, int ring_size)
+{
+ struct txbd8 *new_bd = bdp + stride;
+ return (new_bd >= (base + ring_size)) ? (new_bd - ring_size) : new_bd;
+}
+
+static inline struct txbd8 *next_txbd(struct txbd8 *bdp, struct txbd8 *base,
+ int ring_size)
+{
+ return skip_txbd(bdp, 1, base, ring_size);
+}
+
+static inline struct txfcb *gfar_add_fcb(struct sk_buff *skb)
+{
+ struct txfcb *fcb = (struct txfcb *)skb_push(skb, GMAC_FCB_LEN);
+ memset(fcb, 0, GMAC_FCB_LEN);
+ return fcb;
+}
+
+static inline void gfar_tx_checksum(struct sk_buff *skb, struct txfcb *fcb,
+ int fcb_length)
+{
+ /* If we're here, it's a IP packet with a TCP or UDP
+ * payload. We set it to checksum, using a pseudo-header
+ * we provide
+ */
+ u8 flags = TXFCB_DEFAULT;
+
+ /* Tell the controller what the protocol is
+ * And provide the already calculated phcs
+ */
+ if (ip_hdr(skb)->protocol == IPPROTO_UDP) {
+ flags |= TXFCB_UDP;
+ fcb->phcs = udp_hdr(skb)->check;
+ } else
+ fcb->phcs = tcp_hdr(skb)->check;
+
+ /* l3os is the distance between the start of the
+ * frame (skb->data) and the start of the IP hdr.
+ * l4os is the distance between the start of the
+ * l3 hdr and the l4 hdr
+ */
+ fcb->l3os = (u16)(skb_network_offset(skb) - fcb_length);
+ fcb->l4os = skb_network_header_len(skb);
+ fcb->flags = flags;
+}
+
+static inline bool gfar_csum_errata_12(struct gfar_private *priv,
+ unsigned long fcb_addr)
+{
+ return gfar_has_errata(priv, GFAR_ERRATA_12) &&
+ (fcb_addr % 0x20) > 0x18;
+}
+
+static inline bool gfar_csum_errata_76(struct gfar_private *priv,
+ unsigned int len)
+{
+ return gfar_has_errata(priv, GFAR_ERRATA_76) &&
+ (len > 2500);
+}
+
+static inline void gfar_init_rxbdp(struct gfar_priv_rx_q *rx_queue,
+ struct rxbd8 *bdp, dma_addr_t buf)
+{
+ u32 lstatus;
+
+ bdp->bufPtr = buf;
+
+ lstatus = BD_LFLAG(RXBD_EMPTY | RXBD_INTERRUPT);
+ if (bdp == rx_queue->rx_bd_base + rx_queue->rx_ring_size - 1)
+ lstatus |= BD_LFLAG(RXBD_WRAP);
+
+ eieio();
+
+ bdp->lstatus = lstatus;
+}
+
+static inline void gfar_new_rxbdp(struct gfar_priv_rx_q *rx_queue,
+ struct rxbd8 *bdp, struct sk_buff *skb)
+{
+ struct net_device *dev = rx_queue->dev;
+ struct gfar_private *priv = netdev_priv(dev);
+ dma_addr_t buf;
+
+ buf = dma_map_single(priv->dev, skb->data,
+ priv->rx_buffer_size, DMA_FROM_DEVICE);
+ gfar_init_rxbdp(rx_queue, bdp, buf);
+}
+
+static inline void count_errors(unsigned short status, struct net_device *dev)
+{
+ struct gfar_private *priv = netdev_priv(dev);
+ struct net_device_stats *stats = &dev->stats;
+ struct gfar_extra_stats *estats = &priv->extra_stats;
+
+ /* If the packet was truncated, none of the other errors matter */
+ if (status & RXBD_TRUNCATED) {
+ stats->rx_length_errors++;
+
+ atomic64_inc(&estats->rx_trunc);
+
+ return;
+ }
+ /* Count the errors, if there were any */
+ if (status & (RXBD_LARGE | RXBD_SHORT)) {
+ stats->rx_length_errors++;
+
+ if (status & RXBD_LARGE)
+ atomic64_inc(&estats->rx_large);
+ else
+ atomic64_inc(&estats->rx_short);
+ }
+ if (status & RXBD_NONOCTET) {
+ stats->rx_frame_errors++;
+ atomic64_inc(&estats->rx_nonoctet);
+ }
+ if (status & RXBD_CRCERR) {
+ atomic64_inc(&estats->rx_crcerr);
+ stats->rx_crc_errors++;
+ }
+ if (status & RXBD_OVERRUN) {
+ atomic64_inc(&estats->rx_overrun);
+ stats->rx_crc_errors++;
+ }
+}
+
+static inline void gfar_rx_checksum(struct sk_buff *skb, struct rxfcb *fcb)
+{
+ /* If valid headers were found, and valid sums
+ * were verified, then we tell the kernel that no
+ * checksumming is necessary. Otherwise, it is [FIXME]
+ */
+ if ((fcb->flags & RXFCB_CSUM_MASK) == (RXFCB_CIP | RXFCB_CTU))
+ skb->ip_summed = CHECKSUM_UNNECESSARY;
+ else
+ skb_checksum_none_assert(skb);
+}
+
+static inline void gfar_align_skb(struct sk_buff *skb)
+{
+ /* We need the data buffer to be aligned properly. We will reserve
+ * as many bytes as needed to align the data properly
+ */
+ skb_reserve(skb, RXBUF_ALIGNMENT -
+ (((unsigned long) skb->data) & (RXBUF_ALIGNMENT - 1)));
+}
+
#endif /* __GIANFAR_H */