netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* b44: add 47xx support
@ 2004-07-23 21:35 Florian Schirmer
  2004-07-26 14:11 ` Pekka Pietikainen
  0 siblings, 1 reply; 7+ messages in thread
From: Florian Schirmer @ 2004-07-23 21:35 UTC (permalink / raw)
  To: jgarzik; +Cc: pp, linux-kernel, netdev

[-- Attachment #1: Type: Text/Plain, Size: 549 bytes --]

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Hi,

this patch adds support for the BCM47xx device to the b44 driver. Please 
apply.

BTW what happened to the 1GB DMA fix? The SiliconBackplane cores _are_ limited 
to a 1GB DMA window so we need to take that into account. Any reason why 
those patches where dropped?

Regards,
  Florian

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.4 (GNU/Linux)

iD8DBQFBAYSlXRF2vHoIlBsRAu+YAKCGzT01hW+yW5SMCbFGOCqx89uIxwCguwZT
zeDLpFVyILUSnaYNJe2A4YU=
=6269
-----END PGP SIGNATURE-----

[-- Attachment #2: b44-47xx.patch --]
[-- Type: text/x-diff, Size: 8846 bytes --]

Index: include/linux/pci_ids.h
===================================================================
RCS file: /home/cvs/linux/include/linux/pci_ids.h,v
retrieving revision 1.124
diff -a -u -p -r1.124 pci_ids.h
--- mips/include/linux/pci_ids.h	20 Jul 2004 20:21:26 -0000	1.124
+++ mips/include/linux/pci_ids.h	23 Jul 2004 21:10:45 -0000
@@ -1913,6 +1913,7 @@
 #define PCI_DEVICE_ID_BCM4401		0x4401
 #define PCI_DEVICE_ID_BCM4401B0		0x4402
 #define PCI_DEVICE_ID_BCM4401B1		0x170c
+#define PCI_DEVICE_ID_BCM4713		0x4713
 
 #define PCI_VENDOR_ID_ENE		0x1524
 #define PCI_DEVICE_ID_ENE_1211		0x1211
Index: drivers/net/b44.c
===================================================================
RCS file: /home/cvs/linux/drivers/net/b44.c,v
retrieving revision 1.14
diff -a -u -p -r1.14 b44.c
--- mips/drivers/net/b44.c	9 Jun 2004 14:12:09 -0000	1.14
+++ mips/drivers/net/b44.c	23 Jul 2004 21:10:47 -0000
@@ -75,7 +75,7 @@ static char version[] __devinitdata =
 	DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
 
 MODULE_AUTHOR("David S. Miller (davem@redhat.com)");
-MODULE_DESCRIPTION("Broadcom 4400 10/100 PCI ethernet driver");
+MODULE_DESCRIPTION("Broadcom 4400/47xx 10/100 PCI ethernet driver");
 MODULE_LICENSE("GPL");
 MODULE_PARM(b44_debug, "i");
 MODULE_PARM_DESC(b44_debug, "B44 bitmapped debugging message enable value");
@@ -89,6 +89,8 @@ static struct pci_device_id b44_pci_tbl[
 	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
 	{ PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_BCM4401B1,
 	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
+	{ PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_BCM4713,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
 	{ }	/* terminate list with empty entry */
 };
 
@@ -130,41 +132,8 @@ static int b44_wait_bit(struct b44 *bp, 
  * interrupts disabled.
  */
 
-#define SBID_SDRAM		0
-#define SBID_PCI_MEM		1
-#define SBID_PCI_CFG		2
-#define SBID_PCI_DMA		3
-#define	SBID_SDRAM_SWAPPED	4
-#define SBID_ENUM		5
-#define SBID_REG_SDRAM		6
-#define SBID_REG_ILINE20	7
-#define SBID_REG_EMAC		8
-#define SBID_REG_CODEC		9
-#define SBID_REG_USB		10
-#define SBID_REG_PCI		11
-#define SBID_REG_MIPS		12
-#define SBID_REG_EXTIF		13
-#define	SBID_EXTIF		14
-#define	SBID_EJTAG		15
-#define	SBID_MAX		16
-
-static u32 ssb_get_addr(struct b44 *bp, u32 id, u32 instance)
-{
-	switch (id) {
-	case SBID_PCI_DMA:
-		return 0x40000000;
-	case SBID_ENUM:
-		return 0x18000000;
-	case SBID_REG_EMAC:
-		return 0x18000000;
-	case SBID_REG_CODEC:
-		return 0x18001000;
-	case SBID_REG_PCI:
-		return 0x18002000;
-	default:
-		return 0;
-	};
-}
+#define SB_PCI_DMA		0x40000000	/* Client Mode PCI memory access space (1 GB) */
+#define BCM4400_PCI_CORE_ADDR	0x18002000	/* Address of PCI core on BCM4400 cards */
 
 static u32 ssb_get_core_rev(struct b44 *bp)
 {
@@ -176,8 +145,7 @@ static u32 ssb_pci_setup(struct b44 *bp,
 	u32 bar_orig, pci_rev, val;
 
 	pci_read_config_dword(bp->pdev, SSB_BAR0_WIN, &bar_orig);
-	pci_write_config_dword(bp->pdev, SSB_BAR0_WIN,
-			       ssb_get_addr(bp, SBID_REG_PCI, 0));
+	pci_write_config_dword(bp->pdev, SSB_BAR0_WIN, BCM4400_PCI_CORE_ADDR);
 	pci_rev = ssb_get_core_rev(bp);
 
 	val = br32(B44_SBINTVEC);
@@ -307,6 +275,9 @@ static int b44_readphy(struct b44 *bp, i
 {
 	int err;
 
+	if (bp->flags & B44_FLAG_NO_PHY)
+		return 0;
+
 	bw32(B44_EMAC_ISTAT, EMAC_INT_MII);
 	bw32(B44_MDIO_DATA, (MDIO_DATA_SB_START |
 			     (MDIO_OP_READ << MDIO_DATA_OP_SHIFT) |
@@ -321,6 +292,9 @@ static int b44_readphy(struct b44 *bp, i
 
 static int b44_writephy(struct b44 *bp, int reg, u32 val)
 {
+	if (bp->flags & B44_FLAG_NO_PHY)
+		return 0;
+
 	bw32(B44_EMAC_ISTAT, EMAC_INT_MII);
 	bw32(B44_MDIO_DATA, (MDIO_DATA_SB_START |
 			     (MDIO_OP_WRITE << MDIO_DATA_OP_SHIFT) |
@@ -359,6 +333,9 @@ static int b44_phy_reset(struct b44 *bp)
 	u32 val;
 	int err;
 
+	if (bp->flags & B44_FLAG_NO_PHY)
+		return 0;
+
 	err = b44_writephy(bp, MII_BMCR, BMCR_RESET);
 	if (err)
 		return err;
@@ -429,6 +406,9 @@ static int b44_setup_phy(struct b44 *bp)
 	u32 val;
 	int err;
 
+	if (bp->flags & B44_FLAG_NO_PHY)
+		return 0;
+
 	if ((err = b44_readphy(bp, B44_MII_ALEDCTRL, &val)) != 0)
 		goto out;
 	if ((err = b44_writephy(bp, B44_MII_ALEDCTRL,
@@ -521,6 +501,19 @@ static void b44_check_phy(struct b44 *bp
 {
 	u32 bmsr, aux;
 
+	if (bp->flags & B44_FLAG_NO_PHY) {
+		bp->flags |= B44_FLAG_100_BASE_T;
+		bp->flags |= B44_FLAG_FULL_DUPLEX;
+		if (!netif_carrier_ok(bp->dev)) {
+			u32 val = br32(B44_TX_CTRL);
+			val |= TX_CTRL_DUPLEX;
+			bw32(B44_TX_CTRL, val);
+			netif_carrier_on(bp->dev);
+			b44_link_report(bp);
+		}
+		return;
+	}
+
 	if (!b44_readphy(bp, MII_BMSR, &bmsr) &&
 	    !b44_readphy(bp, B44_MII_AUXCTRL, &aux) &&
 	    (bmsr != 0xffff)) {
@@ -1132,18 +1125,28 @@ static void b44_chip_reset(struct b44 *b
 		bw32(B44_DMARX_CTRL, 0);
 		bp->rx_prod = bp->rx_cons = 0;
 	} else {
-		ssb_pci_setup(bp, (bp->core_unit == 0 ?
-				   SBINTVEC_ENET0 :
-				   SBINTVEC_ENET1));
+		if (bp->pdev->device != PCI_DEVICE_ID_BCM4713)
+			ssb_pci_setup(bp, (bp->core_unit == 0 ?
+					   SBINTVEC_ENET0 :
+					   SBINTVEC_ENET1));
 	}
 
 	ssb_core_reset(bp);
 
 	b44_clear_stats(bp);
 
-	/* Make PHY accessible. */
-	bw32(B44_MDIO_CTRL, (MDIO_CTRL_PREAMBLE |
-			     (0x0d & MDIO_CTRL_MAXF_MASK)));
+	if (bp->pdev->device == PCI_DEVICE_ID_BCM4713) {
+		/* 
+		 * BCM47xx boards don't have a PHY. Usually there is a switch
+		 * chip with multiple PHYs conntected to the PHY port.
+		 */
+		bp->flags |= B44_FLAG_NO_PHY;
+		bw32(B44_MDIO_CTRL, 0x94);
+	} else {
+		/* Make PHY accessible. */
+		bw32(B44_MDIO_CTRL, (MDIO_CTRL_PREAMBLE |
+				     (0x0d & MDIO_CTRL_MAXF_MASK)));
+	}
 	br32(B44_MDIO_CTRL);
 
 	if (!(br32(B44_DEVCTRL) & DEVCTRL_IPP)) {
@@ -1659,21 +1662,38 @@ static int b44_read_eeprom(struct b44 *b
 static int __devinit b44_get_invariants(struct b44 *bp)
 {
 	u8 eeprom[128];
-	int err;
+	int err = 0;
+	static int instance = 0;
 
-	err = b44_read_eeprom(bp, &eeprom[0]);
-	if (err)
-		goto out;
+	if (bp->pdev->device == PCI_DEVICE_ID_BCM4713) {
+		bp->dev->dev_addr[0] = 0x01;
+		bp->dev->dev_addr[1] = 0x01;
+		bp->dev->dev_addr[2] = 0x02;
+		bp->dev->dev_addr[3] = 0x02;
+		bp->dev->dev_addr[4] = 0x01;
+		bp->dev->dev_addr[5] = 0x01 + instance;
+
+		bp->phy_addr = 30;
+		bp->mdc_port = instance++;
+		
+		bp->dma_offset = 0;
+	} else {
+		err = b44_read_eeprom(bp, &eeprom[0]);
+		if (err)
+			goto out;
 
-	bp->dev->dev_addr[0] = eeprom[79];
-	bp->dev->dev_addr[1] = eeprom[78];
-	bp->dev->dev_addr[2] = eeprom[81];
-	bp->dev->dev_addr[3] = eeprom[80];
-	bp->dev->dev_addr[4] = eeprom[83];
-	bp->dev->dev_addr[5] = eeprom[82];
+		bp->dev->dev_addr[0] = eeprom[79];
+		bp->dev->dev_addr[1] = eeprom[78];
+		bp->dev->dev_addr[2] = eeprom[81];
+		bp->dev->dev_addr[3] = eeprom[80];
+		bp->dev->dev_addr[4] = eeprom[83];
+		bp->dev->dev_addr[5] = eeprom[82];
 
-	bp->phy_addr = eeprom[90] & 0x1f;
-	bp->mdc_port = (eeprom[90] >> 14) & 0x1;
+		bp->phy_addr = eeprom[90] & 0x1f;
+		bp->mdc_port = (eeprom[90] >> 14) & 0x1;
+		
+		bp->dma_offset = SB_PCI_DMA;
+	}
 
 	/* With this, plus the rx_header prepended to the data by the
 	 * hardware, we'll land the ethernet header on a 2-byte boundary.
@@ -1683,7 +1703,6 @@ static int __devinit b44_get_invariants(
 	bp->imask = IMASK_DEF;
 
 	bp->core_unit = ssb_core_unit(bp);
-	bp->dma_offset = ssb_get_addr(bp, SBID_PCI_DMA, 0);
 
 	/* XXX - really required? 
 	   bp->flags |= B44_FLAG_BUGGY_TXPTR;
@@ -1818,7 +1837,8 @@ static int __devinit b44_init_one(struct
 
 	pci_save_state(bp->pdev, bp->pci_cfg_state);
 
-	printk(KERN_INFO "%s: Broadcom 4400 10/100BaseT Ethernet ", dev->name);
+	printk(KERN_INFO "%s: Broadcom %s 10/100BaseT Ethernet ", dev->name,
+		(pdev->device == PCI_DEVICE_ID_BCM4713) ? "47xx" : "4400");
 	for (i = 0; i < 6; i++)
 		printk("%2.2x%c", dev->dev_addr[i],
 		       i == 5 ? '\n' : ':');
Index: drivers/net/b44.h
===================================================================
RCS file: /home/cvs/linux/drivers/net/b44.h,v
retrieving revision 1.5
diff -a -u -p -r1.5 b44.h
--- mips/drivers/net/b44.h	6 Jun 2004 02:12:45 -0000	1.5
+++ mips/drivers/net/b44.h	23 Jul 2004 21:10:51 -0000
@@ -356,16 +356,6 @@
 #define  SBIDHIGH_VC_MASK	0xffff0000 /* Vendor Code */
 #define  SBIDHIGH_VC_SHIFT	16
 
-#define  CORE_CODE_ILINE20	0x801
-#define  CORE_CODE_SDRAM	0x803
-#define  CORE_CODE_PCI		0x804
-#define  CORE_CODE_MIPS		0x805
-#define  CORE_CODE_ENET		0x806
-#define  CORE_CODE_CODEC	0x807
-#define  CORE_CODE_USB		0x808
-#define  CORE_CODE_ILINE100	0x80a
-#define  CORE_CODE_EXTIF	0x811
-
 /* SSB PCI config space registers.  */
 #define	SSB_BAR0_WIN		0x80
 #define	SSB_BAR1_WIN		0x84
@@ -520,6 +510,7 @@ struct b44 {
 #define B44_FLAG_ADV_100HALF	0x04000000
 #define B44_FLAG_ADV_100FULL	0x08000000
 #define B44_FLAG_INTERNAL_PHY	0x10000000
+#define B44_FLAG_NO_PHY		0x20000000
 
 	u32			rx_offset;
 

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: b44: add 47xx support
  2004-07-23 21:35 b44: add 47xx support Florian Schirmer
@ 2004-07-26 14:11 ` Pekka Pietikainen
  2004-08-04  0:31   ` [PATCH] b44 1GB DMA workaround (was: b44: add 47xx support) Pekka Pietikainen
  0 siblings, 1 reply; 7+ messages in thread
From: Pekka Pietikainen @ 2004-07-26 14:11 UTC (permalink / raw)
  To: Florian Schirmer; +Cc: jgarzik, linux-kernel, netdev

On Fri, Jul 23, 2004 at 11:35:30PM +0200, Florian Schirmer wrote:
> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA1
> 
> Hi,
> 
> this patch adds support for the BCM47xx device to the b44 driver. Please 
> apply.
> 
> BTW what happened to the 1GB DMA fix? The SiliconBackplane cores _are_ limited 
> to a 1GB DMA window so we need to take that into account. Any reason why 
> those patches where dropped?
Hiya

Looks good (well, won't be able to test that it doesn't break 4401 until
next week :-) ).

As for the 1GB patch going in, I sure hope they would (perhaps in a cleaned
up state, it might be more pretty if I just unconditionally enabled the
workaround and had a b44_alloc_skb() that tries a normal dev_alloc_skb and if
that gives something over 1GB retry with GFP_DMA...

A situation where it breaks even without 4g4g would help in getting the
patch in :-)

 

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH] b44 1GB DMA workaround (was: b44: add 47xx support)
  2004-07-26 14:11 ` Pekka Pietikainen
