Commit 007236e5 authored by Jeff Garzik's avatar Jeff Garzik

Merge bug fixes and PPC-specific feature additions from 2.4.x

into bmac and mace net drivers.

Via Dave Jones.
parent 9a7e6039
...@@ -22,7 +22,8 @@ ...@@ -22,7 +22,8 @@
#include <asm/io.h> #include <asm/io.h>
#include <asm/page.h> #include <asm/page.h>
#include <asm/pgtable.h> #include <asm/pgtable.h>
#include <asm/feature.h> #include <asm/machdep.h>
#include <asm/pmac_feature.h>
#ifdef CONFIG_PMAC_PBOOK #ifdef CONFIG_PMAC_PBOOK
#include <linux/adb.h> #include <linux/adb.h>
#include <linux/pmu.h> #include <linux/pmu.h>
...@@ -155,7 +156,7 @@ static void bmac_reset_and_enable(struct net_device *dev); ...@@ -155,7 +156,7 @@ static void bmac_reset_and_enable(struct net_device *dev);
static void bmac_start_chip(struct net_device *dev); static void bmac_start_chip(struct net_device *dev);
static void bmac_init_chip(struct net_device *dev); static void bmac_init_chip(struct net_device *dev);
static void bmac_init_registers(struct net_device *dev); static void bmac_init_registers(struct net_device *dev);
static void bmac_reset_chip(struct net_device *dev); static void bmac_enable_and_reset_chip(struct net_device *dev);
static int bmac_set_address(struct net_device *dev, void *addr); static int bmac_set_address(struct net_device *dev, void *addr);
static void bmac_misc_intr(int irq, void *dev_id, struct pt_regs *regs); static void bmac_misc_intr(int irq, void *dev_id, struct pt_regs *regs);
static void bmac_txdma_intr(int irq, void *dev_id, struct pt_regs *regs); static void bmac_txdma_intr(int irq, void *dev_id, struct pt_regs *regs);
...@@ -229,21 +230,18 @@ volatile unsigned short bmread(struct net_device *dev, unsigned long reg_offset ...@@ -229,21 +230,18 @@ volatile unsigned short bmread(struct net_device *dev, unsigned long reg_offset
} }
static void static void
bmac_reset_chip(struct net_device *dev) bmac_enable_and_reset_chip(struct net_device *dev)
{ {
struct bmac_data *bp = (struct bmac_data *) dev->priv; struct bmac_data *bp = (struct bmac_data *) dev->priv;
volatile struct dbdma_regs *rd = bp->rx_dma; volatile struct dbdma_regs *rd = bp->rx_dma;
volatile struct dbdma_regs *td = bp->tx_dma; volatile struct dbdma_regs *td = bp->tx_dma;
dbdma_reset(rd); if (rd)
dbdma_reset(td); dbdma_reset(rd);
if (td)
dbdma_reset(td);
feature_set(bp->node, FEATURE_BMac_IO_enable); pmac_call_feature(PMAC_FTR_BMAC_ENABLE, bp->node, 0, 1);
udelay(10000);
feature_set(bp->node, FEATURE_BMac_reset);
udelay(10000);
feature_clear(bp->node, FEATURE_BMac_reset);
udelay(10000);
} }
#define MIFDELAY udelay(10) #define MIFDELAY udelay(10)
...@@ -522,10 +520,7 @@ bmac_sleep_notify(struct pmu_sleep_notifier *self, int when) ...@@ -522,10 +520,7 @@ bmac_sleep_notify(struct pmu_sleep_notifier *self, int when)
} }
} }
} }
feature_set(bp->node, FEATURE_BMac_reset); pmac_call_feature(PMAC_FTR_BMAC_ENABLE, bp->node, 0, 0);
mdelay(10);
feature_clear(bp->node, FEATURE_BMac_IO_enable);
mdelay(10);
break; break;
case PBOOK_WAKE: case PBOOK_WAKE:
/* see if this is enough */ /* see if this is enough */
...@@ -1254,7 +1249,7 @@ static void bmac_reset_and_enable(struct net_device *dev) ...@@ -1254,7 +1249,7 @@ static void bmac_reset_and_enable(struct net_device *dev)
unsigned char *data; unsigned char *data;
save_flags(flags); cli(); save_flags(flags); cli();
bmac_reset_chip(dev); bmac_enable_and_reset_chip(dev);
bmac_init_tx_ring(bp); bmac_init_tx_ring(bp);
bmac_init_rx_ring(bp); bmac_init_rx_ring(bp);
bmac_init_chip(dev); bmac_init_chip(dev);
...@@ -1337,14 +1332,30 @@ static void __init bmac_probe1(struct device_node *bmac, int is_bmac_plus) ...@@ -1337,14 +1332,30 @@ static void __init bmac_probe1(struct device_node *bmac, int is_bmac_plus)
bmac->full_name); bmac->full_name);
return; return;
} }
bp = (struct bmac_data *) dev->priv;
SET_MODULE_OWNER(dev); SET_MODULE_OWNER(dev);
bp->node = bmac;
if (!request_OF_resource(bmac, 0, " (bmac)")) {
printk(KERN_ERR "BMAC: can't request IO resource !\n");
goto err_out;
}
if (!request_OF_resource(bmac, 1, " (bmac tx dma)")) {
printk(KERN_ERR "BMAC: can't request TX DMA resource !\n");
goto err_out;
}
if (!request_OF_resource(bmac, 2, " (bmac rx dma)")) {
printk(KERN_ERR "BMAC: can't request RX DMA resource !\n");
goto err_out;
}
dev->base_addr = (unsigned long) dev->base_addr = (unsigned long)
ioremap(bmac->addrs[0].address, bmac->addrs[0].size); ioremap(bmac->addrs[0].address, bmac->addrs[0].size);
if (!dev->base_addr) if (!dev->base_addr)
goto err_out; goto err_out;
dev->irq = bmac->intrs[0].line; dev->irq = bmac->intrs[0].line;
bmac_enable_and_reset_chip(dev);
bmwrite(dev, INTDISABLE, DisableAll); bmwrite(dev, INTDISABLE, DisableAll);
printk(KERN_INFO "%s: BMAC%s at", dev->name, (is_bmac_plus? "+": "")); printk(KERN_INFO "%s: BMAC%s at", dev->name, (is_bmac_plus? "+": ""));
...@@ -1356,6 +1367,10 @@ static void __init bmac_probe1(struct device_node *bmac, int is_bmac_plus) ...@@ -1356,6 +1367,10 @@ static void __init bmac_probe1(struct device_node *bmac, int is_bmac_plus)
XXDEBUG((", base_addr=%#0lx", dev->base_addr)); XXDEBUG((", base_addr=%#0lx", dev->base_addr));
printk("\n"); printk("\n");
/* Enable chip without interrupts for now */
bmac_enable_and_reset_chip(dev);
bmwrite(dev, INTDISABLE, DisableAll);
dev->open = bmac_open; dev->open = bmac_open;
dev->stop = bmac_close; dev->stop = bmac_close;
dev->hard_start_xmit = bmac_output; dev->hard_start_xmit = bmac_output;
...@@ -1367,7 +1382,6 @@ static void __init bmac_probe1(struct device_node *bmac, int is_bmac_plus) ...@@ -1367,7 +1382,6 @@ static void __init bmac_probe1(struct device_node *bmac, int is_bmac_plus)
if (bmac_verify_checksum(dev) != 0) if (bmac_verify_checksum(dev) != 0)
goto err_out_iounmap; goto err_out_iounmap;
bp = (struct bmac_data *) dev->priv;
bp->is_bmac_plus = is_bmac_plus; bp->is_bmac_plus = is_bmac_plus;
bp->tx_dma = (volatile struct dbdma_regs *) bp->tx_dma = (volatile struct dbdma_regs *)
ioremap(bmac->addrs[1].address, bmac->addrs[1].size); ioremap(bmac->addrs[1].address, bmac->addrs[1].size);
...@@ -1386,7 +1400,6 @@ static void __init bmac_probe1(struct device_node *bmac, int is_bmac_plus) ...@@ -1386,7 +1400,6 @@ static void __init bmac_probe1(struct device_node *bmac, int is_bmac_plus)
bp->queue = (struct sk_buff_head *)(bp->rx_cmds + N_RX_RING + 1); bp->queue = (struct sk_buff_head *)(bp->rx_cmds + N_RX_RING + 1);
skb_queue_head_init(bp->queue); skb_queue_head_init(bp->queue);
bp->node = bmac;
memset((char *) bp->tx_cmds, 0, memset((char *) bp->tx_cmds, 0,
(N_TX_RING + N_RX_RING + 2) * sizeof(struct dbdma_cmd)); (N_TX_RING + N_RX_RING + 2) * sizeof(struct dbdma_cmd));
/* init_timer(&bp->tx_timeout); */ /* init_timer(&bp->tx_timeout); */
...@@ -1408,6 +1421,12 @@ static void __init bmac_probe1(struct device_node *bmac, int is_bmac_plus) ...@@ -1408,6 +1421,12 @@ static void __init bmac_probe1(struct device_node *bmac, int is_bmac_plus)
goto err_out_irq1; goto err_out_irq1;
} }
/* Mask chip interrupts and disable chip, will be
* re-enabled on open()
*/
disable_irq(dev->irq);
pmac_call_feature(PMAC_FTR_BMAC_ENABLE, bp->node, 0, 0);
bp->next_bmac = bmac_devs; bp->next_bmac = bmac_devs;
bmac_devs = dev; bmac_devs = dev;
return; return;
...@@ -1423,6 +1442,12 @@ static void __init bmac_probe1(struct device_node *bmac, int is_bmac_plus) ...@@ -1423,6 +1442,12 @@ static void __init bmac_probe1(struct device_node *bmac, int is_bmac_plus)
err_out_iounmap: err_out_iounmap:
iounmap((void *)dev->base_addr); iounmap((void *)dev->base_addr);
err_out: err_out:
if (bp->node) {
release_OF_resource(bp->node, 0);
release_OF_resource(bp->node, 1);
release_OF_resource(bp->node, 2);
pmac_call_feature(PMAC_FTR_BMAC_ENABLE, bp->node, 0, 0);
}
unregister_netdev(dev); unregister_netdev(dev);
kfree(dev); kfree(dev);
} }
...@@ -1434,6 +1459,7 @@ static int bmac_open(struct net_device *dev) ...@@ -1434,6 +1459,7 @@ static int bmac_open(struct net_device *dev)
/* reset the chip */ /* reset the chip */
bp->opened = 1; bp->opened = 1;
bmac_reset_and_enable(dev); bmac_reset_and_enable(dev);
enable_irq(dev->irq);
dev->flags |= IFF_RUNNING; dev->flags |= IFF_RUNNING;
return 0; return 0;
} }
...@@ -1446,6 +1472,7 @@ static int bmac_close(struct net_device *dev) ...@@ -1446,6 +1472,7 @@ static int bmac_close(struct net_device *dev)
unsigned short config; unsigned short config;
int i; int i;
bp->sleeping = 1;
dev->flags &= ~(IFF_UP | IFF_RUNNING); dev->flags &= ~(IFF_UP | IFF_RUNNING);
/* disable rx and tx */ /* disable rx and tx */
...@@ -1479,6 +1506,8 @@ static int bmac_close(struct net_device *dev) ...@@ -1479,6 +1506,8 @@ static int bmac_close(struct net_device *dev)
XXDEBUG(("bmac: all bufs freed\n")); XXDEBUG(("bmac: all bufs freed\n"));
bp->opened = 0; bp->opened = 0;
disable_irq(dev->irq);
pmac_call_feature(PMAC_FTR_BMAC_ENABLE, bp->node, 0, 0);
return 0; return 0;
} }
...@@ -1548,7 +1577,7 @@ static void bmac_tx_timeout(unsigned long data) ...@@ -1548,7 +1577,7 @@ static void bmac_tx_timeout(unsigned long data)
bmwrite(dev, TXCFG, (config & ~TxMACEnable)); bmwrite(dev, TXCFG, (config & ~TxMACEnable));
out_le32(&td->control, DBDMA_CLEAR(RUN|PAUSE|FLUSH|WAKE|ACTIVE|DEAD)); out_le32(&td->control, DBDMA_CLEAR(RUN|PAUSE|FLUSH|WAKE|ACTIVE|DEAD));
printk(KERN_ERR "bmac: transmit timeout - resetting\n"); printk(KERN_ERR "bmac: transmit timeout - resetting\n");
bmac_reset_chip(dev); bmac_enable_and_reset_chip(dev);
/* restart rx dma */ /* restart rx dma */
cp = bus_to_virt(ld_le32(&rd->cmdptr)); cp = bus_to_virt(ld_le32(&rd->cmdptr));
...@@ -1670,11 +1699,15 @@ static void __exit bmac_cleanup (void) ...@@ -1670,11 +1699,15 @@ static void __exit bmac_cleanup (void)
bp = (struct bmac_data *) dev->priv; bp = (struct bmac_data *) dev->priv;
bmac_devs = bp->next_bmac; bmac_devs = bp->next_bmac;
unregister_netdev(dev);
release_OF_resource(bp->node, 0);
release_OF_resource(bp->node, 1);
release_OF_resource(bp->node, 2);
free_irq(dev->irq, dev); free_irq(dev->irq, dev);
free_irq(bp->tx_dma_intr, dev); free_irq(bp->tx_dma_intr, dev);
free_irq(bp->rx_dma_intr, dev); free_irq(bp->rx_dma_intr, dev);
unregister_netdev(dev);
kfree(dev); kfree(dev);
} while (bmac_devs != NULL); } while (bmac_devs != NULL);
} }
......
...@@ -25,9 +25,6 @@ ...@@ -25,9 +25,6 @@
static struct net_device *mace_devs; static struct net_device *mace_devs;
static int port_aaui = -1; static int port_aaui = -1;
MODULE_PARM(port_aaui, "i");
MODULE_PARM_DESC(port_aaui, "MACE uses AAUI port (0-1)");
#define N_RX_RING 8 #define N_RX_RING 8
#define N_TX_RING 6 #define N_TX_RING 6
#define MAX_TX_ACTIVE 1 #define MAX_TX_ACTIVE 1
...@@ -35,6 +32,9 @@ MODULE_PARM_DESC(port_aaui, "MACE uses AAUI port (0-1)"); ...@@ -35,6 +32,9 @@ MODULE_PARM_DESC(port_aaui, "MACE uses AAUI port (0-1)");
#define RX_BUFLEN (ETH_FRAME_LEN + 8) #define RX_BUFLEN (ETH_FRAME_LEN + 8)
#define TX_TIMEOUT HZ /* 1 second */ #define TX_TIMEOUT HZ /* 1 second */
/* Chip rev needs workaround on HW & multicast addr change */
#define BROKEN_ADDRCHG_REV 0x0941
/* Bits in transmit DMA status */ /* Bits in transmit DMA status */
#define TX_DMA_ERR 0x80 #define TX_DMA_ERR 0x80
...@@ -60,6 +60,8 @@ struct mace_data { ...@@ -60,6 +60,8 @@ struct mace_data {
struct timer_list tx_timeout; struct timer_list tx_timeout;
int timeout_active; int timeout_active;
int port_aaui; int port_aaui;
int chipid;
struct device_node* of_node;
struct net_device *next_mace; struct net_device *next_mace;
}; };
...@@ -153,6 +155,22 @@ static void __init mace_probe1(struct device_node *mace) ...@@ -153,6 +155,22 @@ static void __init mace_probe1(struct device_node *mace)
SET_MODULE_OWNER(dev); SET_MODULE_OWNER(dev);
mp = dev->priv; mp = dev->priv;
mp->of_node = mace;
if (!request_OF_resource(mace, 0, " (mace)")) {
printk(KERN_ERR "MACE: can't request IO resource !\n");
goto err_out;
}
if (!request_OF_resource(mace, 1, " (mace tx dma)")) {
printk(KERN_ERR "MACE: can't request TX DMA resource !\n");
goto err_out;
}
if (!request_OF_resource(mace, 2, " (mace tx dma)")) {
printk(KERN_ERR "MACE: can't request RX DMA resource !\n");
goto err_out;
}
dev->base_addr = mace->addrs[0].address; dev->base_addr = mace->addrs[0].address;
mp->mace = (volatile struct mace *) mp->mace = (volatile struct mace *)
ioremap(mace->addrs[0].address, 0x1000); ioremap(mace->addrs[0].address, 0x1000);
...@@ -164,8 +182,10 @@ static void __init mace_probe1(struct device_node *mace) ...@@ -164,8 +182,10 @@ static void __init mace_probe1(struct device_node *mace)
dev->dev_addr[j] = rev? bitrev(addr[j]): addr[j]; dev->dev_addr[j] = rev? bitrev(addr[j]): addr[j];
printk("%c%.2x", (j? ':': ' '), dev->dev_addr[j]); printk("%c%.2x", (j? ':': ' '), dev->dev_addr[j]);
} }
printk(", chip revision %d.%d\n", mp->chipid = (in_8(&mp->mace->chipid_hi) << 8) |
in_8(&mp->mace->chipid_hi), in_8(&mp->mace->chipid_lo)); in_8(&mp->mace->chipid_lo);
printk(", chip revision %d.%d\n", mp->chipid >> 8, mp->chipid & 0xff);
mp = (struct mace_data *) dev->priv; mp = (struct mace_data *) dev->priv;
mp->maccc = ENXMT | ENRCV; mp->maccc = ENXMT | ENRCV;
...@@ -222,6 +242,16 @@ static void __init mace_probe1(struct device_node *mace) ...@@ -222,6 +242,16 @@ static void __init mace_probe1(struct device_node *mace)
mp->next_mace = mace_devs; mp->next_mace = mace_devs;
mace_devs = dev; mace_devs = dev;
return;
err_out:
unregister_netdev(dev);
if (mp->of_node) {
release_OF_resource(mp->of_node, 0);
release_OF_resource(mp->of_node, 1);
release_OF_resource(mp->of_node, 2);
}
kfree(dev);
} }
static void dbdma_reset(volatile struct dbdma_regs *dma) static void dbdma_reset(volatile struct dbdma_regs *dma)
...@@ -274,14 +304,19 @@ static void mace_reset(struct net_device *dev) ...@@ -274,14 +304,19 @@ static void mace_reset(struct net_device *dev)
__mace_set_address(dev, dev->dev_addr); __mace_set_address(dev, dev->dev_addr);
/* clear the multicast filter */ /* clear the multicast filter */
out_8(&mb->iac, ADDRCHG | LOGADDR); if (mp->chipid == BROKEN_ADDRCHG_REV)
while ((in_8(&mb->iac) & ADDRCHG) != 0) out_8(&mb->iac, LOGADDR);
; else {
for (i = 0; i < 8; ++i) { out_8(&mb->iac, ADDRCHG | LOGADDR);
out_8(&mb->ladrf, 0); while ((in_8(&mb->iac) & ADDRCHG) != 0)
;
} }
for (i = 0; i < 8; ++i)
out_8(&mb->ladrf, 0);
/* done changing address */ /* done changing address */
out_8(&mb->iac, 0); if (mp->chipid != BROKEN_ADDRCHG_REV)
out_8(&mb->iac, 0);
if (mp->port_aaui) if (mp->port_aaui)
out_8(&mb->plscc, PORTSEL_AUI + ENPLSIO); out_8(&mb->plscc, PORTSEL_AUI + ENPLSIO);
...@@ -291,16 +326,23 @@ static void mace_reset(struct net_device *dev) ...@@ -291,16 +326,23 @@ static void mace_reset(struct net_device *dev)
static void __mace_set_address(struct net_device *dev, void *addr) static void __mace_set_address(struct net_device *dev, void *addr)
{ {
volatile struct mace *mb = ((struct mace_data *) dev->priv)->mace; struct mace_data *mp = (struct mace_data *) dev->priv;
volatile struct mace *mb = mp->mace;
unsigned char *p = addr; unsigned char *p = addr;
int i; int i;
/* load up the hardware address */ /* load up the hardware address */
out_8(&mb->iac, ADDRCHG | PHYADDR); if (mp->chipid == BROKEN_ADDRCHG_REV)
while ((in_8(&mb->iac) & ADDRCHG) != 0) out_8(&mb->iac, PHYADDR);
; else {
out_8(&mb->iac, ADDRCHG | PHYADDR);
while ((in_8(&mb->iac) & ADDRCHG) != 0)
;
}
for (i = 0; i < 6; ++i) for (i = 0; i < 6; ++i)
out_8(&mb->padr, dev->dev_addr[i] = p[i]); out_8(&mb->padr, dev->dev_addr[i] = p[i]);
if (mp->chipid != BROKEN_ADDRCHG_REV)
out_8(&mb->iac, 0);
} }
static int mace_set_address(struct net_device *dev, void *addr) static int mace_set_address(struct net_device *dev, void *addr)
...@@ -313,7 +355,6 @@ static int mace_set_address(struct net_device *dev, void *addr) ...@@ -313,7 +355,6 @@ static int mace_set_address(struct net_device *dev, void *addr)
__mace_set_address(dev, addr); __mace_set_address(dev, addr);
out_8(&mb->iac, 0);
/* note: setting ADDRCHG clears ENRCV */ /* note: setting ADDRCHG clears ENRCV */
out_8(&mb->maccc, mp->maccc); out_8(&mb->maccc, mp->maccc);
...@@ -543,12 +584,17 @@ static void mace_set_multicast(struct net_device *dev) ...@@ -543,12 +584,17 @@ static void mace_set_multicast(struct net_device *dev)
printk("\n"); printk("\n");
#endif #endif
out_8(&mb->iac, ADDRCHG | LOGADDR); if (mp->chipid == BROKEN_ADDRCHG_REV)
while ((in_8(&mb->iac) & ADDRCHG) != 0) out_8(&mb->iac, LOGADDR);
; else {
for (i = 0; i < 8; ++i) { out_8(&mb->iac, ADDRCHG | LOGADDR);
out_8(&mb->ladrf, multicast_filter[i]); while ((in_8(&mb->iac) & ADDRCHG) != 0)
;
} }
for (i = 0; i < 8; ++i)
out_8(&mb->ladrf, multicast_filter[i]);
if (mp->chipid != BROKEN_ADDRCHG_REV)
out_8(&mb->iac, 0);
} }
/* reset maccc */ /* reset maccc */
out_8(&mb->maccc, mp->maccc); out_8(&mb->maccc, mp->maccc);
...@@ -899,7 +945,10 @@ static void mace_rxdma_intr(int irq, void *dev_id, struct pt_regs *regs) ...@@ -899,7 +945,10 @@ static void mace_rxdma_intr(int irq, void *dev_id, struct pt_regs *regs)
MODULE_AUTHOR("Paul Mackerras"); MODULE_AUTHOR("Paul Mackerras");
MODULE_DESCRIPTION("PowerMac MACE driver."); MODULE_DESCRIPTION("PowerMac MACE driver.");
MODULE_PARM(port_aaui, "i");
MODULE_PARM_DESC(port_aaui, "MACE uses AAUI port (0-1)");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
EXPORT_NO_SYMBOLS;
static void __exit mace_cleanup (void) static void __exit mace_cleanup (void)
{ {
...@@ -907,19 +956,23 @@ static void __exit mace_cleanup (void) ...@@ -907,19 +956,23 @@ static void __exit mace_cleanup (void)
struct mace_data *mp; struct mace_data *mp;
while ((dev = mace_devs) != 0) { while ((dev = mace_devs) != 0) {
mp = (struct mace_data *) mace_devs->priv; mp = (struct mace_data *) mace_devs->priv;
mace_devs = mp->next_mace; mace_devs = mp->next_mace;
free_irq(dev->irq, dev); unregister_netdev(dev);
free_irq(mp->tx_dma_intr, dev); free_irq(dev->irq, dev);
free_irq(mp->rx_dma_intr, dev); free_irq(mp->tx_dma_intr, dev);
free_irq(mp->rx_dma_intr, dev);
unregister_netdev(dev); release_OF_resource(mp->of_node, 0);
kfree(dev); release_OF_resource(mp->of_node, 1);
release_OF_resource(mp->of_node, 2);
kfree(dev);
} }
if (dummy_buf != NULL) { if (dummy_buf != NULL) {
kfree(dummy_buf); kfree(dummy_buf);
dummy_buf = NULL; dummy_buf = NULL;
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment