diff options
Diffstat (limited to 'drivers/net/wan/farsync.c')
| -rw-r--r-- | drivers/net/wan/farsync.c | 144 | 
1 files changed, 70 insertions, 74 deletions
diff --git a/drivers/net/wan/farsync.c b/drivers/net/wan/farsync.c index 3f0c4f26875..1f041271f7f 100644 --- a/drivers/net/wan/farsync.c +++ b/drivers/net/wan/farsync.c @@ -26,6 +26,7 @@  #include <linux/ioport.h>  #include <linux/init.h>  #include <linux/interrupt.h> +#include <linux/delay.h>  #include <linux/if.h>  #include <linux/hdlc.h>  #include <asm/io.h> @@ -678,7 +679,6 @@ static inline void  fst_cpureset(struct fst_card_info *card)  {  	unsigned char interrupt_line_register; -	unsigned long j = jiffies + 1;  	unsigned int regval;  	if (card->family == FST_FAMILY_TXU) { @@ -696,16 +696,12 @@ fst_cpureset(struct fst_card_info *card)  		/*  		 * We are delaying here to allow the 9054 to reset itself  		 */ -		j = jiffies + 1; -		while (jiffies < j) -			/* Do nothing */ ; +		usleep_range(10, 20);  		outw(0x240f, card->pci_conf + CNTRL_9054 + 2);  		/*  		 * We are delaying here to allow the 9054 to reload its eeprom  		 */ -		j = jiffies + 1; -		while (jiffies < j) -			/* Do nothing */ ; +		usleep_range(10, 20);  		outw(0x040f, card->pci_conf + CNTRL_9054 + 2);  		if (pci_write_config_byte @@ -886,20 +882,18 @@ fst_rx_dma_complete(struct fst_card_info *card, struct fst_port_info *port,   *      Receive a frame through the DMA   */  static inline void -fst_rx_dma(struct fst_card_info *card, dma_addr_t skb, -	   dma_addr_t mem, int len) +fst_rx_dma(struct fst_card_info *card, dma_addr_t dma, u32 mem, int len)  {  	/*  	 * This routine will setup the DMA and start it  	 */ -	dbg(DBG_RX, "In fst_rx_dma %lx %lx %d\n", -	    (unsigned long) skb, (unsigned long) mem, len); +	dbg(DBG_RX, "In fst_rx_dma %x %x %d\n", (u32)dma, mem, len);  	if (card->dmarx_in_progress) {  		dbg(DBG_ASS, "In fst_rx_dma while dma in progress\n");  	} -	outl(skb, card->pci_conf + DMAPADR0);	/* Copy to here */ +	outl(dma, card->pci_conf + DMAPADR0);	/* Copy to here */  	outl(mem, card->pci_conf + DMALADR0);	/* from here */  	outl(len, card->pci_conf + DMASIZ0);	/* for this length */  	outl(0x00000000c, card->pci_conf + DMADPR0);	/* In this direction */ @@ -915,20 +909,19 @@ fst_rx_dma(struct fst_card_info *card, dma_addr_t skb,   *      Send a frame through the DMA   */  static inline void -fst_tx_dma(struct fst_card_info *card, unsigned char *skb, -	   unsigned char *mem, int len) +fst_tx_dma(struct fst_card_info *card, dma_addr_t dma, u32 mem, int len)  {  	/*  	 * This routine will setup the DMA and start it.  	 */ -	dbg(DBG_TX, "In fst_tx_dma %p %p %d\n", skb, mem, len); +	dbg(DBG_TX, "In fst_tx_dma %x %x %d\n", (u32)dma, mem, len);  	if (card->dmatx_in_progress) {  		dbg(DBG_ASS, "In fst_tx_dma while dma in progress\n");  	} -	outl((unsigned long) skb, card->pci_conf + DMAPADR1);	/* Copy from here */ -	outl((unsigned long) mem, card->pci_conf + DMALADR1);	/* to here */ +	outl(dma, card->pci_conf + DMAPADR1);	/* Copy from here */ +	outl(mem, card->pci_conf + DMALADR1);	/* to here */  	outl(len, card->pci_conf + DMASIZ1);	/* for this length */  	outl(0x000000004, card->pci_conf + DMADPR1);	/* In this direction */ @@ -1405,9 +1398,7 @@ do_bottom_half_tx(struct fst_card_info *card)  					card->dma_len_tx = skb->len;  					card->dma_txpos = port->txpos;  					fst_tx_dma(card, -						   (char *) card-> -						   tx_dma_handle_card, -						   (char *) +						   card->tx_dma_handle_card,  						   BUF_OFFSET(txBuffer[pi]  							      [port->txpos][0]),  						   skb->len); @@ -1972,6 +1963,7 @@ fst_get_iface(struct fst_card_info *card, struct fst_port_info *port,  	}  	i = port->index; +	memset(&sync, 0, sizeof(sync));  	sync.clock_rate = FST_RDL(card, portConfig[i].lineSpeed);  	/* Lucky card and linux use same encoding here */  	sync.clock_type = FST_RDB(card, portConfig[i].internalClock) == @@ -2371,7 +2363,7 @@ static char *type_strings[] = {  	"FarSync TE1"  }; -static void +static int  fst_init_card(struct fst_card_info *card)  {  	int i; @@ -2382,24 +2374,21 @@ fst_init_card(struct fst_card_info *card)  	 * we'll have to revise it in some way then.  	 */  	for (i = 0; i < card->nports; i++) { -                err = register_hdlc_device(card->ports[i].dev); -                if (err < 0) { -			int j; +		err = register_hdlc_device(card->ports[i].dev); +		if (err < 0) {  			pr_err("Cannot register HDLC device for port %d (errno %d)\n", -			       i, -err); -			for (j = i; j < card->nports; j++) { -				free_netdev(card->ports[j].dev); -				card->ports[j].dev = NULL; -			} -                        card->nports = i; -                        break; -                } +				i, -err); +			while (i--) +				unregister_hdlc_device(card->ports[i].dev); +			return err; +		}  	}  	pr_info("%s-%s: %s IRQ%d, %d ports\n",  		port_to_dev(&card->ports[0])->name,  		port_to_dev(&card->ports[card->nports - 1])->name,  		type_strings[card->type], card->irq, card->nports); +	return 0;  }  static const struct net_device_ops fst_ops = { @@ -2455,15 +2444,12 @@ fst_add_one(struct pci_dev *pdev, const struct pci_device_id *ent)  	/* Try to enable the device */  	if ((err = pci_enable_device(pdev)) != 0) {  		pr_err("Failed to enable card. Err %d\n", -err); -		kfree(card); -		return err; +		goto enable_fail;  	}  	if ((err = pci_request_regions(pdev, "FarSync")) !=0) {  		pr_err("Failed to allocate regions. Err %d\n", -err); -		pci_disable_device(pdev); -		kfree(card); -	        return err; +		goto regions_fail;  	}  	/* Get virtual addresses of memory regions */ @@ -2472,30 +2458,21 @@ fst_add_one(struct pci_dev *pdev, const struct pci_device_id *ent)  	card->phys_ctlmem = pci_resource_start(pdev, 3);  	if ((card->mem = ioremap(card->phys_mem, FST_MEMSIZE)) == NULL) {  		pr_err("Physical memory remap failed\n"); -		pci_release_regions(pdev); -		pci_disable_device(pdev); -		kfree(card); -		return -ENODEV; +		err = -ENODEV; +		goto ioremap_physmem_fail;  	}  	if ((card->ctlmem = ioremap(card->phys_ctlmem, 0x10)) == NULL) {  		pr_err("Control memory remap failed\n"); -		pci_release_regions(pdev); -		pci_disable_device(pdev); -		iounmap(card->mem); -		kfree(card); -		return -ENODEV; +		err = -ENODEV; +		goto ioremap_ctlmem_fail;  	}  	dbg(DBG_PCI, "kernel mem %p, ctlmem %p\n", card->mem, card->ctlmem);  	/* Register the interrupt handler */  	if (request_irq(pdev->irq, fst_intr, IRQF_SHARED, FST_DEV_NAME, card)) {  		pr_err("Unable to register interrupt %d\n", card->irq); -		pci_release_regions(pdev); -		pci_disable_device(pdev); -		iounmap(card->ctlmem); -		iounmap(card->mem); -		kfree(card); -		return -ENODEV; +		err = -ENODEV; +		goto irq_fail;  	}  	/* Record info we need */ @@ -2521,13 +2498,8 @@ fst_add_one(struct pci_dev *pdev, const struct pci_device_id *ent)  			while (i--)  				free_netdev(card->ports[i].dev);  			pr_err("FarSync: out of memory\n"); -                        free_irq(card->irq, card); -                        pci_release_regions(pdev); -                        pci_disable_device(pdev); -                        iounmap(card->ctlmem); -                        iounmap(card->mem); -                        kfree(card); -                        return -ENODEV; +			err = -ENOMEM; +			goto hdlcdev_fail;  		}  		card->ports[i].dev    = dev;                  card->ports[i].card   = card; @@ -2573,9 +2545,16 @@ fst_add_one(struct pci_dev *pdev, const struct pci_device_id *ent)  	pci_set_drvdata(pdev, card);  	/* Remainder of card setup */ +	if (no_of_cards_added >= FST_MAX_CARDS) { +		pr_err("FarSync: too many cards\n"); +		err = -ENOMEM; +		goto card_array_fail; +	}  	fst_card_array[no_of_cards_added] = card;  	card->card_no = no_of_cards_added++;	/* Record instance and bump it */ -	fst_init_card(card); +	err = fst_init_card(card); +	if (err) +		goto init_card_fail;  	if (card->family == FST_FAMILY_TXU) {  		/*  		 * Allocate a dma buffer for transmit and receives @@ -2585,29 +2564,46 @@ fst_add_one(struct pci_dev *pdev, const struct pci_device_id *ent)  					 &card->rx_dma_handle_card);  		if (card->rx_dma_handle_host == NULL) {  			pr_err("Could not allocate rx dma buffer\n"); -			fst_disable_intr(card); -			pci_release_regions(pdev); -			pci_disable_device(pdev); -			iounmap(card->ctlmem); -			iounmap(card->mem); -			kfree(card); -			return -ENOMEM; +			err = -ENOMEM; +			goto rx_dma_fail;  		}  		card->tx_dma_handle_host =  		    pci_alloc_consistent(card->device, FST_MAX_MTU,  					 &card->tx_dma_handle_card);  		if (card->tx_dma_handle_host == NULL) {  			pr_err("Could not allocate tx dma buffer\n"); -			fst_disable_intr(card); -			pci_release_regions(pdev); -			pci_disable_device(pdev); -			iounmap(card->ctlmem); -			iounmap(card->mem); -			kfree(card); -			return -ENOMEM; +			err = -ENOMEM; +			goto tx_dma_fail;  		}  	}  	return 0;		/* Success */ + +tx_dma_fail: +	pci_free_consistent(card->device, FST_MAX_MTU, +			    card->rx_dma_handle_host, +			    card->rx_dma_handle_card); +rx_dma_fail: +	fst_disable_intr(card); +	for (i = 0 ; i < card->nports ; i++) +		unregister_hdlc_device(card->ports[i].dev); +init_card_fail: +	fst_card_array[card->card_no] = NULL; +card_array_fail: +	for (i = 0 ; i < card->nports ; i++) +		free_netdev(card->ports[i].dev); +hdlcdev_fail: +	free_irq(card->irq, card); +irq_fail: +	iounmap(card->ctlmem); +ioremap_ctlmem_fail: +	iounmap(card->mem); +ioremap_physmem_fail: +	pci_release_regions(pdev); +regions_fail: +	pci_disable_device(pdev); +enable_fail: +	kfree(card); +	return err;  }  /*  | 
