i40e: don't enable PTP support on more than one PF per port
authorJacob Keller <jacob.e.keller@intel.com>
Tue, 11 Nov 2014 20:05:58 +0000 (20:05 +0000)
committerJeff Kirsher <jeffrey.t.kirsher@intel.com>
Sat, 6 Dec 2014 11:47:15 +0000 (03:47 -0800)
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>
drivers/net/ethernet/intel/i40e/i40e_ethtool.c
drivers/net/ethernet/intel/i40e/i40e_ptp.c

index b2402851a9bd669ad5710833d8a4e5226aa41480..4053b344e609a0c66103e05efc9350a35a1de0a4 100644 (file)
@@ -1325,6 +1325,10 @@ static int i40e_get_ts_info(struct net_device *dev,
 {
        struct i40e_pf *pf = i40e_netdev_to_pf(dev);
 
+       /* only report HW timestamping if PTP is enabled */
+       if (!(pf->flags & I40E_FLAG_PTP))
+               return ethtool_op_get_ts_info(dev, info);
+
        info->so_timestamping = SOF_TIMESTAMPING_TX_SOFTWARE |
                                SOF_TIMESTAMPING_RX_SOFTWARE |
                                SOF_TIMESTAMPING_SOFTWARE |
index f91510370c354d9d474f522158a565ebd72ba290..6d1ec926aa3713a6ebc40fa52aa2ee873f8292f4 100644 (file)
@@ -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
         */