@ 2004-08-04  0:31   ` Pekka Pietikainen
  2004-08-04  1:39     ` David S. Miller
  0 siblings, 1 reply; 7+ messages in thread
From: Pekka Pietikainen @ 2004-08-04  0:31 UTC (permalink / raw)
  To: jgarzik; +Cc: Florian Schirmer, linux-kernel, netdev

On Mon, Jul 26, 2004 at 05:11:28PM +0300, Pekka Pietikainen wrote:
> Looks good (well, won't be able to test that it doesn't break 4401 until
> next week :-) ).
The 47xx patch didn't break anything for 4401 so I'm all for merging.
> As for the 1GB patch going in, I sure hope they would (perhaps in a cleaned
> up state, it might be more pretty if I just unconditionally enabled the
> workaround and had a b44_alloc_skb() that tries a normal dev_alloc_skb and if
> that gives something over 1GB retry with GFP_DMA...
I just did that, apart from possibly reducing the default ring sizes to
reduce GFP_DMA usage from the ~= 1.6MB worst-case it is now, it's just about
as good as it'll ever get. Would be nice to get this merged, it seems to
be hitting quite a few people out there.

Signed-off-by: Pekka Pietikainen <pp@ee.oulu.fi>
--- linux-2.6.7-1.503/drivers/net/b44.h.bb	2004-08-04 00:34:37.850485784 +0300
+++ linux-2.6.7-1.503/drivers/net/b44.h	2004-08-04 00:34:48.711834608 +0300
@@ -493,6 +493,7 @@
 
 	struct ring_info	*rx_buffers;
 	struct ring_info	*tx_buffers;
+	unsigned char		*tx_bufs; 
 
 	u32			dma_offset;
 	u32			flags;
@@ -525,7 +526,7 @@
 	struct pci_dev		*pdev;
 	struct net_device	*dev;
 
-	dma_addr_t		rx_ring_dma, tx_ring_dma;
+	dma_addr_t		rx_ring_dma, tx_ring_dma,tx_bufs_dma;
 
 	u32			rx_pending;
 	u32			tx_pending;
--- linux-2.6.7-1.503/drivers/net/b44.c.bb	2004-08-04 00:34:30.653579880 +0300
+++ linux-2.6.7-1.503/drivers/net/b44.c	2004-08-04 02:54:12.756306576 +0300
@@ -27,8 +27,8 @@
 
 #define DRV_MODULE_NAME		"b44"
 #define PFX DRV_MODULE_NAME	": "
-#define DRV_MODULE_VERSION	"0.94"
-#define DRV_MODULE_RELDATE	"May 4, 2004"
+#define DRV_MODULE_VERSION	"0.95"
+#define DRV_MODULE_RELDATE	"Aug 3, 2004"
 
 #define B44_DEF_MSG_ENABLE	  \
 	(NETIF_MSG_DRV		| \
@@ -57,6 +57,7 @@
 #define B44_DEF_TX_RING_PENDING		(B44_TX_RING_SIZE - 1)
 #define B44_TX_RING_BYTES	(sizeof(struct dma_desc) * \
 				 B44_TX_RING_SIZE)
+#define B44_DMA_MASK 0x3fffffff
 
 #define TX_RING_GAP(BP)	\
 	(B44_TX_RING_SIZE - (BP)->tx_pending)
@@ -67,6 +68,7 @@
 #define NEXT_TX(N)		(((N) + 1) & (B44_TX_RING_SIZE - 1))
 
 #define RX_PKT_BUF_SZ		(1536 + bp->rx_offset + 64)
+#define TX_PKT_BUF_SZ		(B44_MAX_MTU + ETH_HLEN + 8)
 
 /* minimum number of free TX descriptors required to wake up TX process */
 #define B44_TX_WAKEUP_THRESH		(B44_TX_RING_SIZE / 4)
@@ -631,10 +633,30 @@
 	if (skb == NULL)
 		return -ENOMEM;
 
-	skb->dev = bp->dev;
 	mapping = pci_map_single(bp->pdev, skb->data,
 				 RX_PKT_BUF_SZ,
 				 PCI_DMA_FROMDEVICE);
+
+	/* Hardware bug work-around, the chip is unable to do PCI DMA
+	   to/from anything above 1GB :-( */
+	if(mapping+RX_PKT_BUF_SZ > B44_DMA_MASK) {
+		/* Sigh... */
+		pci_unmap_single(bp->pdev, mapping, RX_PKT_BUF_SZ,PCI_DMA_FROMDEVICE);
+		dev_kfree_skb_any(skb);
+		skb = __dev_alloc_skb(RX_PKT_BUF_SZ,GFP_DMA);
+		if (skb == NULL)
+			return -ENOMEM;
+		mapping = pci_map_single(bp->pdev, skb->data,
+					 RX_PKT_BUF_SZ,
+					 PCI_DMA_FROMDEVICE);
+		if(mapping+RX_PKT_BUF_SZ > B44_DMA_MASK) {
+			pci_unmap_single(bp->pdev, mapping, RX_PKT_BUF_SZ,PCI_DMA_FROMDEVICE);
+			dev_kfree_skb_any(skb);
+			return -ENOMEM;
+		}
+	}
+
+	skb->dev = bp->dev;
 	skb_reserve(skb, bp->rx_offset);
 
 	rh = (struct rx_header *)
@@ -912,6 +934,13 @@
 
 	entry = bp->tx_prod;
 	mapping = pci_map_single(bp->pdev, skb->data, len, PCI_DMA_TODEVICE);
+	if(mapping+len > B44_DMA_MASK) {
+		/* Chip can't handle DMA to/from >1GB, use bounce buffer */
+		pci_unmap_single(bp->pdev, mapping, len,PCI_DMA_TODEVICE);
+		memcpy(bp->tx_bufs+entry*TX_PKT_BUF_SZ,skb->data,skb->len);
+		skb->data=bp->tx_bufs+entry*TX_PKT_BUF_SZ;
+		mapping = pci_map_single(bp->pdev, skb->data, len, PCI_DMA_TODEVICE);
+	}
 
 	bp->tx_buffers[entry].skb = skb;
 	pci_unmap_addr_set(&bp->tx_buffers[entry], mapping, mapping);
@@ -1059,6 +1088,11 @@
 				    bp->tx_ring, bp->tx_ring_dma);
 		bp->tx_ring = NULL;
 	}
