mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-24 04:34:08 +08:00
eni: fix driver remove function and driver probe error path.
- add eni_do_release() to balance eni_do_init - turn the zeroes DMA area into a per device data Signed-off-by: Francois Romieu <romieu@fr.zoreil.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
4823cd388d
commit
126a3fd251
@ -156,9 +156,6 @@ static int tx_complete = 0,dma_complete = 0,queued = 0,requeued = 0,
|
|||||||
|
|
||||||
static struct atm_dev *eni_boards = NULL;
|
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 */
|
/* Read/write registers on card */
|
||||||
#define eni_in(r) readl(eni_dev->reg+(r)*4)
|
#define eni_in(r) readl(eni_dev->reg+(r)*4)
|
||||||
#define eni_out(v,r) writel((v),eni_dev->reg+(r)*4)
|
#define eni_out(v,r) writel((v),eni_dev->reg+(r)*4)
|
||||||
@ -1138,8 +1135,10 @@ DPRINTK("doing direct send\n"); /* @@@ well, this doesn't work anyway */
|
|||||||
skb_shinfo(skb)->frags[i].page_offset,
|
skb_shinfo(skb)->frags[i].page_offset,
|
||||||
skb_frag_size(&skb_shinfo(skb)->frags[i]));
|
skb_frag_size(&skb_shinfo(skb)->frags[i]));
|
||||||
}
|
}
|
||||||
if (skb->len & 3)
|
if (skb->len & 3) {
|
||||||
put_dma(tx->index,eni_dev->dma,&j,zeroes,4-(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 ... */
|
/* JK for AAL5 trailer - AAL0 doesn't need it, but who cares ... */
|
||||||
eni_dev->dma[j++] = (((tx->tx_pos+size) & (tx->words-1)) <<
|
eni_dev->dma[j++] = (((tx->tx_pos+size) & (tx->words-1)) <<
|
||||||
MID_DMA_COUNT_SHIFT) | (tx->index << MID_DMA_CHAN_SHIFT) |
|
MID_DMA_COUNT_SHIFT) | (tx->index << MID_DMA_CHAN_SHIFT) |
|
||||||
@ -1728,6 +1727,7 @@ static int __devinit eni_do_init(struct atm_dev *dev)
|
|||||||
"mapping\n",dev->number);
|
"mapping\n",dev->number);
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
eni_dev->ioaddr = base;
|
||||||
eni_dev->base_diff = real_base - (unsigned long) base;
|
eni_dev->base_diff = real_base - (unsigned long) base;
|
||||||
/* id may not be present in ASIC Tonga boards - check this @@@ */
|
/* id may not be present in ASIC Tonga boards - check this @@@ */
|
||||||
if (!eni_dev->asic) {
|
if (!eni_dev->asic) {
|
||||||
@ -1789,6 +1789,14 @@ unmap:
|
|||||||
goto out;
|
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_start(struct atm_dev *dev)
|
||||||
{
|
{
|
||||||
@ -2224,44 +2232,56 @@ static int __devinit eni_init_one(struct pci_dev *pci_dev,
|
|||||||
{
|
{
|
||||||
struct atm_dev *dev;
|
struct atm_dev *dev;
|
||||||
struct eni_dev *eni_dev;
|
struct eni_dev *eni_dev;
|
||||||
int error = -ENOMEM;
|
struct eni_zero *zero;
|
||||||
|
int rc;
|
||||||
|
|
||||||
DPRINTK("eni_init_one\n");
|
rc = pci_enable_device(pci_dev);
|
||||||
|
if (rc < 0)
|
||||||
|
goto out;
|
||||||
|
|
||||||
if (pci_enable_device(pci_dev)) {
|
rc = -ENOMEM;
|
||||||
error = -EIO;
|
eni_dev = kmalloc(sizeof(struct eni_dev), GFP_KERNEL);
|
||||||
goto out0;
|
if (!eni_dev)
|
||||||
}
|
goto err_disable;
|
||||||
|
|
||||||
|
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);
|
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);
|
pci_set_drvdata(pci_dev, dev);
|
||||||
eni_dev->pci_dev = pci_dev;
|
eni_dev->pci_dev = pci_dev;
|
||||||
dev->dev_data = eni_dev;
|
|
||||||
eni_dev->asic = ent->driver_data;
|
eni_dev->asic = ent->driver_data;
|
||||||
error = eni_do_init(dev);
|
|
||||||
if (error) goto out3;
|
rc = eni_do_init(dev);
|
||||||
error = eni_start(dev);
|
if (rc < 0)
|
||||||
if (error) goto out3;
|
goto err_unregister;
|
||||||
|
|
||||||
|
rc = eni_start(dev);
|
||||||
|
if (rc < 0)
|
||||||
|
goto err_eni_release;
|
||||||
|
|
||||||
eni_dev->more = eni_boards;
|
eni_dev->more = eni_boards;
|
||||||
eni_boards = dev;
|
eni_boards = dev;
|
||||||
return 0;
|
out:
|
||||||
out3:
|
return rc;
|
||||||
|
|
||||||
|
err_eni_release:
|
||||||
|
eni_do_release(dev);
|
||||||
|
err_unregister:
|
||||||
atm_dev_deregister(dev);
|
atm_dev_deregister(dev);
|
||||||
out2:
|
err_free_consistent:
|
||||||
pci_free_consistent(eni_dev->pci_dev,ENI_ZEROES_SIZE,cpu_zeroes,zeroes);
|
pci_free_consistent(pci_dev, ENI_ZEROES_SIZE, zero->addr, zero->dma);
|
||||||
cpu_zeroes = NULL;
|
err_kfree:
|
||||||
out1:
|
|
||||||
kfree(eni_dev);
|
kfree(eni_dev);
|
||||||
out0:
|
err_disable:
|
||||||
return error;
|
pci_disable_device(pci_dev);
|
||||||
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -2273,9 +2293,17 @@ static struct pci_device_id eni_pci_tbl[] = {
|
|||||||
MODULE_DEVICE_TABLE(pci,eni_pci_tbl);
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -72,6 +72,7 @@ struct eni_dev {
|
|||||||
u32 events; /* pending events */
|
u32 events; /* pending events */
|
||||||
/*-------------------------------- base pointers into Midway address
|
/*-------------------------------- base pointers into Midway address
|
||||||
space */
|
space */
|
||||||
|
void __iomem *ioaddr;
|
||||||
void __iomem *phy; /* PHY interface chip registers */
|
void __iomem *phy; /* PHY interface chip registers */
|
||||||
void __iomem *reg; /* register base */
|
void __iomem *reg; /* register base */
|
||||||
void __iomem *ram; /* RAM base */
|
void __iomem *ram; /* RAM base */
|
||||||
@ -86,6 +87,10 @@ struct eni_dev {
|
|||||||
wait_queue_head_t tx_wait; /* for close */
|
wait_queue_head_t tx_wait; /* for close */
|
||||||
int tx_bw; /* remaining bandwidth */
|
int tx_bw; /* remaining bandwidth */
|
||||||
u32 dma[TX_DMA_BUF*2]; /* DMA request scratch area */
|
u32 dma[TX_DMA_BUF*2]; /* DMA request scratch area */
|
||||||
|
struct eni_zero { /* aligned "magic" zeroes */
|
||||||
|
u32 *addr;
|
||||||
|
dma_addr_t dma;
|
||||||
|
} zero;
|
||||||
int tx_mult; /* buffer size multiplier (percent) */
|
int tx_mult; /* buffer size multiplier (percent) */
|
||||||
/*-------------------------------- RX part */
|
/*-------------------------------- RX part */
|
||||||
u32 serv_read; /* host service read index */
|
u32 serv_read; /* host service read index */
|
||||||
|
Loading…
Reference in New Issue
Block a user