Commit 03f4fafe authored by Chas Williams's avatar Chas Williams Committed by David S. Miller

[ATM]: [horizon] eliminate pci_find_device()

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 92b890d8
...@@ -354,8 +354,7 @@ static inline void __init show_version (void) { ...@@ -354,8 +354,7 @@ static inline void __init show_version (void) {
/********** globals **********/ /********** globals **********/
static hrz_dev * hrz_devs = NULL; static void do_housekeeping (unsigned long arg);
static struct timer_list housekeeping;
static unsigned short debug = 0; static unsigned short debug = 0;
static unsigned short vpi_bits = 0; static unsigned short vpi_bits = 0;
...@@ -1386,7 +1385,7 @@ static inline void rx_data_av_handler (hrz_dev * dev) { ...@@ -1386,7 +1385,7 @@ static inline void rx_data_av_handler (hrz_dev * dev) {
static irqreturn_t interrupt_handler(int irq, void *dev_id, static irqreturn_t interrupt_handler(int irq, void *dev_id,
struct pt_regs *pt_regs) { struct pt_regs *pt_regs) {
hrz_dev * dev = hrz_devs; hrz_dev * dev = (hrz_dev *) dev_id;
u32 int_source; u32 int_source;
unsigned int irq_ok; unsigned int irq_ok;
(void) pt_regs; (void) pt_regs;
...@@ -1397,16 +1396,6 @@ static irqreturn_t interrupt_handler(int irq, void *dev_id, ...@@ -1397,16 +1396,6 @@ static irqreturn_t interrupt_handler(int irq, void *dev_id,
PRINTD (DBG_IRQ|DBG_ERR, "irq with NULL dev_id: %d", irq); PRINTD (DBG_IRQ|DBG_ERR, "irq with NULL dev_id: %d", irq);
return IRQ_NONE; return IRQ_NONE;
} }
// Did one of our cards generate the interrupt?
while (dev) {
if (dev == dev_id)
break;
dev = dev->prev;
}
if (!dev) {
PRINTD (DBG_IRQ, "irq not for me: %d", irq);
return IRQ_NONE;
}
if (irq != dev->irq) { if (irq != dev->irq) {
PRINTD (DBG_IRQ|DBG_ERR, "irq mismatch: %d", irq); PRINTD (DBG_IRQ|DBG_ERR, "irq mismatch: %d", irq);
return IRQ_NONE; return IRQ_NONE;
...@@ -1462,28 +1451,18 @@ static irqreturn_t interrupt_handler(int irq, void *dev_id, ...@@ -1462,28 +1451,18 @@ static irqreturn_t interrupt_handler(int irq, void *dev_id,
/********** housekeeping **********/ /********** housekeeping **********/
static void set_timer (struct timer_list * timer, unsigned int delay) {
timer->expires = jiffies + delay;
add_timer (timer);
return;
}
static void do_housekeeping (unsigned long arg) { static void do_housekeeping (unsigned long arg) {
// just stats at the moment // just stats at the moment
hrz_dev * dev = hrz_devs; hrz_dev * dev = (hrz_dev *) arg;
(void) arg;
// data is set to zero at module unload
if (housekeeping.data) {
while (dev) {
// collect device-specific (not driver/atm-linux) stats here // collect device-specific (not driver/atm-linux) stats here
dev->tx_cell_count += rd_regw (dev, TX_CELL_COUNT_OFF); dev->tx_cell_count += rd_regw (dev, TX_CELL_COUNT_OFF);
dev->rx_cell_count += rd_regw (dev, RX_CELL_COUNT_OFF); dev->rx_cell_count += rd_regw (dev, RX_CELL_COUNT_OFF);
dev->hec_error_count += rd_regw (dev, HEC_ERROR_COUNT_OFF); dev->hec_error_count += rd_regw (dev, HEC_ERROR_COUNT_OFF);
dev->unassigned_cell_count += rd_regw (dev, UNASSIGNED_CELL_COUNT_OFF); dev->unassigned_cell_count += rd_regw (dev, UNASSIGNED_CELL_COUNT_OFF);
dev = dev->prev;
} mod_timer (&dev->housekeeping, jiffies + HZ/10);
set_timer (&housekeeping, HZ/10);
}
return; return;
} }
...@@ -2719,77 +2698,79 @@ static const struct atmdev_ops hrz_ops = { ...@@ -2719,77 +2698,79 @@ static const struct atmdev_ops hrz_ops = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
}; };
static int __init hrz_probe (void) { static int __devinit hrz_probe(struct pci_dev *pci_dev, const struct pci_device_id *pci_ent)
struct pci_dev * pci_dev; {
int devs;
PRINTD (DBG_FLOW, "hrz_probe");
devs = 0;
pci_dev = NULL;
while ((pci_dev = pci_find_device
(PCI_VENDOR_ID_MADGE, PCI_DEVICE_ID_MADGE_HORIZON, pci_dev)
)) {
hrz_dev * dev; hrz_dev * dev;
int err = 0;
// adapter slot free, read resources from PCI configuration space // adapter slot free, read resources from PCI configuration space
u32 iobase = pci_resource_start (pci_dev, 0); u32 iobase = pci_resource_start (pci_dev, 0);
u32 * membase = bus_to_virt (pci_resource_start (pci_dev, 1)); u32 * membase = bus_to_virt (pci_resource_start (pci_dev, 1));
u8 irq = pci_dev->irq; u8 irq = pci_dev->irq;
unsigned char lat;
PRINTD (DBG_FLOW, "hrz_probe");
/* XXX DEV_LABEL is a guess */ /* XXX DEV_LABEL is a guess */
if (!request_region (iobase, HRZ_IO_EXTENT, DEV_LABEL)) if (!request_region(iobase, HRZ_IO_EXTENT, DEV_LABEL))
continue; return -EINVAL;
if (pci_enable_device (pci_dev)) if (pci_enable_device(pci_dev)) {
continue; err = -EINVAL;
goto out_release;
}
dev = kmalloc (sizeof(hrz_dev), GFP_KERNEL); dev = kmalloc(sizeof(hrz_dev), GFP_KERNEL);
if (!dev) { if (!dev) {
// perhaps we should be nice: deregister all adapters and abort? // perhaps we should be nice: deregister all adapters and abort?
PRINTD (DBG_ERR, "out of memory"); PRINTD(DBG_ERR, "out of memory");
continue; err = -ENOMEM;
goto out_disable;
} }
memset (dev, 0, sizeof(hrz_dev)); memset(dev, 0, sizeof(hrz_dev));
pci_set_drvdata(pci_dev, dev);
// grab IRQ and install handler - move this someplace more sensible // grab IRQ and install handler - move this someplace more sensible
if (request_irq (irq, if (request_irq(irq,
interrupt_handler, interrupt_handler,
SA_SHIRQ, /* irqflags guess */ SA_SHIRQ, /* irqflags guess */
DEV_LABEL, /* name guess */ DEV_LABEL, /* name guess */
dev)) { dev)) {
PRINTD (DBG_WARN, "request IRQ failed!"); PRINTD(DBG_WARN, "request IRQ failed!");
// free_irq is at "endif" err = -EINVAL;
} else { goto out_free;
}
PRINTD (DBG_INFO, "found Madge ATM adapter (hrz) at: IO %x, IRQ %u, MEM %p", PRINTD(DBG_INFO, "found Madge ATM adapter (hrz) at: IO %x, IRQ %u, MEM %p",
iobase, irq, membase); iobase, irq, membase);
dev->atm_dev = atm_dev_register (DEV_LABEL, &hrz_ops, -1, NULL); dev->atm_dev = atm_dev_register(DEV_LABEL, &hrz_ops, -1, NULL);
if (!(dev->atm_dev)) { if (!(dev->atm_dev)) {
PRINTD (DBG_ERR, "failed to register Madge ATM adapter"); PRINTD(DBG_ERR, "failed to register Madge ATM adapter");
} else { err = -EINVAL;
unsigned char lat; goto out_free_irq;
}
PRINTD (DBG_INFO, "registered Madge ATM adapter (no. %d) (%p) at %p", PRINTD(DBG_INFO, "registered Madge ATM adapter (no. %d) (%p) at %p",
dev->atm_dev->number, dev, dev->atm_dev); dev->atm_dev->number, dev, dev->atm_dev);
dev->atm_dev->dev_data = (void *) dev; dev->atm_dev->dev_data = (void *) dev;
dev->pci_dev = pci_dev; dev->pci_dev = pci_dev;
// enable bus master accesses // enable bus master accesses
pci_set_master (pci_dev); pci_set_master(pci_dev);
// frobnicate latency (upwards, usually) // frobnicate latency (upwards, usually)
pci_read_config_byte (pci_dev, PCI_LATENCY_TIMER, &lat); pci_read_config_byte(pci_dev, PCI_LATENCY_TIMER, &lat);
if (pci_lat) { if (pci_lat) {
PRINTD (DBG_INFO, "%s PCI latency timer from %hu to %hu", PRINTD(DBG_INFO, "%s PCI latency timer from %hu to %hu",
"changing", lat, pci_lat); "changing", lat, pci_lat);
pci_write_config_byte (pci_dev, PCI_LATENCY_TIMER, pci_lat); pci_write_config_byte(pci_dev, PCI_LATENCY_TIMER, pci_lat);
} else if (lat < MIN_PCI_LATENCY) { } else if (lat < MIN_PCI_LATENCY) {
PRINTK (KERN_INFO, "%s PCI latency timer from %hu to %hu", PRINTK(KERN_INFO, "%s PCI latency timer from %hu to %hu",
"increasing", lat, MIN_PCI_LATENCY); "increasing", lat, MIN_PCI_LATENCY);
pci_write_config_byte (pci_dev, PCI_LATENCY_TIMER, MIN_PCI_LATENCY); pci_write_config_byte(pci_dev, PCI_LATENCY_TIMER, MIN_PCI_LATENCY);
} }
dev->iobase = iobase; dev->iobase = iobase;
...@@ -2829,47 +2810,64 @@ static int __init hrz_probe (void) { ...@@ -2829,47 +2810,64 @@ static int __init hrz_probe (void) {
// Copper: (WRONG) we want 6 into the above, close to 25Mb/s // Copper: (WRONG) we want 6 into the above, close to 25Mb/s
// Copper: (plagarise!) 25600000/8/270*260/53 - n/53 // Copper: (plagarise!) 25600000/8/270*260/53 - n/53
if (hrz_init (dev)) { if (hrz_init(dev)) {
// to be really pedantic, this should be ATM_OC3c_PCR // to be really pedantic, this should be ATM_OC3c_PCR
dev->tx_avail = ATM_OC3_PCR; dev->tx_avail = ATM_OC3_PCR;
dev->rx_avail = ATM_OC3_PCR; dev->rx_avail = ATM_OC3_PCR;
set_bit (ultra, &dev->flags); // NOT "|= ultra" ! set_bit(ultra, &dev->flags); // NOT "|= ultra" !
} else { } else {
dev->tx_avail = ((25600000/8)*26)/(27*53); dev->tx_avail = ((25600000/8)*26)/(27*53);
dev->rx_avail = ((25600000/8)*26)/(27*53); dev->rx_avail = ((25600000/8)*26)/(27*53);
PRINTD (DBG_WARN, "Buggy ASIC: no TX bus-mastering."); PRINTD(DBG_WARN, "Buggy ASIC: no TX bus-mastering.");
} }
// rate changes spinlock // rate changes spinlock
spin_lock_init (&dev->rate_lock); spin_lock_init(&dev->rate_lock);
// on-board memory access spinlock; we want atomic reads and // on-board memory access spinlock; we want atomic reads and
// writes to adapter memory (handles IRQ and SMP) // writes to adapter memory (handles IRQ and SMP)
spin_lock_init (&dev->mem_lock); spin_lock_init(&dev->mem_lock);
init_waitqueue_head (&dev->tx_queue); init_waitqueue_head(&dev->tx_queue);
// vpi in 0..4, vci in 6..10 // vpi in 0..4, vci in 6..10
dev->atm_dev->ci_range.vpi_bits = vpi_bits; dev->atm_dev->ci_range.vpi_bits = vpi_bits;
dev->atm_dev->ci_range.vci_bits = 10-vpi_bits; dev->atm_dev->ci_range.vci_bits = 10-vpi_bits;
// update count and linked list init_timer(&dev->housekeeping);
++devs; dev->housekeeping.function = do_housekeeping;
dev->prev = hrz_devs; dev->housekeeping.data = (unsigned long) dev;
hrz_devs = dev; mod_timer(&dev->housekeeping, jiffies);
// success
continue; out:
return err;
out_free_irq:
free_irq(dev->irq, dev);
out_free:
kfree(dev);
out_disable:
pci_disable_device(pci_dev);
out_release:
release_region(iobase, HRZ_IO_EXTENT);
goto out;
}
/* not currently reached */ static void __devexit hrz_remove_one(struct pci_dev *pci_dev)
atm_dev_deregister (dev->atm_dev); {
} /* atm_dev_register */ hrz_dev *dev;
free_irq (irq, dev);
} /* request_irq */ dev = pci_get_drvdata(pci_dev);
kfree (dev);
release_region(iobase, HRZ_IO_EXTENT); PRINTD(DBG_INFO, "closing %p (atm_dev = %p)", dev, dev->atm_dev);
} /* kmalloc and while */ del_timer_sync(&dev->housekeeping);
return devs; hrz_reset(dev);
atm_dev_deregister(dev->atm_dev);
free_irq(dev->irq, dev);
release_region(dev->iobase, HRZ_IO_EXTENT);
kfree(dev);
pci_disable_device(pci_dev);
} }
static void __init hrz_check_args (void) { static void __init hrz_check_args (void) {
...@@ -2909,11 +2907,22 @@ MODULE_PARM_DESC(max_tx_size, "maximum size of TX AAL5 frames"); ...@@ -2909,11 +2907,22 @@ MODULE_PARM_DESC(max_tx_size, "maximum size of TX AAL5 frames");
MODULE_PARM_DESC(max_rx_size, "maximum size of RX AAL5 frames"); MODULE_PARM_DESC(max_rx_size, "maximum size of RX AAL5 frames");
MODULE_PARM_DESC(pci_lat, "PCI latency in bus cycles"); MODULE_PARM_DESC(pci_lat, "PCI latency in bus cycles");
static struct pci_device_id hrz_pci_tbl[] = {
{ PCI_VENDOR_ID_MADGE, PCI_DEVICE_ID_MADGE_HORIZON, PCI_ANY_ID, PCI_ANY_ID,
0, 0, 0 },
{ 0, }
};
static struct pci_driver hrz_driver = {
.name = "horizon",
.probe = hrz_probe,
.remove = __devexit_p(hrz_remove_one),
.id_table = hrz_pci_tbl,
};
/********** module entry **********/ /********** module entry **********/
static int __init hrz_module_init (void) { static int __init hrz_module_init (void) {
int devs;
// sanity check - cast is needed since printk does not support %Zu // sanity check - cast is needed since printk does not support %Zu
if (sizeof(struct MEMMAP) != 128*1024/4) { if (sizeof(struct MEMMAP) != 128*1024/4) {
PRINTK (KERN_ERR, "Fix struct MEMMAP (is %lu fakewords).", PRINTK (KERN_ERR, "Fix struct MEMMAP (is %lu fakewords).",
...@@ -2927,44 +2936,15 @@ static int __init hrz_module_init (void) { ...@@ -2927,44 +2936,15 @@ static int __init hrz_module_init (void) {
hrz_check_args(); hrz_check_args();
// get the juice // get the juice
devs = hrz_probe(); return pci_module_init(&hrz_driver);
if (devs) {
init_timer (&housekeeping);
housekeeping.function = do_housekeeping;
// paranoia
housekeeping.data = 1;
set_timer (&housekeeping, 0);
} else {
PRINTK (KERN_ERR, "no (usable) adapters found");
}
return devs ? 0 : -ENODEV;
} }
/********** module exit **********/ /********** module exit **********/
static void __exit hrz_module_exit (void) { static void __exit hrz_module_exit (void) {
hrz_dev * dev;
PRINTD (DBG_FLOW, "cleanup_module"); PRINTD (DBG_FLOW, "cleanup_module");
// paranoia return pci_unregister_driver(&hrz_driver);
housekeeping.data = 0;
del_timer (&housekeeping);
while (hrz_devs) {
dev = hrz_devs;
hrz_devs = dev->prev;
PRINTD (DBG_INFO, "closing %p (atm_dev = %p)", dev, dev->atm_dev);
hrz_reset (dev);
atm_dev_deregister (dev->atm_dev);
free_irq (dev->irq, dev);
release_region (dev->iobase, HRZ_IO_EXTENT);
kfree (dev);
}
return;
} }
module_init(hrz_module_init); module_init(hrz_module_init);
......
...@@ -457,7 +457,7 @@ struct hrz_dev { ...@@ -457,7 +457,7 @@ struct hrz_dev {
unsigned long unassigned_cell_count; unsigned long unassigned_cell_count;
struct pci_dev * pci_dev; struct pci_dev * pci_dev;
struct hrz_dev * prev; struct timer_list housekeeping;
}; };
typedef struct hrz_dev hrz_dev; typedef struct hrz_dev hrz_dev;
......
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