📄 ixgbe_main.c
字号:
napi_disable(&adapter->napi); atomic_set(&adapter->irq_sem, 0); ixgbe_irq_disable(adapter); del_timer_sync(&adapter->watchdog_timer); netif_carrier_off(netdev); netif_stop_queue(netdev); ixgbe_reset(adapter); ixgbe_clean_all_tx_rings(adapter); ixgbe_clean_all_rx_rings(adapter);}static int ixgbe_suspend(struct pci_dev *pdev, pm_message_t state){ struct net_device *netdev = pci_get_drvdata(pdev); struct ixgbe_adapter *adapter = netdev_priv(netdev);#ifdef CONFIG_PM int retval = 0;#endif netif_device_detach(netdev); if (netif_running(netdev)) { ixgbe_down(adapter); ixgbe_free_irq(adapter); }#ifdef CONFIG_PM retval = pci_save_state(pdev); if (retval) return retval;#endif pci_enable_wake(pdev, PCI_D3hot, 0); pci_enable_wake(pdev, PCI_D3cold, 0); pci_disable_device(pdev); pci_set_power_state(pdev, pci_choose_state(pdev, state)); return 0;}static void ixgbe_shutdown(struct pci_dev *pdev){ ixgbe_suspend(pdev, PMSG_SUSPEND);}/** * ixgbe_clean - NAPI Rx polling callback * @adapter: board private structure **/static int ixgbe_clean(struct napi_struct *napi, int budget){ struct ixgbe_adapter *adapter = container_of(napi, struct ixgbe_adapter, napi); struct net_device *netdev = adapter->netdev; int tx_cleaned = 0, work_done = 0; /* In non-MSIX case, there is no multi-Tx/Rx queue */ tx_cleaned = ixgbe_clean_tx_irq(adapter, adapter->tx_ring); ixgbe_clean_rx_irq(adapter, &adapter->rx_ring[0], &work_done, budget); if (tx_cleaned) work_done = budget; /* If budget not fully consumed, exit the polling mode */ if (work_done < budget) { netif_rx_complete(netdev, napi); ixgbe_irq_enable(adapter); } return work_done;}/** * ixgbe_tx_timeout - Respond to a Tx Hang * @netdev: network interface device structure **/static void ixgbe_tx_timeout(struct net_device *netdev){ struct ixgbe_adapter *adapter = netdev_priv(netdev); /* Do the reset outside of interrupt context */ schedule_work(&adapter->reset_task);}static void ixgbe_reset_task(struct work_struct *work){ struct ixgbe_adapter *adapter; adapter = container_of(work, struct ixgbe_adapter, reset_task); adapter->tx_timeout_count++; ixgbe_down(adapter); ixgbe_up(adapter);}/** * ixgbe_alloc_queues - Allocate memory for all rings * @adapter: board private structure to initialize * * We allocate one ring per queue at run-time since we don't know the * number of queues at compile-time. The polling_netdev array is * intended for Multiqueue, but should work fine with a single queue. **/static int __devinit ixgbe_alloc_queues(struct ixgbe_adapter *adapter){ int i; adapter->tx_ring = kcalloc(adapter->num_tx_queues, sizeof(struct ixgbe_ring), GFP_KERNEL); if (!adapter->tx_ring) return -ENOMEM; for (i = 0; i < adapter->num_tx_queues; i++) adapter->tx_ring[i].count = IXGBE_DEFAULT_TXD; adapter->rx_ring = kcalloc(adapter->num_rx_queues, sizeof(struct ixgbe_ring), GFP_KERNEL); if (!adapter->rx_ring) { kfree(adapter->tx_ring); return -ENOMEM; } for (i = 0; i < adapter->num_rx_queues; i++) { adapter->rx_ring[i].adapter = adapter; adapter->rx_ring[i].itr_register = IXGBE_EITR(i); adapter->rx_ring[i].count = IXGBE_DEFAULT_RXD; } return 0;}/** * ixgbe_sw_init - Initialize general software structures (struct ixgbe_adapter) * @adapter: board private structure to initialize * * ixgbe_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 ixgbe_sw_init(struct ixgbe_adapter *adapter){ struct ixgbe_hw *hw = &adapter->hw; struct pci_dev *pdev = adapter->pdev; /* default flow control settings */ hw->fc.original_type = ixgbe_fc_full; hw->fc.type = ixgbe_fc_full; hw->mac.link_mode_select = IXGBE_AUTOC_LMS_10G_LINK_NO_AN; if (hw->mac.ops.reset(hw)) { dev_err(&pdev->dev, "HW Init failed\n"); return -EIO; } if (hw->phy.ops.setup_speed(hw, IXGBE_LINK_SPEED_10GB_FULL, true, false)) { dev_err(&pdev->dev, "Link Speed setup failed\n"); return -EIO; } /* initialize eeprom parameters */ if (ixgbe_init_eeprom(hw)) { dev_err(&pdev->dev, "EEPROM initialization failed\n"); return -EIO; } /* Set the default values */ adapter->num_rx_queues = IXGBE_DEFAULT_RXQ; adapter->num_tx_queues = 1; adapter->flags |= IXGBE_FLAG_RX_CSUM_ENABLED; if (ixgbe_alloc_queues(adapter)) { dev_err(&pdev->dev, "Unable to allocate memory for queues\n"); return -ENOMEM; } atomic_set(&adapter->irq_sem, 1); set_bit(__IXGBE_DOWN, &adapter->state); return 0;}/** * ixgbe_setup_tx_resources - allocate Tx resources (Descriptors) * @adapter: board private structure * @txdr: tx descriptor ring (for a specific queue) to setup * * Return 0 on success, negative on failure **/int ixgbe_setup_tx_resources(struct ixgbe_adapter *adapter, struct ixgbe_ring *txdr){ struct pci_dev *pdev = adapter->pdev; int size; size = sizeof(struct ixgbe_tx_buffer) * txdr->count; txdr->tx_buffer_info = vmalloc(size); if (!txdr->tx_buffer_info) { DPRINTK(PROBE, ERR, "Unable to allocate memory for the transmit descriptor ring\n"); return -ENOMEM; } memset(txdr->tx_buffer_info, 0, size); /* round up to nearest 4K */ txdr->size = txdr->count * sizeof(union ixgbe_adv_tx_desc); txdr->size = ALIGN(txdr->size, 4096); txdr->desc = pci_alloc_consistent(pdev, txdr->size, &txdr->dma); if (!txdr->desc) { vfree(txdr->tx_buffer_info); DPRINTK(PROBE, ERR, "Memory allocation failed for the tx desc ring\n"); return -ENOMEM; } txdr->adapter = adapter; txdr->next_to_use = 0; txdr->next_to_clean = 0; txdr->work_limit = txdr->count; spin_lock_init(&txdr->tx_lock); return 0;}/** * ixgbe_setup_rx_resources - allocate Rx resources (Descriptors) * @adapter: board private structure * @rxdr: rx descriptor ring (for a specific queue) to setup * * Returns 0 on success, negative on failure **/int ixgbe_setup_rx_resources(struct ixgbe_adapter *adapter, struct ixgbe_ring *rxdr){ struct pci_dev *pdev = adapter->pdev; int size, desc_len; size = sizeof(struct ixgbe_rx_buffer) * rxdr->count; rxdr->rx_buffer_info = vmalloc(size); if (!rxdr->rx_buffer_info) { DPRINTK(PROBE, ERR, "vmalloc allocation failed for the rx desc ring\n"); return -ENOMEM; } memset(rxdr->rx_buffer_info, 0, size); desc_len = sizeof(union ixgbe_adv_rx_desc); /* Round up to nearest 4K */ rxdr->size = rxdr->count * desc_len; rxdr->size = ALIGN(rxdr->size, 4096); rxdr->desc = pci_alloc_consistent(pdev, rxdr->size, &rxdr->dma); if (!rxdr->desc) { DPRINTK(PROBE, ERR, "Memory allocation failed for the rx desc ring\n"); vfree(rxdr->rx_buffer_info); return -ENOMEM; } rxdr->next_to_clean = 0; rxdr->next_to_use = 0; rxdr->adapter = adapter; return 0;}/** * ixgbe_free_tx_resources - Free Tx Resources per Queue * @adapter: board private structure * @tx_ring: Tx descriptor ring for a specific queue * * Free all transmit software resources **/static void ixgbe_free_tx_resources(struct ixgbe_adapter *adapter, struct ixgbe_ring *tx_ring){ struct pci_dev *pdev = adapter->pdev; ixgbe_clean_tx_ring(adapter, tx_ring); vfree(tx_ring->tx_buffer_info); tx_ring->tx_buffer_info = NULL; pci_free_consistent(pdev, tx_ring->size, tx_ring->desc, tx_ring->dma); tx_ring->desc = NULL;}/** * ixgbe_free_all_tx_resources - Free Tx Resources for All Queues * @adapter: board private structure * * Free all transmit software resources **/static void ixgbe_free_all_tx_resources(struct ixgbe_adapter *adapter){ int i; for (i = 0; i < adapter->num_tx_queues; i++) ixgbe_free_tx_resources(adapter, &adapter->tx_ring[i]);}/** * ixgbe_free_rx_resources - Free Rx Resources * @adapter: board private structure * @rx_ring: ring to clean the resources from * * Free all receive software resources **/static void ixgbe_free_rx_resources(struct ixgbe_adapter *adapter, struct ixgbe_ring *rx_ring){ struct pci_dev *pdev = adapter->pdev; ixgbe_clean_rx_ring(adapter, rx_ring); vfree(rx_ring->rx_buffer_info); rx_ring->rx_buffer_info = NULL; pci_free_consistent(pdev, rx_ring->size, rx_ring->desc, rx_ring->dma); rx_ring->desc = NULL;}/** * ixgbe_free_all_rx_resources - Free Rx Resources for All Queues * @adapter: board private structure * * Free all receive software resources **/static void ixgbe_free_all_rx_resources(struct ixgbe_adapter *adapter){ int i; for (i = 0; i < adapter->num_rx_queues; i++) ixgbe_free_rx_resources(adapter, &adapter->rx_ring[i]);}/** * ixgbe_setup_all_tx_resources - wrapper to allocate Tx resources * (Descriptors) for all queues * @adapter: board private structure * * If this function returns with an error, then it's possible one or * more of the rings is populated (while the rest are not). It is the * callers duty to clean those orphaned rings. * * Return 0 on success, negative on failure **/static int ixgbe_setup_all_tx_resources(struct ixgbe_adapter *adapter){ int i, err = 0; for (i = 0; i < adapter->num_tx_queues; i++) { err = ixgbe_setup_tx_resources(adapter, &adapter->tx_ring[i]); if (err) { DPRINTK(PROBE, ERR, "Allocation for Tx Queue %u failed\n", i); break; } } return err;}/** * ixgbe_setup_all_rx_resources - wrapper to allocate Rx resources * (Descriptors) for all queues * @adapter: board private structure * * If this function returns with an error, then it's possible one or * more of the rings is populated (while the rest are not). It is the * callers duty to clean those orphaned rings. * * Return 0 on success, negative on failure **/static int ixgbe_setup_all_rx_resources(struct ixgbe_adapter *adapter){ int i, err = 0; for (i = 0; i < adapter->num_rx_queues; i++) { err = ixgbe_setup_rx_resources(adapter, &adapter->rx_ring[i]); if (err) { DPRINTK(PROBE, ERR, "Allocation for Rx Queue %u failed\n", i); break; } } return err;}/** * ixgbe_change_mtu - Change the Maximum Transfer Unit * @netdev: network interface device structure * @new_mtu: new value for maximum frame size * * Returns 0 on success, negative on failure **/static int ixgbe_change_mtu(struct net_device *netdev, int new_mtu){ struct ixgbe_adapter *adapter = netdev_priv(netdev); int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN; if ((max_frame < (ETH_ZLEN + ETH_FCS_LEN)) || (max_frame > IXGBE_MAX_JUMBO_FRAME_SIZE)) return -EINVAL; netdev->mtu = new_mtu; if (netif_running(netdev)) { ixgbe_down(adapter); ixgbe_up(adapter); } return 0;}/** * ixgbe_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 ixgbe_open(struct net_device *netdev){ struct ixgbe_adapter *adapter = netdev_priv(netdev); int err; u32 ctrl_ext; u32 num_rx_queues = adapter->num_rx_queues; /* Let firmware know the driver has taken over */ ctrl_ext = IXGBE_READ_REG(&adapter->hw, IXGBE_CTRL_EXT); IXGBE_WRITE_REG(&adapter->hw, IXGBE_CTRL_EXT, ctrl_ext | IXGBE_CTRL_EXT_DRV_LOAD);try_intr_reinit: /* allocate transmit descriptors */ err = ixgbe_setup_all_tx_resources(adapter); if (err) goto err_setup_tx; if (!(adapter->flags & IXGBE_FLAG_MSIX_ENABLED)) { num_rx_queues = 1; adapter->num_rx_queues = num_rx_queues; } /* allocate receive descriptors */ err = ixgbe_setup_all_rx_resources(adapter); if (err) goto err_setup_rx;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -