diff options
Diffstat (limited to 'drivers/net/wan/farsync.c')
| -rw-r--r-- | drivers/net/wan/farsync.c | 171 | 
1 files changed, 84 insertions, 87 deletions
diff --git a/drivers/net/wan/farsync.c b/drivers/net/wan/farsync.c index e050bd65e03..1f041271f7f 100644 --- a/drivers/net/wan/farsync.c +++ b/drivers/net/wan/farsync.c @@ -25,6 +25,8 @@  #include <linux/slab.h>  #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> @@ -596,7 +598,7 @@ fst_q_work_item(u64 * queue, int card_index)  	 * bottom half for the card.  Note the limitation of 64 cards.  	 * That ought to be enough  	 */ -	mask = 1 << card_index; +	mask = (u64)1 << card_index;  	*queue |= mask;  	spin_unlock_irqrestore(&fst_work_q_lock, flags);  } @@ -677,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) { @@ -695,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 @@ -885,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 */ @@ -914,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 */ @@ -1404,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); @@ -1664,10 +1656,9 @@ check_started_ok(struct fst_card_info *card)  	 * existing firmware etc so we just report it for the moment.  	 */  	if (FST_RDL(card, numberOfPorts) != card->nports) { -		pr_warning("Port count mismatch on card %d. " -			   "Firmware thinks %d we say %d\n", -			   card->card_no, -			   FST_RDL(card, numberOfPorts), card->nports); +		pr_warn("Port count mismatch on card %d.  Firmware thinks %d we say %d\n", +			card->card_no, +			FST_RDL(card, numberOfPorts), card->nports);  	}  } @@ -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) == @@ -2203,8 +2195,10 @@ fst_open(struct net_device *dev)  	if (port->mode != FST_RAW) {  		err = hdlc_open(dev); -		if (err) +		if (err) { +			module_put(THIS_MODULE);  			return err; +		}  	}  	fst_openport(port); @@ -2359,7 +2353,7 @@ fst_start_xmit(struct sk_buff *skb, struct net_device *dev)   *      via a printk and leave the corresponding interface and all that follow   *      disabled.   */ -static char *type_strings[] __devinitdata = { +static char *type_strings[] = {  	"no hardware",		/* Should never be seen */  	"FarSync T2P",  	"FarSync T4P", @@ -2369,7 +2363,7 @@ static char *type_strings[] __devinitdata = {  	"FarSync TE1"  }; -static void __devinit +static int  fst_init_card(struct fst_card_info *card)  {  	int i; @@ -2380,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 = { @@ -2413,7 +2404,7 @@ static const struct net_device_ops fst_ops = {   *      Initialise card when detected.   *      Returns 0 to indicate success, or errno otherwise.   */ -static int __devinit +static int  fst_add_one(struct pci_dev *pdev, const struct pci_device_id *ent)  {  	static int no_of_cards_added = 0; @@ -2446,24 +2437,19 @@ fst_add_one(struct pci_dev *pdev, const struct pci_device_id *ent)  	}  	/* Allocate driver private data */ -	card = kzalloc(sizeof (struct fst_card_info), GFP_KERNEL); -	if (card == NULL) { -		pr_err("FarSync card found but insufficient memory for driver storage\n"); +	card = kzalloc(sizeof(struct fst_card_info), GFP_KERNEL); +	if (card == NULL)  		return -ENOMEM; -	}  	/* 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,29 +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); -		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 */ @@ -2520,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; @@ -2572,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 @@ -2584,35 +2564,52 @@ 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;  }  /*   *      Cleanup and close down a card   */ -static void __devexit +static void  fst_remove_one(struct pci_dev *pdev)  {  	struct fst_card_info *card; @@ -2649,7 +2646,7 @@ static struct pci_driver fst_driver = {          .name		= FST_NAME,          .id_table	= fst_pci_dev_id,          .probe		= fst_add_one, -        .remove	= __devexit_p(fst_remove_one), +        .remove	= fst_remove_one,          .suspend	= NULL,          .resume	= NULL,  };  | 
