diff options
Diffstat (limited to 'drivers/net/starfire.c')
| -rw-r--r-- | drivers/net/starfire.c | 83 | 
1 files changed, 62 insertions, 21 deletions
diff --git a/drivers/net/starfire.c b/drivers/net/starfire.c index 1d2ef8f4778..57fb1f71c47 100644 --- a/drivers/net/starfire.c +++ b/drivers/net/starfire.c @@ -42,11 +42,11 @@  #include <linux/mii.h>  #include <linux/if_vlan.h>  #include <linux/mm.h> +#include <linux/firmware.h>  #include <asm/processor.h>		/* Processor type for cache alignment. */  #include <asm/uaccess.h>  #include <asm/io.h> -#include "starfire_firmware.h"  /*   * The current frame processor firmware fails to checksum a fragment   * of length 1. If and when this is fixed, the #define below can be removed. @@ -173,6 +173,10 @@ static int full_duplex[MAX_UNITS] = {0, };  #define skb_first_frag_len(skb)	skb_headlen(skb)  #define skb_num_frags(skb) (skb_shinfo(skb)->nr_frags + 1) +/* Firmware names */ +#define FIRMWARE_RX	"adaptec/starfire_rx.bin" +#define FIRMWARE_TX	"adaptec/starfire_tx.bin" +  /* These identify the driver base version and may not be removed. */  static char version[] =  KERN_INFO "starfire.c:v1.03 7/26/2000  Written by Donald Becker <becker@scyld.com>\n" @@ -182,6 +186,8 @@ MODULE_AUTHOR("Donald Becker <becker@scyld.com>");  MODULE_DESCRIPTION("Adaptec Starfire Ethernet driver");  MODULE_LICENSE("GPL");  MODULE_VERSION(DRV_VERSION); +MODULE_FIRMWARE(FIRMWARE_RX); +MODULE_FIRMWARE(FIRMWARE_TX);  module_param(max_interrupt_work, int, 0);  module_param(mtu, int, 0); @@ -653,7 +659,6 @@ static int __devinit starfire_init_one(struct pci_dev *pdev,  	void __iomem *base;  	int drv_flags, io_size;  	int boguscnt; -	DECLARE_MAC_BUF(mac);  /* when built into the kernel, we only print version if device is found */  #ifndef MODULE @@ -823,9 +828,9 @@ static int __devinit starfire_init_one(struct pci_dev *pdev,  	if (register_netdev(dev))  		goto err_out_cleardev; -	printk(KERN_INFO "%s: %s at %p, %s, IRQ %d.\n", +	printk(KERN_INFO "%s: %s at %p, %pM, IRQ %d.\n",  	       dev->name, netdrv_tbl[chip_idx].name, base, -	       print_mac(mac, dev->dev_addr), irq); +	       dev->dev_addr, irq);  	if (drv_flags & CanHaveMII) {  		int phy, phy_idx = 0; @@ -881,9 +886,9 @@ static int mdio_read(struct net_device *dev, int phy_id, int location)  	void __iomem *mdio_addr = np->base + MIICtrl + (phy_id<<7) + (location<<2);  	int result, boguscnt=1000;  	/* ??? Should we add a busy-wait here? */ -	do +	do {  		result = readl(mdio_addr); -	while ((result & 0xC0000000) != 0x80000000 && --boguscnt > 0); +	} while ((result & 0xC0000000) != 0x80000000 && --boguscnt > 0);  	if (boguscnt == 0)  		return 0;  	if ((result & 0xffff) == 0xffff) @@ -903,9 +908,12 @@ static void mdio_write(struct net_device *dev, int phy_id, int location, int val  static int netdev_open(struct net_device *dev)  { +	const struct firmware *fw_rx, *fw_tx; +	const __be32 *fw_rx_data, *fw_tx_data;  	struct netdev_private *np = netdev_priv(dev);  	void __iomem *ioaddr = np->base;  	int i, retval; +	size_t tx_size, rx_size;  	size_t tx_done_q_size, rx_done_q_size, tx_ring_size, rx_ring_size;  	/* Do we ever need to reset the chip??? */ @@ -1041,11 +1049,40 @@ static int netdev_open(struct net_device *dev)  	writel(ETH_P_8021Q, ioaddr + VlanType);  #endif /* VLAN_SUPPORT */ +	retval = request_firmware(&fw_rx, FIRMWARE_RX, &np->pci_dev->dev); +	if (retval) { +		printk(KERN_ERR "starfire: Failed to load firmware \"%s\"\n", +		       FIRMWARE_RX); +		return retval; +	} +	if (fw_rx->size % 4) { +		printk(KERN_ERR "starfire: bogus length %zu in \"%s\"\n", +		       fw_rx->size, FIRMWARE_RX); +		retval = -EINVAL; +		goto out_rx; +	} +	retval = request_firmware(&fw_tx, FIRMWARE_TX, &np->pci_dev->dev); +	if (retval) { +		printk(KERN_ERR "starfire: Failed to load firmware \"%s\"\n", +		       FIRMWARE_TX); +		goto out_rx; +	} +	if (fw_tx->size % 4) { +		printk(KERN_ERR "starfire: bogus length %zu in \"%s\"\n", +		       fw_tx->size, FIRMWARE_TX); +		retval = -EINVAL; +		goto out_tx; +	} +	fw_rx_data = (const __be32 *)&fw_rx->data[0]; +	fw_tx_data = (const __be32 *)&fw_tx->data[0]; +	rx_size = fw_rx->size / 4; +	tx_size = fw_tx->size / 4; +  	/* Load Rx/Tx firmware into the frame processors */ -	for (i = 0; i < FIRMWARE_RX_SIZE * 2; i++) -		writel(firmware_rx[i], ioaddr + RxGfpMem + i * 4); -	for (i = 0; i < FIRMWARE_TX_SIZE * 2; i++) -		writel(firmware_tx[i], ioaddr + TxGfpMem + i * 4); +	for (i = 0; i < rx_size; i++) +		writel(be32_to_cpup(&fw_rx_data[i]), ioaddr + RxGfpMem + i * 4); +	for (i = 0; i < tx_size; i++) +		writel(be32_to_cpup(&fw_tx_data[i]), ioaddr + TxGfpMem + i * 4);  	if (enable_hw_cksum)  		/* Enable the Rx and Tx units, and the Rx/Tx frame processors. */  		writel(TxEnable|TxGFPEnable|RxEnable|RxGFPEnable, ioaddr + GenCtrl); @@ -1057,7 +1094,11 @@ static int netdev_open(struct net_device *dev)  		printk(KERN_DEBUG "%s: Done netdev_open().\n",  		       dev->name); -	return 0; +out_tx: +	release_firmware(fw_tx); +out_rx: +	release_firmware(fw_rx); +	return retval;  } @@ -1291,8 +1332,8 @@ static irqreturn_t intr_handler(int irq, void *dev_instance)  		if (intr_status & (IntrRxDone | IntrRxEmpty)) {  			u32 enable; -			if (likely(netif_rx_schedule_prep(dev, &np->napi))) { -				__netif_rx_schedule(dev, &np->napi); +			if (likely(netif_rx_schedule_prep(&np->napi))) { +				__netif_rx_schedule(&np->napi);  				enable = readl(ioaddr + IntrEnable);  				enable &= ~(IntrRxDone | IntrRxEmpty);  				writel(enable, ioaddr + IntrEnable); @@ -1452,12 +1493,8 @@ static int __netdev_rx(struct net_device *dev, int *quota)  #ifndef final_version			/* Remove after testing. */  		/* You will want this info for the initial debug. */  		if (debug > 5) { -			printk(KERN_DEBUG "  Rx data " MAC_FMT " " MAC_FMT -			       " %2.2x%2.2x.\n", -			       skb->data[0], skb->data[1], skb->data[2], -			       skb->data[3], skb->data[4], skb->data[5], -			       skb->data[6], skb->data[7], skb->data[8], -			       skb->data[9], skb->data[10], skb->data[11], +			printk(KERN_DEBUG "  Rx data %pM %pM %2.2x%2.2x.\n", +			       skb->data, skb->data + 6,  			       skb->data[12], skb->data[13]);  		}  #endif @@ -1501,7 +1538,6 @@ static int __netdev_rx(struct net_device *dev, int *quota)  		} else  #endif /* VLAN_SUPPORT */  			netif_receive_skb(skb); -		dev->last_rx = jiffies;  		np->stats.rx_packets++;  	next_rx: @@ -1509,6 +1545,11 @@ static int __netdev_rx(struct net_device *dev, int *quota)  		desc->status = 0;  		np->rx_done = (np->rx_done + 1) % DONE_Q_SIZE;  	} + +	if (*quota == 0) {	/* out of rx quota */ +		retcode = 1; +		goto out; +	}  	writew(np->rx_done, np->base + CompletionQConsumerIdx);   out: @@ -1536,7 +1577,7 @@ static int netdev_poll(struct napi_struct *napi, int budget)  		intr_status = readl(ioaddr + IntrStatus);  	} while (intr_status & (IntrRxDone | IntrRxEmpty)); -	netif_rx_complete(dev, napi); +	netif_rx_complete(napi);  	intr_status = readl(ioaddr + IntrEnable);  	intr_status |= IntrRxDone | IntrRxEmpty;  	writel(intr_status, ioaddr + IntrEnable);  | 
