ixgb_main.c
来自「linux 内核源代码」· C语言 代码 · 共 2,360 行 · 第 1/5 页
C
2,360 行
/******************************************************************************* Intel PRO/10GbE Linux driver Copyright(c) 1999 - 2006 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, version 2, as published by the Free Software Foundation. This program is distributed in the hope 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., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. The full GNU General Public License is included in this distribution in the file called "COPYING". Contact Information: Linux NICS <linux.nics@intel.com> e1000-devel Mailing List <e1000-devel@lists.sourceforge.net> Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497*******************************************************************************/#include "ixgb.h"char ixgb_driver_name[] = "ixgb";static char ixgb_driver_string[] = "Intel(R) PRO/10GbE Network Driver";#ifndef CONFIG_IXGB_NAPI#define DRIVERNAPI#else#define DRIVERNAPI "-NAPI"#endif#define DRV_VERSION "1.0.126-k2"DRIVERNAPIconst char ixgb_driver_version[] = DRV_VERSION;static const char ixgb_copyright[] = "Copyright (c) 1999-2006 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_CX4, 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}, {INTEL_VENDOR_ID, IXGB_DEVICE_ID_82597EX_LR, 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);int ixgb_setup_tx_resources(struct ixgb_adapter *adapter);int ixgb_setup_rx_resources(struct ixgb_adapter *adapter);void ixgb_free_tx_resources(struct ixgb_adapter *adapter);void ixgb_free_rx_resources(struct ixgb_adapter *adapter);void ixgb_update_stats(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 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_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 irqreturn_t ixgb_intr(int irq, void *data);static boolean_t ixgb_clean_tx_irq(struct ixgb_adapter *adapter);#ifdef CONFIG_IXGB_NAPIstatic int ixgb_clean(struct napi_struct *napi, 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 void ixgb_tx_timeout(struct net_device *dev);static void ixgb_tx_timeout_task(struct work_struct *work);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);#ifdef CONFIG_NET_POLL_CONTROLLER/* for netdump / net console */static void ixgb_netpoll(struct net_device *dev);#endifstatic pci_ers_result_t ixgb_io_error_detected (struct pci_dev *pdev, enum pci_channel_state state);static pci_ers_result_t ixgb_io_slot_reset (struct pci_dev *pdev);static void ixgb_io_resume (struct pci_dev *pdev);static struct pci_error_handlers ixgb_err_handler = { .error_detected = ixgb_io_error_detected, .slot_reset = ixgb_io_slot_reset, .resume = ixgb_io_resume,};static struct pci_driver ixgb_driver = { .name = ixgb_driver_name, .id_table = ixgb_pci_tbl, .probe = ixgb_probe, .remove = __devexit_p(ixgb_remove), .err_handler = &ixgb_err_handler};MODULE_AUTHOR("Intel Corporation, <linux.nics@intel.com>");MODULE_DESCRIPTION("Intel(R) PRO/10GbE Network Driver");MODULE_LICENSE("GPL");MODULE_VERSION(DRV_VERSION);#define DEFAULT_DEBUG_LEVEL_SHIFT 3static int debug = DEFAULT_DEBUG_LEVEL_SHIFT;module_param(debug, int, 0);MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)");/* some defines for controlling descriptor fetches in h/w */#define RXDCTL_WTHRESH_DEFAULT 15 /* chip writes back at this many or RXT0 */#define RXDCTL_PTHRESH_DEFAULT 0 /* chip considers prefech below * this */#define RXDCTL_HTHRESH_DEFAULT 0 /* chip will only prefetch if tail * is pushed this many descriptors * from head *//** * 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 __initixgb_init_module(void){ printk(KERN_INFO "%s - version %s\n", ixgb_driver_string, ixgb_driver_version); printk(KERN_INFO "%s\n", ixgb_copyright); return pci_register_driver(&ixgb_driver);}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 __exitixgb_exit_module(void){ pci_unregister_driver(&ixgb_driver);}module_exit(ixgb_exit_module);/** * ixgb_irq_disable - Mask off interrupt generation on the NIC * @adapter: board private structure **/static voidixgb_irq_disable(struct ixgb_adapter *adapter){ atomic_inc(&adapter->irq_sem); IXGB_WRITE_REG(&adapter->hw, IMC, ~0); IXGB_WRITE_FLUSH(&adapter->hw); synchronize_irq(adapter->pdev->irq);}/** * ixgb_irq_enable - Enable default interrupt generation settings * @adapter: board private structure **/static voidixgb_irq_enable(struct ixgb_adapter *adapter){ if(atomic_dec_and_test(&adapter->irq_sem)) { IXGB_WRITE_REG(&adapter->hw, IMS, IXGB_INT_RXT0 | IXGB_INT_RXDMT0 | IXGB_INT_TXDW | IXGB_INT_LSC); IXGB_WRITE_FLUSH(&adapter->hw); }}intixgb_up(struct ixgb_adapter *adapter){ struct net_device *netdev = adapter->netdev; int err, irq_flags = IRQF_SHARED; 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_rar_set(hw, netdev->dev_addr, 0); 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); /* disable interrupts and get the hardware into a known state */ IXGB_WRITE_REG(&adapter->hw, IMC, 0xffffffff); /* only enable MSI if bus is in PCI-X mode */ if (IXGB_READ_REG(&adapter->hw, STATUS) & IXGB_STATUS_PCIX_MODE) { err = pci_enable_msi(adapter->pdev); if (!err) { adapter->have_msi = 1; irq_flags = 0; } /* proceed to try to request regular interrupt */ } err = request_irq(adapter->pdev->irq, &ixgb_intr, irq_flags, netdev->name, netdev); if (err) { if (adapter->have_msi) pci_disable_msi(adapter->pdev); DPRINTK(PROBE, ERR, "Unable to allocate interrupt Error: %d\n", err); return err; } 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);#ifdef CONFIG_IXGB_NAPI napi_enable(&adapter->napi);#endif ixgb_irq_enable(adapter); return 0;}voidixgb_down(struct ixgb_adapter *adapter, boolean_t kill_watchdog){ struct net_device *netdev = adapter->netdev;#ifdef CONFIG_IXGB_NAPI napi_disable(&adapter->napi); atomic_set(&adapter->irq_sem, 0);#endif ixgb_irq_disable(adapter); free_irq(adapter->pdev->irq, netdev); if (adapter->have_msi) pci_disable_msi(adapter->pdev); 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);}voidixgb_reset(struct ixgb_adapter *adapter){ struct ixgb_hw *hw = &adapter->hw; ixgb_adapter_stop(hw); if (!ixgb_init_hw(hw)) DPRINTK(PROBE, ERR, "ixgb_init_hw failed.\n"); /* restore frame size information */ 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) { u32 ctrl0 = IXGB_READ_REG(hw, CTRL0); if (!(ctrl0 & IXGB_CTRL0_JFE)) { ctrl0 |= IXGB_CTRL0_JFE; IXGB_WRITE_REG(hw, CTRL0, ctrl0); } }}/** * 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)) && !(err = pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK))) { pci_using_dac = 1; } else { if((err = pci_set_dma_mask(pdev, DMA_32BIT_MASK)) || (err = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK))) { printk(KERN_ERR "ixgb: No usable DMA configuration, aborting\n"); goto err_dma_mask; } pci_using_dac = 0; } if((err = pci_request_regions(pdev, ixgb_driver_name))) goto err_request_regions; pci_set_master(pdev); netdev = alloc_etherdev(sizeof(struct ixgb_adapter)); if(!netdev) { err = -ENOMEM; goto err_alloc_etherdev; } SET_NETDEV_DEV(netdev, &pdev->dev); pci_set_drvdata(pdev, netdev); adapter = netdev_priv(netdev); adapter->netdev = netdev; adapter->pdev = pdev; adapter->hw.back = adapter; adapter->msg_enable = netif_msg_init(debug, DEFAULT_DEBUG_LEVEL_SHIFT); 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; ixgb_set_ethtool_ops(netdev); netdev->tx_timeout = &ixgb_tx_timeout; netdev->watchdog_timeo = 5 * HZ;#ifdef CONFIG_IXGB_NAPI netif_napi_add(netdev, &adapter->napi, ixgb_clean, 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 strncpy(netdev->name, pci_name(pdev), sizeof(netdev->name) - 1); 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; netdev->features |= NETIF_F_TSO;#ifdef NETIF_F_LLTX netdev->features |= NETIF_F_LLTX;#endif if(pci_using_dac) netdev->features |= NETIF_F_HIGHDMA; /* make sure the EEPROM is good */ if(!ixgb_validate_eeprom_checksum(&adapter->hw)) {
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?