ixgb_main.c

来自「优龙2410linux2.6.8内核源代码」· C语言 代码 · 共 2,146 行 · 第 1/4 页

C
2,146
字号
/*******************************************************************************    Copyright(c) 1999 - 2004 Intel Corporation. All rights reserved.    This program is free software; you can redistribute it and/or modify it   under the terms of the GNU General Public License as published by the Free   Software Foundation; either version 2 of the License, or (at your option)   any later version.    This program is distributed in the hope that it will be useful, but WITHOUT   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for   more details.    You should have received a copy of the GNU General Public License along with  this program; if not, write to the Free Software Foundation, Inc., 59   Temple Place - Suite 330, Boston, MA  02111-1307, USA.    The full GNU General Public License is included in this distribution in the  file called LICENSE.    Contact Information:  Linux NICS <linux.nics@intel.com>  Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497*******************************************************************************/#include "ixgb.h"char ixgb_driver_name[] = "ixgb";char ixgb_driver_string[] = "Intel(R) PRO/10GbE Network Driver";char ixgb_driver_version[] = "1.0.66";char ixgb_copyright[] = "Copyright (c) 2001-2004 Intel Corporation.";/* ixgb_pci_tbl - PCI Device ID Table * * Wildcard entries (PCI_ANY_ID) should come last * Last entry must be all 0s * * { Vendor ID, Device ID, SubVendor ID, SubDevice ID, *   Class, Class Mask, private data (not used) } */static struct pci_device_id ixgb_pci_tbl[] = {	{INTEL_VENDOR_ID, IXGB_DEVICE_ID_82597EX,	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},	{INTEL_VENDOR_ID, IXGB_DEVICE_ID_82597EX_SR,	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},	/* required last entry */	{0,}};MODULE_DEVICE_TABLE(pci, ixgb_pci_tbl);/* Local Function Prototypes */int ixgb_up(struct ixgb_adapter *adapter);void ixgb_down(struct ixgb_adapter *adapter, boolean_t kill_watchdog);void ixgb_reset(struct ixgb_adapter *adapter);static int ixgb_init_module(void);static void ixgb_exit_module(void);static int ixgb_probe(struct pci_dev *pdev, const struct pci_device_id *ent);static void __devexit ixgb_remove(struct pci_dev *pdev);static int ixgb_sw_init(struct ixgb_adapter *adapter);static int ixgb_open(struct net_device *netdev);static int ixgb_close(struct net_device *netdev);static int ixgb_setup_tx_resources(struct ixgb_adapter *adapter);static int ixgb_setup_rx_resources(struct ixgb_adapter *adapter);static void ixgb_configure_tx(struct ixgb_adapter *adapter);static void ixgb_configure_rx(struct ixgb_adapter *adapter);static void ixgb_setup_rctl(struct ixgb_adapter *adapter);static void ixgb_clean_tx_ring(struct ixgb_adapter *adapter);static void ixgb_clean_rx_ring(struct ixgb_adapter *adapter);static void ixgb_free_tx_resources(struct ixgb_adapter *adapter);static void ixgb_free_rx_resources(struct ixgb_adapter *adapter);static void ixgb_set_multi(struct net_device *netdev);static void ixgb_watchdog(unsigned long data);static int ixgb_xmit_frame(struct sk_buff *skb, struct net_device *netdev);static struct net_device_stats *ixgb_get_stats(struct net_device *netdev);static int ixgb_change_mtu(struct net_device *netdev, int new_mtu);static int ixgb_set_mac(struct net_device *netdev, void *p);static void ixgb_update_stats(struct ixgb_adapter *adapter);static inline void ixgb_irq_disable(struct ixgb_adapter *adapter);static inline void ixgb_irq_enable(struct ixgb_adapter *adapter);static irqreturn_t ixgb_intr(int irq, void *data, struct pt_regs *regs);static boolean_t ixgb_clean_tx_irq(struct ixgb_adapter *adapter);#ifdef CONFIG_IXGB_NAPIstatic int ixgb_clean(struct net_device *netdev, int *budget);static boolean_t ixgb_clean_rx_irq(struct ixgb_adapter *adapter,				   int *work_done, int work_to_do);#elsestatic boolean_t ixgb_clean_rx_irq(struct ixgb_adapter *adapter);#endifstatic void ixgb_alloc_rx_buffers(struct ixgb_adapter *adapter);static int ixgb_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd);static inline void ixgb_rx_checksum(struct ixgb_adapter *adapter,				    struct ixgb_rx_desc *rx_desc,				    struct sk_buff *skb);static void ixgb_tx_timeout(struct net_device *dev);static void ixgb_tx_timeout_task(struct net_device *dev);static void ixgb_vlan_rx_register(struct net_device *netdev,				  struct vlan_group *grp);static void ixgb_vlan_rx_add_vid(struct net_device *netdev, uint16_t vid);static void ixgb_vlan_rx_kill_vid(struct net_device *netdev, uint16_t vid);static void ixgb_restore_vlan(struct ixgb_adapter *adapter);static int ixgb_notify_reboot(struct notifier_block *, unsigned long event,			      void *ptr);static int ixgb_suspend(struct pci_dev *pdev, uint32_t state);#ifdef CONFIG_NET_POLL_CONTROLLER/* for netdump / net console */static void ixgb_netpoll(struct net_device *dev);#endifstruct notifier_block ixgb_notifier_reboot = {	.notifier_call = ixgb_notify_reboot,	.next = NULL,	.priority = 0};/* Exported from other modules */extern void ixgb_check_options(struct ixgb_adapter *adapter);extern int ixgb_ethtool_ioctl(struct net_device *netdev, struct ifreq *ifr);static struct pci_driver ixgb_driver = {	.name = ixgb_driver_name,	.id_table = ixgb_pci_tbl,	.probe = ixgb_probe,	.remove = __devexit_p(ixgb_remove),	/* Power Managment Hooks */	.suspend = NULL,	.resume = NULL};MODULE_AUTHOR("Intel Corporation, <linux.nics@intel.com>");MODULE_DESCRIPTION("Intel(R) PRO/10GbE Network Driver");MODULE_LICENSE("GPL");/* some defines for controlling descriptor fetches in h/w */#define RXDCTL_PTHRESH_DEFAULT 128	/* chip considers prefech below this */#define RXDCTL_HTHRESH_DEFAULT 16	/* chip will only prefetch if tail is 					   pushed this many descriptors from head */#define RXDCTL_WTHRESH_DEFAULT 16	/* chip writes back at this many or RXT0 *//** * ixgb_init_module - Driver Registration Routine * * ixgb_init_module is the first routine called when the driver is * loaded. All it does is register with the PCI subsystem. **/static int __init ixgb_init_module(void){	int ret;	printk(KERN_INFO "%s - version %s\n",	       ixgb_driver_string, ixgb_driver_version);	printk(KERN_INFO "%s\n", ixgb_copyright);	ret = pci_module_init(&ixgb_driver);	if (ret >= 0) {		register_reboot_notifier(&ixgb_notifier_reboot);	}	return ret;}module_init(ixgb_init_module);/** * ixgb_exit_module - Driver Exit Cleanup Routine * * ixgb_exit_module is called just before the driver is removed * from memory. **/static void __exit ixgb_exit_module(void){	unregister_reboot_notifier(&ixgb_notifier_reboot);	pci_unregister_driver(&ixgb_driver);}module_exit(ixgb_exit_module);int ixgb_up(struct ixgb_adapter *adapter){	struct net_device *netdev = adapter->netdev;	int err;	int max_frame = netdev->mtu + ENET_HEADER_SIZE + ENET_FCS_LENGTH;	struct ixgb_hw *hw = &adapter->hw;	/* hardware has been reset, we need to reload some things */	ixgb_set_multi(netdev);	ixgb_restore_vlan(adapter);	ixgb_configure_tx(adapter);	ixgb_setup_rctl(adapter);	ixgb_configure_rx(adapter);	ixgb_alloc_rx_buffers(adapter);	if ((err = request_irq(adapter->pdev->irq, &ixgb_intr,			       SA_SHIRQ | SA_SAMPLE_RANDOM,			       netdev->name, netdev)))		return err;	/* disable interrupts and get the hardware into a known state */	IXGB_WRITE_REG(&adapter->hw, IMC, 0xffffffff);	if ((hw->max_frame_size != max_frame) ||	    (hw->max_frame_size !=	     (IXGB_READ_REG(hw, MFS) >> IXGB_MFS_SHIFT))) {		hw->max_frame_size = max_frame;		IXGB_WRITE_REG(hw, MFS, hw->max_frame_size << IXGB_MFS_SHIFT);		if (hw->max_frame_size >		    IXGB_MAX_ENET_FRAME_SIZE_WITHOUT_FCS + ENET_FCS_LENGTH) {			uint32_t ctrl0 = IXGB_READ_REG(hw, CTRL0);			if (!(ctrl0 & IXGB_CTRL0_JFE)) {				ctrl0 |= IXGB_CTRL0_JFE;				IXGB_WRITE_REG(hw, CTRL0, ctrl0);			}		}	}	mod_timer(&adapter->watchdog_timer, jiffies);	ixgb_irq_enable(adapter);	return 0;}void ixgb_down(struct ixgb_adapter *adapter, boolean_t kill_watchdog){	struct net_device *netdev = adapter->netdev;	ixgb_irq_disable(adapter);	free_irq(adapter->pdev->irq, netdev);	if (kill_watchdog)		del_timer_sync(&adapter->watchdog_timer);	adapter->link_speed = 0;	adapter->link_duplex = 0;	netif_carrier_off(netdev);	netif_stop_queue(netdev);	ixgb_reset(adapter);	ixgb_clean_tx_ring(adapter);	ixgb_clean_rx_ring(adapter);}void ixgb_reset(struct ixgb_adapter *adapter){	ixgb_adapter_stop(&adapter->hw);	if (!ixgb_init_hw(&adapter->hw))		IXGB_DBG("ixgb_init_hw failed.\n");}/** * ixgb_probe - Device Initialization Routine * @pdev: PCI device information struct * @ent: entry in ixgb_pci_tbl * * Returns 0 on success, negative on failure * * ixgb_probe initializes an adapter identified by a pci_dev structure. * The OS initialization, configuring of the adapter private structure, * and a hardware reset occur. **/static int __devinitixgb_probe(struct pci_dev *pdev, const struct pci_device_id *ent){	struct net_device *netdev = NULL;	struct ixgb_adapter *adapter;	static int cards_found = 0;	unsigned long mmio_start;	int mmio_len;	int pci_using_dac;	int i;	int err;	if ((err = pci_enable_device(pdev)))		return err;	if (!(err = pci_set_dma_mask(pdev, DMA_64BIT_MASK))) {		pci_using_dac = 1;	} else {		if ((err = pci_set_dma_mask(pdev, DMA_32BIT_MASK))) {			IXGB_ERR("No usable DMA configuration, aborting\n");			return err;		}		pci_using_dac = 0;	}	if ((err = pci_request_regions(pdev, ixgb_driver_name)))		return err;	pci_set_master(pdev);	netdev = alloc_etherdev(sizeof(struct ixgb_adapter));	if (!netdev) {		err = -ENOMEM;		goto err_alloc_etherdev;	}	SET_MODULE_OWNER(netdev);	SET_NETDEV_DEV(netdev, &pdev->dev);	pci_set_drvdata(pdev, netdev);	adapter = netdev->priv;	adapter->netdev = netdev;	adapter->pdev = pdev;	adapter->hw.back = adapter;	mmio_start = pci_resource_start(pdev, BAR_0);	mmio_len = pci_resource_len(pdev, BAR_0);	adapter->hw.hw_addr = ioremap(mmio_start, mmio_len);	if (!adapter->hw.hw_addr) {		err = -EIO;		goto err_ioremap;	}	for (i = BAR_1; i <= BAR_5; i++) {		if (pci_resource_len(pdev, i) == 0)			continue;		if (pci_resource_flags(pdev, i) & IORESOURCE_IO) {			adapter->hw.io_base = pci_resource_start(pdev, i);			break;		}	}	netdev->open = &ixgb_open;	netdev->stop = &ixgb_close;	netdev->hard_start_xmit = &ixgb_xmit_frame;	netdev->get_stats = &ixgb_get_stats;	netdev->set_multicast_list = &ixgb_set_multi;	netdev->set_mac_address = &ixgb_set_mac;	netdev->change_mtu = &ixgb_change_mtu;	netdev->do_ioctl = &ixgb_ioctl;	netdev->tx_timeout = &ixgb_tx_timeout;	netdev->watchdog_timeo = HZ;#ifdef CONFIG_IXGB_NAPI	netdev->poll = &ixgb_clean;	netdev->weight = 64;#endif	netdev->vlan_rx_register = ixgb_vlan_rx_register;	netdev->vlan_rx_add_vid = ixgb_vlan_rx_add_vid;	netdev->vlan_rx_kill_vid = ixgb_vlan_rx_kill_vid;#ifdef CONFIG_NET_POLL_CONTROLLER	netdev->poll_controller = ixgb_netpoll;#endif	netdev->mem_start = mmio_start;	netdev->mem_end = mmio_start + mmio_len;	netdev->base_addr = adapter->hw.io_base;	adapter->bd_number = cards_found;	adapter->link_speed = 0;	adapter->link_duplex = 0;	/* setup the private structure */	if ((err = ixgb_sw_init(adapter)))		goto err_sw_init;	netdev->features = NETIF_F_SG |	    NETIF_F_HW_CSUM |	    NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX | NETIF_F_HW_VLAN_FILTER;#ifdef NETIF_F_TSO	netdev->features |= NETIF_F_TSO;#endif	if (pci_using_dac)		netdev->features |= NETIF_F_HIGHDMA;	/* make sure the EEPROM is good */	if (!ixgb_validate_eeprom_checksum(&adapter->hw)) {		printk(KERN_ERR "The EEPROM Checksum Is Not Valid\n");		err = -EIO;		goto err_eeprom;	}	ixgb_get_ee_mac_addr(&adapter->hw, netdev->dev_addr);	if (!is_valid_ether_addr(netdev->dev_addr)) {		err = -EIO;		goto err_eeprom;	}	adapter->part_num = ixgb_get_ee_pba_number(&adapter->hw);	init_timer(&adapter->watchdog_timer);	adapter->watchdog_timer.function = &ixgb_watchdog;	adapter->watchdog_timer.data = (unsigned long)adapter;	INIT_WORK(&adapter->tx_timeout_task,		  (void (*)(void *))ixgb_tx_timeout_task, netdev);	if ((err = register_netdev(netdev)))		goto err_register;	/* we're going to reset, so assume we have no link for now */	netif_carrier_off(netdev);	netif_stop_queue(netdev);	printk(KERN_INFO "%s: Intel(R) PRO/10GbE Network Connection\n",	       netdev->name);	ixgb_check_options(adapter);	/* reset the hardware with the new settings */	ixgb_reset(adapter);	cards_found++;	return 0;      err_register:      err_sw_init:      err_eeprom:	iounmap(adapter->hw.hw_addr);      err_ioremap:	free_netdev(netdev);      err_alloc_etherdev:	pci_release_regions(pdev);	return err;}/** * ixgb_remove - Device Removal Routine * @pdev: PCI device information struct * * ixgb_remove is called by the PCI subsystem to alert the driver * that it should release a PCI device.  The could be caused by a * Hot-Plug event, or because the driver is going to be removed from * memory. **/static void __devexit ixgb_remove(struct pci_dev *pdev){	struct net_device *netdev = pci_get_drvdata(pdev);	struct ixgb_adapter *adapter = netdev->priv;	unregister_netdev(netdev);	iounmap(adapter->hw.hw_addr);	pci_release_regions(pdev);	free_netdev(netdev);}/** * ixgb_sw_init - Initialize general software structures (struct ixgb_adapter) * @adapter: board private structure to initialize * * ixgb_sw_init initializes the Adapter private data structure. * Fields are initialized based on PCI device information and * OS network device settings (MTU size). **/static int __devinit ixgb_sw_init(struct ixgb_adapter *adapter){	struct ixgb_hw *hw = &adapter->hw;	struct net_device *netdev = adapter->netdev;	struct pci_dev *pdev = adapter->pdev;	/* PCI config space info */	hw->vendor_id = pdev->vendor;	hw->device_id = pdev->device;	hw->subsystem_vendor_id = pdev->subsystem_vendor;	hw->subsystem_id = pdev->subsystem_device;	adapter->rx_buffer_len = IXGB_RXBUFFER_2048;	hw->max_frame_size = netdev->mtu + ENET_HEADER_SIZE + ENET_FCS_LENGTH;	if ((hw->device_id == IXGB_DEVICE_ID_82597EX)	    || (hw->device_id == IXGB_DEVICE_ID_82597EX_SR))		hw->mac_type = ixgb_82597;	else {		/* should never have loaded on this device */		printk(KERN_ERR "ixgb: unsupported device id\n");	}	/* enable flow control to be programmed */	hw->fc.send_xon = 1;	atomic_set(&adapter->irq_sem, 1);	spin_lock_init(&adapter->tx_lock);	return 0;}/** * ixgb_open - Called when a network interface is made active * @netdev: network interface device structure * * Returns 0 on success, negative value on failure * * The open entry point is called when a network interface is made * active by the system (IFF_UP).  At this point all resources needed * for transmit and receive operations are allocated, the interrupt * handler is registered with the OS, the watchdog timer is started, * and the stack is notified that the interface is ready. **/static int ixgb_open(struct net_device *netdev){	struct ixgb_adapter *adapter = netdev->priv;	int err;	/* allocate transmit descriptors */	if ((err = ixgb_setup_tx_resources(adapter)))		goto err_setup_tx;	/* allocate receive descriptors */	if ((err = ixgb_setup_rx_resources(adapter)))		goto err_setup_rx;	if ((err = ixgb_up(adapter)))		goto err_up;	return 0;      err_up:	ixgb_free_rx_resources(adapter);

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?