1
0
Fork 0

igc: Add ethtool support

This patch adds basic ethtool support to the device to allow
for configuration.

Signed-off-by: Sasha Neftin <sasha.neftin@intel.com>
Tested-by: Aaron Brown <aaron.f.brown@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
hifive-unleashed-5.1
Sasha Neftin 2019-01-30 19:13:14 +02:00 committed by Jeff Kirsher
parent a865d22d59
commit 8c5ad0dae9
8 changed files with 1169 additions and 18 deletions

View File

@ -7,4 +7,5 @@
obj-$(CONFIG_IGC) += igc.o obj-$(CONFIG_IGC) += igc.o
igc-objs := igc_main.o igc_mac.o igc_i225.o igc_base.o igc_nvm.o igc_phy.o igc-objs := igc_main.o igc_mac.o igc_i225.o igc_base.o igc_nvm.o igc_phy.o \
igc_ethtool.o

View File

@ -13,19 +13,43 @@
#include "igc_hw.h" #include "igc_hw.h"
/* main */ /* forward declaration */
void igc_set_ethtool_ops(struct net_device *);
struct igc_adapter;
struct igc_ring;
void igc_up(struct igc_adapter *adapter);
void igc_down(struct igc_adapter *adapter);
int igc_setup_tx_resources(struct igc_ring *ring);
int igc_setup_rx_resources(struct igc_ring *ring);
void igc_free_tx_resources(struct igc_ring *ring);
void igc_free_rx_resources(struct igc_ring *ring);
unsigned int igc_get_max_rss_queues(struct igc_adapter *adapter);
void igc_set_flag_queue_pairs(struct igc_adapter *adapter,
const u32 max_rss_queues);
int igc_reinit_queues(struct igc_adapter *adapter);
bool igc_has_link(struct igc_adapter *adapter);
void igc_reset(struct igc_adapter *adapter);
int igc_set_spd_dplx(struct igc_adapter *adapter, u32 spd, u8 dplx);
extern char igc_driver_name[]; extern char igc_driver_name[];
extern char igc_driver_version[]; extern char igc_driver_version[];
#define IGC_REGS_LEN 740
#define IGC_RETA_SIZE 128
/* Interrupt defines */ /* Interrupt defines */
#define IGC_START_ITR 648 /* ~6000 ints/sec */ #define IGC_START_ITR 648 /* ~6000 ints/sec */
#define IGC_FLAG_HAS_MSI BIT(0) #define IGC_FLAG_HAS_MSI BIT(0)
#define IGC_FLAG_QUEUE_PAIRS BIT(4) #define IGC_FLAG_QUEUE_PAIRS BIT(3)
#define IGC_FLAG_DMAC BIT(4)
#define IGC_FLAG_NEED_LINK_UPDATE BIT(9) #define IGC_FLAG_NEED_LINK_UPDATE BIT(9)
#define IGC_FLAG_MEDIA_RESET BIT(10) #define IGC_FLAG_MEDIA_RESET BIT(10)
#define IGC_FLAG_MAS_ENABLE BIT(12) #define IGC_FLAG_MAS_ENABLE BIT(12)
#define IGC_FLAG_HAS_MSIX BIT(13) #define IGC_FLAG_HAS_MSIX BIT(13)
#define IGC_FLAG_VLAN_PROMISC BIT(15) #define IGC_FLAG_VLAN_PROMISC BIT(15)
#define IGC_FLAG_RX_LEGACY BIT(16)
#define IGC_START_ITR 648 /* ~6000 ints/sec */ #define IGC_START_ITR 648 /* ~6000 ints/sec */
#define IGC_4K_ITR 980 #define IGC_4K_ITR 980
@ -60,6 +84,7 @@ extern char igc_driver_version[];
#define IGC_RXBUFFER_2048 2048 #define IGC_RXBUFFER_2048 2048
#define IGC_RXBUFFER_3072 3072 #define IGC_RXBUFFER_3072 3072
#define AUTO_ALL_MODES 0
#define IGC_RX_HDR_LEN IGC_RXBUFFER_256 #define IGC_RX_HDR_LEN IGC_RXBUFFER_256
/* RX and TX descriptor control thresholds. /* RX and TX descriptor control thresholds.
@ -340,6 +365,8 @@ struct igc_adapter {
struct igc_mac_addr *mac_table; struct igc_mac_addr *mac_table;
u8 rss_indir_tbl[IGC_RETA_SIZE];
unsigned long link_check_timeout; unsigned long link_check_timeout;
struct igc_info ei; struct igc_info ei;
}; };
@ -418,6 +445,9 @@ static inline s32 igc_read_phy_reg(struct igc_hw *hw, u32 offset, u16 *data)
return 0; return 0;
} }
/* forward declaration */
void igc_reinit_locked(struct igc_adapter *);
#define igc_rx_pg_size(_ring) (PAGE_SIZE << igc_rx_pg_order(_ring)) #define igc_rx_pg_size(_ring) (PAGE_SIZE << igc_rx_pg_order(_ring))
#define IGC_TXD_DCMD (IGC_ADVTXD_DCMD_EOP | IGC_ADVTXD_DCMD_RS) #define IGC_TXD_DCMD (IGC_ADVTXD_DCMD_EOP | IGC_ADVTXD_DCMD_RS)