+	if (bp->tx_bufs) {
+		pci_free_consistent(bp->pdev, B44_TX_RING_SIZE * TX_PKT_BUF_SZ,
+				    bp->tx_bufs, bp->tx_bufs_dma);
+		bp->tx_bufs = NULL;
+	}
 }
 
 /*
@@ -1081,6 +1115,12 @@
 		goto out_err;
 	memset(bp->tx_buffers, 0, size);
 
+	size = B44_TX_RING_SIZE * TX_PKT_BUF_SZ;
+	bp->tx_bufs = pci_alloc_consistent(bp->pdev, size, &bp->tx_bufs_dma);
+	if (!bp->tx_bufs)
+		goto out_err;
+	memset(bp->tx_bufs, 0, size);
+
 	size = DMA_TABLE_BYTES;
 	bp->rx_ring = pci_alloc_consistent(bp->pdev, size, &bp->rx_ring_dma);
 	if (!bp->rx_ring)
@@ -1746,12 +1786,19 @@
 
 	pci_set_master(pdev);
 
-	err = pci_set_dma_mask(pdev, (u64) 0xffffffff);
+	err = pci_set_dma_mask(pdev, (u64) B44_DMA_MASK);
 	if (err) {
 		printk(KERN_ERR PFX "No usable DMA configuration, "
 		       "aborting.\n");
 		goto err_out_free_res;
 	}
+	
+	err = pci_set_consistent_dma_mask(pdev, (u64) B44_DMA_MASK);
+	if (err) {
+	  printk(KERN_ERR PFX "No usable DMA configuration, "
+		 "aborting.\n");
+	  goto err_out_free_res;
+	}
 
 	b44reg_base = pci_resource_start(pdev, 0);
 	b44reg_len = pci_resource_len(pdev, 0);

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH] b44 1GB DMA workaround (was: b44: add 47xx support)
  2004-08-04  0:31   ` [PATCH] b44 1GB DMA workaround (was: b44: add 47xx support) Pekka Pietikainen
@ 2004-08-04  1:39     ` David S. Miller
  2004-08-07 22:40       ` Pekka Pietikainen
  0 siblings, 1 reply; 7+ messages in thread
From: David S. Miller @ 2004-08-04  1:39 UTC (permalink / raw)
  To: Pekka Pietikainen; +Cc: jgarzik, jolt, linux-kernel, netdev

On Wed, 4 Aug 2004 03:31:08 +0300
Pekka Pietikainen <pp@ee.oulu.fi> wrote:

> +	if(mapping+len > B44_DMA_MASK) {
> +		/* Chip can't handle DMA to/from >1GB, use bounce buffer */
> +		pci_unmap_single(bp->pdev, mapping, len,PCI_DMA_TODEVICE);
> +		memcpy(bp->tx_bufs+entry*TX_PKT_BUF_SZ,skb->data,skb->len);
> +		skb->data=bp->tx_bufs+entry*TX_PKT_BUF_SZ;
> +		mapping = pci_map_single(bp->pdev, skb->data, len, PCI_DMA_TODEVICE);
> +	}

Changing skb->data is not legal.  Please implement this in
such a way that skb->data does not get modified.  By modifying
skb->data you will break things such as packet sniffers and
netfilter, and that's just the tip of the iceberg. :-)

I would suggest merely freeing up this TX skb, and marking the
entry in the b44 software state with some dummy skb pointer
such as (void *) 0x1UL or something like that to indicate
this case.

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH] b44 1GB DMA workaround (was: b44: add 47xx support)
  2004-08-04  1:39     ` David S. Miller
@ 2004-08-07 22:40       ` Pekka Pietikainen
  2004-08-08  0:05         ` David S. Miller
  0 siblings, 1 reply; 7+ messages in thread
From: Pekka Pietikainen @ 2004-08-07 22:40 UTC (permalink / raw)
  To: David S. Miller; +Cc: jgarzik, jolt, linux-kernel, netdev

On Tue, Aug 03, 2004 at 06:39:19PM -0700, David S. Miller wrote:
> Changing skb->data is not legal.  Please implement this in
> such a way that skb->data does not get modified.  By modifying
> skb->data you will break things such as packet sniffers and
> netfilter, and that's just the tip of the iceberg. :-)
> 
Haven't noticed any breakage (tm) but I'm just a x86 weenie :-)

Current approach is:

        if(1 (just for testing ;) ) || mapping+len > B44_DMA_MASK) {
                /* Chip can't handle DMA to/from >1GB, use bounce buffer */
                pci_unmap_single(bp->pdev, mapping, len,PCI_DMA_TODEVICE);
                memcpy(bp->tx_bufs+entry*TX_PKT_BUF_SZ,skb->data,skb->len);
                mapping = pci_map_single(bp->pdev,bp->tx_bufs+entry*TX_PKT_BUF_SZ, len, PCI_DMA_TODEVICE);
        }

Which also works (tm). Setting the skb to a special value seems a bit tricky
as skb->len is used in b44_tx for that nop^H^H^Hpci_unmap_single. It looks
to me as the right things when the code gets changed as above (even for
archs where the unmapping is not a nop) get done, but I could easily be
missing something.



-- 
Pekka Pietikainen

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH] b44 1GB DMA workaround (was: b44: add 47xx support)
  2004-08-07 22:40       ` Pekka Pietikainen
