* 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).