Commit 5d80dbd3 authored by Thomas Ebert Hansen's avatar Thomas Ebert Hansen Committed by Carles Cufi
Browse files

Bluetooth: controller: llcp: Fix terminate timer

Add the missing terminate timer for the ACL Termination procedure.

Signed-off-by: default avatarThomas Ebert Hansen <thoh@oticon.com>
parent 2a2856e8
Loading
Loading
Loading
Loading
+4 −2
Changes for subsys/bluetooth/controller/ll_sw/ull_conn.c: 4 added lines, 2 removed lines.
Original line number Diff line number Diff line
@@ -1592,8 +1592,10 @@ void ull_conn_done(struct node_rx_event_done *done)
		}
	}
#else /* CONFIG_BT_LL_SW_LLCP_LEGACY */
	if (-ETIMEDOUT == ull_cp_prt_elapse(conn, elapsed_event)) {
		conn_cleanup(conn, BT_HCI_ERR_LL_RESP_TIMEOUT);
	uint8_t error_code;

	if (-ETIMEDOUT == ull_cp_prt_elapse(conn, elapsed_event, &error_code)) {
		conn_cleanup(conn, error_code);

		return;
	}
+23 −3
Changes for subsys/bluetooth/controller/ll_sw/ull_llcp.c: 23 added lines, 3 removed lines.
Original line number Diff line number Diff line
@@ -542,20 +542,40 @@ static int prt_elapse(uint16_t *expire, uint16_t elapsed_event)
	return 0;
}

int ull_cp_prt_elapse(struct ll_conn *conn, uint16_t elapsed_event)
int ull_cp_prt_elapse(struct ll_conn *conn, uint16_t elapsed_event, uint8_t *error_code)
{
	int loc_ret;
	int rem_ret;

	loc_ret = prt_elapse(&conn->llcp.local.prt_expire, elapsed_event);
	if (loc_ret == -ETIMEDOUT) {
		/* Local Request Machine timed out */

		struct proc_ctx *ctx;

		ctx = llcp_lr_peek(conn);
		LL_ASSERT(ctx);

		if (ctx->proc == PROC_TERMINATE) {
			/* Active procedure is ACL Termination */
			*error_code = ctx->data.term.error_code;
		} else {
			*error_code = BT_HCI_ERR_LL_RESP_TIMEOUT;
		}

		return -ETIMEDOUT;
	}

	rem_ret = prt_elapse(&conn->llcp.remote.prt_expire, elapsed_event);
	if (rem_ret == -ETIMEDOUT) {
		/* Remote Request Machine timed out */

	if (loc_ret == -ETIMEDOUT || rem_ret == -ETIMEDOUT) {
		/* One of the timers expired */
		*error_code = BT_HCI_ERR_LL_RESP_TIMEOUT;
		return -ETIMEDOUT;
	}

	/* Both timers are still running */
	*error_code = BT_HCI_ERR_SUCCESS;
	return 0;
}

+2 −1
Changes for subsys/bluetooth/controller/ll_sw/ull_llcp.h: 2 added lines, 1 removed line.
Original line number Diff line number Diff line
@@ -38,9 +38,10 @@ void ull_cp_release_ntf(struct node_rx_pdu *ntf);
/**
 * @brief Procedure Response Timeout Check
 * @param elapsed_event The number of elapsed events.
 * @param[out] error_code The error code for this timeout.
 * @return 0 on success, -ETIMEDOUT if timer expired.
 */
int ull_cp_prt_elapse(struct ll_conn *conn, uint16_t elapsed_event);
int ull_cp_prt_elapse(struct ll_conn *conn, uint16_t elapsed_event, uint8_t *error_code);

void ull_cp_prt_reload_set(struct ll_conn *conn, uint32_t conn_intv);

+9 −0
Changes for subsys/bluetooth/controller/ll_sw/ull_llcp_common.c: 9 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -162,7 +162,16 @@ static void lp_comm_tx(struct ll_conn *conn, struct proc_ctx *ctx)
	llcp_tx_enqueue(conn, tx);

	/* Restart procedure response timeout timer */
	if (ctx->proc != PROC_TERMINATE) {
		/* Use normal timeout value of 40s */
		llcp_lr_prt_restart(conn);
	} else {
		/* Use supervision timeout value
		 * NOTE: As the supervision timeout is at most 32s the normal procedure response
		 * timeout of 40s will never come into play for the ACL Termination procedure.
		 */
		llcp_lr_prt_restart_with_value(conn, conn->supervision_reload);
	}
}

static void lp_comm_ntf_feature_exchange(struct ll_conn *conn, struct proc_ctx *ctx,
+1 −0
Changes for subsys/bluetooth/controller/ll_sw/ull_llcp_internal.h: 1 added line, 0 removed lines.
Original line number Diff line number Diff line
@@ -359,6 +359,7 @@ void llcp_tx_resume_data(struct ll_conn *conn, enum llcp_tx_q_pause_data_mask re
 * LLCP Procedure Response Timeout
 */
void llcp_lr_prt_restart(struct ll_conn *conn);
void llcp_lr_prt_restart_with_value(struct ll_conn *conn, uint16_t value);
void llcp_lr_prt_stop(struct ll_conn *conn);
void llcp_rr_prt_restart(struct ll_conn *conn);
void llcp_rr_prt_stop(struct ll_conn *conn);
Loading