@ 2004-08-08  0:05         ` David S. Miller
  2004-08-08  9:31           ` [PATCH] b44 1GB DMA workaround Pekka Pietikainen
  0 siblings, 1 reply; 7+ messages in thread
From: David S. Miller @ 2004-08-08  0:05 UTC (permalink / raw)
  To: Pekka Pietikainen; +Cc: jgarzik, jolt, linux-kernel, netdev

On Sun, 8 Aug 2004 01:40:19 +0300
Pekka Pietikainen <pp@ee.oulu.fi> wrote:

> On Tue, Aug 03, 2004 at 06:39:19PM -0700, David S. Miller wrote:
> > Changing skb->data is not legal.  Please implement this in
> > such a way that skb->data does not get modified.  By modifying
> > skb->data you will break things such as packet sniffers and
> > netfilter, and that's just the tip of the iceberg. :-)
> > 
> Haven't noticed any breakage (tm) but I'm just a x86 weenie :-)

Not an x86 specific problem :-)  Just run tcpdump in a shell when
one of these TX bounce cases happen, your skb->data modification could
will make tcpdump see a corrupt packet.

> Current approach is:
> 
>         if(1 (just for testing ;) ) || mapping+len > B44_DMA_MASK) {
>                 /* Chip can't handle DMA to/from >1GB, use bounce buffer */
>                 pci_unmap_single(bp->pdev, mapping, len,PCI_DMA_TODEVICE);
>                 memcpy(bp->tx_bufs+entry*TX_PKT_BUF_SZ,skb->data,skb->len);
>                 mapping = pci_map_single(bp->pdev,bp->tx_bufs+entry*TX_PKT_BUF_SZ, len, PCI_DMA_TODEVICE);
>         }

This looks a bit better.

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH] b44 1GB DMA workaround
  2004-08-08  0:05         ` David S. Miller
@ 2004-08-08  9:31           ` Pekka Pietikainen
  0 siblings, 0 replies; 7+ messages in thread
From: Pekka Pietikainen @ 2004-08-08  9:31 UTC (permalink / raw)
  To: David S. Miller; +Cc: jgarzik, jolt, linux-kernel, netdev

On Sat, Aug 07, 2004 at 05:05:03PM -0700, David S. Miller wrote:
> >         if(1 (just for testing ;) ) || mapping+len > B44_DMA_MASK) {
> >                 /* Chip can't handle DMA to/from >1GB, use bounce buffer */
> >                 pci_unmap_single(bp->pdev, mapping, len,PCI_DMA_TODEVICE);
> >                 memcpy(bp->tx_bufs+entry*TX_PKT_BUF_SZ,skb->data,skb->len);
> >                 mapping = pci_map_single(bp->pdev,bp->tx_bufs+entry*TX_PKT_BUF_SZ, len, PCI_DMA_TODEVICE);
> >         }
> 
> This looks a bit better.
Excellent, here's the full patch:

Signed-off-by: Pekka Pietikainen <pp@ee.oulu.fi>
--- linux-2.6.8-rc3/drivers/net/b44.h.4g4g	2004-08-08 10:54:03.979353080 +0300
+++ linux-2.6.8-rc3/drivers/net/b44.h	2004-08-08 10:54:17.928232528 +0300
@@ -493,6 +493,7 @@
 
 	struct ring_info	*rx_buffers;
 	struct ring_info	*tx_buffers;
+	unsigned char		*tx_bufs; 
 
 	u32			dma_offset;
 	u32			flags;
@@ -525,7 +526,7 @@
 	struct pci_dev		*pdev;
 	struct net_device	*dev;
 
-	dma_addr_t		rx_ring_dma, tx_ring_dma;
+	dma_addr_t		rx_ring_dma, tx_ring_dma,tx_bufs_dma;
 
 	u32			rx_pending;
 	u32			tx_pending;
--- linux-2.6.8-rc3/drivers/net/b44.c.4g4g	2004-08-08 10:53:58.724151992 +0300
+++ linux-2.6.8-rc3/drivers/net/b44.c	2004-08-08 10:54:17.657273720 +0300
@@ -27,8 +27,8 @@
 
 #define DRV_MODULE_NAME		"b44"
 #define PFX DRV_MODULE_NAME	": "
-#define DRV_MODULE_VERSION	"0.94"
-#define DRV_MODULE_RELDATE	"May 4, 2004"
+#define DRV_MODULE_VERSION	"0.95"
+#define DRV_MODULE_RELDATE	"Aug 8, 2004"
 
 #define B44_DEF_MSG_ENABLE	  \
 	(NETIF_MSG_DRV		| \
@@ -57,6 +57,7 @@
 #define B44_DEF_TX_RING_PENDING		(B44_TX_RING_SIZE - 1)
 #define B44_TX_RING_BYTES	(sizeof(struct dma_desc) * \
 				 B44_TX_RING_SIZE)
+#define B44_DMA_MASK 0x3fffffff
 
 #define TX_RING_GAP(BP)	\
 	(B44_TX_RING_SIZE - (BP)->tx_pending)
@@ -67,6 +68,7 @@
 #define NEXT_TX(N)		(((N) + 1) & (B44_TX_RING_SIZE - 1))
 
 #define RX_PKT_BUF_SZ		(1536 + bp->rx_offset + 64)
+#define TX_PKT_BUF_SZ		(B44_MAX_MTU + ETH_HLEN + 8)
 
 /* minimum number of free TX descriptors required to wake up TX process */
 #define B44_TX_WAKEUP_THRESH		(B44_TX_RING_SIZE / 4)
@@ -631,10 +633,30 @@
 	if (skb == NULL)
 		return -ENOMEM;
 
