diff options
Diffstat (limited to 'drivers/net/ethernet/intel/igc/igc_main.c')
-rw-r--r-- | drivers/net/ethernet/intel/igc/igc_main.c | 166 |
1 files changed, 114 insertions, 52 deletions
diff --git a/drivers/net/ethernet/intel/igc/igc_main.c b/drivers/net/ethernet/intel/igc/igc_main.c index 9d85707e8a81..87a11879bf2d 100644 --- a/drivers/net/ethernet/intel/igc/igc_main.c +++ b/drivers/net/ethernet/intel/igc/igc_main.c @@ -12,6 +12,8 @@ #define DRV_VERSION "0.0.1-k" #define DRV_SUMMARY "Intel(R) 2.5G Ethernet Linux Driver" +#define DEFAULT_MSG_ENABLE (NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_LINK) + static int debug = -1; MODULE_AUTHOR("Intel Corporation, <linux.nics@intel.com>"); @@ -66,7 +68,7 @@ enum latency_range { latency_invalid = 255 }; -static void igc_reset(struct igc_adapter *adapter) +void igc_reset(struct igc_adapter *adapter) { struct pci_dev *pdev = adapter->pdev; struct igc_hw *hw = &adapter->hw; @@ -150,7 +152,7 @@ static void igc_get_hw_control(struct igc_adapter *adapter) * * Free all transmit software resources */ -static void igc_free_tx_resources(struct igc_ring *tx_ring) +void igc_free_tx_resources(struct igc_ring *tx_ring) { igc_clean_tx_ring(tx_ring); @@ -261,7 +263,7 @@ static void igc_clean_all_tx_rings(struct igc_adapter *adapter) * * Return 0 on success, negative on failure */ -static int igc_setup_tx_resources(struct igc_ring *tx_ring) +int igc_setup_tx_resources(struct igc_ring *tx_ring) { struct device *dev = tx_ring->dev; int size = 0; @@ -381,7 +383,7 @@ static void igc_clean_all_rx_rings(struct igc_adapter *adapter) * * Free all receive software resources */ -static void igc_free_rx_resources(struct igc_ring *rx_ring) +void igc_free_rx_resources(struct igc_ring *rx_ring) { igc_clean_rx_ring(rx_ring); @@ -418,7 +420,7 @@ static void igc_free_all_rx_resources(struct igc_adapter *adapter) * * Returns 0 on success, negative on failure */ -static int igc_setup_rx_resources(struct igc_ring *rx_ring) +int igc_setup_rx_resources(struct igc_ring *rx_ring) { struct device *dev = rx_ring->dev; int size, desc_len; @@ -865,6 +867,8 @@ static int igc_tx_map(struct igc_ring *tx_ring, /* set the timestamp */ first->time_stamp = jiffies; + skb_tx_timestamp(skb); + /* Force memory writes to complete before letting h/w know there * are new descriptors to fetch. (Only applicable for weak-ordered * memory model archs, such as IA-64). @@ -959,8 +963,6 @@ static netdev_tx_t igc_xmit_frame_ring(struct sk_buff *skb, first->bytecount = skb->len; first->gso_segs = 1; - skb_tx_timestamp(skb); - /* record initial flags and protocol */ first->tx_flags = tx_flags; first->protocol = protocol; @@ -1108,7 +1110,7 @@ static struct sk_buff *igc_build_skb(struct igc_ring *rx_ring, /* update pointers within the skb to store the data */ skb_reserve(skb, IGC_SKB_PAD); - __skb_put(skb, size); + __skb_put(skb, size); /* update buffer offset */ #if (PAGE_SIZE < 8192) @@ -1160,9 +1162,9 @@ static struct sk_buff *igc_construct_skb(struct igc_ring *rx_ring, (va + headlen) - page_address(rx_buffer->page), size, truesize); #if (PAGE_SIZE < 8192) - rx_buffer->page_offset ^= truesize; + rx_buffer->page_offset ^= truesize; #else - rx_buffer->page_offset += truesize; + rx_buffer->page_offset += truesize; #endif } else { rx_buffer->pagecnt_bias++; @@ -1668,8 +1670,8 @@ static bool igc_clean_tx_irq(struct igc_q_vector *q_vector, int napi_budget) tx_buffer->next_to_watch, jiffies, tx_buffer->next_to_watch->wb.status); - netif_stop_subqueue(tx_ring->netdev, - tx_ring->queue_index); + netif_stop_subqueue(tx_ring->netdev, + tx_ring->queue_index); /* we are about to reset, no point in enabling stuff */ return true; @@ -1700,24 +1702,10 @@ static bool igc_clean_tx_irq(struct igc_q_vector *q_vector, int napi_budget) } /** - * igc_ioctl - I/O control method - * @netdev: network interface device structure - * @ifreq: frequency - * @cmd: command - */ -static int igc_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) -{ - switch (cmd) { - default: - return -EOPNOTSUPP; - } -} - -/** * igc_up - Open the interface and prepare it to handle traffic * @adapter: board private structure */ -static void igc_up(struct igc_adapter *adapter) +void igc_up(struct igc_adapter *adapter) { struct igc_hw *hw = &adapter->hw; int i = 0; @@ -1762,7 +1750,7 @@ static void igc_nfc_filter_exit(struct igc_adapter *adapter) * igc_down - Close the interface * @adapter: board private structure */ -static void igc_down(struct igc_adapter *adapter) +void igc_down(struct igc_adapter *adapter) { struct net_device *netdev = adapter->netdev; struct igc_hw *hw = &adapter->hw; @@ -1824,7 +1812,7 @@ static void igc_down(struct igc_adapter *adapter) igc_clean_all_rx_rings(adapter); } -static void igc_reinit_locked(struct igc_adapter *adapter) +void igc_reinit_locked(struct igc_adapter *adapter) { WARN_ON(in_interrupt()); while (test_and_set_bit(__IGC_RESETTING, &adapter->state)) @@ -1936,7 +1924,7 @@ static void igc_configure(struct igc_adapter *adapter) /** * igc_rar_set_index - Sync RAL[index] and RAH[index] registers with MAC table - * @adapter: Pointer to adapter structure + * @adapter: address of board private structure * @index: Index of the RAR entry which need to be synced with MAC table */ static void igc_rar_set_index(struct igc_adapter *adapter, u32 index) @@ -2312,7 +2300,7 @@ static void igc_update_phy_info(struct timer_list *t) * igc_has_link - check shared code for link and determine up/down * @adapter: pointer to driver private info */ -static bool igc_has_link(struct igc_adapter *adapter) +bool igc_has_link(struct igc_adapter *adapter) { struct igc_hw *hw = &adapter->hw; bool link_active = false; @@ -2866,11 +2854,13 @@ static int igc_poll(struct napi_struct *napi, int budget) if (!clean_complete) return budget; - /* If not enough Rx work done, exit the polling mode */ - napi_complete_done(napi, work_done); - igc_ring_irq_enable(q_vector); + /* Exit the polling mode, but don't re-enable interrupts if stack might + * poll us due to busy-polling + */ + if (likely(napi_complete_done(napi, work_done))) + igc_ring_irq_enable(q_vector); - return 0; + return min(work_done, budget - 1); } /** @@ -2968,22 +2958,21 @@ static int igc_alloc_q_vector(struct igc_adapter *adapter, { struct igc_q_vector *q_vector; struct igc_ring *ring; - int ring_count, size; + int ring_count; /* igc only supports 1 Tx and/or 1 Rx queue per vector */ if (txr_count > 1 || rxr_count > 1) return -ENOMEM; ring_count = txr_count + rxr_count; - size = sizeof(struct igc_q_vector) + - (sizeof(struct igc_ring) * ring_count); /* allocate q_vector and rings */ q_vector = adapter->q_vector[v_idx]; if (!q_vector) - q_vector = kzalloc(size, GFP_KERNEL); + q_vector = kzalloc(struct_size(q_vector, ring, ring_count), + GFP_KERNEL); else - memset(q_vector, 0, size); + memset(q_vector, 0, struct_size(q_vector, ring, ring_count)); if (!q_vector) return -ENOMEM; @@ -3358,7 +3347,7 @@ static int __igc_open(struct net_device *netdev, bool resuming) goto err_req_irq; /* Notify the stack of the actual queue counts. */ - netif_set_real_num_tx_queues(netdev, adapter->num_tx_queues); + err = netif_set_real_num_tx_queues(netdev, adapter->num_tx_queues); if (err) goto err_set_queues; @@ -3445,7 +3434,6 @@ static const struct net_device_ops igc_netdev_ops = { .ndo_set_mac_address = igc_set_mac, .ndo_change_mtu = igc_change_mtu, .ndo_get_stats = igc_get_stats, - .ndo_do_ioctl = igc_ioctl, }; /* PCIe configuration access */ @@ -3514,6 +3502,57 @@ u32 igc_rd32(struct igc_hw *hw, u32 reg) return value; } +int igc_set_spd_dplx(struct igc_adapter *adapter, u32 spd, u8 dplx) +{ + struct pci_dev *pdev = adapter->pdev; + struct igc_mac_info *mac = &adapter->hw.mac; + + mac->autoneg = 0; + + /* Make sure dplx is at most 1 bit and lsb of speed is not set + * for the switch() below to work + */ + if ((spd & 1) || (dplx & ~1)) + goto err_inval; + + switch (spd + dplx) { + case SPEED_10 + DUPLEX_HALF: + mac->forced_speed_duplex = ADVERTISE_10_HALF; + break; + case SPEED_10 + DUPLEX_FULL: + mac->forced_speed_duplex = ADVERTISE_10_FULL; + break; + case SPEED_100 + DUPLEX_HALF: + mac->forced_speed_duplex = ADVERTISE_100_HALF; + break; + case SPEED_100 + DUPLEX_FULL: + mac->forced_speed_duplex = ADVERTISE_100_FULL; + break; + case SPEED_1000 + DUPLEX_FULL: + mac->autoneg = 1; + adapter->hw.phy.autoneg_advertised = ADVERTISE_1000_FULL; + break; + case SPEED_1000 + DUPLEX_HALF: /* not supported */ + goto err_inval; + case SPEED_2500 + DUPLEX_FULL: + mac->autoneg = 1; + adapter->hw.phy.autoneg_advertised = ADVERTISE_2500_FULL; + break; + case SPEED_2500 + DUPLEX_HALF: /* not supported */ + default: + goto err_inval; + } + + /* clear MDI, MDI(-X) override is only allowed when autoneg enabled */ + adapter->hw.phy.mdix = AUTO_ALL_MODES; + + return 0; + +err_inval: + dev_err(&pdev->dev, "Unsupported Speed/Duplex configuration\n"); + return -EINVAL; +} + /** * igc_probe - Device Initialization Routine * @pdev: PCI device information struct @@ -3532,26 +3571,23 @@ static int igc_probe(struct pci_dev *pdev, struct net_device *netdev; struct igc_hw *hw; const struct igc_info *ei = igc_info_tbl[ent->driver_data]; - int err, pci_using_dac; + int err; err = pci_enable_device_mem(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) { - IGC_ERR("Wrong DMA configuration, aborting\n"); + dev_err(&pdev->dev, "igc: Wrong DMA config\n"); goto err_dma; } } @@ -3584,7 +3620,7 @@ static int igc_probe(struct pci_dev *pdev, hw = &adapter->hw; hw->back = adapter; adapter->port_num = hw->bus.func; - adapter->msg_enable = GENMASK(debug - 1, 0); + adapter->msg_enable = netif_msg_init(debug, DEFAULT_MSG_ENABLE); err = pci_save_state(pdev); if (err) @@ -3600,7 +3636,7 @@ static int igc_probe(struct pci_dev *pdev, hw->hw_addr = adapter->io_addr; netdev->netdev_ops = &igc_netdev_ops; - + igc_set_ethtool_ops(netdev); netdev->watchdog_timeo = 5 * HZ; netdev->mem_start = pci_resource_start(pdev, 0); @@ -3760,8 +3796,8 @@ static struct pci_driver igc_driver = { .remove = igc_remove, }; -static void igc_set_flag_queue_pairs(struct igc_adapter *adapter, - const u32 max_rss_queues) +void igc_set_flag_queue_pairs(struct igc_adapter *adapter, + const u32 max_rss_queues) { /* Determine if we need to pair queues. */ /* If rss_queues > half of max_rss_queues, pair the queues in @@ -3773,7 +3809,7 @@ static void igc_set_flag_queue_pairs(struct igc_adapter *adapter, adapter->flags &= ~IGC_FLAG_QUEUE_PAIRS; } -static unsigned int igc_get_max_rss_queues(struct igc_adapter *adapter) +unsigned int igc_get_max_rss_queues(struct igc_adapter *adapter) { unsigned int max_rss_queues; @@ -3853,6 +3889,32 @@ static int igc_sw_init(struct igc_adapter *adapter) } /** + * igc_reinit_queues - return error + * @adapter: pointer to adapter structure + */ +int igc_reinit_queues(struct igc_adapter *adapter) +{ + struct net_device *netdev = adapter->netdev; + struct pci_dev *pdev = adapter->pdev; + int err = 0; + + if (netif_running(netdev)) + igc_close(netdev); + + igc_reset_interrupt_capability(adapter); + + if (igc_init_interrupt_scheme(adapter, true)) { + dev_err(&pdev->dev, "Unable to allocate memory for queues\n"); + return -ENOMEM; + } + + if (netif_running(netdev)) + err = igc_open(netdev); + + return err; +} + +/** * igc_get_hw_dev - return device * @hw: pointer to hardware structure * |