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