-	skb->dev = bp->dev;
 	mapping = pci_map_single(bp->pdev, skb->data,
 				 RX_PKT_BUF_SZ,
 				 PCI_DMA_FROMDEVICE);
+
+	/* Hardware bug work-around, the chip is unable to do PCI DMA
+	   to/from anything above 1GB :-( */
+	if(mapping+RX_PKT_BUF_SZ > B44_DMA_MASK) {
+		/* Sigh... */
+		pci_unmap_single(bp->pdev, mapping, RX_PKT_BUF_SZ,PCI_DMA_FROMDEVICE);
+		dev_kfree_skb_any(skb);
+		skb = __dev_alloc_skb(RX_PKT_BUF_SZ,GFP_DMA);
+		if (skb == NULL)
+			return -ENOMEM;
+		mapping = pci_map_single(bp->pdev, skb->data,
+					 RX_PKT_BUF_SZ,
+					 PCI_DMA_FROMDEVICE);
+		if(mapping+RX_PKT_BUF_SZ > B44_DMA_MASK) {
+			pci_unmap_single(bp->pdev, mapping, RX_PKT_BUF_SZ,PCI_DMA_FROMDEVICE);
+			dev_kfree_skb_any(skb);
+			return -ENOMEM;
+		}
+	}
+
+	skb->dev = bp->dev;
 	skb_reserve(skb, bp->rx_offset);
 
 	rh = (struct rx_header *)
@@ -912,6 +934,12 @@
 
 	entry = bp->tx_prod;
 	mapping = pci_map_single(bp->pdev, skb->data, len, PCI_DMA_TODEVICE);
+	if(mapping+len > B44_DMA_MASK) {
+		/* Chip can't handle DMA to/from >1GB, use bounce buffer */
+		pci_unmap_single(bp->pdev, mapping, len,PCI_DMA_TODEVICE);
+		memcpy(bp->tx_bufs+entry*TX_PKT_BUF_SZ,skb->data,skb->len);
+		mapping = pci_map_single(bp->pdev, bp->tx_bufs+entry*TX_PKT_BUF_SZ, len, PCI_DMA_TODEVICE);
+	}
 
 	bp->tx_buffers[entry].skb = skb;
 	pci_unmap_addr_set(&bp->tx_buffers[entry], mapping, mapping);
@@ -1059,6 +1087,11 @@
 				    bp->tx_ring, bp->tx_ring_dma);
 		bp->tx_ring = NULL;
 	}
+	if (bp->tx_bufs) {
+		pci_free_consistent(bp->pdev, B44_TX_RING_SIZE * TX_PKT_BUF_SZ,
+				    bp->tx_bufs, bp->tx_bufs_dma);
+		bp->tx_bufs = NULL;
+	}
 }
 
 /*
@@ -1081,6 +1114,12 @@
 		goto out_err;
 	memset(bp->tx_buffers, 0, size);
 
+	size = B44_TX_RING_SIZE * TX_PKT_BUF_SZ;
+	bp->tx_bufs = pci_alloc_consistent(bp->pdev, size, &bp->tx_bufs_dma);
+	if (!bp->tx_bufs)
+		goto out_err;
+	memset(bp->tx_bufs, 0, size);
+
 	size = DMA_TABLE_BYTES;
 	bp->rx_ring = pci_alloc_consistent(bp->pdev, size, &bp->rx_ring_dma);
 	if (!bp->rx_ring)
@@ -1746,12 +1785,19 @@
 
 	pci_set_master(pdev);
 
-	err = pci_set_dma_mask(pdev, (u64) 0xffffffff);
+	err = pci_set_dma_mask(pdev, (u64) B44_DMA_MASK);
 	if (err) {
 		printk(KERN_ERR PFX "No usable DMA configuration, "
 		       "aborting.\n");
 		goto err_out_free_res;
 	}
+	
+	err = pci_set_consistent_dma_mask(pdev, (u64) B44_DMA_MASK);
+	if (err) {
+	  printk(KERN_ERR PFX "No usable DMA configuration, "
+		 "aborting.\n");
+	  goto err_out_free_res;
+	}
 
 	b44reg_base = pci_resource_start(pdev, 0);
 	b44reg_len = pci_resource_len(pdev, 0);

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2004-08-08  9:31 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2004-07-23 21:35 b44: add 47xx support Florian Schirmer
2004-07-26 14:11 ` Pekka Pietikainen
2004-08-04  0:31   ` [PATCH] b44 1GB DMA workaround (was: b44: add 47xx support) Pekka Pietikainen
2004-08-04  1:39     ` David S. Miller
2004-08-07 22:40       ` Pekka Pietikainen
2004-08-08  0:05         ` David S. Miller
2004-08-08  9:31           ` [PATCH] b44 1GB DMA workaround Pekka Pietikainen

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).