Index: freebsd/sys/dev/dwc/if_dwc.c
===================================================================
--- freebsd/sys/dev/dwc/if_dwc.c	(revision a6818538781db144c6884f0e6a78fdc9bc8e8a4b)
+++ freebsd/sys/dev/dwc/if_dwc.c	(revision 6b176ce6683dce004b4c68b3dadd11b813e9f70a)
@@ -108,4 +108,7 @@
 #define	DDESC_TDES0_TXFIRST		(1 << 28)
 #define	DDESC_TDES0_TXCRCDIS		(1 << 27)
+#define	DDESC_TDES0_CIC_IP_HDR		(0x1 << 22)
+#define	DDESC_TDES0_CIC_IP_HDR_PYL	(0x2 << 22)
+#define	DDESC_TDES0_CIC_IP_HDR_PYL_PHDR	(0x3 << 22)
 #define	DDESC_TDES0_TXRINGEND		(1 << 21)
 #define	DDESC_TDES0_TXCHAIN		(1 << 20)
@@ -114,5 +117,11 @@
 #define	DDESC_RDES0_FL_MASK		0x3fff
 #define	DDESC_RDES0_FL_SHIFT		16	/* Frame Length */
+#define	DDESC_RDES0_ESA			(1 << 0)
 #define	DDESC_RDES1_CHAINED		(1 << 14)
+#define	DDESC_RDES4_IP_PYL_ERR		(1 << 4)
+#define	DDESC_RDES4_IP_HDR_ERR		(1 << 3)
+#define	DDESC_RDES4_IP_PYL_TYPE_MSK	0x7
+#define	DDESC_RDES4_IP_PYL_UDP		1
+#define	DDESC_RDES4_IP_PYL_TCP		2
 
 struct dwc_bufmap {
@@ -133,4 +142,8 @@
 	uint32_t addr;		/* pointer to buffer data */
 	uint32_t addr_next;	/* link to next descriptor */
+	uint32_t tdes4;
+	uint32_t tdes5;
+	uint32_t timestamp_low;
+	uint32_t timestamp_high;
 };
 
@@ -157,4 +170,7 @@
  */
 #define	DWC_DESC_RING_ALIGN		2048
+
+#define DWC_CKSUM_ASSIST	(CSUM_IP | CSUM_TCP | CSUM_UDP | \
+				 CSUM_TCP_IPV6 | CSUM_UDP_IPV6)
 
 struct dwc_softc {
@@ -241,6 +257,6 @@
 
 static void
-dwc_setup_txdesc(struct dwc_softc *sc, int idx, bus_dma_segment_t segs[TX_MAX_DMA_SEGS],
-    int nsegs)
+dwc_setup_txdesc(struct dwc_softc *sc, int csum_flags, int idx,
+    bus_dma_segment_t segs[TX_MAX_DMA_SEGS], int nsegs)
 {
 	int i;
@@ -267,6 +283,13 @@
 		    DDESC_TDES0_OWN;
 
-		if (i == 0)
+		if (i == 0) {
 			tdes0 |= DDESC_TDES0_TXFIRST;
+
+			if ((csum_flags & (CSUM_TCP | CSUM_UDP |
+			    CSUM_TCP_IPV6 | CSUM_UDP_IPV6)) != 0)
+				tdes0 |= DDESC_TDES0_CIC_IP_HDR_PYL_PHDR;
+			else if ((csum_flags & CSUM_IP) != 0)
+				tdes0 |= DDESC_TDES0_CIC_IP_HDR;
+		}
 
 		if (i == nsegs - 1)
@@ -351,5 +374,5 @@
 #endif /* __rtems__ */
 
-	dwc_setup_txdesc(sc, idx, segs, nsegs);
+	dwc_setup_txdesc(sc, m->m_pkthdr.csum_flags, idx, segs, nsegs);
 
 	ETHER_BPF_MTAP(sc->ifp, m);
@@ -570,4 +593,5 @@
 	/* Enable transmitters */
 	reg = READ4(sc, MAC_CONFIGURATION);
+	reg |= (CONF_IPC);
 	reg |= (CONF_JD | CONF_ACS | CONF_BE);
 	reg |= (CONF_TE | CONF_RE);
@@ -882,5 +906,6 @@
 	struct mbuf *m;
 	int error;
-	int rdes0;
+	uint32_t rdes0;
+	uint32_t rdes4;
 	int idx;
 	int len;
@@ -907,4 +932,30 @@
 			m->m_pkthdr.len = len;
 			m->m_len = len;
+
+			/* Check checksum offload flags. */
+			if ((rdes0 & DDESC_RDES0_ESA) != 0) {
+				rdes4 = sc->rxdesc_ring[idx].tdes4;
+
+				/* TCP or UDP checks out, IP checks out too. */
+				if ((rdes4 & DDESC_RDES4_IP_PYL_TYPE_MSK) ==
+				    DDESC_RDES4_IP_PYL_UDP ||
+				    (rdes4 & DDESC_RDES4_IP_PYL_TYPE_MSK) ==
+				    DDESC_RDES4_IP_PYL_TCP) {
+					m->m_pkthdr.csum_flags |=
+						CSUM_IP_CHECKED |
+						CSUM_IP_VALID |
+						CSUM_DATA_VALID |
+						CSUM_PSEUDO_HDR;
+					m->m_pkthdr.csum_data = 0xffff;
+				} else if ((rdes4 & (DDESC_RDES4_IP_PYL_ERR |
+				    DDESC_RDES4_IP_HDR_ERR)) == 0) {
+					/* Only IP checks out. */
+					m->m_pkthdr.csum_flags |=
+						CSUM_IP_CHECKED |
+						CSUM_IP_VALID;
+					m->m_pkthdr.csum_data = 0xffff;
+				}
+			}
+
 #ifndef __rtems__
 			if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1);
@@ -1147,4 +1198,5 @@
 			goto out;
 		}
