Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 3 May 2003 02:42:03 -0400
From:      Jake Burkholder <jake@locore.ca>
To:        Prafulla Deuskar <pdeuskar@FreeBSD.org>
Cc:        cvs-all@FreeBSD.org
Subject:   Re: cvs commit: src/sys/dev/em if_em.c if_em.h if_em_hw.c if_em_hw.h if_em_osdep.h
Message-ID:  <20030503064203.GB17896@locore.ca>
In-Reply-To: <200305022117.h42LH8VD046042@repoman.freebsd.org>
References:  <200305022117.h42LH8VD046042@repoman.freebsd.org>

next in thread | previous in thread | raw e-mail | index | archive | help
Apparently, On Fri, May 02, 2003 at 02:17:08PM -0700,
	Prafulla Deuskar said words to the effect of;

> pdeuskar    2003/05/02 14:17:08 PDT
> 
>   FreeBSD src repository
> 
>   Modified files:
>     sys/dev/em           if_em.c if_em.h if_em_hw.c if_em_hw.h 
>                          if_em_osdep.h 
>   Log:
>   - Bus DMA'fy the driver
>   - Use htole* macros where appropriate so that the driver could work on
>     non-x86 architectures
>   - Use m_getcl() instead of MGETHDR/MCLGET macros
>   Submitted by:   sam (Sam Leffler)

This isn't 64 bit clean and breaks when compiled with PAE.  Passing pointers
to 32 bit values to bus_dmamap_load causes the next 4 bytes of memory to get
overwritten when a 64 bit value is assigned through the pointer.  The tx and
rx header structures used to be allocated with contigmalloc, which is highly
unlikely to allocate a physical address above 4G even when passed incorrect
arguments, so it did not matter much that the top 32 bits were ignored.  You
really need to set the top 32 bits of the hardware registers which point to
these structures now that they are allocated with malloc.  Included below is
a patch to fix these problems and make the driver work with PAE in large
memory machines again.  This is the only network driver we have which works
in large memory machines without requiring bounce buffers, so its important
to have it working for 5.1-RELEASE.

I also fixed an unnecessary vtophys call for the tx_desc_base, you should
use the bus address returned from bus_dmamap_load instead of converting it
again with vtophys.  vtophys is still used on the rx_buffer_area, this
should be allocated with bus_dmamem_alloc, and bus_dmamap_load should be
used to get the bus address.  Bus addresses may not be equal to physical
addresses, portable device drivers which make proper use of busdma must not
use vtophys.

Jake

Index: if_em.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/em/if_em.c,v
retrieving revision 1.23
diff -u -r1.23 if_em.c
--- if_em.c	2 May 2003 21:17:07 -0000	1.23
+++ if_em.c	2 May 2003 23:29:54 -0000
@@ -1895,11 +1895,12 @@
 {
 	u_int32_t       reg_tctl;
 	u_int32_t       reg_tipg = 0;
+	u_int64_t	bus_addr;
 
 	/* Setup the Base and Length of the Tx Descriptor Ring */
-	E1000_WRITE_REG(&adapter->hw, TDBAL, 
-			vtophys((vm_offset_t) adapter->tx_desc_base));
-	E1000_WRITE_REG(&adapter->hw, TDBAH, 0);
+	bus_addr = adapter->txdma.dma_paddr;
+	E1000_WRITE_REG(&adapter->hw, TDBAL, (u_int32_t)bus_addr);
+	E1000_WRITE_REG(&adapter->hw, TDBAH, (u_int32_t)(bus_addr >> 32));
 	E1000_WRITE_REG(&adapter->hw, TDLEN, 
 			adapter->num_tx_desc *
 			sizeof(struct em_tx_desc));
@@ -2170,7 +2171,7 @@
         register struct mbuf    *mp = nmp;
         struct em_buffer *rx_buffer;
         struct ifnet   *ifp;
-        u_int32_t paddr;
+        bus_addr_t paddr;
         int error;
 
         ifp = &adapter->interface_data.ac_if;
@@ -2317,6 +2318,7 @@
 	u_int32_t       reg_rctl;
 	u_int32_t       reg_rxcsum;
 	struct ifnet    *ifp;
+	u_int64_t	bus_addr;
 
 	ifp = &adapter->interface_data.ac_if;
 
@@ -2338,9 +2340,9 @@
         }       
 
 	/* Setup the Base and Length of the Rx Descriptor Ring */
-	E1000_WRITE_REG(&adapter->hw, RDBAL, 
-			vtophys((vm_offset_t) adapter->rx_desc_base));
-	E1000_WRITE_REG(&adapter->hw, RDBAH, 0);
+	bus_addr = vtophys((vm_offset_t)adapter->rx_desc_base);
+	E1000_WRITE_REG(&adapter->hw, RDBAL, (u_int32_t)bus_addr);
+	E1000_WRITE_REG(&adapter->hw, RDBAH, (u_int32_t)(bus_addr >> 32));
 	E1000_WRITE_REG(&adapter->hw, RDLEN, adapter->num_rx_desc *
 			sizeof(struct em_rx_desc));
 
Index: if_em.h
===================================================================
RCS file: /home/ncvs/src/sys/dev/em/if_em.h,v
retrieving revision 1.14
diff -u -r1.14 if_em.h
--- if_em.h	2 May 2003 21:17:07 -0000	1.14
+++ if_em.h	2 May 2003 23:13:54 -0000
@@ -282,7 +282,7 @@
  * em_dma_malloc and em_dma_free.
  */
 struct em_dma_alloc {
-        u_int32_t               dma_paddr;
+        bus_addr_t              dma_paddr;
         caddr_t                 dma_vaddr;
         bus_dma_tag_t           dma_tag;
         bus_dmamap_t            dma_map;



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20030503064203.GB17896>