Extend the ENA PHC communication layer to retrieve error bound from
the device.

Update ena_com_phc_get_timestamp() to retrieve error_bound alongside
timestamps.
Add error handling and statistics for error_bound retrieval failures.

Signed-off-by: Amit Bernstein <[email protected]>
Signed-off-by: Arthur Kiyanovski <[email protected]>
---
 .../device_drivers/ethernet/amazon/ena.rst    |  2 ++
 drivers/net/ethernet/amazon/ena/ena_com.c     | 36 ++++++++++++-------
 drivers/net/ethernet/amazon/ena/ena_com.h     |  5 ++-
 drivers/net/ethernet/amazon/ena/ena_debugfs.c |  3 ++
 drivers/net/ethernet/amazon/ena/ena_phc.c     |  3 +-
 5 files changed, 34 insertions(+), 15 deletions(-)

diff --git a/Documentation/networking/device_drivers/ethernet/amazon/ena.rst 
b/Documentation/networking/device_drivers/ethernet/amazon/ena.rst
index 14784a0..ce9ba84 100644
--- a/Documentation/networking/device_drivers/ethernet/amazon/ena.rst
+++ b/Documentation/networking/device_drivers/ethernet/amazon/ena.rst
@@ -306,6 +306,8 @@ PHC errors must remain below 1% of all PHC requests to 
maintain the desired leve
 **phc_err_dv**      | Number of failed get time attempts due to device errors 
(entering into block state).
 **phc_err_ts**      | Number of failed get time attempts due to timestamp 
errors (entering into block state),
                     | This occurs if driver exceeded the request limit or 
device received an invalid timestamp.
+**phc_err_eb**      | Number of failed get time attempts due to error bound 
errors (entering into block state),
+                    | This occurs if device received an excessively high or 
invalid error bound.
 =================   ======================================================
 
 PHC timeouts:
diff --git a/drivers/net/ethernet/amazon/ena/ena_com.c 
b/drivers/net/ethernet/amazon/ena/ena_com.c
index 2579104..832c4c1 100644
--- a/drivers/net/ethernet/amazon/ena/ena_com.c
+++ b/drivers/net/ethernet/amazon/ena/ena_com.c
@@ -45,7 +45,8 @@
 #define ENA_PHC_DEFAULT_EXPIRE_TIMEOUT_USEC 10
 #define ENA_PHC_DEFAULT_BLOCK_TIMEOUT_USEC 1000
 #define ENA_PHC_REQ_ID_OFFSET 0xDEAD
-#define ENA_PHC_ERROR_FLAGS (ENA_ADMIN_PHC_ERROR_FLAG_TIMESTAMP)
+#define ENA_PHC_ERROR_FLAGS (ENA_ADMIN_PHC_ERROR_FLAG_TIMESTAMP | \
+                            ENA_ADMIN_PHC_ERROR_FLAG_ERROR_BOUND)
 
 /*****************************************************************************/
 /*****************************************************************************/
@@ -1726,7 +1727,7 @@ int ena_com_phc_config(struct ena_com_dev *ena_dev)
        if (phc->expire_timeout_usec > phc->block_timeout_usec)
                phc->expire_timeout_usec = phc->block_timeout_usec;
 
-       /* Prepare PHC feature command */
+       /* Prepare PHC config feature command */
        memset(&set_feat_cmd, 0x0, sizeof(set_feat_cmd));
        set_feat_cmd.aq_common_descriptor.opcode = ENA_ADMIN_SET_FEATURE;
        set_feat_cmd.feat_common.feature_id = ENA_ADMIN_PHC_CONFIG;
@@ -1781,7 +1782,8 @@ void ena_com_phc_destroy(struct ena_com_dev *ena_dev)
        phc->virt_addr = NULL;
 }
 
-int ena_com_phc_get_timestamp(struct ena_com_dev *ena_dev, u64 *timestamp)
+int ena_com_phc_get_timestamp(struct ena_com_dev *ena_dev, u64 *timestamp,
+                             u32 *error_bound)
 {
        const ktime_t zero_system_time = ktime_set(0, 0);
        struct ena_com_phc_info *phc = &ena_dev->phc;
@@ -1828,6 +1830,8 @@ int ena_com_phc_get_timestamp(struct ena_com_dev 
*ena_dev, u64 *timestamp)
                         * a PHC error, this occurs if device:
                         * - exceeded the get time request limit
                         * - received an invalid timestamp
+                        * - received an excessively high error bound
+                        * - received an invalid error bound
                         */
                        netdev_err(ena_dev->net_device,
                                   "PHC get time request 0x%x failed (error 
0x%x)\n",
@@ -1835,9 +1839,11 @@ int ena_com_phc_get_timestamp(struct ena_com_dev 
*ena_dev, u64 *timestamp)
                                   resp->error_flags);
                        phc->stats.phc_err_ts += !!(resp->error_flags &
                                ENA_ADMIN_PHC_ERROR_FLAG_TIMESTAMP);
+                       phc->stats.phc_err_eb += !!(resp->error_flags &
+                               ENA_ADMIN_PHC_ERROR_FLAG_ERROR_BOUND);
                } else {
                        /* Device updated req_id during blocking time
-                        * with valid timestamp
+                        * with valid timestamp and error bound
                         */
                        phc->stats.phc_exp++;
                }