View File

@ -131,6 +131,7 @@ static s32 igc_init_nvm_params_base(struct igc_hw *hw)
if (size > 15) if (size > 15)
size = 15; size = 15;
nvm->type = igc_nvm_eeprom_spi;
nvm->word_size = BIT(size); nvm->word_size = BIT(size);
nvm->opcode_bits = 8; nvm->opcode_bits = 8;
nvm->delay_usec = 1; nvm->delay_usec = 1;

View File

@ -4,6 +4,10 @@
#ifndef _IGC_DEFINES_H_ #ifndef _IGC_DEFINES_H_
#define _IGC_DEFINES_H_ #define _IGC_DEFINES_H_
/* Number of Transmit and Receive Descriptors must be a multiple of 8 */
#define REQ_TX_DESCRIPTOR_MULTIPLE 8
#define REQ_RX_DESCRIPTOR_MULTIPLE 8
#define IGC_CTRL_EXT_DRV_LOAD 0x10000000 /* Drv loaded bit for FW */ #define IGC_CTRL_EXT_DRV_LOAD 0x10000000 /* Drv loaded bit for FW */
/* PCI Bus Info */ /* PCI Bus Info */

File diff suppressed because it is too large Load Diff

View File

@ -55,6 +55,7 @@ enum igc_media_type {
enum igc_nvm_type { enum igc_nvm_type {
igc_nvm_unknown = 0, igc_nvm_unknown = 0,
igc_nvm_eeprom_spi,
igc_nvm_flash_hw, igc_nvm_flash_hw,
igc_nvm_invm, igc_nvm_invm,
}; };

View File

@ -12,6 +12,8 @@
#define DRV_VERSION "0.0.1-k" #define DRV_VERSION "0.0.1-k"
#define DRV_SUMMARY "Intel(R) 2.5G Ethernet Linux Driver" #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; static int debug = -1;
MODULE_AUTHOR("Intel Corporation, <linux.nics@intel.com>"); MODULE_AUTHOR("Intel Corporation, <linux.nics@intel.com>");
@ -66,7 +68,7 @@ enum latency_range {
latency_invalid = 255 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 pci_dev *pdev = adapter->pdev;
struct igc_hw *hw = &adapter->hw; 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 * 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); 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 * 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; struct device *dev = tx_ring->dev;
int size = 0; int size = 0;
@ -381,7 +383,7 @@ static void igc_clean_all_rx_rings(struct igc_adapter *adapter)
* *
* Free all receive software resources * 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); 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 * 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; struct device *dev = rx_ring->dev;
int size, desc_len; int size, desc_len;
@ -1703,7 +1705,7 @@ static bool igc_clean_tx_irq(struct igc_q_vector *q_vector, int napi_budget)
* igc_up - Open the interface and prepare it to handle traffic * igc_up - Open the interface and prepare it to handle traffic
* @adapter: board private structure * @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; struct igc_hw *hw = &adapter->hw;
int i = 0; int i = 0;
@ -1748,7 +1750,7 @@ static void igc_nfc_filter_exit(struct igc_adapter *adapter)
* igc_down - Close the interface * igc_down - Close the interface
* @adapter: board private structure * @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 net_device *netdev = adapter->netdev;
struct igc_hw *hw = &adapter->hw; struct igc_hw *hw = &adapter->hw;
@ -1810,7 +1812,7 @@ static void igc_down(struct igc_adapter *adapter)
igc_clean_all_rx_rings(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()); WARN_ON(in_interrupt());
while (test_and_set_bit(__IGC_RESETTING, &adapter->state)) while (test_and_set_bit(__IGC_RESETTING, &adapter->state))
@ -1922,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 * 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 * @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) static void igc_rar_set_index(struct igc_adapter *adapter, u32 index)
@ -2298,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 * igc_has_link - check shared code for link and determine up/down
* @adapter: pointer to driver private info * @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; struct igc_hw *hw = &adapter->hw;
bool link_active = false; bool link_active = false;
@ -3501,6 +3503,57 @@ u32 igc_rd32(struct igc_hw *hw, u32 reg)
return value; 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 * igc_probe - Device Initialization Routine
* @pdev: PCI device information struct * @pdev: PCI device information struct
@ -3568,7 +3621,7 @@ static int igc_probe(struct pci_dev *pdev,
hw = &adapter->hw; hw = &adapter->hw;
hw->back = adapter; hw->back = adapter;
adapter->port_num = hw->bus.func; 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); err = pci_save_state(pdev);
if (err) if (err)
@ -3584,7 +3637,7 @@ static int igc_probe(struct pci_dev *pdev,
hw->hw_addr = adapter->io_addr; hw->hw_addr = adapter->io_addr;
netdev->netdev_ops = &igc_netdev_ops; netdev->netdev_ops = &igc_netdev_ops;
igc_set_ethtool_ops(netdev);
netdev->watchdog_timeo = 5 * HZ; netdev->watchdog_timeo = 5 * HZ;
netdev->mem_start = pci_resource_start(pdev, 0); netdev->mem_start = pci_resource_start(pdev, 0);
@ -3744,8 +3797,8 @@ static struct pci_driver igc_driver = {
.remove = igc_remove, .remove = igc_remove,
}; };
static void igc_set_flag_queue_pairs(struct igc_adapter *adapter, void igc_set_flag_queue_pairs(struct igc_adapter *adapter,
const u32 max_rss_queues) const u32 max_rss_queues)
{ {
/* Determine if we need to pair queues. */ /* Determine if we need to pair queues. */
/* If rss_queues > half of max_rss_queues, pair the queues in /* If rss_queues > half of max_rss_queues, pair the queues in
@ -3757,7 +3810,7 @@ static void igc_set_flag_queue_pairs(struct igc_adapter *adapter,
adapter->flags &= ~IGC_FLAG_QUEUE_PAIRS; 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; unsigned int max_rss_queues;
@ -3836,6 +3889,32 @@ static int igc_sw_init(struct igc_adapter *adapter)
return 0; return 0;
} }
/**
* 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 * igc_get_hw_dev - return device
* @hw: pointer to hardware structure * @hw: pointer to hardware structure

View File

@ -80,6 +80,9 @@
/* MSI-X Table Register Descriptions */ /* MSI-X Table Register Descriptions */
#define IGC_PBACL 0x05B68 /* MSIx PBA Clear - R/W 1 to clear */ #define IGC_PBACL 0x05B68 /* MSIx PBA Clear - R/W 1 to clear */
/* Redirection Table - RW Array */
#define IGC_RETA(_i) (0x05C00 + ((_i) * 4))
/* Receive Register Descriptions */ /* Receive Register Descriptions */
#define IGC_RCTL 0x00100 /* Rx Control - RW */ #define IGC_RCTL 0x00100 /* Rx Control - RW */
#define IGC_SRRCTL(_n) (0x0C00C + ((_n) * 0x40)) #define IGC_SRRCTL(_n) (0x0C00C + ((_n) * 0x40))