Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 126a3fd2 authored by françois romieu's avatar françois romieu Committed by David S. Miller
Browse files

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: default avatarFrancois Romieu <romieu@fr.zoreil.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 4823cd38
Loading
Loading
Loading
Loading
+63 −35
Original line number Diff line number Diff line
@@ -156,9 +156,6 @@ static int tx_complete = 0,dma_complete = 0,queued = 0,requeued = 0,

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)
@@ -1138,8 +1135,10 @@ DPRINTK("doing direct send\n"); /* @@@ well, this doesn't work anyway */
					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) |
@@ -1728,6 +1727,7 @@ static int __devinit eni_do_init(struct atm_dev *dev)
		    "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) {
@@ -1789,6 +1789,14 @@ static int __devinit eni_do_init(struct atm_dev *dev)
	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)
{
@@ -2224,44 +2232,56 @@ static int __devinit eni_init_one(struct pci_dev *pci_dev,
{
	struct atm_dev *dev;
	struct eni_dev *eni_dev;
	int error = -ENOMEM;

	DPRINTK("eni_init_one\n");
	struct eni_zero *zero;
	int rc;

	if (pci_enable_device(pci_dev)) {
		error = -EIO;
		goto out0;
	}
	rc = pci_enable_device(pci_dev);
	if (rc < 0)
		goto out;

	rc = -ENOMEM;
	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;
	}
	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;

	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;
}


@@ -2273,9 +2293,17 @@ static struct pci_device_id 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);
}


+5 −0
Original line number Diff line number Diff line
@@ -72,6 +72,7 @@ struct eni_dev {
	u32 events;			/* pending events */
	/*-------------------------------- base pointers into Midway address
					   space */
	void __iomem *ioaddr;
	void __iomem *phy;		/* PHY interface chip registers */
	void __iomem *reg;		/* register base */
	void __iomem *ram;		/* RAM base */
@@ -86,6 +87,10 @@ struct eni_dev {
	wait_queue_head_t tx_wait;	/* for close */
	int tx_bw;			/* remaining bandwidth */
	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) */
	/*-------------------------------- RX part */
	u32 serv_read;			/* host service read index */