static struct atm_dev *eni_boards = NULL;
-static u32 *cpu_zeroes = NULL; /* aligned "magic" zeroes */
-static dma_addr_t zeroes;
-
/* Read/write registers on card */
#define eni_in(r) readl(eni_dev->reg+(r)*4)
#define eni_out(v,r) writel((v),eni_dev->reg+(r)*4)
skb_shinfo(skb)->frags[i].page_offset,
skb_frag_size(&skb_shinfo(skb)->frags[i]));
}
- if (skb->len & 3)
- put_dma(tx->index,eni_dev->dma,&j,zeroes,4-(skb->len & 3));
+ if (skb->len & 3) {
+ put_dma(tx->index, eni_dev->dma, &j, eni_dev->zero.dma,
+ 4 - (skb->len & 3));
+ }
/* JK for AAL5 trailer - AAL0 doesn't need it, but who cares ... */
eni_dev->dma[j++] = (((tx->tx_pos+size) & (tx->words-1)) <<
MID_DMA_COUNT_SHIFT) | (tx->index << MID_DMA_CHAN_SHIFT) |
"mapping\n",dev->number);
return error;
}
+ eni_dev->ioaddr = base;
eni_dev->base_diff = real_base - (unsigned long) base;
/* id may not be present in ASIC Tonga boards - check this @@@ */
if (!eni_dev->asic) {
goto out;
}
+static void eni_do_release(struct atm_dev *dev)
+{
+ struct eni_dev *ed = ENI_DEV(dev);
+
+ dev->phy->stop(dev);
+ dev->phy = NULL;
+ iounmap(ed->ioaddr);
+}
static int __devinit eni_start(struct atm_dev *dev)
{
static int __devinit eni_init_one(struct pci_dev *pci_dev,
- const struct pci_device_id *ent)
+ const struct pci_device_id *ent)
{
struct atm_dev *dev;
struct eni_dev *eni_dev;
- int error = -ENOMEM;
+ struct eni_zero *zero;
+ int rc;
+
+ rc = pci_enable_device(pci_dev);
+ if (rc < 0)
+ goto out;
- DPRINTK("eni_init_one\n");
+ rc = -ENOMEM;
+ eni_dev = kmalloc(sizeof(struct eni_dev), GFP_KERNEL);
+ if (!eni_dev)
+ goto err_disable;
- if (pci_enable_device(pci_dev)) {
- error = -EIO;
- goto out0;
- }
+ zero = &eni_dev->zero;
+ zero->addr = pci_alloc_consistent(pci_dev, ENI_ZEROES_SIZE, &zero->dma);
+ if (!zero->addr)
+ goto err_kfree;
- eni_dev = kmalloc(sizeof(struct eni_dev),GFP_KERNEL);
- if (!eni_dev) goto out0;
- if (!cpu_zeroes) {
- cpu_zeroes = pci_alloc_consistent(pci_dev,ENI_ZEROES_SIZE,
- &zeroes);
- if (!cpu_zeroes) goto out1;
- }
dev = atm_dev_register(DEV_LABEL, &pci_dev->dev, &ops, -1, NULL);
- if (!dev) goto out2;
+ if (!dev)
+ goto err_free_consistent;
+
+ dev->dev_data = eni_dev;
pci_set_drvdata(pci_dev, dev);
eni_dev->pci_dev = pci_dev;
- dev->dev_data = eni_dev;
eni_dev->asic = ent->driver_data;
- error = eni_do_init(dev);
- if (error) goto out3;
- error = eni_start(dev);
- if (error) goto out3;
+
+ rc = eni_do_init(dev);
+ if (rc < 0)
+ goto err_unregister;
+
+ rc = eni_start(dev);
+ if (rc < 0)
+ goto err_eni_release;
+
eni_dev->more = eni_boards;
eni_boards = dev;
- return 0;
-out3:
+out:
+ return rc;
+
+err_eni_release:
+ eni_do_release(dev);
+err_unregister:
atm_dev_deregister(dev);
-out2:
- pci_free_consistent(eni_dev->pci_dev,ENI_ZEROES_SIZE,cpu_zeroes,zeroes);
- cpu_zeroes = NULL;
-out1:
+err_free_consistent:
+ pci_free_consistent(pci_dev, ENI_ZEROES_SIZE, zero->addr, zero->dma);
+err_kfree:
kfree(eni_dev);
-out0:
- return error;
+err_disable:
+ pci_disable_device(pci_dev);
+ goto out;
}
MODULE_DEVICE_TABLE(pci,eni_pci_tbl);
-static void __devexit eni_remove_one(struct pci_dev *pci_dev)
+static void __devexit eni_remove_one(struct pci_dev *pdev)
{
- /* grrr */
+ struct atm_dev *dev = pci_get_drvdata(pdev);
+ struct eni_dev *ed = ENI_DEV(dev);
+ struct eni_zero *zero = &ed->zero;
+
+ eni_do_release(dev);
+ atm_dev_deregister(dev);
+ pci_free_consistent(pdev, ENI_ZEROES_SIZE, zero->addr, zero->dma);
+ kfree(ed);
+ pci_disable_device(pdev);
}