diff options
Diffstat (limited to 'drivers/net/ethernet/intel/igb/igb_ptp.c')
-rw-r--r-- | drivers/net/ethernet/intel/igb/igb_ptp.c | 64 |
1 files changed, 43 insertions, 21 deletions
diff --git a/drivers/net/ethernet/intel/igb/igb_ptp.c b/drivers/net/ethernet/intel/igb/igb_ptp.c index 5a54e3dc535d..2cca8fd5e574 100644 --- a/drivers/net/ethernet/intel/igb/igb_ptp.c +++ b/drivers/net/ethernet/intel/igb/igb_ptp.c @@ -12,9 +12,8 @@ * 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 Street, Fifth Floor, Boston, MA 02110-1301 USA. + * You should have received a copy of the GNU General Public License along with + * this program; if not, see <http://www.gnu.org/licenses/>. */ #include <linux/module.h> #include <linux/device.h> @@ -75,6 +74,8 @@ #define INCVALUE_82576 (16 << IGB_82576_TSYNC_SHIFT) #define IGB_NBITS_82580 40 +static void igb_ptp_tx_hwtstamp(struct igb_adapter *adapter); + /* SYSTIM read access for the 82576 */ static cycle_t igb_ptp_read_82576(const struct cyclecounter *cc) { @@ -372,7 +373,7 @@ static int igb_ptp_enable(struct ptp_clock_info *ptp, * This work function polls the TSYNCTXCTL valid bit to determine when a * timestamp has been taken for the current stored skb. **/ -void igb_ptp_tx_work(struct work_struct *work) +static void igb_ptp_tx_work(struct work_struct *work) { struct igb_adapter *adapter = container_of(work, struct igb_adapter, ptp_tx_work); @@ -386,6 +387,7 @@ void igb_ptp_tx_work(struct work_struct *work) IGB_PTP_TX_TIMEOUT)) { dev_kfree_skb_any(adapter->ptp_tx_skb); adapter->ptp_tx_skb = NULL; + clear_bit_unlock(__IGB_PTP_TX_IN_PROGRESS, &adapter->state); adapter->tx_hwtstamp_timeouts++; dev_warn(&adapter->pdev->dev, "clearing Tx timestamp hang"); return; @@ -466,7 +468,7 @@ void igb_ptp_rx_hang(struct igb_adapter *adapter) * available, then it must have been for this skb here because we only * allow only one such packet into the queue. **/ -void igb_ptp_tx_hwtstamp(struct igb_adapter *adapter) +static void igb_ptp_tx_hwtstamp(struct igb_adapter *adapter) { struct e1000_hw *hw = &adapter->hw; struct skb_shared_hwtstamps shhwtstamps; @@ -479,6 +481,7 @@ void igb_ptp_tx_hwtstamp(struct igb_adapter *adapter) skb_tstamp_tx(adapter->ptp_tx_skb, &shhwtstamps); dev_kfree_skb_any(adapter->ptp_tx_skb); adapter->ptp_tx_skb = NULL; + clear_bit_unlock(__IGB_PTP_TX_IN_PROGRESS, &adapter->state); } /** @@ -540,10 +543,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 @@ -557,12 +576,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; @@ -570,14 +588,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: @@ -586,7 +604,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; @@ -610,7 +628,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; @@ -621,12 +639,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; } @@ -643,7 +661,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; @@ -707,7 +725,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; } @@ -798,7 +816,7 @@ void igb_ptp_init(struct igb_adapter *adapter) /* Initialize the time sync interrupts for devices that support it. */ if (hw->mac.type >= e1000_82580) { - wr32(E1000_TSIM, E1000_TSIM_TXTS); + wr32(E1000_TSIM, TSYNC_INTERRUPTS); wr32(E1000_IMS, E1000_IMS_TS); } @@ -841,6 +859,7 @@ void igb_ptp_stop(struct igb_adapter *adapter) if (adapter->ptp_tx_skb) { dev_kfree_skb_any(adapter->ptp_tx_skb); adapter->ptp_tx_skb = NULL; + clear_bit_unlock(__IGB_PTP_TX_IN_PROGRESS, &adapter->state); } if (adapter->ptp_clock) { @@ -864,6 +883,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. */ @@ -876,7 +898,7 @@ void igb_ptp_reset(struct igb_adapter *adapter) case e1000_i211: /* Enable the timer functions and interrupts. */ wr32(E1000_TSAUXC, 0x0); - wr32(E1000_TSIM, E1000_TSIM_TXTS); + wr32(E1000_TSIM, TSYNC_INTERRUPTS); wr32(E1000_IMS, E1000_IMS_TS); break; default: |