diff options
author | David S. Miller <davem@davemloft.net> | 2014-03-24 12:45:16 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2014-03-24 12:45:16 -0400 |
commit | 35d499ee3a63b645f355d98dc407b22751896a43 (patch) | |
tree | 7650549beb70a46cbe5f6e7e5f0315a71bb1920b /drivers/net/ethernet/intel/igb | |
parent | 0b8c7f6f2a26ed2dee24881299fc69f554596dbb (diff) | |
parent | b709323d2477614823a38c2f2a9a206e087e28fc (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/jkirsher/net-next
Jeff Kirsher says:
====================
Intel Wired LAN Driver Updates
This series contains updates to igb, ixgbe, ixgbevf, i40e and i40evf.
Anjali provides a i40e/i40evf patch to add Energy Efficient Ethernet
Low Power Idle stats and a fix for i40e to change the string
"Side Band" to "Sideband" for consistency.
Mitch provides 2 patches for i40evf to fix if the driver encounters
an error while communicating with the PF driver, do not shut down the
admin queue unconditionally. Add an error message when the admin
queue message never completes and fix formatting on another message
that was unnecessarily wrapped.
Mark provides a ixgbe patch and five ixgbevf patches. Fix a possible
infinite recursion when an adapter is removed and registers all read
as all one's in ixgbe_clear_vmdq_generic() and ixgbe_clear_rar_generic().
Converts macros to static inline functions to align kernel coding standard
and prepare for adding Live Error Recovery (LER) to ixgbevf. Change the
ethtool register test to use the normal register accessor functions and
eliminate macors used for calling register test functions to make error
exits more clear. Checks all register reads for adapter removal by checking
the status register after any register read that returns all F's since the
status register will never return 0xFFFFFFFF unless the adapter is removed.
Jacob implements SIOCGHWTSTAMP ioctl for igb which enables user processes
to read the current hardware stamp config settings non-destructively.
Todd adds the initial register read and write for surprise removal (LER)
for igb.
Christian Engelmayer fixes an igb memory leak in the igb_get_module_eeprom()
error handling path.
Ken Ichikawa provides a fix for igb, specifically for 82575 hardware to
specify -1 to the phc_index for ethtool's get_ts_info, otherwise a wrong
value will be set to the phc_index.
Christopher Paasch fixes a null pointer dereference in igb and makes sure
to unset the HAS_MSIX flag when the driver falls back to MSI only.
====================
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ethernet/intel/igb')
-rw-r--r-- | drivers/net/ethernet/intel/igb/e1000_regs.h | 21 | ||||
-rw-r--r-- | drivers/net/ethernet/intel/igb/igb.h | 5 | ||||
-rw-r--r-- | drivers/net/ethernet/intel/igb/igb_ethtool.c | 14 | ||||
-rw-r--r-- | drivers/net/ethernet/intel/igb/igb_main.c | 33 | ||||
-rw-r--r-- | drivers/net/ethernet/intel/igb/igb_ptp.c | 46 |
5 files changed, 93 insertions, 26 deletions
diff --git a/drivers/net/ethernet/intel/igb/e1000_regs.h b/drivers/net/ethernet/intel/igb/e1000_regs.h index d0f14be3d94f..bdb246e848e1 100644 --- a/drivers/net/ethernet/intel/igb/e1000_regs.h +++ b/drivers/net/ethernet/intel/igb/e1000_regs.h @@ -362,12 +362,25 @@ * Filter - RW */ #define E1000_VMVIR(_n) (0x03700 + (4 * (_n))) -#define wr32(reg, value) (writel(value, hw->hw_addr + reg)) -#define rd32(reg) (readl(hw->hw_addr + reg)) +struct e1000_hw; + +u32 igb_rd32(struct e1000_hw *hw, u32 reg); + +/* write operations, indexed using DWORDS */ +#define wr32(reg, val) \ +do { \ + u8 __iomem *hw_addr = ACCESS_ONCE((hw)->hw_addr); \ + if (!E1000_REMOVED(hw_addr)) \ + writel((val), &hw_addr[(reg)]); \ +} while (0) + +#define rd32(reg) (igb_rd32(hw, reg)) + #define wrfl() ((void)rd32(E1000_STATUS)) #define array_wr32(reg, offset, value) \ - (writel(value, hw->hw_addr + reg + ((offset) << 2))) + wr32((reg) + ((offset) << 2), (value)) + #define array_rd32(reg, offset) \ (readl(hw->hw_addr + reg + ((offset) << 2))) @@ -406,4 +419,6 @@ #define E1000_INVM_DATA_REG(_n) (0x12120 + 4*(_n)) #define E1000_INVM_SIZE 64 /* Number of INVM Data Registers */ +#define E1000_REMOVED(h) unlikely(!(h)) + #endif diff --git a/drivers/net/ethernet/intel/igb/igb.h b/drivers/net/ethernet/intel/igb/igb.h index a202c9640e93..411b213c63be 100644 --- a/drivers/net/ethernet/intel/igb/igb.h +++ b/drivers/net/ethernet/intel/igb/igb.h @@ -434,6 +434,7 @@ struct igb_adapter { struct delayed_work ptp_overflow_work; struct work_struct ptp_tx_work; struct sk_buff *ptp_tx_skb; + struct hwtstamp_config tstamp_config; unsigned long ptp_tx_start; unsigned long last_rx_ptp_check; spinlock_t tmreg_lock; @@ -545,8 +546,8 @@ static inline void igb_ptp_rx_hwtstamp(struct igb_ring *rx_ring, rx_ring->last_rx_timestamp = jiffies; } -int igb_ptp_hwtstamp_ioctl(struct net_device *netdev, struct ifreq *ifr, - int cmd); +int igb_ptp_set_ts_config(struct net_device *netdev, struct ifreq *ifr); +int igb_ptp_get_ts_config(struct net_device *netdev, struct ifreq *ifr); #ifdef CONFIG_IGB_HWMON void igb_sysfs_exit(struct igb_adapter *adapter); int igb_sysfs_init(struct igb_adapter *adapter); diff --git a/drivers/net/ethernet/intel/igb/igb_ethtool.c b/drivers/net/ethernet/intel/igb/igb_ethtool.c index e35bc1faa452..e5570acbeea8 100644 --- a/drivers/net/ethernet/intel/igb/igb_ethtool.c +++ b/drivers/net/ethernet/intel/igb/igb_ethtool.c @@ -2353,6 +2353,11 @@ static int igb_get_ts_info(struct net_device *dev, { struct igb_adapter *adapter = netdev_priv(dev); + if (adapter->ptp_clock) + info->phc_index = ptp_clock_index(adapter->ptp_clock); + else + info->phc_index = -1; + switch (adapter->hw.mac.type) { case e1000_82575: info->so_timestamping = @@ -2374,11 +2379,6 @@ static int igb_get_ts_info(struct net_device *dev, SOF_TIMESTAMPING_RX_HARDWARE | SOF_TIMESTAMPING_RAW_HARDWARE; - if (adapter->ptp_clock) - info->phc_index = ptp_clock_index(adapter->ptp_clock); - else - info->phc_index = -1; - info->tx_types = (1 << HWTSTAMP_TX_OFF) | (1 << HWTSTAMP_TX_ON); @@ -2791,9 +2791,11 @@ static int igb_get_module_eeprom(struct net_device *netdev, /* Read EEPROM block, SFF-8079/SFF-8472, word at a time */ for (i = 0; i < last_word - first_word + 1; i++) { status = igb_read_phy_reg_i2c(hw, first_word + i, &dataword[i]); - if (status != E1000_SUCCESS) + if (status != E1000_SUCCESS) { /* Error occurred while reading module */ + kfree(dataword); return -EIO; + } be16_to_cpus(&dataword[i]); } diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c index 17feea0ea2b0..cd20409858d1 100644 --- a/drivers/net/ethernet/intel/igb/igb_main.c +++ b/drivers/net/ethernet/intel/igb/igb_main.c @@ -751,6 +751,28 @@ static void igb_cache_ring_register(struct igb_adapter *adapter) } } +u32 igb_rd32(struct e1000_hw *hw, u32 reg) +{ + struct igb_adapter *igb = container_of(hw, struct igb_adapter, hw); + u8 __iomem *hw_addr = ACCESS_ONCE(hw->hw_addr); + u32 value = 0; + + if (E1000_REMOVED(hw_addr)) + return ~value; + + value = readl(&hw_addr[reg]); + + /* reads should not return all F's */ + if (!(~value) && (!reg || !(~readl(hw_addr)))) { + struct net_device *netdev = igb->netdev; + hw->hw_addr = NULL; + netif_device_detach(netdev); + netdev_err(netdev, "PCIe link lost, device now detached\n"); + } + + return value; +} + /** * igb_write_ivar - configure ivar for given MSI-X vector * @hw: pointer to the HW structure @@ -1013,6 +1035,12 @@ static void igb_reset_q_vector(struct igb_adapter *adapter, int v_idx) { struct igb_q_vector *q_vector = adapter->q_vector[v_idx]; + /* Coming from igb_set_interrupt_capability, the vectors are not yet + * allocated. So, q_vector is NULL so we should stop here. + */ + if (!q_vector) + return; + if (q_vector->tx.ring) adapter->tx_ring[q_vector->tx.ring->queue_index] = NULL; @@ -1121,6 +1149,7 @@ static void igb_set_interrupt_capability(struct igb_adapter *adapter, bool msix) /* If we can't do MSI-X, try MSI */ msi_only: + adapter->flags &= ~IGB_FLAG_HAS_MSIX; #ifdef CONFIG_PCI_IOV /* disable SR-IOV for non MSI-X configurations */ if (adapter->vf_data) { @@ -7162,8 +7191,10 @@ static int igb_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) case SIOCGMIIREG: case SIOCSMIIREG: return igb_mii_ioctl(netdev, ifr, cmd); + case SIOCGHWTSTAMP: + return igb_ptp_get_ts_config(netdev, ifr); case SIOCSHWTSTAMP: - return igb_ptp_hwtstamp_ioctl(netdev, ifr, cmd); + return igb_ptp_set_ts_config(netdev, ifr); default: return -EOPNOTSUPP; } diff --git a/drivers/net/ethernet/intel/igb/igb_ptp.c b/drivers/net/ethernet/intel/igb/igb_ptp.c index a894551ae3c0..da55fbb090b2 100644 --- a/drivers/net/ethernet/intel/igb/igb_ptp.c +++ b/drivers/net/ethernet/intel/igb/igb_ptp.c @@ -541,10 +541,26 @@ void igb_ptp_rx_rgtstamp(struct igb_q_vector *q_vector, } /** - * igb_ptp_hwtstamp_ioctl - control hardware time stamping + * igb_ptp_get_ts_config - get hardware time stamping config + * @netdev: + * @ifreq: + * + * Get the hwtstamp_config settings to return to the user. Rather than attempt + * to deconstruct the settings from the registers, just return a shadow copy + * of the last known settings. + **/ +int igb_ptp_get_ts_config(struct net_device *netdev, struct ifreq *ifr) +{ + struct igb_adapter *adapter = netdev_priv(netdev); + struct hwtstamp_config *config = &adapter->tstamp_config; + + return copy_to_user(ifr->ifr_data, config, sizeof(*config)) ? + -EFAULT : 0; +} +/** + * igb_ptp_set_ts_config - control hardware time stamping * @netdev: * @ifreq: - * @cmd: * * Outgoing time stamping can be enabled and disabled. Play nice and * disable it when requested, although it shouldn't case any overhead @@ -558,12 +574,11 @@ void igb_ptp_rx_rgtstamp(struct igb_q_vector *q_vector, * not supported, with the exception of "all V2 events regardless of * level 2 or 4". **/ -int igb_ptp_hwtstamp_ioctl(struct net_device *netdev, - struct ifreq *ifr, int cmd) +int igb_ptp_set_ts_config(struct net_device *netdev, struct ifreq *ifr) { struct igb_adapter *adapter = netdev_priv(netdev); struct e1000_hw *hw = &adapter->hw; - struct hwtstamp_config config; + struct hwtstamp_config *config = &adapter->tstamp_config; u32 tsync_tx_ctl = E1000_TSYNCTXCTL_ENABLED; u32 tsync_rx_ctl = E1000_TSYNCRXCTL_ENABLED; u32 tsync_rx_cfg = 0; @@ -571,14 +586,14 @@ int igb_ptp_hwtstamp_ioctl(struct net_device *netdev, bool is_l2 = false; u32 regval; - if (copy_from_user(&config, ifr->ifr_data, sizeof(config))) + if (copy_from_user(config, ifr->ifr_data, sizeof(*config))) return -EFAULT; /* reserved for future extensions */ - if (config.flags) + if (config->flags) return -EINVAL; - switch (config.tx_type) { + switch (config->tx_type) { case HWTSTAMP_TX_OFF: tsync_tx_ctl = 0; case HWTSTAMP_TX_ON: @@ -587,7 +602,7 @@ int igb_ptp_hwtstamp_ioctl(struct net_device *netdev, return -ERANGE; } - switch (config.rx_filter) { + switch (config->rx_filter) { case HWTSTAMP_FILTER_NONE: tsync_rx_ctl = 0; break; @@ -611,7 +626,7 @@ int igb_ptp_hwtstamp_ioctl(struct net_device *netdev, case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ: case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ: tsync_rx_ctl |= E1000_TSYNCRXCTL_TYPE_EVENT_V2; - config.rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT; + config->rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT; is_l2 = true; is_l4 = true; break; @@ -622,12 +637,12 @@ int igb_ptp_hwtstamp_ioctl(struct net_device *netdev, */ if (hw->mac.type != e1000_82576) { tsync_rx_ctl |= E1000_TSYNCRXCTL_TYPE_ALL; - config.rx_filter = HWTSTAMP_FILTER_ALL; + config->rx_filter = HWTSTAMP_FILTER_ALL; break; } /* fall through */ default: - config.rx_filter = HWTSTAMP_FILTER_NONE; + config->rx_filter = HWTSTAMP_FILTER_NONE; return -ERANGE; } @@ -644,7 +659,7 @@ int igb_ptp_hwtstamp_ioctl(struct net_device *netdev, if ((hw->mac.type >= e1000_82580) && tsync_rx_ctl) { tsync_rx_ctl = E1000_TSYNCRXCTL_ENABLED; tsync_rx_ctl |= E1000_TSYNCRXCTL_TYPE_ALL; - config.rx_filter = HWTSTAMP_FILTER_ALL; + config->rx_filter = HWTSTAMP_FILTER_ALL; is_l2 = true; is_l4 = true; @@ -708,7 +723,7 @@ int igb_ptp_hwtstamp_ioctl(struct net_device *netdev, regval = rd32(E1000_RXSTMPL); regval = rd32(E1000_RXSTMPH); - return copy_to_user(ifr->ifr_data, &config, sizeof(config)) ? + return copy_to_user(ifr->ifr_data, config, sizeof(*config)) ? -EFAULT : 0; } @@ -865,6 +880,9 @@ void igb_ptp_reset(struct igb_adapter *adapter) if (!(adapter->flags & IGB_FLAG_PTP)) return; + /* reset the tstamp_config */ + memset(&adapter->tstamp_config, 0, sizeof(adapter->tstamp_config)); + switch (adapter->hw.mac.type) { case e1000_82576: /* Dial the nominal frequency. */ |