@@ -1864,9 +1870,9 @@ int ena_com_phc_get_timestamp(struct ena_com_dev 
*ena_dev, u64 *timestamp)
        /* Stalling until the device updates req_id */
        while (1) {
                if (unlikely(ktime_after(ktime_get(), expire_time))) {
-                       /* Gave up waiting for updated req_id, PHC enters into
-                        * blocked state until passing blocking time,
-                        * during this time any get PHC timestamp will fail with
+                       /* Gave up waiting for updated req_id,
+                        * PHC enters into blocked state until passing blocking
+                        * time, during this time, any request will fail with
                         * device busy error
                         */
                        ret = -EBUSY;
@@ -1882,14 +1888,15 @@ int ena_com_phc_get_timestamp(struct ena_com_dev 
*ena_dev, u64 *timestamp)
                }
 
                /* req_id was updated by the device which indicates that
-                * PHC timestamp and error_flags are updated too,
-                * checking errors before retrieving timestamp
+                * PHC timestamp, error_bound and error_flags are updated too,
+                * checking error flags before retrieving timestamp and
+                * error_bound values
                 */
                if (unlikely(resp->error_flags & ENA_PHC_ERROR_FLAGS)) {
-                       /* Retrieved invalid PHC timestamp, PHC enters into
-                        * blocked state until passing blocking time,
-                        * during this time any get PHC timestamp requests
-                        * will fail with device busy error
+                       /* Retrieved timestamp or error bound errors,
+                        * PHC enters into blocked state until passing blocking
+                        * time, during this time, any request will fail with
+                        * device busy error
                         */
                        ret = -EBUSY;
                        break;
@@ -1897,12 +1904,15 @@ int ena_com_phc_get_timestamp(struct ena_com_dev 
*ena_dev, u64 *timestamp)
 
                /* PHC timestamp value is returned to the caller */
                *timestamp = resp->timestamp;
+               if (error_bound)
+                       *error_bound = resp->error_bound;
 
                /* Update statistic on valid PHC timestamp retrieval */
                phc->stats.phc_cnt++;
 
                /* This indicates PHC state is active */
                phc->system_time = zero_system_time;
+
                break;
        }
 
diff --git a/drivers/net/ethernet/amazon/ena/ena_com.h 
b/drivers/net/ethernet/amazon/ena/ena_com.h
index 64df2c4..fcbff1a 100644
--- a/drivers/net/ethernet/amazon/ena/ena_com.h
+++ b/drivers/net/ethernet/amazon/ena/ena_com.h
@@ -216,6 +216,7 @@ struct ena_com_stats_phc {
        u64 phc_skp;
        u64 phc_err_dv;
        u64 phc_err_ts;
+       u64 phc_err_eb;
 };
 
 struct ena_com_admin_queue {
@@ -462,9 +463,11 @@ void ena_com_phc_destroy(struct ena_com_dev *ena_dev);
 /* ena_com_phc_get_timestamp - Retrieve PHC timestamp
  * @ena_dev: ENA communication layer struct
  * @timestamp: Retrieved PHC timestamp
+ * @error_bound: maximum possible deviation of the timestamp (nanosecond)
  * @return - 0 on success, negative value on failure
  */
-int ena_com_phc_get_timestamp(struct ena_com_dev *ena_dev, u64 *timestamp);
+int ena_com_phc_get_timestamp(struct ena_com_dev *ena_dev, u64 *timestamp,
+                             u32 *error_bound);
 
 /* ena_com_set_mmio_read_mode - Enable/disable the indirect mmio reg read 
mechanism
  * @ena_dev: ENA communication layer struct
diff --git a/drivers/net/ethernet/amazon/ena/ena_debugfs.c 
b/drivers/net/ethernet/amazon/ena/ena_debugfs.c
index 46ed809..db9d184 100644
--- a/drivers/net/ethernet/amazon/ena/ena_debugfs.c
+++ b/drivers/net/ethernet/amazon/ena/ena_debugfs.c
@@ -32,6 +32,9 @@ static int phc_stats_show(struct seq_file *file, void *priv)
        seq_printf(file,
                   "phc_err_ts: %llu\n",
                   adapter->ena_dev->phc.stats.phc_err_ts);
+       seq_printf(file,
+                  "phc_err_eb: %llu\n",
+                  adapter->ena_dev->phc.stats.phc_err_eb);
 
        return 0;
 }
diff --git a/drivers/net/ethernet/amazon/ena/ena_phc.c 
b/drivers/net/ethernet/amazon/ena/ena_phc.c
index c2a3ff1..2bcb5af 100644
--- a/drivers/net/ethernet/amazon/ena/ena_phc.c
+++ b/drivers/net/ethernet/amazon/ena/ena_phc.c
@@ -40,7 +40,8 @@ static int ena_phc_gettimex64(struct ptp_clock_info 
*clock_info,
        ptp_read_system_prets(sts);
 
        rc = ena_com_phc_get_timestamp(phc_info->adapter->ena_dev,
-                                      &timestamp_nsec);
+                                      &timestamp_nsec,
+                                      NULL);
 
        ptp_read_system_postts(sts);
 
-- 
2.47.3


Reply via email to