提交 6ecb7667 编写于 作者: D Don Fry 提交者: Jeff Garzik

pcnet32: only allocate init_block dma consistent

The patch below moves the init_block out of the private struct and
only allocates init block with pci_alloc_consistent.

This has two effects:

1. Performance increase for non cache coherent machines, because the
   CPU only data in the private struct are now cached

2. locks are working now for platforms, which need to have locks
   in cached memory
Signed-off-by: NThomas Bogendoerfer <tsbogend@alpha.franken.de>
Acked-by: NDon Fry <pcnet32@verizon.net>
Signed-off-by: NJeff Garzik <jeff@garzik.org>
上级 1c8816c6
...@@ -253,12 +253,12 @@ struct pcnet32_access { ...@@ -253,12 +253,12 @@ struct pcnet32_access {
* so the structure should be allocated using pci_alloc_consistent(). * so the structure should be allocated using pci_alloc_consistent().
*/ */
struct pcnet32_private { struct pcnet32_private {
struct pcnet32_init_block init_block; struct pcnet32_init_block *init_block;
/* The Tx and Rx ring entries must be aligned on 16-byte boundaries in 32bit mode. */ /* The Tx and Rx ring entries must be aligned on 16-byte boundaries in 32bit mode. */
struct pcnet32_rx_head *rx_ring; struct pcnet32_rx_head *rx_ring;
struct pcnet32_tx_head *tx_ring; struct pcnet32_tx_head *tx_ring;
dma_addr_t dma_addr;/* DMA address of beginning of this dma_addr_t init_dma_addr;/* DMA address of beginning of the init block,
object, returned by pci_alloc_consistent */ returned by pci_alloc_consistent */
struct pci_dev *pci_dev; struct pci_dev *pci_dev;
const char *name; const char *name;
/* The saved address of a sent-in-place packet/buffer, for skfree(). */ /* The saved address of a sent-in-place packet/buffer, for skfree(). */
...@@ -1592,7 +1592,6 @@ static int __devinit ...@@ -1592,7 +1592,6 @@ static int __devinit
pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev) pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev)
{ {
struct pcnet32_private *lp; struct pcnet32_private *lp;
dma_addr_t lp_dma_addr;
int i, media; int i, media;
int fdx, mii, fset, dxsuflo; int fdx, mii, fset, dxsuflo;
int chip_version; int chip_version;
...@@ -1714,7 +1713,7 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev) ...@@ -1714,7 +1713,7 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev)
dxsuflo = 1; dxsuflo = 1;
} }
dev = alloc_etherdev(0); dev = alloc_etherdev(sizeof(*lp));
if (!dev) { if (!dev) {
if (pcnet32_debug & NETIF_MSG_PROBE) if (pcnet32_debug & NETIF_MSG_PROBE)
printk(KERN_ERR PFX "Memory allocation failed.\n"); printk(KERN_ERR PFX "Memory allocation failed.\n");
...@@ -1805,25 +1804,22 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev) ...@@ -1805,25 +1804,22 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev)
} }
dev->base_addr = ioaddr; dev->base_addr = ioaddr;
lp = dev->priv;
/* pci_alloc_consistent returns page-aligned memory, so we do not have to check the alignment */ /* pci_alloc_consistent returns page-aligned memory, so we do not have to check the alignment */
if ((lp = if ((lp->init_block =
pci_alloc_consistent(pdev, sizeof(*lp), &lp_dma_addr)) == NULL) { pci_alloc_consistent(pdev, sizeof(*lp->init_block), &lp->init_dma_addr)) == NULL) {
if (pcnet32_debug & NETIF_MSG_PROBE) if (pcnet32_debug & NETIF_MSG_PROBE)
printk(KERN_ERR PFX printk(KERN_ERR PFX
"Consistent memory allocation failed.\n"); "Consistent memory allocation failed.\n");
ret = -ENOMEM; ret = -ENOMEM;
goto err_free_netdev; goto err_free_netdev;
} }
memset(lp, 0, sizeof(*lp));
lp->dma_addr = lp_dma_addr;
lp->pci_dev = pdev; lp->pci_dev = pdev;
spin_lock_init(&lp->lock); spin_lock_init(&lp->lock);
SET_MODULE_OWNER(dev); SET_MODULE_OWNER(dev);
SET_NETDEV_DEV(dev, &pdev->dev); SET_NETDEV_DEV(dev, &pdev->dev);
dev->priv = lp;
lp->name = chipname; lp->name = chipname;
lp->shared_irq = shared; lp->shared_irq = shared;
lp->tx_ring_size = TX_RING_SIZE; /* default tx ring size */ lp->tx_ring_size = TX_RING_SIZE; /* default tx ring size */
...@@ -1870,23 +1866,21 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev) ...@@ -1870,23 +1866,21 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev)
&& dev->dev_addr[2] == 0x75) && dev->dev_addr[2] == 0x75)
lp->options = PCNET32_PORT_FD | PCNET32_PORT_GPSI; lp->options = PCNET32_PORT_FD | PCNET32_PORT_GPSI;
lp->init_block.mode = le16_to_cpu(0x0003); /* Disable Rx and Tx. */ lp->init_block->mode = le16_to_cpu(0x0003); /* Disable Rx and Tx. */
lp->init_block.tlen_rlen = lp->init_block->tlen_rlen =
le16_to_cpu(lp->tx_len_bits | lp->rx_len_bits); le16_to_cpu(lp->tx_len_bits | lp->rx_len_bits);
for (i = 0; i < 6; i++) for (i = 0; i < 6; i++)
lp->init_block.phys_addr[i] = dev->dev_addr[i]; lp->init_block->phys_addr[i] = dev->dev_addr[i];
lp->init_block.filter[0] = 0x00000000; lp->init_block->filter[0] = 0x00000000;
lp->init_block.filter[1] = 0x00000000; lp->init_block->filter[1] = 0x00000000;
lp->init_block.rx_ring = (u32) le32_to_cpu(lp->rx_ring_dma_addr); lp->init_block->rx_ring = (u32) le32_to_cpu(lp->rx_ring_dma_addr);
lp->init_block.tx_ring = (u32) le32_to_cpu(lp->tx_ring_dma_addr); lp->init_block->tx_ring = (u32) le32_to_cpu(lp->tx_ring_dma_addr);
/* switch pcnet32 to 32bit mode */ /* switch pcnet32 to 32bit mode */
a->write_bcr(ioaddr, 20, 2); a->write_bcr(ioaddr, 20, 2);
a->write_csr(ioaddr, 1, (lp->dma_addr + offsetof(struct pcnet32_private, a->write_csr(ioaddr, 1, (lp->init_dma_addr & 0xffff));
init_block)) & 0xffff); a->write_csr(ioaddr, 2, (lp->init_dma_addr >> 16));
a->write_csr(ioaddr, 2, (lp->dma_addr + offsetof(struct pcnet32_private,
init_block)) >> 16);
if (pdev) { /* use the IRQ provided by PCI */ if (pdev) { /* use the IRQ provided by PCI */
dev->irq = pdev->irq; dev->irq = pdev->irq;
...@@ -1992,7 +1986,8 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev) ...@@ -1992,7 +1986,8 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev)
err_free_ring: err_free_ring:
pcnet32_free_ring(dev); pcnet32_free_ring(dev);
err_free_consistent: err_free_consistent:
pci_free_consistent(lp->pci_dev, sizeof(*lp), lp, lp->dma_addr); pci_free_consistent(lp->pci_dev, sizeof(*lp->init_block),
lp->init_block, lp->init_dma_addr);
err_free_netdev: err_free_netdev:
free_netdev(dev); free_netdev(dev);
err_release_region: err_release_region:
...@@ -2134,8 +2129,7 @@ static int pcnet32_open(struct net_device *dev) ...@@ -2134,8 +2129,7 @@ static int pcnet32_open(struct net_device *dev)
"%s: pcnet32_open() irq %d tx/rx rings %#x/%#x init %#x.\n", "%s: pcnet32_open() irq %d tx/rx rings %#x/%#x init %#x.\n",
dev->name, dev->irq, (u32) (lp->tx_ring_dma_addr), dev->name, dev->irq, (u32) (lp->tx_ring_dma_addr),
(u32) (lp->rx_ring_dma_addr), (u32) (lp->rx_ring_dma_addr),
(u32) (lp->dma_addr + (u32) (lp->init_dma_addr));
offsetof(struct pcnet32_private, init_block)));
/* set/reset autoselect bit */ /* set/reset autoselect bit */
val = lp->a.read_bcr(ioaddr, 2) & ~2; val = lp->a.read_bcr(ioaddr, 2) & ~2;
...@@ -2274,7 +2268,7 @@ static int pcnet32_open(struct net_device *dev) ...@@ -2274,7 +2268,7 @@ static int pcnet32_open(struct net_device *dev)
} }
#endif #endif
lp->init_block.mode = lp->init_block->mode =
le16_to_cpu((lp->options & PCNET32_PORT_PORTSEL) << 7); le16_to_cpu((lp->options & PCNET32_PORT_PORTSEL) << 7);
pcnet32_load_multicast(dev); pcnet32_load_multicast(dev);
...@@ -2284,12 +2278,8 @@ static int pcnet32_open(struct net_device *dev) ...@@ -2284,12 +2278,8 @@ static int pcnet32_open(struct net_device *dev)
} }
/* Re-initialize the PCNET32, and start it when done. */ /* Re-initialize the PCNET32, and start it when done. */
lp->a.write_csr(ioaddr, 1, (lp->dma_addr + lp->a.write_csr(ioaddr, 1, (lp->init_dma_addr & 0xffff));
offsetof(struct pcnet32_private, lp->a.write_csr(ioaddr, 2, (lp->init_dma_addr >> 16));
init_block)) & 0xffff);
lp->a.write_csr(ioaddr, 2,
(lp->dma_addr +
offsetof(struct pcnet32_private, init_block)) >> 16);
lp->a.write_csr(ioaddr, CSR4, 0x0915); /* auto tx pad */ lp->a.write_csr(ioaddr, CSR4, 0x0915); /* auto tx pad */
lp->a.write_csr(ioaddr, CSR0, CSR0_INIT); lp->a.write_csr(ioaddr, CSR0, CSR0_INIT);
...@@ -2316,8 +2306,7 @@ static int pcnet32_open(struct net_device *dev) ...@@ -2316,8 +2306,7 @@ static int pcnet32_open(struct net_device *dev)
printk(KERN_DEBUG printk(KERN_DEBUG
"%s: pcnet32 open after %d ticks, init block %#x csr0 %4.4x.\n", "%s: pcnet32 open after %d ticks, init block %#x csr0 %4.4x.\n",
dev->name, i, dev->name, i,
(u32) (lp->dma_addr + (u32) (lp->init_dma_addr),
offsetof(struct pcnet32_private, init_block)),
lp->a.read_csr(ioaddr, CSR0)); lp->a.read_csr(ioaddr, CSR0));
spin_unlock_irqrestore(&lp->lock, flags); spin_unlock_irqrestore(&lp->lock, flags);
...@@ -2417,12 +2406,12 @@ static int pcnet32_init_ring(struct net_device *dev) ...@@ -2417,12 +2406,12 @@ static int pcnet32_init_ring(struct net_device *dev)
lp->tx_dma_addr[i] = 0; lp->tx_dma_addr[i] = 0;
} }
lp->init_block.tlen_rlen = lp->init_block->tlen_rlen =
le16_to_cpu(lp->tx_len_bits | lp->rx_len_bits); le16_to_cpu(lp->tx_len_bits | lp->rx_len_bits);
for (i = 0; i < 6; i++) for (i = 0; i < 6; i++)
lp->init_block.phys_addr[i] = dev->dev_addr[i]; lp->init_block->phys_addr[i] = dev->dev_addr[i];
lp->init_block.rx_ring = (u32) le32_to_cpu(lp->rx_ring_dma_addr); lp->init_block->rx_ring = (u32) le32_to_cpu(lp->rx_ring_dma_addr);
lp->init_block.tx_ring = (u32) le32_to_cpu(lp->tx_ring_dma_addr); lp->init_block->tx_ring = (u32) le32_to_cpu(lp->tx_ring_dma_addr);
wmb(); /* Make sure all changes are visible */ wmb(); /* Make sure all changes are visible */
return 0; return 0;
} }
...@@ -2707,7 +2696,7 @@ static struct net_device_stats *pcnet32_get_stats(struct net_device *dev) ...@@ -2707,7 +2696,7 @@ static struct net_device_stats *pcnet32_get_stats(struct net_device *dev)
static void pcnet32_load_multicast(struct net_device *dev) static void pcnet32_load_multicast(struct net_device *dev)
{ {
struct pcnet32_private *lp = dev->priv; struct pcnet32_private *lp = dev->priv;
volatile struct pcnet32_init_block *ib = &lp->init_block; volatile struct pcnet32_init_block *ib = lp->init_block;
volatile u16 *mcast_table = (u16 *) & ib->filter; volatile u16 *mcast_table = (u16 *) & ib->filter;
struct dev_mc_list *dmi = dev->mc_list; struct dev_mc_list *dmi = dev->mc_list;
unsigned long ioaddr = dev->base_addr; unsigned long ioaddr = dev->base_addr;
...@@ -2767,12 +2756,12 @@ static void pcnet32_set_multicast_list(struct net_device *dev) ...@@ -2767,12 +2756,12 @@ static void pcnet32_set_multicast_list(struct net_device *dev)
if (netif_msg_hw(lp)) if (netif_msg_hw(lp))
printk(KERN_INFO "%s: Promiscuous mode enabled.\n", printk(KERN_INFO "%s: Promiscuous mode enabled.\n",
dev->name); dev->name);
lp->init_block.mode = lp->init_block->mode =
le16_to_cpu(0x8000 | (lp->options & PCNET32_PORT_PORTSEL) << le16_to_cpu(0x8000 | (lp->options & PCNET32_PORT_PORTSEL) <<
7); 7);
lp->a.write_csr(ioaddr, CSR15, csr15 | 0x8000); lp->a.write_csr(ioaddr, CSR15, csr15 | 0x8000);
} else { } else {
lp->init_block.mode = lp->init_block->mode =
le16_to_cpu((lp->options & PCNET32_PORT_PORTSEL) << 7); le16_to_cpu((lp->options & PCNET32_PORT_PORTSEL) << 7);
lp->a.write_csr(ioaddr, CSR15, csr15 & 0x7fff); lp->a.write_csr(ioaddr, CSR15, csr15 & 0x7fff);
pcnet32_load_multicast(dev); pcnet32_load_multicast(dev);
...@@ -2965,7 +2954,8 @@ static void __devexit pcnet32_remove_one(struct pci_dev *pdev) ...@@ -2965,7 +2954,8 @@ static void __devexit pcnet32_remove_one(struct pci_dev *pdev)
unregister_netdev(dev); unregister_netdev(dev);
pcnet32_free_ring(dev); pcnet32_free_ring(dev);
release_region(dev->base_addr, PCNET32_TOTAL_SIZE); release_region(dev->base_addr, PCNET32_TOTAL_SIZE);
pci_free_consistent(lp->pci_dev, sizeof(*lp), lp, lp->dma_addr); pci_free_consistent(lp->pci_dev, sizeof(*lp->init_block),
lp->init_block, lp->init_dma_addr);
free_netdev(dev); free_netdev(dev);
pci_disable_device(pdev); pci_disable_device(pdev);
pci_set_drvdata(pdev, NULL); pci_set_drvdata(pdev, NULL);
...@@ -3045,7 +3035,8 @@ static void __exit pcnet32_cleanup_module(void) ...@@ -3045,7 +3035,8 @@ static void __exit pcnet32_cleanup_module(void)
unregister_netdev(pcnet32_dev); unregister_netdev(pcnet32_dev);
pcnet32_free_ring(pcnet32_dev); pcnet32_free_ring(pcnet32_dev);
release_region(pcnet32_dev->base_addr, PCNET32_TOTAL_SIZE); release_region(pcnet32_dev->base_addr, PCNET32_TOTAL_SIZE);
pci_free_consistent(lp->pci_dev, sizeof(*lp), lp, lp->dma_addr); pci_free_consistent(lp->pci_dev, sizeof(*lp->init_block),
lp->init_block, lp->init_dma_addr);
free_netdev(pcnet32_dev); free_netdev(pcnet32_dev);
pcnet32_dev = next_dev; pcnet32_dev = next_dev;
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册