diff options
author | Alex Hong <rurumihong@google.com> | 2021-11-25 19:54:41 +0800 |
---|---|---|
committer | Alex Hong <rurumihong@google.com> | 2021-11-25 19:54:49 +0800 |
commit | d75480a9fae3b4da3c77508be3aef07ecc79dabe (patch) | |
tree | df7a03d7f7c7bf8c217207e7571ad4d69718a774 | |
parent | 114cf21edc68b961c1d268f51706d1669b064f4b (diff) | |
parent | b86fb29e205b1f3553f06fbbc635f140a54fd7a1 (diff) | |
download | uwb-d75480a9fae3b4da3c77508be3aef07ecc79dabe.tar.gz |
Merge android12-gs-pixel-5.10-sc-v2 into android13-gs-pixel-5.10
Bug: 199698959
Change-Id: Iff8213c278c2d725e3e2693ab26b4035cf3fb57e
Signed-off-by: Alex Hong <rurumihong@google.com>
26 files changed, 616 insertions, 1074 deletions
diff --git a/kernel/drivers/net/ieee802154/Kbuild b/kernel/drivers/net/ieee802154/Kbuild index 768fdbf..b88dc40 100644 --- a/kernel/drivers/net/ieee802154/Kbuild +++ b/kernel/drivers/net/ieee802154/Kbuild @@ -8,7 +8,6 @@ dw3000-y := \ dw3000_nfcc_coex_buffer.o \ dw3000_nfcc_coex_msg.o \ dw3000_nfcc_coex_mcps.o \ - dw3000_nfcc_coex_testmode.o \ dw3000_calib.o \ dw3000_chip_c0.o \ dw3000_chip_d0.o \ diff --git a/kernel/drivers/net/ieee802154/dw3000.h b/kernel/drivers/net/ieee802154/dw3000.h index 0725b97..e29ab03 100644 --- a/kernel/drivers/net/ieee802154/dw3000.h +++ b/kernel/drivers/net/ieee802154/dw3000.h @@ -494,7 +494,6 @@ struct dw3000_rctu_conv { * @sp0_rx_antenna: Special rx antenna to use for SP0, -1 if deactivated * @lna_pa_mode: LNA/PA configuration to use * @autoack: auto-ack status, true if activated - * @ccc: CCC related data * @pgf_cal_running: true if pgf calibration is running * @stm: High-priority thread state machine * @rx: received skbuff and associated spinlock diff --git a/kernel/drivers/net/ieee802154/dw3000_chip_d0.c b/kernel/drivers/net/ieee802154/dw3000_chip_d0.c index cd54d62..032c3b2 100644 --- a/kernel/drivers/net/ieee802154/dw3000_chip_d0.c +++ b/kernel/drivers/net/ieee802154/dw3000_chip_d0.c @@ -115,8 +115,8 @@ int dw3000_d0_init(struct dw3000 *dw) int rc = 0; if (dw->current_operational_state != DW3000_OP_STATE_DEEP_SLEEP) { - /* Disable CCC Mailbox only if the chip is not in deep sleep. - * Else, on wake up, the CCC state will be not detectable. */ + /* Disable nfcc_coex mail box only if the chip is not in deep sleep. + * Else, on wake up, the nfcc_coex state will be not detectable. */ rc = dw3000_nfcc_coex_disable(dw); } return rc; diff --git a/kernel/drivers/net/ieee802154/dw3000_core.c b/kernel/drivers/net/ieee802154/dw3000_core.c index 2b116ca..f840c02 100644 --- a/kernel/drivers/net/ieee802154/dw3000_core.c +++ b/kernel/drivers/net/ieee802154/dw3000_core.c @@ -4128,7 +4128,7 @@ static int dw3000_backup_registers(struct dw3000 *dw, bool after) */ void dw3000_wakeup_timer_start(struct dw3000 *dw, int delay_us) { - hrtimer_start(&dw->deep_sleep_timer, ns_to_ktime(delay_us * 1000), + hrtimer_start(&dw->deep_sleep_timer, ns_to_ktime(delay_us * 1000ull), HRTIMER_MODE_REL); dw->call_timer_expired = true; trace_dw3000_wakeup_timer_start(dw, delay_us); @@ -6626,7 +6626,7 @@ void dw3000_isr(struct dw3000 *dw) goto spi_err; } - /* Handle the SPI1 Available events in CCC mode only */ + /* Handle the SPI1 Available events in nfcc_coex mode only */ if (dw->nfcc_coex.enabled && (isr.dss_stat & DW3000_DSS_STAT_SPI1_AVAIL_BIT_MASK)) { rc = dw3000_clear_dss_status( diff --git a/kernel/drivers/net/ieee802154/dw3000_nfcc_coex.h b/kernel/drivers/net/ieee802154/dw3000_nfcc_coex.h index 8a56882..682c7bd 100644 --- a/kernel/drivers/net/ieee802154/dw3000_nfcc_coex.h +++ b/kernel/drivers/net/ieee802154/dw3000_nfcc_coex.h @@ -26,10 +26,8 @@ #include <linux/module.h> #include <net/vendor_cmd.h> -#include "dw3000_nfcc_coex_testmode.h" - /* Main defines */ -#define DW3000_NFCC_COEX_VER_ID 1 +#define DW3000_NFCC_COEX_VER_ID 2 #define DW3000_NFCC_COEX_SIGNATURE_STR "QORVO" #define DW3000_NFCC_COEX_SIGNATURE_LEN 5 #define DW3000_NFCC_COEX_MAX_NB_TLV 12 @@ -49,6 +47,9 @@ #define MSG_HEADER_LEN (DW3000_NFCC_COEX_SIGNATURE_LEN + 3) #define MSG_LEN(x) (MSG_HEADER_LEN + (x).tlvs_len) +#define DW3000_NFCC_COEX_UUS_PER_SYS_POWER 8 /* To use with right shift. */ +#define DW3000_NFCC_COEX_DTU_PER_UUS_POWER 4 /* To use with left shift. */ + /** * struct dw3000_nfcc_coex_msg - Message read/write from/to scratch memory. */ @@ -86,7 +87,7 @@ struct dw3000_nfcc_coex_buffer { */ u8 raw[DW3000_NFCC_COEX_MSG_MAX_SIZE]; /** - * @msg: CCC Message. + * @msg: nfcc_coex message. */ struct dw3000_nfcc_coex_msg msg; }; @@ -101,23 +102,22 @@ struct dw3000_nfcc_coex_buffer { */ struct dw3000_nfcc_coex_rx_msg_info { /** - * @next_timestamp_sys_time: Next NFCC access requested. + * @next_timestamp_dtu: Next NFCC access requested. */ - u32 next_timestamp_sys_time; + u32 next_timestamp_dtu; /** - * @next_duration_sys_time: Next NFCC duration access. + * @next_duration_dtu: Next NFCC duration access. */ - int next_duration_sys_time; + int next_duration_dtu; /** * @next_slot_found: True when first next slot is found. */ bool next_slot_found; - /** - * @slot_list: Pointer to array of slot. - */ - const struct dw3000_nfcc_coex_tlv_slot_list *slot_list; }; +/* Forward declaration. */ +struct dw3000; + /** * typedef dw3000_nfcc_coex_spi_avail_cb - SPI available isr handler. * @dw: Driver context. @@ -133,10 +133,6 @@ typedef int (*dw3000_nfcc_coex_spi_avail_cb)( */ struct dw3000_nfcc_coex { /** - * @testmode_config: config with testmode enabled. - */ - const struct dw3000_nfcc_coex_testmode_config *testmode_config; - /** * @access_info: Access information to provide to upper layer. */ struct dw3000_vendor_cmd_nfcc_coex_get_access_info access_info; @@ -145,13 +141,13 @@ struct dw3000_nfcc_coex { */ dw3000_nfcc_coex_spi_avail_cb spi_avail_cb; /** - * @testmode_round_count: Index number of NFCC session. - */ - u32 testmode_round_count; + * @session_time0_dtu: Timestamp used as reference between NFCC and AP. + */ + u32 session_time0_dtu; /** - * @session_start_dtu: start date of nfcc session in DTU. + * @access_start_dtu: start date of nfcc session in DTU. */ - u32 session_start_dtu; + u32 access_start_dtu; /** * @prev_offset_sys_time: Previous offset between local and decawave time. */ diff --git a/kernel/drivers/net/ieee802154/dw3000_nfcc_coex_core.c b/kernel/drivers/net/ieee802154/dw3000_nfcc_coex_core.c index 1004577..2fa642f 100644 --- a/kernel/drivers/net/ieee802154/dw3000_nfcc_coex_core.c +++ b/kernel/drivers/net/ieee802154/dw3000_nfcc_coex_core.c @@ -105,7 +105,7 @@ static int dw3000_nfcc_coex_enable_SPIxMAVAIL_interrupts(struct dw3000 *dw) return rc; /* Set SPI1MAVAIL and SPI2MAVAIL masks */ reg |= (DW3000_SPI_SEM_SPI1MAVAIL_BIT_MASK >> 8) | - (DW3000_SPI_SEM_SPI2MAVAIL_BIT_MASK >> 8); + (DW3000_SPI_SEM_SPI2MAVAIL_BIT_MASK >> 8); return dw3000_reg_write8(dw, DW3000_SPI_SEM_ID, 1, reg); } @@ -125,8 +125,8 @@ static int dw3000_nfcc_coex_disable_SPIxMAVAIL_interrupts(struct dw3000 *dw) if (rc) return rc; /* Reset SPI1MAVAIL and SPI2MAVAIL masks. */ - reg = reg & ~(DW3000_SPI_SEM_SPI1MAVAIL_BIT_MASK >> 8) & - ~(DW3000_SPI_SEM_SPI2MAVAIL_BIT_MASK >> 8); + reg &= ~(DW3000_SPI_SEM_SPI1MAVAIL_BIT_MASK >> 8) & + ~(DW3000_SPI_SEM_SPI2MAVAIL_BIT_MASK >> 8); rc = dw3000_reg_write8(dw, DW3000_SPI_SEM_ID, 1, reg); if (rc) return rc; @@ -150,7 +150,7 @@ static int dw3000_nfcc_coex_do_watchdog_timeout(struct dw3000 *dw, dw->nfcc_coex.access_info.stop = true; /* FIXME: The expected is a hard reset of decawave when the semaphore * haven't been released. - * But CCC firmware can not currently provide a message with nb_tlv=0. */ + * But nfcc_coex firmware can not currently provide a message with nb_tlv=0. */ dw3000_nfcc_coex_disable(dw); mcps802154_tx_done(dw->llhw); @@ -336,7 +336,7 @@ int dw3000_nfcc_coex_disable(struct dw3000 *dw) if (rc) { trace_dw3000_nfcc_coex_err( dw, - "ccc_disable error while restoring channel"); + "nfcc_coex_disable error while restoring channel"); return rc; } } diff --git a/kernel/drivers/net/ieee802154/dw3000_nfcc_coex_mcps.c b/kernel/drivers/net/ieee802154/dw3000_nfcc_coex_mcps.c index 74d1590..17229b9 100644 --- a/kernel/drivers/net/ieee802154/dw3000_nfcc_coex_mcps.c +++ b/kernel/drivers/net/ieee802154/dw3000_nfcc_coex_mcps.c @@ -38,33 +38,24 @@ static void dw3000_nfcc_coex_update_access_info( struct dw3000 *dw, const struct dw3000_nfcc_coex_buffer *buffer) { - struct dw3000_nfcc_coex *nfcc_coex = &dw->nfcc_coex; struct dw3000_vendor_cmd_nfcc_coex_get_access_info *access_info = &dw->nfcc_coex.access_info; struct dw3000_nfcc_coex_rx_msg_info rx_msg_info = {}; int r; r = dw3000_nfcc_coex_message_check(dw, buffer, &rx_msg_info); - if (r) + if (r) { + trace_dw3000_nfcc_coex_warn(dw, "message check failure"); goto failure; + } /* Update access_info. */ access_info->stop = !rx_msg_info.next_slot_found; access_info->watchdog_timeout = false; if (rx_msg_info.next_slot_found) { - u32 diff_sys_time; - - /* Build the next date with the difference, because the sys_time is - * faster than dtu time. */ - diff_sys_time = rx_msg_info.next_timestamp_sys_time - - dw3000_dtu_to_sys_time( - dw, nfcc_coex->session_start_dtu); access_info->next_timestamp_dtu = - nfcc_coex->session_start_dtu + - (diff_sys_time >> DW3000_DTU_PER_SYS_POWER); - access_info->next_duration_dtu = - rx_msg_info.next_duration_sys_time >> - DW3000_DTU_PER_SYS_POWER; + rx_msg_info.next_timestamp_dtu; + access_info->next_duration_dtu = rx_msg_info.next_duration_dtu; } return; @@ -120,15 +111,12 @@ static int dw3000_nfcc_coex_handle_access(struct dw3000 *dw, void *data, const struct dw3000_vendor_cmd_nfcc_coex_handle_access *info = data; struct dw3000_nfcc_coex *nfcc_coex = &dw->nfcc_coex; const u32 dtu_per_ms = dw->llhw->dtu_freq_hz / 1000; - u32 cur_time_dtu; u32 diff_dtu, diff_ms; int r; if (!info || data_len != sizeof(*info)) return -EINVAL; - cur_time_dtu = dw3000_get_dtu_time(dw); - if (timer_pending(&nfcc_coex->watchdog_timer)) { trace_dw3000_nfcc_coex_err(dw, "watchdog timer is pending"); return -EBUSY; @@ -141,10 +129,11 @@ static int dw3000_nfcc_coex_handle_access(struct dw3000 *dw, void *data, return r; } + trace_dw3000_nfcc_coex_handle_access(dw, info); /* Save start session date, to retrieve MSB bits lost for next date. */ - nfcc_coex->session_start_dtu = info->timestamp_dtu; + nfcc_coex->access_start_dtu = info->timestamp_dtu; /* Setup watchdog timer. */ - diff_dtu = info->timestamp_dtu - cur_time_dtu; + diff_dtu = info->timestamp_dtu - dw3000_get_dtu_time(dw); diff_ms = diff_dtu / dtu_per_ms; nfcc_coex->watchdog_timer.expires = jiffies + diff --git a/kernel/drivers/net/ieee802154/dw3000_nfcc_coex_msg.c b/kernel/drivers/net/ieee802154/dw3000_nfcc_coex_msg.c index 1517678..0058f61 100644 --- a/kernel/drivers/net/ieee802154/dw3000_nfcc_coex_msg.c +++ b/kernel/drivers/net/ieee802154/dw3000_nfcc_coex_msg.c @@ -33,12 +33,6 @@ #define TLV_U32_LEN (4 + 1) /* u32 + ack/nack. */ #define TLV_SLOTS_LEN(nbslots) \ (1 + (8 * (nbslots)) + 1) /* nslots + slots + ack/nack. */ - -/* Error codes for TLV_ERROR type. */ -#define CCC_ERR_LATE_SPIMAVAIL 0 -#define CCC_ERR_SLOT_CONFLICT 1 -#define CCC_ERR_CODE_SZ 2 - #define MSG_NEXT_TLV(buffer, offset) \ (struct dw3000_nfcc_coex_tlv *)((buffer)->msg.tlvs + (offset)) @@ -70,6 +64,8 @@ void dw3000_nfcc_coex_header_put(struct dw3000 *dw, { struct dw3000_nfcc_coex_msg *msg = &buffer->msg; + trace_dw3000_nfcc_coex_header_put(dw, DW3000_NFCC_COEX_VER_ID, + dw->nfcc_coex.tx_seq_num); memcpy(msg->signature, DW3000_NFCC_COEX_SIGNATURE_STR, DW3000_NFCC_COEX_SIGNATURE_LEN); msg->ver_id = DW3000_NFCC_COEX_VER_ID; @@ -79,37 +75,14 @@ void dw3000_nfcc_coex_header_put(struct dw3000 *dw, } /** - * dw3000_nfcc_coex_single_tlv_slot_put() - Fill buffer payload for a single TLV slot. - * @buffer: Message buffer to fill. - * @start: Start date of NFCC session in ms. - * @end: End date of NFCC session in ms. - */ -void dw3000_nfcc_coex_single_tlv_slot_put( - struct dw3000_nfcc_coex_buffer *buffer, u32 start, u32 end) -{ - struct dw3000_nfcc_coex_msg *msg = &buffer->msg; - struct dw3000_nfcc_coex_tlv *tlv; - struct dw3000_nfcc_coex_tlv_slot_list *slot_list; - - tlv = MSG_NEXT_TLV(buffer, buffer->tlvs_len); - msg->nb_tlv++; - tlv->type = TLV_SLOT_LIST; - tlv->len = TLV_SLOTS_LEN(1); - slot_list = (struct dw3000_nfcc_coex_tlv_slot_list *)&tlv->tlv; - slot_list->nb_slots = 1; - slot_list->slots[0].start_sys_time = start; - slot_list->slots[0].end_sys_time = end; - buffer->tlvs_len += TLV_TYPELEN_LEN + tlv->len; -} - -/** * dw3000_nfcc_coex_tlv_u32_put() - Fill buffer payload for a TLV. * @buffer: Message buffer to fill. * @type: Type id of the TLV. * @value: Value of TLV. */ -void dw3000_nfcc_coex_tlv_u32_put(struct dw3000_nfcc_coex_buffer *buffer, - u8 type, u32 value) +static void dw3000_nfcc_coex_tlv_u32_put(struct dw3000_nfcc_coex_buffer *buffer, + enum dw3000_nfcc_coex_tlv_type type, + u32 value) { struct dw3000_nfcc_coex_msg *msg = &buffer->msg; struct dw3000_nfcc_coex_tlv *tlv; @@ -125,26 +98,6 @@ void dw3000_nfcc_coex_tlv_u32_put(struct dw3000_nfcc_coex_buffer *buffer, } /** - * dw3000_nfcc_coex_tlv_slots_put() - Fill buffer payload for a TLV slots. - * @buffer: Message buffer to fill. - * @slot_list: TLV slots. - */ -void dw3000_nfcc_coex_tlv_slots_put( - struct dw3000_nfcc_coex_buffer *buffer, - const struct dw3000_nfcc_coex_tlv_slot_list *slot_list) -{ - struct dw3000_nfcc_coex_msg *msg = &buffer->msg; - struct dw3000_nfcc_coex_tlv *tlv; - - tlv = MSG_NEXT_TLV(buffer, buffer->tlvs_len); - msg->nb_tlv++; - tlv->type = TLV_SLOT_LIST; - tlv->len = TLV_SLOTS_LEN(slot_list->nb_slots); - memcpy(&tlv->tlv, slot_list, sizeof(*slot_list)); - buffer->tlvs_len += TLV_TYPELEN_LEN + tlv->len; -} - -/** * dw3000_nfcc_coex_clock_sync_payload_put() - Fill clock sync frame payload. * @dw: Driver context. * @buffer: Buffer to set with help of handle_access. @@ -154,12 +107,16 @@ dw3000_nfcc_coex_clock_sync_payload_put(struct dw3000 *dw, struct dw3000_nfcc_coex_buffer *buffer) { u32 session_time0_sys_time = - dw3000_dtu_to_sys_time(dw, dw->nfcc_coex.session_start_dtu); + dw3000_dtu_to_sys_time(dw, dw->nfcc_coex.access_start_dtu); + /* Update clock reference. */ + dw->nfcc_coex.session_time0_dtu = dw->nfcc_coex.access_start_dtu; + /* Prepare message. */ trace_dw3000_nfcc_coex_clock_sync_payload_put(dw, session_time0_sys_time); dw3000_nfcc_coex_header_put(dw, buffer); - dw3000_nfcc_coex_tlv_u32_put(buffer, TLV_SESSION_TIME0, + dw3000_nfcc_coex_tlv_u32_put(buffer, + DW3000_NFCC_COEX_TLV_TYPE_SESSION_TIME0, session_time0_sys_time); } @@ -167,7 +124,7 @@ dw3000_nfcc_coex_clock_sync_payload_put(struct dw3000 *dw, * dw3000_nfcc_coex_clock_offset_payload_put() - Fill clock offset payload. * @dw: Driver context. * @buffer: Buffer to set with help of handle_access. - * @clock_offset_sys_time: Offset to add to next ccc schedule. + * @clock_offset_sys_time: Offset to add to next nfcc_coex schedule. */ static void dw3000_nfcc_coex_clock_offset_payload_put( struct dw3000 *dw, struct dw3000_nfcc_coex_buffer *buffer, @@ -176,7 +133,8 @@ static void dw3000_nfcc_coex_clock_offset_payload_put( trace_dw3000_nfcc_coex_clock_offset_payload_put(dw, clock_offset_sys_time); dw3000_nfcc_coex_header_put(dw, buffer); - dw3000_nfcc_coex_tlv_u32_put(buffer, TLV_UWBCNT_OFFS, + dw3000_nfcc_coex_tlv_u32_put(buffer, + DW3000_NFCC_COEX_TLV_TYPE_TLV_UWBCNT_OFFS, clock_offset_sys_time); } @@ -282,35 +240,30 @@ dw3000_nfcc_coex_tlvs_check(struct dw3000 *dw, if (tlvs_len > tlvs_len_max) return -EINVAL; - switch (tlv->type) { - case TLV_SLOT_LIST: + trace_dw3000_nfcc_coex_tlv_check(dw, tlv->type, tlv->len, + tlv->tlv); + if (tlv->type == DW3000_NFCC_COEX_TLV_TYPE_SLOT_LIST_UUS) { /* Reject a new TLV with same type. Behavior not defined. */ if (slot_list) return -EINVAL; slot_list = (const struct dw3000_nfcc_coex_tlv_slot_list *)&tlv->tlv; - /* Keep the pointer ref for testmode. */ - rx_msg_info->slot_list = slot_list; /* Update rx_msg_info. */ if (slot_list->nb_slots > 0) { const struct dw3000_nfcc_coex_tlv_slot *slot = &slot_list->slots[0]; + u32 next_in_session_dtu = + slot->t_start_uus + << DW3000_NFCC_COEX_DTU_PER_UUS_POWER; rx_msg_info->next_slot_found = true; - rx_msg_info->next_timestamp_sys_time = - slot->start_sys_time; - rx_msg_info->next_duration_sys_time = - slot->end_sys_time - - slot->start_sys_time; + rx_msg_info->next_timestamp_dtu = + dw->nfcc_coex.session_time0_dtu + + next_in_session_dtu; + rx_msg_info->next_duration_dtu = + (slot->t_end_uus - slot->t_start_uus) + << DW3000_NFCC_COEX_DTU_PER_UUS_POWER; } - break; - case TLV_ERROR: - trace_dw3000_nfcc_coex_err(dw, "nfcc sent an error"); - break; - default: - trace_dw3000_nfcc_coex_warn( - dw, "ignoring unexpected TLV type"); - break; } } @@ -341,7 +294,7 @@ int dw3000_nfcc_coex_message_check( if (rx_msg_info->next_slot_found) trace_dw3000_nfcc_coex_rx_msg_info( - dw, rx_msg_info->next_timestamp_sys_time, - rx_msg_info->next_duration_sys_time); + dw, rx_msg_info->next_timestamp_dtu, + rx_msg_info->next_duration_dtu); return 0; } diff --git a/kernel/drivers/net/ieee802154/dw3000_nfcc_coex_msg.h b/kernel/drivers/net/ieee802154/dw3000_nfcc_coex_msg.h index cb51efc..d2e0eac 100644 --- a/kernel/drivers/net/ieee802154/dw3000_nfcc_coex_msg.h +++ b/kernel/drivers/net/ieee802154/dw3000_nfcc_coex_msg.h @@ -26,29 +26,48 @@ #include <linux/module.h> #include "dw3000_nfcc_coex.h" +#define TLV_MAX_NB_SLOTS 4 + /* Forward declaration. */ struct dw3000; -/* TLVs types. */ -#define TLV_SESSION_TIME0 1 -#define TLV_SLOT_LIST 2 -#define TLV_UWBCNT_OFFS 3 -#define TLV_ERROR 4 +/** + * enum dw3000_nfcc_coex_tlv_type - TLVs types. + * + * @DW3000_NFCC_COEX_TLV_TYPE_UNSPEC: Invalid command. + * @DW3000_NFCC_COEX_TLV_TYPE_SESSION_TIME0: + * Indicate start of UWB session in RCTU time unit. + * @DW3000_NFCC_COEX_TLV_TYPE_SLOT_LIST: + * Indicate the requested next time slots. + * @DW3000_NFCC_COEX_TLV_TYPE_TLV_UWBCNT_OFFS: + * Indicate the UWB clock offset in V1 protocol. + * @DW3000_NFCC_COEX_TLV_TYPE_ERROR: + * Indicate error condition. + * @DW3000_NFCC_COEX_TLV_TYPE_SLOT_LIST_UUS: + * Indicate the UWB clock offset in V2 protocol. + */ +enum dw3000_nfcc_coex_tlv_type { + DW3000_NFCC_COEX_TLV_TYPE_UNSPEC, -#define TLV_MAX_NB_SLOTS 4 + DW3000_NFCC_COEX_TLV_TYPE_SESSION_TIME0, + DW3000_NFCC_COEX_TLV_TYPE_SLOT_LIST, + DW3000_NFCC_COEX_TLV_TYPE_TLV_UWBCNT_OFFS, + DW3000_NFCC_COEX_TLV_TYPE_ERROR, + DW3000_NFCC_COEX_TLV_TYPE_SLOT_LIST_UUS, +}; /** * struct dw3000_nfcc_coex_tlv_slot - TLV slot definition. */ struct dw3000_nfcc_coex_tlv_slot { /** - * @start_sys_time: Start date in sys time unit. + * @t_start_uus: Start date in 65536*RCTU (close to usec unit). */ - u32 start_sys_time; + u32 t_start_uus; /** - * @end_sys_time: End date in sys time unit. + * @t_end_uus: End date in 65536*RCTU (close to usec unit). */ - u32 end_sys_time; + u32 t_end_uus; }; /** @@ -67,13 +86,6 @@ struct dw3000_nfcc_coex_tlv_slot_list { void dw3000_nfcc_coex_header_put(struct dw3000 *dw, struct dw3000_nfcc_coex_buffer *buffer); -void dw3000_nfcc_coex_single_tlv_slot_put( - struct dw3000_nfcc_coex_buffer *buffer, u32 start, u32 end); -void dw3000_nfcc_coex_tlv_u32_put(struct dw3000_nfcc_coex_buffer *buffer, - u8 type, u32 value); -void dw3000_nfcc_coex_tlv_slots_put( - struct dw3000_nfcc_coex_buffer *buffer, - const struct dw3000_nfcc_coex_tlv_slot_list *slot_list); int dw3000_nfcc_coex_message_send(struct dw3000 *dw); int dw3000_nfcc_coex_message_check( struct dw3000 *dw, const struct dw3000_nfcc_coex_buffer *buffer, diff --git a/kernel/drivers/net/ieee802154/dw3000_nfcc_coex_testmode.c b/kernel/drivers/net/ieee802154/dw3000_nfcc_coex_testmode.c deleted file mode 100644 index e7a9d1f..0000000 --- a/kernel/drivers/net/ieee802154/dw3000_nfcc_coex_testmode.c +++ /dev/null @@ -1,335 +0,0 @@ -/* - * This file is part of the UWB stack for linux. - * - * Copyright (c) 2021 Qorvo US, Inc. - * - * This software is provided under the GNU General Public License, version 2 - * (GPLv2), as well as under a Qorvo commercial license. - * - * You may choose to use this software under the terms of the GPLv2 License, - * version 2 ("GPLv2"), as published by the Free Software Foundation. - * You should have received a copy of the GPLv2 along with this program. If - * not, see <http://www.gnu.org/licenses/>. - * - * This program is distributed under the GPLv2 in the hope that it will be - * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GPLv2 for more - * details. - * - * If you cannot meet the requirements of the GPLv2, you may not use this - * software for any purpose without first obtaining a commercial license from - * Qorvo. Please contact Qorvo to inquire about licensing terms. - */ - -#include "dw3000_nfcc_coex_testmode.h" -#include "dw3000_nfcc_coex_msg.h" -#include "dw3000_nfcc_coex_core.h" -#include "dw3000_nfcc_coex_buffer.h" -#include "dw3000_nfcc_coex.h" -#include "dw3000.h" -#include "dw3000_trc.h" -#include "dw3000_core.h" - -#define CCC_TEST_SLOT_DELTA_PC 15 /* Percent. */ -/* Request an end of access without error on current access. */ -#define DW3000_CCC_RETURN_STOP 1 - -/** - * dw3000_nfcc_coex_generate_test_slots() - Generates a series of valid, interleaved slots. - * @in: Slots found in incomming message. - * @out: Slots output to write. - * @margin_pc: Margin in pourcent. - * @slot_after: True when reuse last free slot duration is permit. - * - * Return: 0 on success, else an error. - * - * For instance, if given the input: - * [t_start0, t_end0], [t_start1, t_end1], [t_start2, t_end2] - * We generate the output: - * [t_end0 + DELTA0, t_start1 - DELTA0], [t_end1 + DELTA1, t_start2 - DELTA1] - * Where DELTAn = (( t_startn+1 - t_endn ) * margin_pc) / 100 - * - * NB : - * - assumes input slots are valid, i.e in->nb_slots <= TLV_MAX_NB_SLOTS - * - If slot_after is passed true, append a last slot AFTER all NFCC slots - */ -static int dw3000_nfcc_coex_generate_test_slots( - const struct dw3000_nfcc_coex_tlv_slot_list *in, - struct dw3000_nfcc_coex_tlv_slot_list *out, u32 margin_pc, - bool slot_after) -{ - int i; - u32 free_slot_duration; - u32 delta_i; - - if (in->nb_slots == 0) - return -1; - - out->nb_slots = in->nb_slots - 1; - for (i = 0; i < out->nb_slots; i++) { - free_slot_duration = in->slots[i + 1].end_sys_time - - in->slots[i].start_sys_time; - delta_i = (free_slot_duration * margin_pc) / 100; - /* gen slot : [t_endi + DELTAi, t_starti+1 - DELTAi] */ - out->slots[i].start_sys_time = - in->slots[i].end_sys_time + delta_i; - out->slots[i].end_sys_time = - in->slots[i + 1].start_sys_time - delta_i; - } - - if (slot_after) { - if (out->nb_slots == 0) { - /* we need a value for free_slot_duration and delta_i. */ - free_slot_duration = in->slots[0].end_sys_time - - in->slots[0].start_sys_time; - delta_i = (free_slot_duration * margin_pc) / 100; - } - /* Add a last slot reusing last free_slot_duration and delta_i. */ - out->nb_slots++; - out->slots[i].start_sys_time = - in->slots[i].end_sys_time + delta_i; - out->slots[i].end_sys_time = in->slots[i].end_sys_time - - delta_i + free_slot_duration; - } - return 0; -} - -/** - * dw3000_nfcc_coex_testmode_config_spi_avail_handler() - Config testmode callback. - * @dw: Driver context. - * @buffer: Memory read from scratch memory. - * - * Return: 0 on success, else an error. - */ -static int dw3000_nfcc_coex_testmode_config_spi_avail_handler( - struct dw3000 *dw, const struct dw3000_nfcc_coex_buffer *buffer) -{ - const struct dw3000_nfcc_coex_testmode_config *test_conf = - dw->nfcc_coex.testmode_config; - const u32 dtu_per_ms = dw->llhw->dtu_freq_hz / 1000; - struct dw3000_nfcc_coex_rx_msg_info rx_msg_info = {}; - struct dw3000_nfcc_coex_buffer out = {}; - struct dw3000_nfcc_coex_tlv_slot_list out_slot_list = {}; - u32 cur_time_dtu, next_slot_dtu; - u32 diff_dtu, diff_ms; - int rc; - - dw->nfcc_coex.testmode_round_count++; - - rc = dw3000_nfcc_coex_message_check(dw, buffer, &rx_msg_info); - if (rc) - return rc; - - if (!rx_msg_info.next_slot_found) - return dw3000_nfcc_coex_disable(dw); - - dw3000_nfcc_coex_header_put(dw, &out); - cur_time_dtu = dw3000_get_dtu_time(dw); - - /* Behavior depends on test mode. */ - switch (test_conf->mode) { - case DW3000_CCC_TEST_DIRECT: - break; - case DW3000_CCC_TEST_WAIT: - /* Margin is typically 100ms hence msleep is used. */ - msleep(test_conf->margin_ms); - break; - case DW3000_CCC_TEST_LATE: - if (rx_msg_info.next_timestamp_sys_time == 0) - break; - next_slot_dtu = dw3000_sys_time_to_dtu( - dw, rx_msg_info.next_timestamp_sys_time, cur_time_dtu); - diff_dtu = next_slot_dtu - cur_time_dtu; - diff_ms = diff_dtu / dtu_per_ms; - if (test_conf->RRcount == 0 || - dw->nfcc_coex.testmode_round_count++ % test_conf->RRcount == - 0) { - /* Margin is typically 100ms and diff_ms is a - * multiple of 96ms, hence msleep is used. */ - msleep(diff_ms + test_conf->margin_ms); - break; - } - if (diff_dtu > dw3000_nfcc_coex_margin_dtu) { - /* Difference is a multiple of 96ms, hence msleep - * is used. */ - msleep((diff_dtu - dw3000_nfcc_coex_margin_dtu) / - dtu_per_ms); - } - break; - case DW3000_CCC_TEST_CONFLICT: - if (dw3000_nfcc_coex_generate_test_slots( - rx_msg_info.slot_list, &out_slot_list, - CCC_TEST_SLOT_DELTA_PC, true)) - break; - if ((test_conf->RRcount == 0 || - (dw->nfcc_coex.testmode_round_count++ % - test_conf->RRcount == - 0)) && - test_conf->conflict_slot_idx < out_slot_list.nb_slots) { - /* We want a conflict this round - * and we have enough slot, given conflict_slot_idx. - * So, just copy the input slot values. */ - const int n = test_conf->conflict_slot_idx; - const struct dw3000_nfcc_coex_tlv_slot *slot_b = - &rx_msg_info.slot_list->slots[n]; - struct dw3000_nfcc_coex_tlv_slot *slot_a = - &out_slot_list.slots[n]; - - *slot_a = *slot_b; - } - dw3000_nfcc_coex_tlv_slots_put(&out, &out_slot_list); - break; - case DW3000_CCC_TEST_SLEEP_OFFSET: - dw3000_nfcc_coex_tlv_u32_put(&out, TLV_UWBCNT_OFFS, - test_conf->offset_ms); - break; - default: - return DW3000_CCC_RETURN_STOP; - } - - return dw3000_nfcc_coex_write_buffer(dw, &out, MSG_LEN(out)); -} - -/** - * dw3000_nfcc_coex_testmode_write_msg() - Write custom message for NFCC. - * @dw: Driver context. - * @session_time0: Offset in ms to add to current time. - * @start: Start date of NFCC session in ms. - * @end: End date of NFCC session in ms. - * - * Return: 0 on success, else an error. - */ -static int dw3000_nfcc_coex_testmode_write_msg(struct dw3000 *dw, - u32 session_time0, u32 start, - u32 end) -{ - u32 absolute_session_time0_sys; - u32 start_time_dtu; - u64 session_time0_dtu; - struct dw3000_nfcc_coex_buffer buffer; - - start_time_dtu = dw3000_get_dtu_time(dw); - dw3000_nfcc_coex_header_put(dw, &buffer); - /* session_time0 is the offset of the NFCC ranging start time in - * microseconds. The absolute NFCC ranging start time is transmitted - * to the NFCC in SYS_TIME. */ - session_time0_dtu = - ((u64)session_time0 * (u64)(dw->llhw->dtu_freq_hz)) / 1000000; - absolute_session_time0_sys = (start_time_dtu + session_time0_dtu) - << DW3000_DTU_PER_SYS_POWER; - - dw3000_nfcc_coex_tlv_u32_put(&buffer, TLV_SESSION_TIME0, - absolute_session_time0_sys); - - if (start && end) { - start *= (u64)(dw->llhw->dtu_freq_hz) / 1000000; - start += start_time_dtu; - end *= (u64)(dw->llhw->dtu_freq_hz) / 1000000; - end += start_time_dtu; - dw3000_nfcc_coex_single_tlv_slot_put(&buffer, start, end); - } - - return dw3000_nfcc_coex_write_buffer(dw, &buffer, MSG_LEN(buffer)); -} - -/** - * dw3000_nfcc_coex_testmode_session_spi_avail_handler() - Start testmode callback. - * @dw: Driver context. - * @buffer: Memory read from scratch memory. - * - * Return: 0 on success, else an error. - */ -static int dw3000_nfcc_coex_testmode_session_spi_avail_handler( - struct dw3000 *dw, const struct dw3000_nfcc_coex_buffer *buffer) -{ - struct dw3000_nfcc_coex_rx_msg_info rx_msg_info = {}; - struct dw3000_nfcc_coex_buffer out = {}; - u32 curtime_dtu = 0; - u32 nextslot_dtu = 0; - u32 diff_dtu; - int rc = -1; - - rc = dw3000_nfcc_coex_message_check(dw, buffer, &rx_msg_info); - if (rc) - return rc; - - if (!rx_msg_info.next_slot_found) - return dw3000_nfcc_coex_disable(dw); - - curtime_dtu = dw3000_get_dtu_time(dw); - nextslot_dtu = dw3000_sys_time_to_dtu( - dw, rx_msg_info.next_timestamp_sys_time, curtime_dtu); - diff_dtu = nextslot_dtu - curtime_dtu; - if (diff_dtu > dw3000_nfcc_coex_margin_dtu) { - /* Wait for next slot, use a margin, as it looks like we do have a - * lot of fluctuations on NFCC side, leading to TXLATE when trying small - * delay. - * The next message is send in dw3000_isr_handle_spi_ready() on the wake up. - */ - rc = dw3000_nfcc_coex_sleep( - dw, diff_dtu - dw3000_nfcc_coex_margin_dtu); - } else { - /* The delay is too short to sleep before respond to the NFCC. */ - dw3000_nfcc_coex_header_put(dw, &out); - rc = dw3000_nfcc_coex_write_buffer(dw, &out, MSG_LEN(out)); - } - return rc; -} - -/** - * dw3000_nfcc_coex_testmode_session() - Start one custom NFCC session. - * @dw: Driver context. - * @chan: Channel number. - * @session_time0: Offset in ms to add to current time. - * @start: Start date of NFCC session in ms. - * @end: End date of NFCC session in ms. - * - * Return: 0 on success, else an error. - */ -int dw3000_nfcc_coex_testmode_session(struct dw3000 *dw, u8 chan, - u32 session_time0, u32 start, u32 end) -{ - int r; - - r = dw3000_nfcc_coex_enable( - dw, chan, dw3000_nfcc_coex_testmode_session_spi_avail_handler); - if (r) - return r; - - trace_dw3000_nfcc_coex_warn(dw, "testmode start"); - return dw3000_nfcc_coex_testmode_write_msg(dw, session_time0, start, - end); -} - -/** - * dw3000_nfcc_coex_testmode_config() - Process testmode config. - * @dw: Driver context. - * @testmode_config: Pointer on persistente config to use. - * - * Return: 0 on success, else an error. - */ -int dw3000_nfcc_coex_testmode_config( - struct dw3000 *dw, - const struct dw3000_nfcc_coex_testmode_config *testmode_config) -{ - int r; - - if (!testmode_config) { - trace_dw3000_nfcc_coex_err( - dw, "can't start testmode with a NULL conf"); - return -EINVAL; - } - - dw->nfcc_coex.testmode_config = testmode_config; - dw->nfcc_coex.testmode_round_count = 0; - r = dw3000_nfcc_coex_enable( - dw, testmode_config->channel, - dw3000_nfcc_coex_testmode_config_spi_avail_handler); - if (r) - return r; - - trace_dw3000_nfcc_coex_warn(dw, "testmode run config"); - return dw3000_nfcc_coex_testmode_write_msg( - dw, testmode_config->session_time0, testmode_config->start, - testmode_config->end); -} diff --git a/kernel/drivers/net/ieee802154/dw3000_nfcc_coex_testmode.h b/kernel/drivers/net/ieee802154/dw3000_nfcc_coex_testmode.h deleted file mode 100644 index 10e5c90..0000000 --- a/kernel/drivers/net/ieee802154/dw3000_nfcc_coex_testmode.h +++ /dev/null @@ -1,84 +0,0 @@ -/* - * This file is part of the UWB stack for linux. - * - * Copyright (c) 2021 Qorvo US, Inc. - * - * This software is provided under the GNU General Public License, version 2 - * (GPLv2), as well as under a Qorvo commercial license. - * - * You may choose to use this software under the terms of the GPLv2 License, - * version 2 ("GPLv2"), as published by the Free Software Foundation. - * You should have received a copy of the GPLv2 along with this program. If - * not, see <http://www.gnu.org/licenses/>. - * - * This program is distributed under the GPLv2 in the hope that it will be - * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GPLv2 for more - * details. - * - * If you cannot meet the requirements of the GPLv2, you may not use this - * software for any purpose without first obtaining a commercial license from - * Qorvo. Please contact Qorvo to inquire about licensing terms. - */ -#ifndef __DW3000_NFCC_COEX_TESTMODE_H -#define __DW3000_NFCC_COEX_TESTMODE_H - -#include <linux/module.h> - -/* Forward declaration. */ -struct dw3000; - -/** - * struct dw3000_nfcc_coex_testmode_config - Test config used in testmode. - */ -struct dw3000_nfcc_coex_testmode_config { - /** - * @mode: test mode identifier. - */ - enum { DW3000_CCC_TEST_DIRECT, - DW3000_CCC_TEST_WAIT, - DW3000_CCC_TEST_LATE, - DW3000_CCC_TEST_CONFLICT, - DW3000_CCC_TEST_SLEEP_OFFSET, - } mode; - /** - * @margin_ms: Delay in ms to apply after Ranging Round(RR). - */ - u32 margin_ms; - /** - * @RRcount: Ranging Round count. - */ - u32 RRcount; - /** - * @conflict_slot_idx: slot index with conflict on date. - */ - u32 conflict_slot_idx; - /** - * @offset_ms: Duration in ms to add to NFCC base time; - */ - u32 offset_ms; - /** - * @channel: Channel number. - */ - u8 channel; - /** - * @session_time0: Offset in ms to add to SESSION_TIME0. - */ - u32 session_time0; - /** - * @start: Start offset in ms for the first slot. - */ - u32 start; - /** - * @end: End offset in ms for the first slot. - */ - u32 end; -}; - -int dw3000_nfcc_coex_testmode_session(struct dw3000 *dw, u8 chan, - u32 session_time0, u32 start, u32 end); -int dw3000_nfcc_coex_testmode_config( - struct dw3000 *dw, - const struct dw3000_nfcc_coex_testmode_config *testmode_config); - -#endif /* __DW3000_NFCC_COEX_TESTMODE_H */ diff --git a/kernel/drivers/net/ieee802154/dw3000_stm.c b/kernel/drivers/net/ieee802154/dw3000_stm.c index 0fb84b8..4b0f1cb 100644 --- a/kernel/drivers/net/ieee802154/dw3000_stm.c +++ b/kernel/drivers/net/ieee802154/dw3000_stm.c @@ -87,8 +87,8 @@ int dw3000_enqueue_generic(struct dw3000 *dw, struct dw3000_stm_command *cmd) stm->pending_work |= work; stm->generic_work = cmd; wake_up_locked(&stm->work_wq); - while (-ERESTARTSYS == wait_event_interruptible_locked_irq(stm->work_wq, - !(stm->pending_work & work))) {} + wait_event_interruptible_locked_irq(stm->work_wq, + !(stm->pending_work & work)); spin_unlock_irqrestore(&stm->work_wq.lock, flags); mutex_unlock(&stm->mtx); return cmd->ret; diff --git a/kernel/drivers/net/ieee802154/dw3000_testmode.c b/kernel/drivers/net/ieee802154/dw3000_testmode.c index 3afb2a4..fea6360 100644 --- a/kernel/drivers/net/ieee802154/dw3000_testmode.c +++ b/kernel/drivers/net/ieee802154/dw3000_testmode.c @@ -29,7 +29,6 @@ #include "dw3000_trc.h" #include "dw3000_testmode.h" #include "dw3000_testmode_nl.h" -#include "dw3000_nfcc_coex_testmode.h" static const struct nla_policy dw3000_tm_policy[DW3000_TM_ATTR_MAX + 1] = { [DW3000_TM_ATTR_CMD] = { .type = NLA_U32 }, @@ -40,14 +39,6 @@ static const struct nla_policy dw3000_tm_policy[DW3000_TM_ATTR_MAX + 1] = { [DW3000_TM_ATTR_OTP_ADDR] = { .type = NLA_U16 }, [DW3000_TM_ATTR_OTP_VAL] = { .type = NLA_U32 }, [DW3000_TM_ATTR_OTP_DONE] = { .type = NLA_U8 }, - [DW3000_TM_ATTR_CCC_TIME0] = { .type = NLA_U32 }, - [DW3000_TM_ATTR_CCC_CHANNEL] = { .type = NLA_U8 }, - [DW3000_TM_ATTR_CCC_TSTART] = { .type = NLA_U32 }, - [DW3000_TM_ATTR_CCC_TEND] = { .type = NLA_U32 }, - [DW3000_TM_ATTR_CCC_MARGIN_MS] = { .type = NLA_U32 }, - [DW3000_TM_ATTR_CCC_RR_COUNT] = { .type = NLA_U32 }, - [DW3000_TM_ATTR_CCC_OFFSET_MS] = { .type = NLA_U32 }, - [DW3000_TM_ATTR_CCC_CONFLICT_SLOT_IDX] = { .type = NLA_U32 }, [DW3000_TM_ATTR_DEEP_SLEEP_DELAY_MS] = { .type = NLA_U32 }, [DW3000_TM_ATTR_CONTTX_FRAME_LENGHT] = { .type = NLA_U32 }, [DW3000_TM_ATTR_CONTTX_RATE] = { .type = NLA_U32 }, @@ -258,318 +249,6 @@ nla_put_failure: return rc; } -/* helper function for common CCC command returning their rc code */ -static int tm_ccc_cmd_done(struct dw3000 *dw, struct mcps802154_llhw *llhw, - u8 ccc_cmd_rc) -{ - struct sk_buff *msg; - int rc; - - msg = mcps802154_testmode_alloc_reply_skb(llhw, 2 * sizeof(u32)); - if (!msg) { - dev_err(dw->dev, "failed to alloc skb reply\n"); - return -ENOMEM; - } - - /* Append ccc cmd rc to the netlink message */ - rc = nla_put_u8(msg, DW3000_TM_ATTR_CCC_CMD_RC, ccc_cmd_rc); - if (rc) { - dev_err(dw->dev, "failed to put testmode ccc cmd rc: %d\n", rc); - goto nla_put_failure; - } - return mcps802154_testmode_reply(llhw, msg); - -nla_put_failure: - nlmsg_free(msg); - return rc; -} - -static int do_tm_cmd_ccc_start(struct dw3000 *dw, const void *in, void *out) -{ - const struct do_tm_cmd_params *params = in; - u8 channel; - u32 session_time0; - u32 start = 0; - u32 end = 0; - u8 ccc_cmd_rc; - - /* Verify the ccc channel attribute exists */ - if (!params->nl_attr[DW3000_TM_ATTR_CCC_CHANNEL]) - return -EINVAL; - channel = nla_get_u8(params->nl_attr[DW3000_TM_ATTR_CCC_CHANNEL]); - - /* Verify the ccc time0 attribute exists */ - if (!params->nl_attr[DW3000_TM_ATTR_CCC_TIME0]) - return -EINVAL; - session_time0 = nla_get_u32(params->nl_attr[DW3000_TM_ATTR_CCC_TIME0]); - - if (params->nl_attr[DW3000_TM_ATTR_CCC_TSTART] && - params->nl_attr[DW3000_TM_ATTR_CCC_TEND]) { - start = nla_get_u32(params->nl_attr[DW3000_TM_ATTR_CCC_TSTART]); - end = nla_get_u32(params->nl_attr[DW3000_TM_ATTR_CCC_TEND]); - } - - if (dw3000_nfcc_coex_testmode_session(dw, channel, session_time0, start, - end)) - ccc_cmd_rc = 0; - else - ccc_cmd_rc = 1; - - return tm_ccc_cmd_done(dw, params->llhw, ccc_cmd_rc); -} - -static int do_tm_cmd_ccc_test_scratch(struct dw3000 *dw, const void *in, - void *out) -{ - const struct do_tm_cmd_params *params = in; - u8 ccc_cmd_rc; - - /* TODO: write to the whole memory, read back, validate */ - ccc_cmd_rc = 1; - - return tm_ccc_cmd_done(dw, params->llhw, ccc_cmd_rc); -} - -static int do_tm_cmd_ccc_test_spi1(struct dw3000 *dw, const void *in, void *out) -{ - const struct do_tm_cmd_params *params = in; - u8 ccc_cmd_rc; - - /** - * TODO: test SPI1 - * - enable SPI1 - * - check SPI1 is enabled - * - release SPI1 - * - check SPI1 is disabled - */ - ccc_cmd_rc = 1; - - return tm_ccc_cmd_done(dw, params->llhw, ccc_cmd_rc); -} - -static int do_tm_cmd_ccc_test_spi2(struct dw3000 *dw, const void *in, void *out) -{ - const struct do_tm_cmd_params *params = in; - u8 ccc_cmd_rc; - - /** - * TODO: test SPI2 - * - enable SPI2 - * - wait for release (from other side code or watchdog?) - */ - ccc_cmd_rc = 1; - - return tm_ccc_cmd_done(dw, params->llhw, ccc_cmd_rc); -} - -static int do_tm_cmd_ccc_test_direct(struct dw3000 *dw, const void *in, - void *out) -{ - const struct do_tm_cmd_params *params = in; - u8 ccc_cmd_rc; - static struct dw3000_nfcc_coex_testmode_config conf = { - .mode = DW3000_CCC_TEST_DIRECT, - .start = 0, - .end = 0, - }; - - /* Verify the ccc channel attribute exists */ - if (!params->nl_attr[DW3000_TM_ATTR_CCC_CHANNEL]) - return -EINVAL; - conf.channel = nla_get_u8(params->nl_attr[DW3000_TM_ATTR_CCC_CHANNEL]); - - /* Verify the ccc time0 attribute exists */ - if (!params->nl_attr[DW3000_TM_ATTR_CCC_TIME0]) - return -EINVAL; - conf.session_time0 = - nla_get_u32(params->nl_attr[DW3000_TM_ATTR_CCC_TIME0]); - - if (dw3000_nfcc_coex_testmode_config(dw, &conf)) - ccc_cmd_rc = 0; - else - ccc_cmd_rc = 1; - - return tm_ccc_cmd_done(dw, params->llhw, ccc_cmd_rc); -} - -static int do_tm_cmd_ccc_test_wait(struct dw3000 *dw, const void *in, void *out) -{ - const struct do_tm_cmd_params *params = in; - u8 ccc_cmd_rc; - static struct dw3000_nfcc_coex_testmode_config conf = { - .mode = DW3000_CCC_TEST_WAIT, - .margin_ms = 0, - .start = 0, - .end = 0, - }; - - /* Verify the ccc channel attribute exists */ - if (!params->nl_attr[DW3000_TM_ATTR_CCC_CHANNEL]) - return -EINVAL; - conf.channel = nla_get_u8(params->nl_attr[DW3000_TM_ATTR_CCC_CHANNEL]); - - /* Verify the ccc time0 attribute exists */ - if (!params->nl_attr[DW3000_TM_ATTR_CCC_TIME0]) - return -EINVAL; - conf.session_time0 = - nla_get_u32(params->nl_attr[DW3000_TM_ATTR_CCC_TIME0]); - - /* margin_ms is optional */ - if (params->nl_attr[DW3000_TM_ATTR_CCC_MARGIN_MS]) - conf.margin_ms = nla_get_u32( - params->nl_attr[DW3000_TM_ATTR_CCC_MARGIN_MS]); - - if (dw3000_nfcc_coex_testmode_config(dw, &conf)) - ccc_cmd_rc = 0; - else - ccc_cmd_rc = 1; - - return tm_ccc_cmd_done(dw, params->llhw, ccc_cmd_rc); -} - -static int do_tm_cmd_ccc_test_late(struct dw3000 *dw, const void *in, void *out) -{ - const struct do_tm_cmd_params *params = in; - u8 ccc_cmd_rc; - static struct dw3000_nfcc_coex_testmode_config conf = { - .mode = DW3000_CCC_TEST_LATE, - .margin_ms = 0, - .RRcount = 0, - .start = 0, - .end = 0, - }; - - /* Verify the ccc channel attribute exists */ - if (!params->nl_attr[DW3000_TM_ATTR_CCC_CHANNEL]) - return -EINVAL; - conf.channel = nla_get_u8(params->nl_attr[DW3000_TM_ATTR_CCC_CHANNEL]); - - /* Verify the ccc time0 attribute exists */ - if (!params->nl_attr[DW3000_TM_ATTR_CCC_TIME0]) - return -EINVAL; - conf.session_time0 = - nla_get_u32(params->nl_attr[DW3000_TM_ATTR_CCC_TIME0]); - - /* margin_ms is mandatory */ - if (!params->nl_attr[DW3000_TM_ATTR_CCC_MARGIN_MS]) - return -EINVAL; - conf.margin_ms = - nla_get_u32(params->nl_attr[DW3000_TM_ATTR_CCC_MARGIN_MS]); - - /* RRcount is optional */ - if (params->nl_attr[DW3000_TM_ATTR_CCC_RR_COUNT]) - conf.RRcount = nla_get_u32( - params->nl_attr[DW3000_TM_ATTR_CCC_RR_COUNT]); - - if (dw3000_nfcc_coex_testmode_config(dw, &conf)) - ccc_cmd_rc = 0; - else - ccc_cmd_rc = 1; - - return tm_ccc_cmd_done(dw, params->llhw, ccc_cmd_rc); -} - -static int do_tm_cmd_ccc_test_conflict(struct dw3000 *dw, const void *in, - void *out) -{ - const struct do_tm_cmd_params *params = in; - u8 ccc_cmd_rc; - static struct dw3000_nfcc_coex_testmode_config conf = { - .mode = DW3000_CCC_TEST_CONFLICT, - .RRcount = 0, - .start = 0, - .end = 0, - }; - - /* Verify the ccc channel attribute exists */ - if (!params->nl_attr[DW3000_TM_ATTR_CCC_CHANNEL]) - return -EINVAL; - conf.channel = nla_get_u8(params->nl_attr[DW3000_TM_ATTR_CCC_CHANNEL]); - - /* Verify the ccc time0 attribute exists */ - if (!params->nl_attr[DW3000_TM_ATTR_CCC_TIME0]) - return -EINVAL; - conf.session_time0 = - nla_get_u32(params->nl_attr[DW3000_TM_ATTR_CCC_TIME0]); - - /* conflict_slot_idx is mandatory */ - if (!params->nl_attr[DW3000_TM_ATTR_CCC_CONFLICT_SLOT_IDX]) - return -EINVAL; - conf.conflict_slot_idx = nla_get_u32( - params->nl_attr[DW3000_TM_ATTR_CCC_CONFLICT_SLOT_IDX]); - - /* RRcount is optional */ - if (params->nl_attr[DW3000_TM_ATTR_CCC_RR_COUNT]) - conf.RRcount = nla_get_u32( - params->nl_attr[DW3000_TM_ATTR_CCC_RR_COUNT]); - - if (dw3000_nfcc_coex_testmode_config(dw, &conf)) - ccc_cmd_rc = 0; - else - ccc_cmd_rc = 1; - - return tm_ccc_cmd_done(dw, params->llhw, ccc_cmd_rc); -} - -static int do_tm_cmd_ccc_test_offset(struct dw3000 *dw, const void *in, - void *out) -{ - const struct do_tm_cmd_params *params = in; - u8 ccc_cmd_rc; - static struct dw3000_nfcc_coex_testmode_config conf = { - .mode = DW3000_CCC_TEST_SLEEP_OFFSET, - .offset_ms = 0, - .start = 0, - .end = 0, - }; - - /* Verify the ccc channel attribute exists */ - if (!params->nl_attr[DW3000_TM_ATTR_CCC_CHANNEL]) - return -EINVAL; - conf.channel = nla_get_u8(params->nl_attr[DW3000_TM_ATTR_CCC_CHANNEL]); - - /* Verify the ccc time0 attribute exists */ - if (!params->nl_attr[DW3000_TM_ATTR_CCC_TIME0]) - return -EINVAL; - conf.session_time0 = - nla_get_u32(params->nl_attr[DW3000_TM_ATTR_CCC_TIME0]); - - /* offset_ms is mandatory */ - if (!params->nl_attr[DW3000_TM_ATTR_CCC_OFFSET_MS]) - return -EINVAL; - conf.offset_ms = - nla_get_u32(params->nl_attr[DW3000_TM_ATTR_CCC_OFFSET_MS]); - if (dw3000_nfcc_coex_testmode_config(dw, &conf)) - ccc_cmd_rc = 0; - else - ccc_cmd_rc = 1; - - return tm_ccc_cmd_done(dw, params->llhw, ccc_cmd_rc); -} - -static int do_tm_cmd_ccc_read_tlvs(struct dw3000 *dw, const void *in, void *out) -{ - const struct do_tm_cmd_params *params = in; - u8 ccc_cmd_rc; - - /* TODO: read tlvs values */ - ccc_cmd_rc = 1; - - return tm_ccc_cmd_done(dw, params->llhw, ccc_cmd_rc); -} - -static int do_tm_cmd_ccc_write_tlvs(struct dw3000 *dw, const void *in, - void *out) -{ - const struct do_tm_cmd_params *params = in; - u8 ccc_cmd_rc; - - /* TODO: write tlvs values */ - ccc_cmd_rc = 1; - - return tm_ccc_cmd_done(dw, params->llhw, ccc_cmd_rc); -} - static int do_tm_cmd_deep_sleep(struct dw3000 *dw, const void *in, void *out) { const struct do_tm_cmd_params *params = in; @@ -647,17 +326,6 @@ int dw3000_tm_cmd(struct mcps802154_llhw *llhw, void *data, int len) [DW3000_TM_CMD_STOP_TX_CWTONE] = do_tm_cmd_stop_tx_cwtone, [DW3000_TM_CMD_START_CONTINUOUS_TX] = do_tm_cmd_start_cont_tx, [DW3000_TM_CMD_STOP_CONTINUOUS_TX] = do_tm_cmd_stop_cont_tx, - [DW3000_TM_CMD_CCC_START] = do_tm_cmd_ccc_start, - [DW3000_TM_CMD_CCC_TEST_SCRATCH] = do_tm_cmd_ccc_test_scratch, - [DW3000_TM_CMD_CCC_TEST_SPI1] = do_tm_cmd_ccc_test_spi1, - [DW3000_TM_CMD_CCC_TEST_SPI2] = do_tm_cmd_ccc_test_spi2, - [DW3000_TM_CMD_CCC_READ_TLVS] = do_tm_cmd_ccc_read_tlvs, - [DW3000_TM_CMD_CCC_WRITE_TLVS] = do_tm_cmd_ccc_write_tlvs, - [DW3000_TM_CMD_CCC_TEST_DIRECT] = do_tm_cmd_ccc_test_direct, - [DW3000_TM_CMD_CCC_TEST_WAIT] = do_tm_cmd_ccc_test_wait, - [DW3000_TM_CMD_CCC_TEST_LATE] = do_tm_cmd_ccc_test_late, - [DW3000_TM_CMD_CCC_TEST_CONFLICT] = do_tm_cmd_ccc_test_conflict, - [DW3000_TM_CMD_CCC_TEST_OFFSET] = do_tm_cmd_ccc_test_offset, [DW3000_TM_CMD_DEEP_SLEEP] = do_tm_cmd_deep_sleep, }; u32 tm_cmd; diff --git a/kernel/drivers/net/ieee802154/dw3000_testmode_nl.h b/kernel/drivers/net/ieee802154/dw3000_testmode_nl.h index 68d4c81..0fa1495 100644 --- a/kernel/drivers/net/ieee802154/dw3000_testmode_nl.h +++ b/kernel/drivers/net/ieee802154/dw3000_testmode_nl.h @@ -61,15 +61,6 @@ enum dw3000_tm_attr { DW3000_TM_ATTR_OTP_ADDR, DW3000_TM_ATTR_OTP_VAL, DW3000_TM_ATTR_OTP_DONE, - DW3000_TM_ATTR_CCC_TIME0, - DW3000_TM_ATTR_CCC_CHANNEL, - DW3000_TM_ATTR_CCC_TSTART, - DW3000_TM_ATTR_CCC_TEND, - DW3000_TM_ATTR_CCC_MARGIN_MS, - DW3000_TM_ATTR_CCC_RR_COUNT, - DW3000_TM_ATTR_CCC_OFFSET_MS, - DW3000_TM_ATTR_CCC_CONFLICT_SLOT_IDX, - DW3000_TM_ATTR_CCC_CMD_RC, DW3000_TM_ATTR_DEEP_SLEEP_DELAY_MS, DW3000_TM_ATTR_CONTTX_FRAME_LENGHT, DW3000_TM_ATTR_CONTTX_RATE, @@ -98,7 +89,7 @@ enum dw3000_tm_cmd { DW3000_TM_CMD_START_CONTINUOUS_TX, DW3000_TM_CMD_STOP_CONTINUOUS_TX, - /* CCC NFCC/AP coexistence test commands */ + /* TODO: CCC enum could be remove, as their are no more used. */ DW3000_TM_CMD_CCC_START, DW3000_TM_CMD_CCC_TEST_SCRATCH, DW3000_TM_CMD_CCC_TEST_SPI1, diff --git a/kernel/drivers/net/ieee802154/dw3000_trc.h b/kernel/drivers/net/ieee802154/dw3000_trc.h index ffd42f0..a69ab40 100644 --- a/kernel/drivers/net/ieee802154/dw3000_trc.h +++ b/kernel/drivers/net/ieee802154/dw3000_trc.h @@ -30,6 +30,7 @@ #include "dw3000.h" #include "dw3000_nfcc_coex.h" +#include "dw3000_nfcc_coex_msg.h" #include "dw3000_testmode_nl.h" #include "dw3000_core_reg.h" #include "dw3000_core.h" @@ -248,6 +249,33 @@ TRACE_DEFINE_ENUM(DW3000_PWR_TX); #define TX_FRAME_INFO_FLAGS_PR_ARG \ __print_flags(__entry->flags, "|", TX_FRAME_INFO_FLAGS) +#define dw3000_nfcc_coex_tlv_type_name(name) \ + { \ + DW3000_NFCC_COEX_TLV_TYPE_##name, #name \ + } + +#define DW3000_NFCC_COEX_TLV_TYPE_ENTRY \ + __field(enum dw3000_nfcc_coex_tlv_type, type) +#define DW3000_NFCC_COEX_TLV_TYPE_ASSIGN __entry->type = type +#define DW3000_NFCC_COEX_TLV_TYPE_PR_FMT "type: %s" +/* clang-format off */ +#define DW3000_NFCC_COEX_TLV_TYPE_SYMBOLS \ + dw3000_nfcc_coex_tlv_type_name(UNSPEC), \ + dw3000_nfcc_coex_tlv_type_name(SESSION_TIME0), \ + dw3000_nfcc_coex_tlv_type_name(SLOT_LIST), \ + dw3000_nfcc_coex_tlv_type_name(TLV_UWBCNT_OFFS), \ + dw3000_nfcc_coex_tlv_type_name(ERROR), \ + dw3000_nfcc_coex_tlv_type_name(SLOT_LIST_UUS) +/* clang-format on */ +TRACE_DEFINE_ENUM(DW3000_NFCC_COEX_TLV_TYPE_UNSPEC); +TRACE_DEFINE_ENUM(DW3000_NFCC_COEX_TLV_TYPE_SESSION_TIME0); +TRACE_DEFINE_ENUM(DW3000_NFCC_COEX_TLV_TYPE_SLOT_LIST); +TRACE_DEFINE_ENUM(DW3000_NFCC_COEX_TLV_TYPE_TLV_UWBCNT_OFFS); +TRACE_DEFINE_ENUM(DW3000_NFCC_COEX_TLV_TYPE_ERROR); +TRACE_DEFINE_ENUM(DW3000_NFCC_COEX_TLV_TYPE_SLOT_LIST_UUS); +#define DW3000_NFCC_COEX_TLV_TYPE_ARG \ + __print_symbolic(__entry->type, DW3000_NFCC_COEX_TLV_TYPE_SYMBOLS) + /* We don't want clang-format to modify the following events definition! Look at net/wireless/trace.h for the required format. */ /* clang-format off */ @@ -284,7 +312,7 @@ TRACE_EVENT(dw3000_return_int, DW_ASSIGN; __entry->ret = ret; ), - TP_printk(DW_PR_FMT ", return %d", DW_PR_ARG, __entry->ret) + TP_printk(DW_PR_FMT ", return: %d", DW_PR_ARG, __entry->ret) ); TRACE_EVENT(dw3000_return_int_u32, @@ -300,7 +328,7 @@ TRACE_EVENT(dw3000_return_int_u32, __entry->ret = ret; __entry->val = val; ), - TP_printk(DW_PR_FMT ", return %d, value %#x", DW_PR_ARG, + TP_printk(DW_PR_FMT ", return: %d, value: 0x%x", DW_PR_ARG, __entry->ret, __entry->val) ); @@ -317,7 +345,7 @@ TRACE_EVENT(dw3000_return_int_u64, __entry->ret = ret; __entry->val = val; ), - TP_printk(DW_PR_FMT ", return %d, value %#llx", DW_PR_ARG, + TP_printk(DW_PR_FMT ", return: %d, value: 0x%llx", DW_PR_ARG, __entry->ret, __entry->val) ); @@ -352,6 +380,24 @@ TRACE_EVENT(dw3000_mcps_tx_frame, DW_PR_ARG, TX_FRAME_INFO_FLAGS_PR_ARG,__entry->len) ); +TRACE_EVENT(dw3000_mcps_tx_frame_too_late, + TP_PROTO(struct dw3000 *dw, u32 tx_date_dtu, u32 cur_time_dtu), + TP_ARGS(dw, tx_date_dtu, cur_time_dtu), + TP_STRUCT__entry( + DW_ENTRY + __field(u32, tx_date_dtu) + __field(u32, cur_time_dtu) + ), + TP_fast_assign( + DW_ASSIGN; + __entry->tx_date_dtu = tx_date_dtu; + __entry->cur_time_dtu = cur_time_dtu; + ), + TP_printk(DW_PR_FMT ", cannot program delayed, tx_date_dtu: 0x%x" + ", cur_time_dtu: 0x%x", DW_PR_ARG, __entry->tx_date_dtu, + __entry->cur_time_dtu) +); + TRACE_EVENT(dw3000_mcps_rx_enable, TP_PROTO(struct dw3000 *dw, u8 flags, int timeout), TP_ARGS(dw, flags, timeout), @@ -369,6 +415,23 @@ TRACE_EVENT(dw3000_mcps_rx_enable, DW_PR_ARG, RX_INFO_FLAGS_PR_ARG, __entry->timeout) ); +TRACE_EVENT(dw3000_mcps_rx_enable_too_late, + TP_PROTO(struct dw3000 *dw, u32 rx_date_dtu, u32 cur_time_dtu), + TP_ARGS(dw, rx_date_dtu, cur_time_dtu), + TP_STRUCT__entry( + DW_ENTRY + __field(u32, rx_date_dtu) + __field(u32, cur_time_dtu) + ), + TP_fast_assign( + DW_ASSIGN; + __entry->rx_date_dtu = rx_date_dtu; + __entry->cur_time_dtu = cur_time_dtu; + ), + TP_printk(DW_PR_FMT ", too late to program delayed, rx_date_dtu: 0x%x, current_dtu: 0x%x", + DW_PR_ARG, __entry->rx_date_dtu, __entry->cur_time_dtu) +); + DEFINE_EVENT(dw_only_evt, dw3000_mcps_rx_disable, TP_PROTO(struct dw3000 *dw), TP_ARGS(dw) @@ -573,6 +636,21 @@ TRACE_EVENT(dw3000_isr, DW_PR_ARG, DW3000_SYS_STATUS_FLAGS_PR_ARG) ); +TRACE_EVENT(dw3000_check_idlerc, + TP_PROTO(struct dw3000 *dw, u32 low_sys_status), + TP_ARGS(dw, low_sys_status), + TP_STRUCT__entry( + DW_ENTRY + __field(u32, low_sys_status) + ), + TP_fast_assign( + DW_ASSIGN; + __entry->low_sys_status = low_sys_status; + ), + TP_printk(DW_PR_FMT ", low_sys_status: 0x%08x", + DW_PR_ARG, __entry->low_sys_status) +); + TRACE_EVENT(dw3000_set_operational_state, TP_PROTO(struct dw3000 *dw, enum operational_state operational_state), TP_ARGS(dw, operational_state), @@ -862,8 +940,8 @@ TRACE_EVENT(dw3000_rx_rssi, __entry->prf_64mhz = prf_64mhz; __entry->dgc_dec = dgc_dec; ), - TP_printk(DW_PR_FMT ", chip: %s sts: %u cir_pwr: %u pacc_cnt: %u" - " prf_64mhz: %u dgc_dec: %u", + TP_printk(DW_PR_FMT ", chip: %s, sts: %u, cir_pwr: %u, pacc_cnt: %u" + ", prf_64mhz: %u, dgc_dec: %u", DW_PR_ARG, __entry->chip_name, __entry->sts, __entry->cir_pwr, __entry->pacc_cnt, __entry->prf_64mhz, __entry->dgc_dec) @@ -880,7 +958,7 @@ TRACE_EVENT(dw3000_nfcc_coex_isr, DW_ASSIGN; __entry->dss_stat = dss_stat; ), - TP_printk(DW_PR_FMT ", dss_stat=%#x", DW_PR_ARG, __entry->dss_stat) + TP_printk(DW_PR_FMT ", dss_stat: 0x%x", DW_PR_ARG, __entry->dss_stat) ); TRACE_EVENT(dw3000_nfcc_coex_sleep, @@ -894,7 +972,24 @@ TRACE_EVENT(dw3000_nfcc_coex_sleep, DW_ASSIGN; __entry->sleep_dtu = sleep_dtu; ), - TP_printk(DW_PR_FMT ", sleep_dtu=%u", DW_PR_ARG, __entry->sleep_dtu) + TP_printk(DW_PR_FMT ", sleep_dtu: 0x%08x", DW_PR_ARG, __entry->sleep_dtu) +); + +TRACE_EVENT(dw3000_nfcc_coex_header_put, + TP_PROTO(struct dw3000 *dw, u8 ver_id, u8 seq_num), + TP_ARGS(dw, ver_id, seq_num), + TP_STRUCT__entry( + DW_ENTRY + __field(u8, ver_id) + __field(u8, seq_num) + ), + TP_fast_assign( + DW_ASSIGN; + __entry->ver_id = ver_id; + __entry->seq_num = seq_num; + ), + TP_printk(DW_PR_FMT ", ver_id: %u, seq_num: %u", DW_PR_ARG, + __entry->ver_id, __entry->seq_num) ); TRACE_EVENT(dw3000_nfcc_coex_clock_sync_payload_put, @@ -908,7 +1003,7 @@ TRACE_EVENT(dw3000_nfcc_coex_clock_sync_payload_put, DW_ASSIGN; __entry->session_time0_sys_time = session_time0_sys_time; ), - TP_printk(DW_PR_FMT ", session_time0_sys_time=%#08x", DW_PR_ARG, + TP_printk(DW_PR_FMT ", session_time0_sys_time: 0x%08x", DW_PR_ARG, __entry->session_time0_sys_time) ); @@ -923,28 +1018,27 @@ TRACE_EVENT(dw3000_nfcc_coex_clock_offset_payload_put, DW_ASSIGN; __entry->clock_offset_sys_time = clock_offset_sys_time; ), - TP_printk(DW_PR_FMT ", clock_offset_sys_time=%#08x", DW_PR_ARG, + TP_printk(DW_PR_FMT ", clock_offset_sys_time: 0x%08x", DW_PR_ARG, __entry->clock_offset_sys_time) ); TRACE_EVENT(dw3000_nfcc_coex_rx_msg_info, - TP_PROTO(struct dw3000 *dw, u32 next_timestamp_sys_time, - int next_duration_sys_time), - TP_ARGS(dw, next_timestamp_sys_time, next_duration_sys_time), + TP_PROTO(struct dw3000 *dw, u32 next_timestamp_dtu, + int next_duration_dtu), + TP_ARGS(dw, next_timestamp_dtu, next_duration_dtu), TP_STRUCT__entry( DW_ENTRY - __field(u32, next_timestamp_sys_time) - __field(int, next_duration_sys_time) + __field(u32, next_timestamp_dtu) + __field(int, next_duration_dtu) ), TP_fast_assign( DW_ASSIGN; - __entry->next_timestamp_sys_time = next_timestamp_sys_time; - __entry->next_duration_sys_time = next_duration_sys_time; + __entry->next_timestamp_dtu = next_timestamp_dtu; + __entry->next_duration_dtu = next_duration_dtu; ), - TP_printk(DW_PR_FMT ", next_timestamp_sys_time=%#08x" - ", next_duration_sys_time=%#08x", DW_PR_ARG, - __entry->next_timestamp_sys_time, - __entry->next_duration_sys_time) + TP_printk(DW_PR_FMT ", next_timestamp_dtu: 0x%08x" + ", next_duration_dtu: 0x%08x", DW_PR_ARG, + __entry->next_timestamp_dtu, __entry->next_duration_dtu) ); TRACE_EVENT(dw3000_nfcc_coex_header_check, @@ -966,11 +1060,56 @@ TRACE_EVENT(dw3000_nfcc_coex_header_check, __entry->seq_num = seq_num; __entry->nb_tlv = nb_tlv; ), - TP_printk(DW_PR_FMT ", signature=%s, ver_id=%u, seq_num=%u, nb_tlv=%u", DW_PR_ARG, - __print_array(__entry->signature, DW3000_NFCC_COEX_SIGNATURE_LEN, sizeof(u8)), + TP_printk(DW_PR_FMT ", signature: %s, ver_id: %u, seq_num: %u" + ", nb_tlv: %u", DW_PR_ARG, + __print_array(__entry->signature, + DW3000_NFCC_COEX_SIGNATURE_LEN, sizeof(u8)), __entry->ver_id, __entry->seq_num, __entry->nb_tlv) ); +TRACE_EVENT(dw3000_nfcc_coex_tlv_check, + TP_PROTO(struct dw3000 *dw, enum dw3000_nfcc_coex_tlv_type type, + u8 len, const u8 *data), + TP_ARGS(dw, type, len, data), + TP_STRUCT__entry( + DW_ENTRY + DW3000_NFCC_COEX_TLV_TYPE_ENTRY + __dynamic_array(u8, data, len) + ), + TP_fast_assign( + DW_ASSIGN; + DW3000_NFCC_COEX_TLV_TYPE_ASSIGN; + memcpy(__get_dynamic_array(data), data, + __get_dynamic_array_len(data)); + ), + TP_printk(DW_PR_FMT ", " DW3000_NFCC_COEX_TLV_TYPE_PR_FMT ", data: %s", + DW_PR_ARG, DW3000_NFCC_COEX_TLV_TYPE_ARG, + __print_hex(__get_dynamic_array(data), __get_dynamic_array_len(data))) +); + +TRACE_EVENT(dw3000_nfcc_coex_handle_access, + TP_PROTO(struct dw3000 *dw, const struct dw3000_vendor_cmd_nfcc_coex_handle_access *info), + TP_ARGS(dw, info), + TP_STRUCT__entry( + DW_ENTRY + __field(bool, start) + __field(u32, timestamp_dtu) + __field(int, duration_dtu) + __field(int, chan) + ), + TP_fast_assign( + DW_ASSIGN; + __entry->start = info->start; + __entry->timestamp_dtu = info->timestamp_dtu; + __entry->duration_dtu = info->duration_dtu; + __entry->chan = info->chan; + ), + TP_printk(DW_PR_FMT ", start: %s, timestamp_dtu: 0x%08x" + ", duration_dtu: 0x%08x, chan: %d", DW_PR_ARG, + __entry->start ? "true" : "false", __entry->timestamp_dtu, + __entry->duration_dtu, __entry->chan) +); + TRACE_EVENT(dw3000_nfcc_coex_err, TP_PROTO(struct dw3000 *dw, const char *err), TP_ARGS(dw, err), @@ -982,7 +1121,7 @@ TRACE_EVENT(dw3000_nfcc_coex_err, DW_ASSIGN; __assign_str(err, err); ), - TP_printk(DW_PR_FMT ", err=\"%s\"", DW_PR_ARG, __get_str(err)) + TP_printk(DW_PR_FMT ", err: \"%s\"", DW_PR_ARG, __get_str(err)) ); TRACE_EVENT(dw3000_nfcc_coex_warn, @@ -996,7 +1135,7 @@ TRACE_EVENT(dw3000_nfcc_coex_warn, DW_ASSIGN; __assign_str(warn, warn); ), - TP_printk(DW_PR_FMT ", warn=\"%s\"", DW_PR_ARG, __get_str(warn)) + TP_printk(DW_PR_FMT ", warn: \"%s\"", DW_PR_ARG, __get_str(warn)) ); DEFINE_EVENT(dw_only_evt, dw3000_nfcc_coex_watchdog, @@ -1015,7 +1154,7 @@ TRACE_EVENT(dw3000_nfcc_coex_enable, DW_ASSIGN; __entry->channel = channel; ), - TP_printk(DW_PR_FMT ", channel=%d", DW_PR_ARG, __entry->channel) + TP_printk(DW_PR_FMT ", channel: %d", DW_PR_ARG, __entry->channel) ); DEFINE_EVENT(dw_only_evt, dw3000_nfcc_coex_disable, @@ -1056,7 +1195,7 @@ TRACE_EVENT(dw3000_set_pdoa, DW_ASSIGN; __entry->mode = mode; ), - TP_printk(DW_PR_FMT " Set PDoA mode to %d", DW_PR_ARG, + TP_printk(DW_PR_FMT ", mode: %d", DW_PR_ARG, __entry->mode) ); @@ -1071,7 +1210,7 @@ TRACE_EVENT(dw3000_read_pdoa, DW_ASSIGN; __entry->pdoa = pdoa; ), - TP_printk(DW_PR_FMT " pdoa=%#08x", DW_PR_ARG, + TP_printk(DW_PR_FMT ", pdoa: 0x%08x", DW_PR_ARG, __entry->pdoa) ); @@ -1090,7 +1229,7 @@ TRACE_EVENT(dw3000_testmode_continuous_tx_start, __entry->len = len; __entry->rate = rate; ), - TP_printk(DW_PR_FMT " chan=%d, len=%d, rate=%d", DW_PR_ARG, + TP_printk(DW_PR_FMT ", chan: %d, len: %d, rate: %d", DW_PR_ARG, __entry->chan, __entry->len, __entry->rate) @@ -1119,7 +1258,7 @@ TRACE_EVENT(dw3000_read_clockoffset, DW_ASSIGN; __entry->cfo = cfo; ), - TP_printk(DW_PR_FMT " clockoffset=%d", DW_PR_ARG, + TP_printk(DW_PR_FMT ", clockoffset: %d", DW_PR_ARG, __entry->cfo) ); diff --git a/kernel/net/mcps802154/fira_trace.h b/kernel/net/mcps802154/fira_trace.h index 4edab7e..0005946 100644 --- a/kernel/net/mcps802154/fira_trace.h +++ b/kernel/net/mcps802154/fira_trace.h @@ -123,6 +123,7 @@ TRACE_EVENT(region_fira_session_params, __field(int, initiation_time_ms) __field(int, slot_duration_dtu) __field(int, block_duration_dtu) + __field(int, block_stride_len) __field(int, round_duration_slots) __field(bool, round_hopping) __field(int, priority) @@ -155,6 +156,7 @@ TRACE_EVENT(region_fira_session_params, __entry->initiation_time_ms = params->initiation_time_ms; __entry->slot_duration_dtu = params->slot_duration_dtu; __entry->block_duration_dtu = params->block_duration_dtu; + __entry->block_stride_len = params->block_stride_len; __entry->round_duration_slots = params->round_duration_slots; __entry->round_hopping = params->round_hopping; __entry->priority = params->priority; @@ -180,7 +182,7 @@ TRACE_EVENT(region_fira_session_params, ), TP_printk(FIRA_SESSION_PR_FMT " device_type=%s ranging_round_usage=%s multi_node_mode=%s " "controller_short_addr=0x%x initiation_time_ms=%d slot_duration_dtu=%d " - "block_duration_dtu=%d round_duration_slots=%d round_hopping=%d " + "block_duration_dtu=%d block_stride_len=%d round_duration_slots=%d round_hopping=%d " "priority=%d channel_number=%d preamble_code_index=%d rframe_config=%s " "preamble_duration=%s sfd_id=%d psdu_data_rate=%s mac_fcs_type=%s " "sts_config=%s vupper64=%s aoa_result_req=%d report_tof=%d report_aoa_azimuth=%d " @@ -195,6 +197,7 @@ TRACE_EVENT(region_fira_session_params, __entry->initiation_time_ms, __entry->slot_duration_dtu, __entry->block_duration_dtu, + __entry->block_stride_len, __entry->round_duration_slots, __entry->round_hopping, __entry->priority, @@ -260,6 +263,42 @@ TRACE_EVENT(region_fira_tx_message_type, ) ); +TRACE_EVENT(region_fira_block_index, + TP_PROTO(const struct fira_session *session, + int block_index), + TP_ARGS(session, block_index), + TP_STRUCT__entry( + FIRA_SESSION_ENTRY + __field(int, block_index) + ), + TP_fast_assign( + FIRA_SESSION_ASSIGN; + __entry->block_index = block_index; + ), + TP_printk(FIRA_SESSION_PR_FMT "block index = %d", + FIRA_SESSION_PR_ARG, + __entry->block_index + ) + ); + +TRACE_EVENT(region_fira_next_block, + TP_PROTO(const struct fira_session *session, + int block_index), + TP_ARGS(session, block_index), + TP_STRUCT__entry( + FIRA_SESSION_ENTRY + __field(int, block_index) + ), + TP_fast_assign( + FIRA_SESSION_ASSIGN; + __entry->block_index = block_index; + ), + TP_printk(FIRA_SESSION_PR_FMT "next block index = %d", + FIRA_SESSION_PR_ARG, + __entry->block_index + ) + ); + #endif /* !FIRA_TRACE_H || TRACE_HEADER_MULTI_READ */ #undef TRACE_INCLUDE_PATH diff --git a/mac/fira_access.c b/mac/fira_access.c index adcbcfb..7931d39 100644 --- a/mac/fira_access.c +++ b/mac/fira_access.c @@ -39,7 +39,6 @@ #define FIRA_STS_FOM_THRESHOLD 153 -static void fira_update_antennas_id(struct fira_session *session); static struct mcps802154_access * fira_access_controlee(struct fira_local *local, struct fira_session *session); @@ -258,7 +257,7 @@ static void fira_rx_frame_control(struct fira_local *local, struct mcps802154_ie_get_context ie_get = {}; u32 sts_index; unsigned int n_slots; - int last_slot_index; + int last_slot_index, block_stride_len; int i; bool stop_ranging; @@ -274,11 +273,12 @@ static void fira_rx_frame_control(struct fira_local *local, goto failed; if (allow_resync_session) { session = local->current_session = allow_resync_session; + fira_session_prepare(local, session); fira_access_controlee(local, session); } if (!fira_frame_control_payload_check(local, skb, &ie_get, &n_slots, - &stop_ranging)) + &stop_ranging, &block_stride_len)) goto failed; fira_session_resync(local, session, sts_index, info->timestamp_dtu); @@ -310,6 +310,8 @@ static void fira_rx_frame_control(struct fira_local *local, session->params.slot_duration_dtu * (last_slot_index + 1); local->access.n_frames = n_slots; + session->next_block_stride_len = block_stride_len; + return; failed: fira_ranging_info_set_status(ranging_info, @@ -542,44 +544,6 @@ struct mcps802154_access_ops fira_access_ops = { .tx_return = fira_tx_return, }; -static int fira_next_in_bitfield_u8(u8 bitfield, int prev) -{ - u32 padded_bitfield = 1 << 16 | bitfield << 8 | bitfield; - u32 rotated_bitfield = padded_bitfield >> (prev + 1); - - return (ffs(rotated_bitfield) + prev) % 8; -} - -static void fira_update_antennas_id(struct fira_session *session) -{ - const struct fira_session_params *p = &session->params; - - session->tx_ant = fira_next_in_bitfield_u8(p->tx_antenna_selection, - session->tx_ant); - - switch (p->rx_antenna_switch) { - default: - case FIRA_RX_ANTENNA_SWITCH_BETWEEN_ROUND: - /* Switch pairs between round. */ - session->rx_ant_pair[0] = session->rx_ant_pair[1] = - fira_next_in_bitfield_u8(p->rx_antenna_selection, - session->rx_ant_pair[0]); - break; - case FIRA_RX_ANTENNA_SWITCH_DURING_ROUND: - session->rx_ant_pair[0] = p->rx_antenna_pair_azimuth; - session->rx_ant_pair[1] = p->rx_antenna_pair_elevation; - break; - case FIRA_RX_ANTENNA_SWITCH_TWO_RANGING: - /* Switch from one ranging to another. */ - if (session->rx_ant_pair[0] == p->rx_antenna_pair_azimuth) - session->rx_ant_pair[0] = p->rx_antenna_pair_elevation; - else - session->rx_ant_pair[0] = p->rx_antenna_pair_azimuth; - session->rx_ant_pair[1] = session->rx_ant_pair[0]; - break; - } -} - static __le16 fira_access_set_short_address(struct fira_local *local, struct fira_session *session, struct mcps802154_access *access) @@ -649,8 +613,6 @@ fira_access_controller(struct fira_local *local, struct fira_session *session) access->frames = local->frames; access->channel = fira_access_channel(local, session); - fira_update_antennas_id(session); - local->n_stopped_controlees_short_addr = 0; for (i = 0; i < controlees_array->size; i++) { const struct fira_controlee *c = &controlees_array->data[i]; @@ -773,7 +735,6 @@ fira_access_controlee(struct fira_local *local, struct fira_session *session) access->frames = local->frames; access->n_frames = 1; access->channel = fira_access_channel(local, session); - fira_update_antennas_id(session); ri = local->ranging_info; memset(ri, 0, sizeof(*ri)); @@ -841,6 +802,7 @@ struct mcps802154_access *fira_get_access(struct mcps802154_region *region, struct mcps802154_access *fira_compute_access(struct fira_local *local, struct fira_session *session) { + fira_session_prepare(local, session); if (session->params.device_type == FIRA_DEVICE_TYPE_CONTROLLER) return fira_access_controller(local, session); else diff --git a/mac/fira_frame.c b/mac/fira_frame.c index a526c3b..663bc7d 100644 --- a/mac/fira_frame.c +++ b/mac/fira_frame.c @@ -142,7 +142,7 @@ void fira_frame_control_payload_put(const struct fira_local *local, *p++ = n_mngt; *p++ = 0; - *p++ = 0; + *p++ = session->next_block_stride_len; for (i = 0; i < local->access.n_frames - 1; i++) { const struct fira_slot *slot = &local->slots[i + 1]; @@ -384,11 +384,11 @@ bool fira_frame_header_check(const struct fira_local *local, static bool fira_frame_control_read(struct fira_local *local, u8 *p, unsigned int ie_len, unsigned int *n_slots, - bool *stop) + bool *stop, int *block_stride_len) { const struct fira_session *session = local->current_session; struct fira_slot *slot, last; - int n_mngt, stride_len, i; + int n_mngt, i; u16 msg_ids = 0; bool stop_found = false; @@ -397,10 +397,7 @@ static bool fira_frame_control_read(struct fira_local *local, u8 *p, return false; p++; - stride_len = *p++; - if (stride_len) - /* Not supported for the moment. */ - return false; + *block_stride_len = *p++; slot = local->slots; last = *slot++; @@ -474,7 +471,8 @@ static bool fira_frame_control_read(struct fira_local *local, u8 *p, bool fira_frame_control_payload_check(struct fira_local *local, struct sk_buff *skb, struct mcps802154_ie_get_context *ie_get, - unsigned int *n_slots, bool *stop_ranging) + unsigned int *n_slots, bool *stop_ranging, + int *block_stride_len) { bool fira_payload_seen = false; int r; @@ -505,7 +503,8 @@ bool fira_frame_control_payload_check(struct fira_local *local, return false; if (!fira_frame_control_read(local, p, ie_get->len, - n_slots, stop_ranging)) + n_slots, stop_ranging, + block_stride_len)) return false; fira_payload_seen = true; diff --git a/mac/fira_frame.h b/mac/fira_frame.h index d038ca8..6ef5a88 100644 --- a/mac/fira_frame.h +++ b/mac/fira_frame.h @@ -106,14 +106,15 @@ bool fira_frame_header_check(const struct fira_local *local, * @ie_get: Context used to read IE, must have been used to read header first. * @n_slots: Pointer where to store number of used slots. * @stop_ranging: True if the message indicates that the ranging must be stopped. + * @block_stride_len: Pointer where to store number of blocks to stride. * * Return: true if message is correct. Extra payload is accepted. */ bool fira_frame_control_payload_check(struct fira_local *local, struct sk_buff *skb, struct mcps802154_ie_get_context *ie_get, - unsigned int *n_slots, - bool *stop_ranging); + unsigned int *n_slots, bool *stop_ranging, + int *block_stride_len); /** * fira_frame_measurement_report_payload_check() - Check FiRa frame payload for diff --git a/mac/fira_region.c b/mac/fira_region.c index 2322d84..a9cc6a7 100644 --- a/mac/fira_region.c +++ b/mac/fira_region.c @@ -245,7 +245,7 @@ void fira_report(struct fira_local *local, struct fira_session *session, { struct sk_buff *msg; struct nlattr *data, *measurements, *measurement; - int block_duration_ms, i, r; + int ranging_interval_ms, i, r; bool stop_completed; msg = mcps802154_region_event_alloc_skb(local->llhw, &local->region, @@ -262,12 +262,13 @@ void fira_report(struct fira_local *local, struct fira_session *session, if (!data) goto nla_put_failure; - block_duration_ms = session->params.block_duration_dtu / - (local->llhw->dtu_freq_hz / 1000); + ranging_interval_ms = session->params.block_duration_dtu * + (session->block_stride_len + 1) / + (local->llhw->dtu_freq_hz / 1000); if (nla_put_u32(msg, FIRA_RANGING_DATA_ATTR_BLOCK_INDEX, session->block_index) || nla_put_u32(msg, FIRA_RANGING_DATA_ATTR_RANGING_INTERVAL_MS, - block_duration_ms)) + ranging_interval_ms)) goto nla_put_failure; stop_completed = session->stop_request && diff --git a/mac/fira_region.h b/mac/fira_region.h index d2b8910..3003574 100644 --- a/mac/fira_region.h +++ b/mac/fira_region.h @@ -38,6 +38,7 @@ #define FIRA_IN_BAND_TERMINATION_ATTEMPT_COUNT_MAX 10 #define FIRA_IN_BAND_TERMINATION_ATTEMPT_COUNT_MIN 1 #define FIRA_BOOLEAN_MAX 1 +#define FIRA_BLOCK_STRIDE_LEN_MAX 255 #define FIRA_FRAMES_MAX (3 + 3 * FIRA_CONTROLEES_MAX) #define FIRA_CONTROLEE_FRAMES_MAX (3 + 3 + 1) /* IEEE 802.15.4z 2020 section 6.9.7.2 */ diff --git a/mac/fira_region_call.c b/mac/fira_region_call.c index 5cdf5b8..251e770 100644 --- a/mac/fira_region_call.c +++ b/mac/fira_region_call.c @@ -66,16 +66,15 @@ static const struct nla_policy fira_session_param_nla_policy[FIRA_SESSION_PARAM_ [FIRA_SESSION_PARAM_ATTR_SLOT_DURATION_RSTU] = { .type = NLA_U32 }, [FIRA_SESSION_PARAM_ATTR_BLOCK_DURATION_MS] = { .type = NLA_U32 }, [FIRA_SESSION_PARAM_ATTR_ROUND_DURATION_SLOTS] = { .type = NLA_U32 }, - [FIRA_SESSION_PARAM_ATTR_BLOCK_STRIDING_VALUE] = { .type = NLA_U32 }, + [FIRA_SESSION_PARAM_ATTR_BLOCK_STRIDE_LENGTH] = { + .type = NLA_U32, .validation_type = NLA_VALIDATE_MAX, + .max = FIRA_BLOCK_STRIDE_LEN_MAX }, + [FIRA_SESSION_PARAM_ATTR_MAX_NUMBER_OF_MEASUREMENTS] = { .type = NLA_U32 }, [FIRA_SESSION_PARAM_ATTR_MAX_RR_RETRY] = { .type = NLA_U32 }, [FIRA_SESSION_PARAM_ATTR_ROUND_HOPPING] = { .type = NLA_U8, .validation_type = NLA_VALIDATE_MAX, .max = FIRA_BOOLEAN_MAX }, - [FIRA_SESSION_PARAM_ATTR_BLOCK_STRIDING] = { - .type = NLA_U8, .validation_type = NLA_VALIDATE_MAX, - .max = FIRA_BOOLEAN_MAX - }, [FIRA_SESSION_PARAM_ATTR_PRIORITY] = { .type = NLA_U8, .validation_type = NLA_VALIDATE_MAX, .max = FIRA_PRIORITY_MAX @@ -273,6 +272,7 @@ static int fira_session_start(struct fira_local *local, u32 session_id, if (!active) { u32 now_dtu; int initiation_time_dtu; + int block_stride_len; int r; r = fira_crypto_derive_per_session(local, session); @@ -305,6 +305,12 @@ static int fira_session_start(struct fira_local *local, u32 session_id, } else { initiation_time_dtu = 0; } + + if (session->params.device_type == FIRA_DEVICE_TYPE_CONTROLLER) + block_stride_len = session->params.block_stride_len; + else + block_stride_len = 0; + session->block_start_dtu = now_dtu + initiation_time_dtu; session->block_index = 0; session->sts_index = session->crypto.sts_index_init; @@ -312,11 +318,13 @@ static int fira_session_start(struct fira_local *local, u32 session_id, session->params.round_hopping; session->round_index = 0; session->next_round_index = 0; + session->block_stride_len = block_stride_len; + session->next_block_stride_len = block_stride_len; session->synchronised = false; session->last_access_timestamp_dtu = -1; session->last_access_duration_dtu = 0; - session->last_block_index = -1; - fira_session_round_hopping(session); + session->last_block_index = -(block_stride_len + 1); + fira_session_update_round_index(session); session->tx_ant = -1; session->rx_ant_pair[0] = -1; session->rx_ant_pair[1] = -1; @@ -426,14 +434,25 @@ static int fira_session_deinit(struct fira_local *local, u32 session_id, return 0; } -static int is_allowed_param_active(int param) +static int is_allowed_param_active(enum fira_device_type dev_type, int param) { - /* This array contains attributes which can be changed in an active - session */ - static const int allowed_param_active[] = { + /* These arrays contain attributes which can be changed in an active + controller or controlee session */ + static const int allowed_controller_param_active[] = { FIRA_SESSION_PARAM_ATTR_DATA_PAYLOAD, + FIRA_SESSION_PARAM_ATTR_BLOCK_STRIDE_LENGTH, }; - static const int num_allowed = ARRAY_SIZE(allowed_param_active); + static const int allowed_controlee_param_active[] = { + FIRA_SESSION_PARAM_ATTR_DATA_PAYLOAD, + }; + const int *allowed_param_active = + dev_type == FIRA_DEVICE_TYPE_CONTROLLER ? + allowed_controller_param_active : + allowed_controlee_param_active; + const int num_allowed = + dev_type == FIRA_DEVICE_TYPE_CONTROLLER ? + ARRAY_SIZE(allowed_controller_param_active) : + ARRAY_SIZE(allowed_controlee_param_active); int i; for (i = 0; i < num_allowed; i++) @@ -474,18 +493,19 @@ static int fira_session_set_parameters(struct fira_local *local, u32 session_id, if (r) return r; + p = &session->params; + if (active) { int i; for (i = FIRA_SESSION_PARAM_ATTR_UNSPEC + 1; i <= FIRA_SESSION_PARAM_ATTR_MAX; i++) { - if (attrs[i] && !is_allowed_param_active(i)) + if (attrs[i] && + !is_allowed_param_active(p->device_type, i)) return -EBUSY; } } - p = &session->params; - #define P(attr, member, type, conv) \ do { \ int x; \ @@ -529,6 +549,7 @@ static int fira_session_set_parameters(struct fira_local *local, u32 session_id, /* Behaviour parameters. */ P(MAX_RR_RETRY, max_rr_retry, u32, x); P(ROUND_HOPPING, round_hopping, u8, !!x); + P(BLOCK_STRIDE_LENGTH, block_stride_len, u32, x); P(PRIORITY, priority, u8, x); P(RESULT_REPORT_PHASE, result_report_phase, u8, !!x); P(MAX_NUMBER_OF_MEASUREMENTS, max_number_of_measurements, u16, x); @@ -632,43 +653,6 @@ nla_put_failure: } /** - * fira_session_get_count() - Get count of active and inactive sessions. - * @local: FiRa context. - * - * Return: 0 or error. - */ -static int fira_session_get_count(struct fira_local *local) -{ - struct fira_session *session; - struct sk_buff *msg; - uint8_t count = 0; - - list_for_each_entry(session, &local->inactive_sessions, entry) { - count++; - } - - list_for_each_entry(session, &local->active_sessions, entry) { - count++; - } - - msg = mcps802154_region_call_alloc_reply_skb( - local->llhw, &local->region, FIRA_CALL_SESSION_GET_COUNT, - NLMSG_DEFAULT_SIZE); - if (!msg) - return -ENOMEM; - - if (nla_put_u8(msg, FIRA_CALL_ATTR_SESSION_COUNT, count)) - goto nla_put_failure; - - return mcps802154_region_call_reply(local->llhw, msg); - -nla_put_failure: - kfree_skb(msg); - return -ENOBUFS; - -} - -/** * fira_session_get_parameters() - Get Fira session parameters. * @local: FiRa context. * @session_id: Fira session id. @@ -899,8 +883,111 @@ static int fira_manage_controlees(struct fira_local *local, u32 call_id, int fira_get_capabilities(struct fira_local *local, const struct genl_info *info) { - /* TODO: inform netlink about capabilities. */ - return 0; + struct sk_buff *msg; + struct nlattr *capabilities; + + if (!info) + return 0; + + msg = mcps802154_region_call_alloc_reply_skb(local->llhw, + &local->region, + FIRA_CALL_GET_CAPABILITIES, + NLMSG_DEFAULT_SIZE); + if (!msg) + return -ENOMEM; + + capabilities = nla_nest_start(msg, FIRA_CALL_ATTR_CAPABILITIES); + if (!capabilities) { + goto nla_put_failure; + } + +#define P(name, type, value) \ + do { \ + if (nla_put_##type(msg, FIRA_CAPABILITY_ATTR_##name, value)) { \ + goto nla_put_failure; \ + } \ + } while (0) +#define F(name) \ + do { \ + if (nla_put_flag(msg, FIRA_CAPABILITY_ATTR_##name)) { \ + goto nla_put_failure; \ + } \ + } while (0) + + /* Main session capabilities. */ + P(FIRA_PHY_VERSION_RANGE, u32, 0x01010101); + P(FIRA_MAC_VERSION_RANGE, u32, 0x01010101); + P(DEVICE_CLASS, u8, 1); + F(DEVICE_TYPE_CONTROLEE_RESPONDER); + F(DEVICE_TYPE_CONTROLLER_INITIATOR); + F(MULTI_NODE_MODE_UNICAST); + F(MULTI_NODE_MODE_ONE_TO_MANY); + F(RANGING_ROUND_USAGE_DS_TWR); + P(NUMBER_OF_CONTROLEES_MAX, u32, FIRA_CONTROLEES_MAX); + /* Behaviour. */ + F(ROUND_HOPPING); + F(BLOCK_STRIDING); + /* Radio. */ + P(CHANNEL_NUMBER, u16, + local->llhw->hw->phy->supported + .channels[local->llhw->hw->phy->current_page]); + F(RFRAME_CONFIG_SP1); + F(RFRAME_CONFIG_SP3); + F(PRF_MODE_BPRF); + F(PREAMBLE_DURATION_64); + F(SFD_ID_2); + F(NUMBER_OF_STS_SEGMENTS_0); + F(NUMBER_OF_STS_SEGMENTS_1); + F(PSDU_DATA_RATE_6M81); + F(BPRF_PHR_DATA_RATE_850K); + F(TX_ADAPTIVE_PAYLOAD_POWER); + /* Antenna. */ + P(RX_ANTENNA_PAIRS, u32, local->llhw->rx_antenna_pairs); + P(TX_ANTENNAS, u32, local->llhw->tx_antennas); + /* STS and crypto capabilities. */ + F(STS_CONFIG_STATIC); + /* Report. */ + F(AOA_AZIMUTH); + F(AOA_ELEVATION); + F(AOA_FOM); +#undef F +#undef P + + nla_nest_end(msg, capabilities); + return mcps802154_region_call_reply(local->llhw, msg); +nla_put_failure: + kfree_skb(msg); + return -ENOBUFS; +} + +int fira_session_get_count(struct fira_local *local) +{ + struct fira_session *session; + struct sk_buff *msg; + u32 count = 0; + + list_for_each_entry (session, &local->inactive_sessions, entry) { + count++; + } + + list_for_each_entry (session, &local->active_sessions, entry) { + count++; + } + + msg = mcps802154_region_call_alloc_reply_skb( + local->llhw, &local->region, FIRA_CALL_SESSION_GET_COUNT, + NLMSG_DEFAULT_SIZE); + if (!msg) + return -ENOMEM; + + if (nla_put_u32(msg, FIRA_CALL_ATTR_SESSION_COUNT, count)) + goto nla_put_failure; + + return mcps802154_region_call_reply(local->llhw, msg); + +nla_put_failure: + kfree_skb(msg); + return -ENOBUFS; } int fira_session_control(struct fira_local *local, u32 call_id, diff --git a/mac/fira_session.c b/mac/fira_session.c index 6f673ad..90f6dc3 100644 --- a/mac/fira_session.c +++ b/mac/fira_session.c @@ -25,6 +25,7 @@ #include "fira_crypto.h" #include "fira_round_hopping_sequence.h" #include "fira_access.h" +#include "fira_trace.h" #include "mcps802154_i.h" #include <linux/errno.h> @@ -275,13 +276,68 @@ bool fira_session_is_ready(struct fira_local *local, round_duration_dtu < params->block_duration_dtu; } -void fira_session_round_hopping(struct fira_session *session) +static int fira_next_in_bitfield_u8(u8 bitfield, int prev) +{ + u32 padded_bitfield = 1 << 16 | bitfield << 8 | bitfield; + u32 rotated_bitfield = padded_bitfield >> (prev + 1); + + return (ffs(rotated_bitfield) + prev) % 8; +} + +static void fira_update_antennas_id(struct fira_session *session) +{ + const struct fira_session_params *p = &session->params; + + session->tx_ant = fira_next_in_bitfield_u8(p->tx_antenna_selection, + session->tx_ant); + + switch (p->rx_antenna_switch) { + default: + case FIRA_RX_ANTENNA_SWITCH_BETWEEN_ROUND: + /* Switch pairs between round. */ + session->rx_ant_pair[0] = session->rx_ant_pair[1] = + fira_next_in_bitfield_u8(p->rx_antenna_selection, + session->rx_ant_pair[0]); + break; + case FIRA_RX_ANTENNA_SWITCH_DURING_ROUND: + session->rx_ant_pair[0] = p->rx_antenna_pair_azimuth; + session->rx_ant_pair[1] = p->rx_antenna_pair_elevation; + break; + case FIRA_RX_ANTENNA_SWITCH_TWO_RANGING: + /* Switch from one ranging to another. */ + if (session->rx_ant_pair[0] == p->rx_antenna_pair_azimuth) + session->rx_ant_pair[0] = p->rx_antenna_pair_elevation; + else + session->rx_ant_pair[0] = p->rx_antenna_pair_azimuth; + session->rx_ant_pair[1] = session->rx_ant_pair[0]; + break; + } +} + +void fira_session_prepare(struct fira_local *local, + struct fira_session *session) +{ + fira_update_antennas_id(session); + if (session->params.device_type == FIRA_DEVICE_TYPE_CONTROLLER) { + session->next_block_stride_len = + session->params.block_stride_len; + if (session->params.round_hopping) { + u32 next_block_index = session->block_index + + session->next_block_stride_len + + 1; + trace_region_fira_next_block(session, next_block_index); + session->next_round_index = + fira_round_hopping_sequence_get( + session, next_block_index); + } + } +} + +void fira_session_update_round_index(struct fira_session *session) { if (session->hopping_sequence_generation) { session->round_index = fira_round_hopping_sequence_get( session, session->block_index); - session->next_round_index = fira_round_hopping_sequence_get( - session, session->block_index + 1); } else { session->round_index = session->next_round_index; session->hopping_sequence_generation = @@ -293,35 +349,75 @@ static void fira_session_update(struct fira_local *local, struct fira_session *session, u32 next_timestamp_dtu) { + u32 access_dtu; s32 diff_dtu; int block_duration_margin_dtu = 0; if (session->params.device_type == FIRA_DEVICE_TYPE_CONTROLEE) block_duration_margin_dtu = fira_session_get_block_duration_margin(local, session); - diff_dtu = session->block_start_dtu + - fira_session_get_round_slot(session) * - session->params.slot_duration_dtu - - block_duration_margin_dtu - next_timestamp_dtu; + + /* Do we have the time to participate in the current block? */ + access_dtu = session->block_start_dtu + + fira_session_get_round_slot(session) * + session->params.slot_duration_dtu - + block_duration_margin_dtu; + diff_dtu = access_dtu - next_timestamp_dtu; if (diff_dtu < 0) { int block_duration_dtu = session->params.block_duration_dtu; int block_duration_slots = block_duration_dtu / session->params.slot_duration_dtu; - int add_blocks; + int block_stride_len = session->block_stride_len; + int block_stride_duration_dtu = + block_duration_dtu * (block_stride_len + 1); + int add_blocks, add_strides; + + /* + * No time in current block, which block should we try? The + * result of this can be 0, meaning that we are still in the + * same block, but the access was earlier in this block. + */ + diff_dtu = session->block_start_dtu - + block_duration_margin_dtu - next_timestamp_dtu; + add_strides = -diff_dtu / block_stride_duration_dtu; + add_blocks = add_strides * (block_stride_len + 1); - add_blocks = (-diff_dtu + block_duration_dtu - 1) / - block_duration_dtu; session->block_start_dtu += add_blocks * block_duration_dtu; session->block_index += add_blocks; session->sts_index += add_blocks * block_duration_slots; - if (add_blocks != 1) - session->hopping_sequence_generation = - session->params.round_hopping; - fira_session_round_hopping(session); + if (add_blocks != 0) { + /* + * More than one ranging round skipped, can not trust + * last hopping instructions. + */ + if (add_blocks > block_stride_len + 1) + session->hopping_sequence_generation = + session->params.round_hopping; + fira_session_update_round_index(session); + } + + /* Retry in the found block. */ + access_dtu = session->block_start_dtu + + fira_session_get_round_slot(session) * + session->params.slot_duration_dtu - + block_duration_margin_dtu; + diff_dtu = access_dtu - next_timestamp_dtu; + + if (diff_dtu < 0) { + /* Still no time, next one will be OK. */ + add_blocks = block_stride_len + 1; + session->block_start_dtu += + add_blocks * block_duration_dtu; + session->block_index += add_blocks; + session->sts_index += add_blocks * block_duration_slots; + fira_session_update_round_index(session); + } + trace_region_fira_block_index(session, session->block_index); } } + static inline bool fira_session_has_higher_priority(const struct fira_session *session, const struct fira_session *selected_session) @@ -397,9 +493,11 @@ static struct fira_session *fira_session_find_next(struct fira_local *local, access_duration_dtu = demand.duration_dtu; unsync_access_duration_dtu = U32_MAX; if (session->params.max_rr_retry) { - int nb_blocks = session->params.max_rr_retry + - session->last_block_index - - session->block_index; + int nb_blocks = + session->params.max_rr_retry * + (session->block_stride_len + 1) + + session->last_block_index - + session->block_index; unsync_access_duration_dtu = min((u32)session->params.block_duration_dtu * @@ -457,7 +555,8 @@ fira_session_check_max_number_of_measurements(struct fira_local *local, static bool fira_session_check_max_rr_retry(struct fira_session *session) { if (session->params.max_rr_retry && - !((s32)(session->block_index - session->last_block_index - + !((s32)((session->block_index - session->last_block_index) / + (session->block_stride_len + 1) - session->params.max_rr_retry) < 0)) { session->stop_no_response = true; return true; @@ -638,5 +737,6 @@ void fira_session_access_done(struct fira_local *local, if (session == local->current_session) { fira_session_stop_expired_sessions(local); + session->block_stride_len = session->next_block_stride_len; } } diff --git a/mac/fira_session.h b/mac/fira_session.h index c1e334b..47abf84 100644 --- a/mac/fira_session.h +++ b/mac/fira_session.h @@ -59,6 +59,7 @@ struct fira_session_params { int max_number_of_measurements; int max_rr_retry; bool round_hopping; + int block_stride_len; int priority; bool result_report_phase; /* Radio. */ @@ -136,6 +137,15 @@ struct fira_session { */ int next_round_index; /** + * @block_stride_len: Stride length for the reference block. + */ + int block_stride_len; + /** + * @next_block_stride_len: Stride length for the block after the + * reference block. + */ + int next_block_stride_len; + /** * @tx_ant: Antenna index to use for transmission in the reference * block. */ @@ -307,6 +317,14 @@ bool fira_session_is_ready(struct fira_local *local, struct fira_session *session); /** + * fira_session_prepare() - Prepare a FiRa session to run. + * @local: FiRa context. + * @session: Session. + */ +void fira_session_prepare(struct fira_local *local, + struct fira_session *session); + +/** * fira_session_next() - Find the next session to use after the given timestamp. * @local: FiRa context. * @next_timestamp_dtu: Next access opportunity. @@ -319,10 +337,10 @@ struct fira_session *fira_session_next(struct fira_local *local, u32 max_access_duration_dtu); /** - * fira_session_round_hopping() - Update round index for round hopping. + * fira_session_update_round_index() - Update round index for round hopping. * @session: Session to update. */ -void fira_session_round_hopping(struct fira_session *session); +void fira_session_update_round_index(struct fira_session *session); /** * fira_session_resync() - Resync session parameters on control message. @@ -381,6 +399,7 @@ fira_session_get_block_duration_margin(struct fira_local *local, const struct fira_session *session) { return (long long int)session->params.block_duration_dtu * + (session->block_stride_len + 1) * local->block_duration_rx_margin_ppm / 1000000; } diff --git a/mac/include/net/fira_region_nl.h b/mac/include/net/fira_region_nl.h index 714f1b8..3e390d2 100644 --- a/mac/include/net/fira_region_nl.h +++ b/mac/include/net/fira_region_nl.h @@ -259,6 +259,7 @@ enum fira_call_attrs { FIRA_CALL_ATTR_SESSION_PARAMS, FIRA_CALL_ATTR_CONTROLEES, FIRA_CALL_ATTR_RANGING_DATA, + FIRA_CALL_ATTR_CAPABILITIES, FIRA_CALL_ATTR_SESSION_STATE, FIRA_CALL_ATTR_SESSION_COUNT, @@ -289,7 +290,7 @@ enum fira_call_attrs { * Block size in unit of 1200 RSTU (same as ms), default 200. * @FIRA_SESSION_PARAM_ATTR_ROUND_DURATION_SLOTS: * Number of slots per ranging round, default 30 (UCI: SLOTS_PER_RR) - * @FIRA_SESSION_PARAM_ATTR_BLOCK_STRIDING_VALUE: + * @FIRA_SESSION_PARAM_ATTR_BLOCK_STRIDE_LENGTH: * Value of block striding, default 0, can be changed when the * session is active [controller only] * @FIRA_SESSION_PARAM_ATTR_MAX_RR_RETRY: @@ -297,8 +298,6 @@ enum fira_call_attrs { * or disabled (0, default) [controller only] * @FIRA_SESSION_PARAM_ATTR_ROUND_HOPPING: * Disabled (0, default) or enabled (1) - * @FIRA_SESSION_PARAM_ATTR_BLOCK_STRIDING: - * Disabled (0, default) or enabled upon controller decision (1) * @FIRA_SESSION_PARAM_ATTR_PRIORITY: * Priority value, higher has more priority (1-100, default 50) * @FIRA_SESSION_PARAM_ATTR_RESULT_REPORT_PHASE: @@ -402,11 +401,10 @@ enum fira_session_param_attrs { FIRA_SESSION_PARAM_ATTR_SLOT_DURATION_RSTU, FIRA_SESSION_PARAM_ATTR_BLOCK_DURATION_MS, FIRA_SESSION_PARAM_ATTR_ROUND_DURATION_SLOTS, - FIRA_SESSION_PARAM_ATTR_BLOCK_STRIDING_VALUE, + FIRA_SESSION_PARAM_ATTR_BLOCK_STRIDE_LENGTH, /* Behaviour */ FIRA_SESSION_PARAM_ATTR_MAX_RR_RETRY, FIRA_SESSION_PARAM_ATTR_ROUND_HOPPING, - FIRA_SESSION_PARAM_ATTR_BLOCK_STRIDING, FIRA_SESSION_PARAM_ATTR_PRIORITY, FIRA_SESSION_PARAM_ATTR_RESULT_REPORT_PHASE, FIRA_SESSION_PARAM_ATTR_MR_AT_INITIATOR, diff --git a/mac/include/net/mcps802154.h b/mac/include/net/mcps802154.h index 1de283d..bf3847d 100644 --- a/mac/include/net/mcps802154.h +++ b/mac/include/net/mcps802154.h @@ -121,6 +121,14 @@ struct mcps802154_llhw { */ int current_preamble_code; /** + * @rx_antenna_pairs: Number of antenna pairs for RX. + */ + u32 rx_antenna_pairs; + /** + * @tx_antennas: Number of antennas for TX. + */ + u32 tx_antennas; + /** * @flags: Low-level hardware flags, see &enum mcps802154_llhw_flags. */ u32 flags; |