* 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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.