+		sc->rxdesc_ring[idx].tdes4 = 0;
 	}
 
@@ -1264,4 +1316,5 @@
 
 	reg = READ4(sc, BUS_MODE);
+	reg |= (BUS_MODE_ATDS);
 	reg |= (BUS_MODE_EIGHTXPBL);
 	reg |= (BUS_MODE_PBL_BEATS_8 << BUS_MODE_PBL_SHIFT);
@@ -1298,6 +1351,8 @@
 	if_initname(ifp, device_get_name(dev), device_get_unit(dev));
 	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
-	ifp->if_capabilities = IFCAP_VLAN_MTU;
+	ifp->if_capabilities |= IFCAP_HWCSUM | IFCAP_HWCSUM_IPV6 |
+	    IFCAP_VLAN_MTU | IFCAP_VLAN_HWCSUM;
 	ifp->if_capenable = ifp->if_capabilities;
+	ifp->if_hwassist = DWC_CKSUM_ASSIST;
 	ifp->if_start = dwc_txstart;
 	ifp->if_ioctl = dwc_ioctl;
Index: freebsd/sys/dev/dwc/if_dwc.h
===================================================================
--- freebsd/sys/dev/dwc/if_dwc.h	(revision a6818538781db144c6884f0e6a78fdc9bc8e8a4b)
+++ freebsd/sys/dev/dwc/if_dwc.h	(revision 6b176ce6683dce004b4c68b3dadd11b813e9f70a)
@@ -41,4 +41,5 @@
 #define	 CONF_FES		(1 << 14)	/* MII speed select */
 #define	 CONF_DM		(1 << 11)	/* Full Duplex Enable */
+#define	 CONF_IPC		(1 << 10)	/* Checksum Enable */
 #define	 CONF_ACS		(1 << 7)
 #define	 CONF_TE		(1 << 3)
@@ -210,4 +211,5 @@
 #define	 BUS_MODE_PBL_SHIFT	8 /* Single block transfer size */
 #define	 BUS_MODE_PBL_BEATS_8	8
+#define	 BUS_MODE_ATDS		(1 << 7) /* Alternate Descriptor Size */
 #define	 BUS_MODE_SWR		(1 << 0) /* Reset */
 #define	TRANSMIT_POLL_DEMAND	0x1004
