aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/intel/i40e/i40e_ptp.c
diff options
context:
space:
mode:
authorJacob Keller <jacob.e.keller@intel.com>2014-11-11 20:05:58 +0000
committerJeff Kirsher <jeffrey.t.kirsher@intel.com>2014-12-06 03:47:15 -0800
commitfe88bda9e61a367e497cf2b7adedc4079ef62480 (patch)
tree7128472aaba2ca3e82cb315cf545b70af5153f80 /drivers/net/ethernet/intel/i40e/i40e_ptp.c
parenti40e: Add description to misc and fd interrupts (diff)
downloadlinux-dev-fe88bda9e61a367e497cf2b7adedc4079ef62480.tar.xz
linux-dev-fe88bda9e61a367e497cf2b7adedc4079ef62480.zip
i40e: don't enable PTP support on more than one PF per port
Resolve an issue related to images with multiple PFs per physical port. We cannot fully support 1588 PTP features, since only one port should control (ie: write) the registers at a time. Doing so can cause interference of functionality. It may be possible to partially implement the API for only those features without side effects. However, this at minimum means non controlling PFs lose Tx timestamps, frequency atunement, and possibly SYSTIME adjustment. There may be further impact I did not discover. Since the API in the kernel expects these features to work, it is simpler and less dangerous to just disable PTP features on all PFs not identified as the controlling PF in PRTTSYN_CTL0.PF_ID. This change also removes the warning printed when hwtstaml IOCTL is called on the wrong PF. This is actually meaningless now, since only one PF per port will support it. In addition, the ethtool get_ts_info IOCTL was updated so that only the controlling port will even indicate support (so as not to confuse users). The overall downside is complete loss of functionality on non controlling PF, vs the possible gain of partial support. The biggest factor for choosing this approach is simplicity and ensuring that the main PF will work. There could easily be other portions of the 1588 logic with side effects I am not aware, and the reduced functionality that might be made available is significantly less useful. In addition, the API does not allow for proper indication of why particular features are not supported. These reasons are enough to decide for the simpler approach to resolving this issue. Change-ID: If4696bae686fc18aef6552b67dd417213d987c16 Signed-off-by: Jacob Keller <jacob.e.keller@intel.com> Tested-by: Jim Young <jamesx.m.young@intel.com> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Diffstat (limited to '')
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_ptp.c32
1 files changed, 21 insertions, 11 deletions
diff --git a/drivers/net/ethernet/intel/i40e/i40e_ptp.c b/drivers/net/ethernet/intel/i40e/i40e_ptp.c
index f91510370c35..6d1ec926aa37 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_ptp.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_ptp.c
@@ -424,6 +424,9 @@ int i40e_ptp_get_ts_config(struct i40e_pf *pf, struct ifreq *ifr)
{
struct hwtstamp_config *config = &pf->tstamp_config;
+ if (!(pf->flags & I40E_FLAG_PTP))
+ return -EOPNOTSUPP;
+
return copy_to_user(ifr->ifr_data, config, sizeof(*config)) ?
-EFAULT : 0;
}
@@ -444,22 +447,12 @@ static int i40e_ptp_set_timestamp_mode(struct i40e_pf *pf,
struct hwtstamp_config *config)
{
struct i40e_hw *hw = &pf->hw;
- u32 pf_id, tsyntype, regval;
+ u32 tsyntype, regval;
/* Reserved for future extensions. */
if (config->flags)
return -EINVAL;
- /* Confirm that 1588 is supported on this PF. */
- pf_id = (rd32(hw, I40E_PRTTSYN_CTL0) & I40E_PRTTSYN_CTL0_PF_ID_MASK) >>
- I40E_PRTTSYN_CTL0_PF_ID_SHIFT;
- if (hw->pf_id != pf_id) {
- dev_err(&pf->pdev->dev,
- "PF %d attempted to control timestamp mode on port %d, which is owned by PF %d\n",
- hw->pf_id, hw->port, pf_id);
- return -EPERM;
- }
-
switch (config->tx_type) {
case HWTSTAMP_TX_OFF:
pf->ptp_tx = false;
@@ -562,6 +555,9 @@ int i40e_ptp_set_ts_config(struct i40e_pf *pf, struct ifreq *ifr)
struct hwtstamp_config config;
int err;
+ if (!(pf->flags & I40E_FLAG_PTP))
+ return -EOPNOTSUPP;
+
if (copy_from_user(&config, ifr->ifr_data, sizeof(config)))
return -EFAULT;
@@ -631,8 +627,22 @@ void i40e_ptp_init(struct i40e_pf *pf)
{
struct net_device *netdev = pf->vsi[pf->lan_vsi]->netdev;
struct i40e_hw *hw = &pf->hw;
+ u32 pf_id;
long err;
+ /* Only one PF is assigned to control 1588 logic per port. Do not
+ * enable any support for PFs not assigned via PRTTSYN_CTL0.PF_ID
+ */
+ pf_id = (rd32(hw, I40E_PRTTSYN_CTL0) & I40E_PRTTSYN_CTL0_PF_ID_MASK) >>
+ I40E_PRTTSYN_CTL0_PF_ID_SHIFT;
+ if (hw->pf_id != pf_id) {
+ pf->flags &= ~I40E_FLAG_PTP;
+ dev_info(&pf->pdev->dev, "%s: PTP not supported on %s\n",
+ __func__,
+ netdev->name);
+ return;
+ }
+
/* we have to initialize the lock first, since we can't control
* when the user will enter the PHC device entry points
*/