diff options
Diffstat (limited to 'drivers/atm/eni.c')
| -rw-r--r-- | drivers/atm/eni.c | 132 | 
1 files changed, 77 insertions, 55 deletions
diff --git a/drivers/atm/eni.c b/drivers/atm/eni.c index 97c5898cd76..b1955ba40d6 100644 --- a/drivers/atm/eni.c +++ b/drivers/atm/eni.c @@ -19,9 +19,8 @@  #include <linux/atm_eni.h>  #include <linux/bitops.h>  #include <linux/slab.h> -#include <asm/system.h>  #include <asm/io.h> -#include <asm/atomic.h> +#include <linux/atomic.h>  #include <asm/uaccess.h>  #include <asm/string.h>  #include <asm/byteorder.h> @@ -156,9 +155,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) @@ -1134,11 +1130,14 @@ DPRINTK("doing direct send\n"); /* @@@ well, this doesn't work anyway */  				    skb_headlen(skb));  			else  				put_dma(tx->index,eni_dev->dma,&j,(unsigned long) -				    skb_shinfo(skb)->frags[i].page + skb_shinfo(skb)->frags[i].page_offset, -				    skb_shinfo(skb)->frags[i].size); +				    skb_frag_page(&skb_shinfo(skb)->frags[i]) + +					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, eni_dev->zero.dma, +			4 - (skb->len & 3));  	} -	if (skb->len & 3) -		put_dma(tx->index,eni_dev->dma,&j,zeroes,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) | @@ -1469,10 +1468,7 @@ if (eni_boards) printk(KERN_INFO "loss: %ld\n",ENI_DEV(eni_boards)->lost);  static void bug_int(struct atm_dev *dev,unsigned long reason)  { -	struct eni_dev *eni_dev; -  	DPRINTK(">bug_int\n"); -	eni_dev = ENI_DEV(dev);  	if (reason & MID_DMA_ERR_ACK)  		printk(KERN_CRIT DEV_LABEL "(itf %d): driver error - DMA "  		    "error\n",dev->number); @@ -1571,7 +1567,7 @@ tx_complete++;  /*--------------------------------- entries ---------------------------------*/ -static const char *media_name[] __devinitdata = { +static char * const media_name[] = {      "MMF", "SMF", "MMF", "03?", /*  0- 3 */      "UTP", "05?", "06?", "07?", /*  4- 7 */      "TAXI","09?", "10?", "11?", /*  8-11 */ @@ -1595,7 +1591,7 @@ static const char *media_name[] __devinitdata = {    } }) -static int __devinit get_esi_asic(struct atm_dev *dev) +static int get_esi_asic(struct atm_dev *dev)  {  	struct eni_dev *eni_dev;  	unsigned char tonga; @@ -1687,7 +1683,7 @@ static int __devinit get_esi_asic(struct atm_dev *dev)  #undef GET_SEPROM -static int __devinit get_esi_fpga(struct atm_dev *dev, void __iomem *base) +static int get_esi_fpga(struct atm_dev *dev, void __iomem *base)  {  	void __iomem *mac_base;  	int i; @@ -1698,7 +1694,7 @@ static int __devinit get_esi_fpga(struct atm_dev *dev, void __iomem *base)  } -static int __devinit eni_do_init(struct atm_dev *dev) +static int eni_do_init(struct atm_dev *dev)  {  	struct midway_eprom __iomem *eprom;  	struct eni_dev *eni_dev; @@ -1730,6 +1726,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) { @@ -1791,8 +1788,16 @@ unmap:  	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 eni_start(struct atm_dev *dev)  {  	struct eni_dev *eni_dev; @@ -1875,7 +1880,7 @@ free_list:  	kfree(eni_dev->free_list);  free_irq: -	free_irq(eni_dev->irq, eni_dev); +	free_irq(eni_dev->irq, dev);  out:  	return error; @@ -1900,7 +1905,6 @@ static void eni_close(struct atm_vcc *vcc)  static int eni_open(struct atm_vcc *vcc)  { -	struct eni_dev *eni_dev;  	struct eni_vcc *eni_vcc;  	int error;  	short vpi = vcc->vpi; @@ -1910,7 +1914,6 @@ static int eni_open(struct atm_vcc *vcc)  	EVENT("eni_open\n",0,0);  	if (!test_bit(ATM_VF_PARTIAL,&vcc->flags))  		vcc->dev_data = NULL; -	eni_dev = ENI_DEV(vcc->dev);  	if (vci != ATM_VPI_UNSPEC && vpi != ATM_VCI_UNSPEC)  		set_bit(ATM_VF_ADDR,&vcc->flags);  	if (vcc->qos.aal != ATM_AAL0 && vcc->qos.aal != ATM_AAL5) @@ -2090,7 +2093,6 @@ static unsigned char eni_phy_get(struct atm_dev *dev,unsigned long addr)  static int eni_proc_read(struct atm_dev *dev,loff_t *pos,char *page)  { -	struct hlist_node *node;  	struct sock *s;  	static const char *signal[] = { "LOST","unknown","okay" };  	struct eni_dev *eni_dev = ENI_DEV(dev); @@ -2168,7 +2170,7 @@ static int eni_proc_read(struct atm_dev *dev,loff_t *pos,char *page)  	for(i = 0; i < VCC_HTABLE_SIZE; ++i) {  		struct hlist_head *head = &vcc_hash[i]; -		sk_for_each(s, node, head) { +		sk_for_each(s, head) {  			struct eni_vcc *eni_vcc;  			int length; @@ -2223,49 +2225,61 @@ static const struct atmdev_ops ops = {  }; -static int __devinit eni_init_one(struct pci_dev *pci_dev, -    const struct pci_device_id *ent) +static int eni_init_one(struct pci_dev *pci_dev, +			const struct pci_device_id *ent)  {  	struct atm_dev *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)) { -		error = -EIO; -		goto out0; -	} +	rc = -ENOMEM; +	eni_dev = kmalloc(sizeof(struct eni_dev), GFP_KERNEL); +	if (!eni_dev) +		goto err_disable; -	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,&ops,-1,NULL); -	if (!dev) goto out2; +	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 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;  } @@ -2277,9 +2291,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 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);  } @@ -2287,7 +2309,7 @@ static struct pci_driver eni_driver = {  	.name		= DEV_LABEL,  	.id_table	= eni_pci_tbl,  	.probe		= eni_init_one, -	.remove		= __devexit_p(eni_remove_one), +	.remove		= eni_remove_one,  };  | 
