diff options
author | Osama Abboud <osamaabb@amazon.com> | 2024-08-07 06:24:14 +0000 |
---|---|---|
committer | Osama Abboud <osamaabb@FreeBSD.org> | 2024-10-15 16:54:28 +0000 |
commit | 26ce6c06126c01d4b7bcee753f580ee7c7deb3ed (patch) | |
tree | 39e3daab3325e9141908d48907e2c909b4fd28e6 | |
parent | 15441c801ad91322e355f4fd46d1adde9416fdf6 (diff) |
ena: PHC error bound/flags support
PTP Hardware Clock (PHC) algorithm is updated to support reading new
PHC values.
Until this change, the driver retrieved PHC timestamp from the device's
PHC address, this change expands this API by adding 2 new values
to ena_admin_phc_resp:
1. PHC error bound:
PTP HW clock error bound refers to the maximum allowable difference
between the clock of the device and the reference clock.
The error bound is used to ensure that the clock of the device
remains within a certain level of accuracy relative to the reference
clock. The error bound (expressed in nanoseconds) is calculated by
the device, taking into account the accuracy of the PTA device,
march hare network, TOR, Chrony, Pacemaker and ENA driver read delay.
Error bound (u32) may contain values of 0-4294967295 (nsec) while
driver may only report values of 0-4294967294 (nsec) because max
error bound value will be used to represent error bound read error.
The error bound value is retrieved from the device by the driver upon
every get PHC timestamp request and is cached for future retrieval by
the user.
2. PHC error flags:
Indicates on any PHC timestamp and error bound errors.
The error flags value is retrieved from the device by the driver upon
every get PHC timestamp request.
Any PHC error type will:
1. Enter the PHC into blocked state until passing blocking time
2. Return device busy error to timestamp caller
3. Return device busy error to error bound caller
This new error flags eliminates the need to check if the driver got
a bad PHC timestamp (ENA_PHC_TIMESTAMP_ERROR).
Approved by: cperciva (mentor)
MFC after: 2 weeks
Sponsored by: Amazon, Inc.
-rw-r--r-- | ena_com.c | 62 | ||||
-rw-r--r-- | ena_com.h | 22 | ||||
-rw-r--r-- | ena_defs/ena_admin_defs.h | 19 |
3 files changed, 79 insertions, 24 deletions
diff --git a/ena_com.c b/ena_com.c index 01b592c20f54..e8cf7c7a0e45 100644 --- a/ena_com.c +++ b/ena_com.c @@ -79,8 +79,10 @@ /* PHC definitions */ #define ENA_PHC_DEFAULT_EXPIRE_TIMEOUT_USEC 20 #define ENA_PHC_DEFAULT_BLOCK_TIMEOUT_USEC 1000 -#define ENA_PHC_TIMESTAMP_ERROR 0xFFFFFFFFFFFFFFFF +#define ENA_PHC_MAX_ERROR_BOUND 0xFFFFFFFF #define ENA_PHC_REQ_ID_OFFSET 0xDEAD +#define ENA_PHC_ERROR_FLAGS (ENA_ADMIN_PHC_ERROR_FLAG_TIMESTAMP | \ + ENA_ADMIN_PHC_ERROR_FLAG_ERROR_BOUND) /*****************************************************************************/ /*****************************************************************************/ @@ -1840,11 +1842,11 @@ int ena_com_phc_config(struct ena_com_dev *ena_dev) get_feat_resp.u.phc.block_timeout_usec : ENA_PHC_DEFAULT_BLOCK_TIMEOUT_USEC; - /* Sanity check - expire timeout must not be above skip timeout */ + /* Sanity check - expire timeout must not exceed block timeout */ if (phc->expire_timeout_usec > phc->block_timeout_usec) phc->expire_timeout_usec = phc->block_timeout_usec; - /* Prepare PHC feature command with PHC output address */ + /* Prepare PHC 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; @@ -1893,7 +1895,7 @@ void ena_com_phc_destroy(struct ena_com_dev *ena_dev) ENA_SPINLOCK_DESTROY(phc->lock); } -int ena_com_phc_get(struct ena_com_dev *ena_dev, u64 *timestamp) +int ena_com_phc_get_timestamp(struct ena_com_dev *ena_dev, u64 *timestamp) { volatile struct ena_admin_phc_resp *read_resp = ena_dev->phc.virt_addr; struct ena_com_phc_info *phc = &ena_dev->phc; @@ -1922,9 +1924,9 @@ int ena_com_phc_get(struct ena_com_dev *ena_dev, u64 *timestamp) goto skip; } - /* PHC is in active state, update statistics according to req_id and timestamp */ + /* PHC is in active state, update statistics according to req_id and error_flags */ if ((READ_ONCE16(read_resp->req_id) != phc->req_id) || - (read_resp->timestamp == ENA_PHC_TIMESTAMP_ERROR)) { + (read_resp->error_flags & ENA_PHC_ERROR_FLAGS)) { /* Device didn't update req_id during blocking time or timestamp is invalid, * this indicates on a device error */ @@ -1955,31 +1957,41 @@ int ena_com_phc_get(struct ena_com_dev *ena_dev, u64 *timestamp) while (1) { if (unlikely(ENA_TIME_EXPIRE_HIGH_RES(expire_time))) { /* Gave up waiting for updated req_id, PHC enters into blocked state until - * passing blocking time + * passing blocking time, during this time any get PHC timestamp or + * error bound requests will fail with device busy error */ + phc->error_bound = ENA_PHC_MAX_ERROR_BOUND; ret = ENA_COM_DEVICE_BUSY; break; } /* Check if req_id was updated by the device */ if (READ_ONCE16(read_resp->req_id) != phc->req_id) { - /* req_id was not updated by the device, check again on next loop */ + /* req_id was not updated by the device yet, check again on next loop */ continue; } - /* req_id was updated which indicates that PHC timestamp was updated too */ - *timestamp = read_resp->timestamp; - - /* PHC timestamp validty check */ - if (unlikely(*timestamp == ENA_PHC_TIMESTAMP_ERROR)) { - /* Retrieved invalid PHC timestamp, PHC enters into blocked state until - * passing blocking time + /* req_id was updated by the device which indicates that PHC timestamp, error_bound + * and error_flags are updated too, checking errors before retrieving timestamp and + * error_bound values + */ + if (unlikely(read_resp->error_flags & ENA_PHC_ERROR_FLAGS)) { + /* Retrieved timestamp or error bound errors, PHC enters into blocked state + * until passing blocking time, during this time any get PHC timestamp or + * error bound requests will fail with device busy error */ + phc->error_bound = ENA_PHC_MAX_ERROR_BOUND; ret = ENA_COM_DEVICE_BUSY; break; } - /* Retrieved valid PHC timestamp */ + /* PHC timestamp value is returned to the caller */ + *timestamp = read_resp->timestamp; + + /* Error bound value is cached for future retrieval by caller */ + phc->error_bound = read_resp->error_bound; + + /* Update statistic on valid PHC timestamp retrieval */ phc->stats.phc_cnt++; /* This indicates PHC state is active */ @@ -1993,6 +2005,24 @@ skip: return ret; } +int ena_com_phc_get_error_bound(struct ena_com_dev *ena_dev, u32 *error_bound) +{ + struct ena_com_phc_info *phc = &ena_dev->phc; + u32 local_error_bound = phc->error_bound; + + if (!phc->active) { + ena_trc_err(ena_dev, "PHC feature is not active in the device\n"); + return ENA_COM_UNSUPPORTED; + } + + if (local_error_bound == ENA_PHC_MAX_ERROR_BOUND) + return ENA_COM_DEVICE_BUSY; + + *error_bound = local_error_bound; + + return ENA_COM_OK; +} + int ena_com_mmio_reg_read_request_init(struct ena_com_dev *ena_dev) { struct ena_com_mmio_read *mmio_read = &ena_dev->mmio_read; diff --git a/ena_com.h b/ena_com.h index 347ca4031fda..9164b98593ae 100644 --- a/ena_com.h +++ b/ena_com.h @@ -321,17 +321,20 @@ struct ena_com_phc_info { */ u32 block_timeout_usec; + /* Cached error bound per timestamp sample */ + u32 error_bound; + /* Request id sent to the device */ u16 req_id; /* True if PHC is active in the device */ bool active; - /* PHC shared memory - memory handle */ - ena_mem_handle_t mem_handle; - /* PHC shared memory - physical address */ dma_addr_t phys_addr; + + /* PHC shared memory handle */ + ena_mem_handle_t mem_handle; }; struct ena_rss { @@ -496,12 +499,19 @@ int ena_com_phc_config(struct ena_com_dev *ena_dev); */ void ena_com_phc_destroy(struct ena_com_dev *ena_dev); -/* ena_com_phc_get - Retrieve PHC timestamp +/* ena_com_phc_get_timestamp - Retrieve PHC timestamp + * @ena_dev: ENA communication layer struct + * @timestamp: Retrieved PHC timestamp + * @return - 0 on success, negative value on failure + */ +int ena_com_phc_get_timestamp(struct ena_com_dev *ena_dev, u64 *timestamp); + +/* ena_com_phc_get_error_bound - Retrieve cached PHC error bound * @ena_dev: ENA communication layer struct - * @timestamp: Retrieve PHC timestamp + * @error_bound: Cached PHC error bound * @return - 0 on success, negative value on failure */ -int ena_com_phc_get(struct ena_com_dev *ena_dev, u64 *timestamp); +int ena_com_phc_get_error_bound(struct ena_com_dev *ena_dev, 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/ena_defs/ena_admin_defs.h b/ena_defs/ena_admin_defs.h index 1d408469aa9d..3ad2467c6111 100644 --- a/ena_defs/ena_admin_defs.h +++ b/ena_defs/ena_admin_defs.h @@ -173,10 +173,15 @@ enum ena_admin_get_stats_scope { ENA_ADMIN_ETH_TRAFFIC = 1, }; -enum ena_admin_get_phc_type { +enum ena_admin_phc_type { ENA_ADMIN_PHC_TYPE_READLESS = 0, }; +enum ena_admin_phc_error_flags { + ENA_ADMIN_PHC_ERROR_FLAG_TIMESTAMP = BIT(0), + ENA_ADMIN_PHC_ERROR_FLAG_ERROR_BOUND = BIT(1), +}; + /* ENA SRD configuration for ENI */ enum ena_admin_ena_srd_flags { /* Feature enabled */ @@ -1301,13 +1306,23 @@ struct ena_admin_ena_mmio_req_read_less_resp { }; struct ena_admin_phc_resp { + /* Request Id, received from DB register */ uint16_t req_id; uint8_t reserved1[6]; + /* PHC timestamp (nsec) */ uint64_t timestamp; - uint8_t reserved2[48]; + uint8_t reserved2[8]; + + /* Timestamp error limit (nsec) */ + uint32_t error_bound; + + /* Bit field of enum ena_admin_phc_error_flags */ + uint32_t error_flags; + + uint8_t reserved3[32]; }; /* aq_common_desc */ |