summaryrefslogtreecommitdiff
path: root/drivers/net/ethernet/intel/ixgb/ixgb_main.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/ethernet/intel/ixgb/ixgb_main.c')
-rw-r--r--drivers/net/ethernet/intel/ixgb/ixgb_main.c2332
1 files changed, 2332 insertions, 0 deletions
diff --git a/drivers/net/ethernet/intel/ixgb/ixgb_main.c b/drivers/net/ethernet/intel/ixgb/ixgb_main.c
new file mode 100644
index 000000000000..6a130eb51cfa
--- /dev/null
+++ b/drivers/net/ethernet/intel/ixgb/ixgb_main.c
@@ -0,0 +1,2332 @@
+/*******************************************************************************
+
+ Intel PRO/10GbE Linux driver
+ Copyright(c) 1999 - 2008 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
+
+*******************************************************************************/
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/prefetch.h>
+#include "ixgb.h"
+
+char ixgb_driver_name[] = "ixgb";
+static char ixgb_driver_string[] = "Intel(R) PRO/10GbE Network Driver";
+
+#define DRIVERNAPI "-NAPI"
+#define DRV_VERSION "1.0.135-k2" DRIVERNAPI
+const char ixgb_driver_version[] = DRV_VERSION;
+static const char ixgb_copyright[] = "Copyright (c) 1999-2008 Intel Corporation.";
+
+#define IXGB_CB_LENGTH 256
+static unsigned int copybreak __read_mostly = IXGB_CB_LENGTH;
+module_param(copybreak, uint, 0644);
+MODULE_PARM_DESC(copybreak,
+ "Maximum size of packet that is copied to a new buffer on receive");
+
+/* 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 DEFINE_PCI_DEVICE_TABLE(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 */
+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 netdev_tx_t 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 bool ixgb_clean_tx_irq(struct ixgb_adapter *adapter);
+
+static int ixgb_clean(struct napi_struct *, int);
+static bool ixgb_clean_rx_irq(struct ixgb_adapter *, int *, int);
+static void ixgb_alloc_rx_buffers(struct ixgb_adapter *, int);
+
+static void ixgb_tx_timeout(struct net_device *dev);
+static void ixgb_tx_timeout_task(struct work_struct *work);
+
+static void ixgb_vlan_strip_enable(struct ixgb_adapter *adapter);
+static void ixgb_vlan_strip_disable(struct ixgb_adapter *adapter);
+static void ixgb_vlan_rx_add_vid(struct net_device *netdev, u16 vid);
+static void ixgb_vlan_rx_kill_vid(struct net_device *netdev, u16 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);
+#endif
+
+static 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 3
+static int debug = DEFAULT_DEBUG_LEVEL_SHIFT;
+module_param(debug, int, 0);
+MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)");
+
+/**
+ * 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)
+{
+ pr_info("%s - version %s\n", ixgb_driver_string, ixgb_driver_version);
+ pr_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 __exit
+ixgb_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 void
+ixgb_irq_disable(struct ixgb_adapter *adapter)
+{
+ 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 void
+ixgb_irq_enable(struct ixgb_adapter *adapter)
+{
+ u32 val = IXGB_INT_RXT0 | IXGB_INT_RXDMT0 |
+ IXGB_INT_TXDW | IXGB_INT_LSC;
+ if (adapter->hw.subsystem_vendor_id == SUN_SUBVENDOR_ID)
+ val |= IXGB_INT_GPI0;
+ IXGB_WRITE_REG(&adapter->hw, IMS, val);
+ IXGB_WRITE_FLUSH(&adapter->hw);
+}
+
+int
+ixgb_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, IXGB_DESC_UNUSED(&adapter->rx_ring));
+
+ /* 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);
+ netif_err(adapter, probe, adapter->netdev,
+ "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) {
+ u32 ctrl0 = IXGB_READ_REG(hw, CTRL0);
+
+ if (!(ctrl0 & IXGB_CTRL0_JFE)) {
+ ctrl0 |= IXGB_CTRL0_JFE;
+ IXGB_WRITE_REG(hw, CTRL0, ctrl0);
+ }
+ }
+ }
+
+ clear_bit(__IXGB_DOWN, &adapter->flags);
+
+ napi_enable(&adapter->napi);
+ ixgb_irq_enable(adapter);
+
+ netif_wake_queue(netdev);
+
+ mod_timer(&adapter->watchdog_timer, jiffies);
+
+ return 0;
+}
+
+void
+ixgb_down(struct ixgb_adapter *adapter, bool kill_watchdog)
+{
+ struct net_device *netdev = adapter->netdev;
+
+ /* prevent the interrupt handler from restarting watchdog */
+ set_bit(__IXGB_DOWN, &adapter->flags);
+
+ napi_disable(&adapter->napi);
+ /* waiting for NAPI to complete can re-enable interrupts */
+ 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);
+}
+
+void
+ixgb_reset(struct ixgb_adapter *adapter)
+{
+ struct ixgb_hw *hw = &adapter->hw;
+
+ ixgb_adapter_stop(hw);
+ if (!ixgb_init_hw(hw))
+ netif_err(adapter, probe, adapter->netdev, "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);
+ }
+ }
+}
+
+static const struct net_device_ops ixgb_netdev_ops = {
+ .ndo_open = ixgb_open,
+ .ndo_stop = ixgb_close,
+ .ndo_start_xmit = ixgb_xmit_frame,
+ .ndo_get_stats = ixgb_get_stats,
+ .ndo_set_multicast_list = ixgb_set_multi,
+ .ndo_validate_addr = eth_validate_addr,
+ .ndo_set_mac_address = ixgb_set_mac,
+ .ndo_change_mtu = ixgb_change_mtu,
+ .ndo_tx_timeout = ixgb_tx_timeout,
+ .ndo_vlan_rx_add_vid = ixgb_vlan_rx_add_vid,
+ .ndo_vlan_rx_kill_vid = ixgb_vlan_rx_kill_vid,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ .ndo_poll_controller = ixgb_netpoll,
+#endif
+};
+
+/**
+ * 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 __devinit
+ixgb_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;
+ int pci_using_dac;
+ int i;
+ int err;
+
+ err = pci_enable_device(pdev);
+ if (err)
+ return err;
+
+ pci_using_dac = 0;
+ err = dma_set_mask(&pdev->dev, DMA_BIT_MASK(64));
+ if (!err) {
+ err = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(64));
+ if (!err)
+ pci_using_dac = 1;
+ } else {
+ err = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32));
+ if (err) {
+ err = dma_set_coherent_mask(&pdev->dev,
+ DMA_BIT_MASK(32));
+ if (err) {
+ pr_err("No usable DMA configuration, aborting\n");
+ goto err_dma_mask;
+ }
+ }
+ }
+
+ err = pci_request_regions(pdev, ixgb_driver_name);
+ if (err)
+ 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);
+
+ adapter->hw.hw_addr = pci_ioremap_bar(pdev, BAR_0);
+ 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->netdev_ops = &ixgb_netdev_ops;
+ ixgb_set_ethtool_ops(netdev);
+ netdev->watchdog_timeo = 5 * HZ;
+ netif_napi_add(netdev, &adapter->napi, ixgb_clean, 64);
+
+ strncpy(netdev->name, pci_name(pdev), sizeof(netdev->name) - 1);
+
+ adapter->bd_number = cards_found;
+ adapter->link_speed = 0;
+ adapter->link_duplex = 0;
+
+ /* setup the private structure */
+
+ err = ixgb_sw_init(adapter);
+ if (err)
+ 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;
+
+ if (pci_using_dac) {
+ netdev->features |= NETIF_F_HIGHDMA;
+ netdev->vlan_features |= NETIF_F_HIGHDMA;
+ }
+
+ /* make sure the EEPROM is good */
+
+ if (!ixgb_validate_eeprom_checksum(&adapter->hw)) {
+ netif_err(adapter, probe, adapter->netdev,
+ "The EEPROM Checksum Is Not Valid\n");
+ err = -EIO;
+ goto err_eeprom;
+ }
+
+ ixgb_get_ee_mac_addr(&adapter->hw, netdev->dev_addr);
+ memcpy(netdev->perm_addr, netdev->dev_addr, netdev->addr_len);
+
+ if (!is_valid_ether_addr(netdev->perm_addr)) {
+ netif_err(adapter, probe, adapter->netdev, "Invalid MAC Address\n");
+ 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, ixgb_tx_timeout_task);
+
+ strcpy(netdev->name, "eth%d");
+ err = register_netdev(netdev);
+ if (err)
+ goto err_register;
+
+ /* carrier off reporting is important to ethtool even BEFORE open */
+ netif_carrier_off(netdev);
+
+ netif_info(adapter, probe, adapter->netdev,
+ "Intel(R) PRO/10GbE Network Connection\n");
+ 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);
+err_request_regions:
+err_dma_mask:
+ pci_disable_device(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(netdev);
+
+ cancel_work_sync(&adapter->tx_timeout_task);
+
+ unregister_netdev(netdev);
+
+ iounmap(adapter->hw.hw_addr);
+ pci_release_regions(pdev);
+
+ free_netdev(netdev);
+ pci_disable_device(pdev);
+}
+
+/**
+ * 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;
+
+ hw->max_frame_size = netdev->mtu + ENET_HEADER_SIZE + ENET_FCS_LENGTH;
+ adapter->rx_buffer_len = hw->max_frame_size + 8; /* + 8 for errata */
+
+ if ((hw->device_id == IXGB_DEVICE_ID_82597EX) ||
+ (hw->device_id == IXGB_DEVICE_ID_82597EX_CX4) ||
+ (hw->device_id == IXGB_DEVICE_ID_82597EX_LR) ||
+ (hw->device_id == IXGB_DEVICE_ID_82597EX_SR))
+ hw->mac_type = ixgb_82597;
+ else {
+ /* should never have loaded on this device */
+ netif_err(adapter, probe, adapter->netdev, "unsupported device id\n");
+ }
+
+ /* enable flow control to be programmed */
+ hw->fc.send_xon = 1;
+
+ set_bit(__IXGB_DOWN, &adapter->flags);
+ 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(netdev);
+ int err;
+
+ /* allocate transmit descriptors */
+ err = ixgb_setup_tx_resources(adapter);
+ if (err)
+ goto err_setup_tx;
+
+ netif_carrier_off(netdev);
+
+ /* allocate receive descriptors */
+
+ err = ixgb_setup_rx_resources(adapter);
+ if (err)
+ goto err_setup_rx;
+
+ err = ixgb_up(adapter);
+ if (err)
+ goto err_up;
+
+ netif_start_queue(netdev);
+
+ return 0;
+
+err_up:
+ ixgb_free_rx_resources(adapter);
+err_setup_rx:
+ ixgb_free_tx_resources(adapter);
+err_setup_tx:
+ ixgb_reset(adapter);
+
+ return err;
+}
+
+/**
+ * ixgb_close - Disables a network interface
+ * @netdev: network interface device structure
+ *
+ * Returns 0, this is not allowed to fail
+ *
+ * The close entry point is called when an interface is de-activated
+ * by the OS. The hardware is still under the drivers control, but
+ * needs to be disabled. A global MAC reset is issued to stop the
+ * hardware, and all transmit and receive resources are freed.
+ **/
+
+static int
+ixgb_close(struct net_device *netdev)
+{
+ struct ixgb_adapter *adapter = netdev_priv(netdev);
+
+ ixgb_down(adapter, true);
+
+ ixgb_free_tx_resources(adapter);
+ ixgb_free_rx_resources(adapter);
+
+ return 0;
+}
+
+/**
+ * ixgb_setup_tx_resources - allocate Tx resources (Descriptors)
+ * @adapter: board private structure
+ *
+ * Return 0 on success, negative on failure
+ **/
+
+int
+ixgb_setup_tx_resources(struct ixgb_adapter *adapter)
+{
+ struct ixgb_desc_ring *txdr = &adapter->tx_ring;
+ struct pci_dev *pdev = adapter->pdev;
+ int size;
+
+ size = sizeof(struct ixgb_buffer) * txdr->count;
+ txdr->buffer_info = vzalloc(size);
+ if (!txdr->buffer_info) {
+ netif_err(adapter, probe, adapter->netdev,
+ "Unable to allocate transmit descriptor ring memory\n");
+ return -ENOMEM;
+ }
+
+ /* round up to nearest 4K */
+
+ txdr->size = txdr->count * sizeof(struct ixgb_tx_desc);
+ txdr->size = ALIGN(txdr->size, 4096);
+
+ txdr->desc = dma_alloc_coherent(&pdev->dev, txdr->size, &txdr->dma,
+ GFP_KERNEL);
+ if (!txdr->desc) {
+ vfree(txdr->buffer_info);
+ netif_err(adapter, probe, adapter->netdev,
+ "Unable to allocate transmit descriptor memory\n");
+ return -ENOMEM;
+ }
+ memset(txdr->desc, 0, txdr->size);
+
+ txdr->next_to_use = 0;
+ txdr->next_to_clean = 0;
+
+ return 0;
+}
+
+/**
+ * ixgb_configure_tx - Configure 82597 Transmit Unit after Reset.
+ * @adapter: board private structure
+ *
+ * Configure the Tx unit of the MAC after a reset.
+ **/
+
+static void
+ixgb_configure_tx(struct ixgb_adapter *adapter)
+{
+ u64 tdba = adapter->tx_ring.dma;
+ u32 tdlen = adapter->tx_ring.count * sizeof(struct ixgb_tx_desc);
+ u32 tctl;
+ struct ixgb_hw *hw = &adapter->hw;
+
+ /* Setup the Base and Length of the Tx Descriptor Ring
+ * tx_ring.dma can be either a 32 or 64 bit value
+ */
+
+ IXGB_WRITE_REG(hw, TDBAL, (tdba & 0x00000000ffffffffULL));
+ IXGB_WRITE_REG(hw, TDBAH, (tdba >> 32));
+
+ IXGB_WRITE_REG(hw, TDLEN, tdlen);
+
+ /* Setup the HW Tx Head and Tail descriptor pointers */
+
+ IXGB_WRITE_REG(hw, TDH, 0);
+ IXGB_WRITE_REG(hw, TDT, 0);
+
+ /* don't set up txdctl, it induces performance problems if configured
+ * incorrectly */
+ /* Set the Tx Interrupt Delay register */
+
+ IXGB_WRITE_REG(hw, TIDV, adapter->tx_int_delay);
+
+ /* Program the Transmit Control Register */
+
+ tctl = IXGB_TCTL_TCE | IXGB_TCTL_TXEN | IXGB_TCTL_TPDE;
+ IXGB_WRITE_REG(hw, TCTL, tctl);
+
+ /* Setup Transmit Descriptor Settings for this adapter */
+ adapter->tx_cmd_type =
+ IXGB_TX_DESC_TYPE |
+ (adapter->tx_int_delay_enable ? IXGB_TX_DESC_CMD_IDE : 0);
+}
+
+/**
+ * ixgb_setup_rx_resources - allocate Rx resources (Descriptors)
+ * @adapter: board private structure
+ *
+ * Returns 0 on success, negative on failure
+ **/
+
+int
+ixgb_setup_rx_resources(struct ixgb_adapter *adapter)
+{
+ struct ixgb_desc_ring *rxdr = &adapter->rx_ring;
+ struct pci_dev *pdev = adapter->pdev;
+ int size;
+
+ size = sizeof(struct ixgb_buffer) * rxdr->count;
+ rxdr->buffer_info = vzalloc(size);
+ if (!rxdr->buffer_info) {
+ netif_err(adapter, probe, adapter->netdev,
+ "Unable to allocate receive descriptor ring\n");
+ return -ENOMEM;
+ }
+
+ /* Round up to nearest 4K */
+
+ rxdr->size = rxdr->count * sizeof(struct ixgb_rx_desc);
+ rxdr->size = ALIGN(rxdr->size, 4096);
+
+ rxdr->desc = dma_alloc_coherent(&pdev->dev, rxdr->size, &rxdr->dma,
+ GFP_KERNEL);
+
+ if (!rxdr->desc) {
+ vfree(rxdr->buffer_info);
+ netif_err(adapter, probe, adapter->netdev,
+ "Unable to allocate receive descriptors\n");
+ return -ENOMEM;
+ }
+ memset(rxdr->desc, 0, rxdr->size);
+
+ rxdr->next_to_clean = 0;
+ rxdr->next_to_use = 0;
+
+ return 0;
+}
+
+/**
+ * ixgb_setup_rctl - configure the receive control register
+ * @adapter: Board private structure
+ **/
+
+static void
+ixgb_setup_rctl(struct ixgb_adapter *adapter)
+{
+ u32 rctl;
+
+ rctl = IXGB_READ_REG(&adapter->hw, RCTL);
+
+ rctl &= ~(3 << IXGB_RCTL_MO_SHIFT);
+
+ rctl |=
+ IXGB_RCTL_BAM | IXGB_RCTL_RDMTS_1_2 |
+ IXGB_RCTL_RXEN | IXGB_RCTL_CFF |
+ (adapter->hw.mc_filter_type << IXGB_RCTL_MO_SHIFT);
+
+ rctl |= IXGB_RCTL_SECRC;
+
+ if (adapter->rx_buffer_len <= IXGB_RXBUFFER_2048)
+ rctl |= IXGB_RCTL_BSIZE_2048;
+ else if (adapter->rx_buffer_len <= IXGB_RXBUFFER_4096)
+ rctl |= IXGB_RCTL_BSIZE_4096;
+ else if (adapter->rx_buffer_len <= IXGB_RXBUFFER_8192)
+ rctl |= IXGB_RCTL_BSIZE_8192;
+ else if (adapter->rx_buffer_len <= IXGB_RXBUFFER_16384)
+ rctl |= IXGB_RCTL_BSIZE_16384;
+
+ IXGB_WRITE_REG(&adapter->hw, RCTL, rctl);
+}
+
+/**
+ * ixgb_configure_rx - Configure 82597 Receive Unit after Reset.
+ * @adapter: board private structure
+ *
+ * Configure the Rx unit of the MAC after a reset.
+ **/
+
+static void
+ixgb_configure_rx(struct ixgb_adapter *adapter)
+{
+ u64 rdba = adapter->rx_ring.dma;
+ u32 rdlen = adapter->rx_ring.count * sizeof(struct ixgb_rx_desc);
+ struct ixgb_hw *hw = &adapter->hw;
+ u32 rctl;
+ u32 rxcsum;
+
+ /* make sure receives are disabled while setting up the descriptors */
+
+ rctl = IXGB_READ_REG(hw, RCTL);
+ IXGB_WRITE_REG(hw, RCTL, rctl & ~IXGB_RCTL_RXEN);
+
+ /* set the Receive Delay Timer Register */
+
+ IXGB_WRITE_REG(hw, RDTR, adapter->rx_int_delay);
+
+ /* Setup the Base and Length of the Rx Descriptor Ring */
+
+ IXGB_WRITE_REG(hw, RDBAL, (rdba & 0x00000000ffffffffULL));
+ IXGB_WRITE_REG(hw, RDBAH, (rdba >> 32));
+
+ IXGB_WRITE_REG(hw, RDLEN, rdlen);
+
+ /* Setup the HW Rx Head and Tail Descriptor Pointers */
+ IXGB_WRITE_REG(hw, RDH, 0);
+ IXGB_WRITE_REG(hw, RDT, 0);
+
+ /* due to the hardware errata with RXDCTL, we are unable to use any of
+ * the performance enhancing features of it without causing other
+ * subtle bugs, some of the bugs could include receive length
+ * corruption at high data rates (WTHRESH > 0) and/or receive
+ * descriptor ring irregularites (particularly in hardware cache) */
+ IXGB_WRITE_REG(hw, RXDCTL, 0);
+
+ /* Enable Receive Checksum Offload for TCP and UDP */
+ if (adapter->rx_csum) {
+ rxcsum = IXGB_READ_REG(hw, RXCSUM);
+ rxcsum |= IXGB_RXCSUM_TUOFL;
+ IXGB_WRITE_REG(hw, RXCSUM, rxcsum);
+ }
+
+ /* Enable Receives */
+
+ IXGB_WRITE_REG(hw, RCTL, rctl);
+}
+
+/**
+ * ixgb_free_tx_resources - Free Tx Resources
+ * @adapter: board private structure
+ *
+ * Free all transmit software resources
+ **/
+
+void
+ixgb_free_tx_resources(struct ixgb_adapter *adapter)
+{
+ struct pci_dev *pdev = adapter->pdev;
+
+ ixgb_clean_tx_ring(adapter);
+
+ vfree(adapter->tx_ring.buffer_info);
+ adapter->tx_ring.buffer_info = NULL;
+
+ dma_free_coherent(&pdev->dev, adapter->tx_ring.size,
+ adapter->tx_ring.desc, adapter->tx_ring.dma);
+
+ adapter->tx_ring.desc = NULL;
+}
+
+static void
+ixgb_unmap_and_free_tx_resource(struct ixgb_adapter *adapter,
+ struct ixgb_buffer *buffer_info)
+{
+ if (buffer_info->dma) {
+ if (buffer_info->mapped_as_page)
+ dma_unmap_page(&adapter->pdev->dev, buffer_info->dma,
+ buffer_info->length, DMA_TO_DEVICE);
+ else
+ dma_unmap_single(&adapter->pdev->dev, buffer_info->dma,
+ buffer_info->length, DMA_TO_DEVICE);
+ buffer_info->dma = 0;
+ }
+
+ if (buffer_info->skb) {
+ dev_kfree_skb_any(buffer_info->skb);
+ buffer_info->skb = NULL;
+ }
+ buffer_info->time_stamp = 0;
+ /* these fields must always be initialized in tx
+ * buffer_info->length = 0;
+ * buffer_info->next_to_watch = 0; */
+}
+
+/**
+ * ixgb_clean_tx_ring - Free Tx Buffers
+ * @adapter: board private structure
+ **/
+
+static void
+ixgb_clean_tx_ring(struct ixgb_adapter *adapter)
+{
+ struct ixgb_desc_ring *tx_ring = &adapter->tx_ring;
+ struct ixgb_buffer *buffer_info;
+ unsigned long size;
+ unsigned int i;
+
+ /* Free all the Tx ring sk_buffs */
+
+ for (i = 0; i < tx_ring->count; i++) {
+ buffer_info = &tx_ring->buffer_info[i];
+ ixgb_unmap_and_free_tx_resource(adapter, buffer_info);
+ }
+
+ size = sizeof(struct ixgb_buffer) * tx_ring->count;
+ memset(tx_ring->buffer_info, 0, size);
+
+ /* Zero out the descriptor ring */
+
+ memset(tx_ring->desc, 0, tx_ring->size);
+
+ tx_ring->next_to_use = 0;
+ tx_ring->next_to_clean = 0;
+
+ IXGB_WRITE_REG(&adapter->hw, TDH, 0);
+ IXGB_WRITE_REG(&adapter->hw, TDT, 0);
+}
+
+/**
+ * ixgb_free_rx_resources - Free Rx Resources
+ * @adapter: board private structure
+ *
+ * Free all receive software resources
+ **/
+
+void
+ixgb_free_rx_resources(struct ixgb_adapter *adapter)
+{
+ struct ixgb_desc_ring *rx_ring = &adapter->rx_ring;
+ struct pci_dev *pdev = adapter->pdev;
+
+ ixgb_clean_rx_ring(adapter);
+
+ vfree(rx_ring->buffer_info);
+ rx_ring->buffer_info = NULL;
+
+ dma_free_coherent(&pdev->dev, rx_ring->size, rx_ring->desc,
+ rx_ring->dma);
+
+ rx_ring->desc = NULL;
+}
+
+/**
+ * ixgb_clean_rx_ring - Free Rx Buffers
+ * @adapter: board private structure
+ **/
+
+static void
+ixgb_clean_rx_ring(struct ixgb_adapter *adapter)
+{
+ struct ixgb_desc_ring *rx_ring = &adapter->rx_ring;
+ struct ixgb_buffer *buffer_info;
+ struct pci_dev *pdev = adapter->pdev;
+ unsigned long size;
+ unsigned int i;
+
+ /* Free all the Rx ring sk_buffs */
+
+ for (i = 0; i < rx_ring->count; i++) {
+ buffer_info = &rx_ring->buffer_info[i];
+ if (buffer_info->dma) {
+ dma_unmap_single(&pdev->dev,
+ buffer_info->dma,
+ buffer_info->length,
+ DMA_FROM_DEVICE);
+ buffer_info->dma = 0;
+ buffer_info->length = 0;
+ }
+
+ if (buffer_info->skb) {
+ dev_kfree_skb(buffer_info->skb);
+ buffer_info->skb = NULL;
+ }
+ }
+
+ size = sizeof(struct ixgb_buffer) * rx_ring->count;
+ memset(rx_ring->buffer_info, 0, size);
+
+ /* Zero out the descriptor ring */
+
+ memset(rx_ring->desc, 0, rx_ring->size);
+
+ rx_ring->next_to_clean = 0;
+ rx_ring->next_to_use = 0;
+
+ IXGB_WRITE_REG(&adapter->hw, RDH, 0);
+ IXGB_WRITE_REG(&adapter->hw, RDT, 0);
+}
+
+/**
+ * ixgb_set_mac - Change the Ethernet Address of the NIC
+ * @netdev: network interface device structure
+ * @p: pointer to an address structure
+ *
+ * Returns 0 on success, negative on failure
+ **/
+
+static int
+ixgb_set_mac(struct net_device *netdev, void *p)
+{
+ struct ixgb_adapter *adapter = netdev_priv(netdev);
+ struct sockaddr *addr = p;
+
+ if (!is_valid_ether_addr(addr->sa_data))
+ return -EADDRNOTAVAIL;
+
+ memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
+
+ ixgb_rar_set(&adapter->hw, addr->sa_data, 0);
+
+ return 0;
+}
+
+/**
+ * ixgb_set_multi - Multicast and Promiscuous mode set
+ * @netdev: network interface device structure
+ *
+ * The set_multi entry point is called whenever the multicast address
+ * list or the network interface flags are updated. This routine is
+ * responsible for configuring the hardware for proper multicast,
+ * promiscuous mode, and all-multi behavior.
+ **/
+
+static void
+ixgb_set_multi(struct net_device *netdev)
+{
+ struct ixgb_adapter *adapter = netdev_priv(netdev);
+ struct ixgb_hw *hw = &adapter->hw;
+ struct netdev_hw_addr *ha;
+ u32 rctl;
+ int i;
+
+ /* Check for Promiscuous and All Multicast modes */
+
+ rctl = IXGB_READ_REG(hw, RCTL);
+
+ if (netdev->flags & IFF_PROMISC) {
+ rctl |= (IXGB_RCTL_UPE | IXGB_RCTL_MPE);
+ /* disable VLAN filtering */
+ rctl &= ~IXGB_RCTL_CFIEN;
+ rctl &= ~IXGB_RCTL_VFE;
+ } else {
+ if (netdev->flags & IFF_ALLMULTI) {
+ rctl |= IXGB_RCTL_MPE;
+ rctl &= ~IXGB_RCTL_UPE;
+ } else {
+ rctl &= ~(IXGB_RCTL_UPE | IXGB_RCTL_MPE);
+ }
+ /* enable VLAN filtering */
+ rctl |= IXGB_RCTL_VFE;
+ rctl &= ~IXGB_RCTL_CFIEN;
+ }
+
+ if (netdev_mc_count(netdev) > IXGB_MAX_NUM_MULTICAST_ADDRESSES) {
+ rctl |= IXGB_RCTL_MPE;
+ IXGB_WRITE_REG(hw, RCTL, rctl);
+ } else {
+ u8 mta[IXGB_MAX_NUM_MULTICAST_ADDRESSES *
+ IXGB_ETH_LENGTH_OF_ADDRESS];
+
+ IXGB_WRITE_REG(hw, RCTL, rctl);
+
+ i = 0;
+ netdev_for_each_mc_addr(ha, netdev)
+ memcpy(&mta[i++ * IXGB_ETH_LENGTH_OF_ADDRESS],
+ ha->addr, IXGB_ETH_LENGTH_OF_ADDRESS);
+
+ ixgb_mc_addr_list_update(hw, mta, netdev_mc_count(netdev), 0);
+ }
+
+ if (netdev->features & NETIF_F_HW_VLAN_RX)
+ ixgb_vlan_strip_enable(adapter);
+ else
+ ixgb_vlan_strip_disable(adapter);
+
+}
+
+/**
+ * ixgb_watchdog - Timer Call-back
+ * @data: pointer to netdev cast into an unsigned long
+ **/
+
+static void
+ixgb_watchdog(unsigned long data)
+{
+ struct ixgb_adapter *adapter = (struct ixgb_adapter *)data;
+ struct net_device *netdev = adapter->netdev;
+ struct ixgb_desc_ring *txdr = &adapter->tx_ring;
+
+ ixgb_check_for_link(&adapter->hw);
+
+ if (ixgb_check_for_bad_link(&adapter->hw)) {
+ /* force the reset path */
+ netif_stop_queue(netdev);
+ }
+
+ if (adapter->hw.link_up) {
+ if (!netif_carrier_ok(netdev)) {
+ netdev_info(netdev,
+ "NIC Link is Up 10 Gbps Full Duplex, Flow Control: %s\n",
+ (adapter->hw.fc.type == ixgb_fc_full) ?
+ "RX/TX" :
+ (adapter->hw.fc.type == ixgb_fc_rx_pause) ?
+ "RX" :
+ (adapter->hw.fc.type == ixgb_fc_tx_pause) ?
+ "TX" : "None");
+ adapter->link_speed = 10000;
+ adapter->link_duplex = FULL_DUPLEX;
+ netif_carrier_on(netdev);
+ }
+ } else {
+ if (netif_carrier_ok(netdev)) {
+ adapter->link_speed = 0;
+ adapter->link_duplex = 0;
+ netdev_info(netdev, "NIC Link is Down\n");
+ netif_carrier_off(netdev);
+ }
+ }
+
+ ixgb_update_stats(adapter);
+