Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 76db9426 authored by Treehugger Robot's avatar Treehugger Robot Committed by Gerrit Code Review
Browse files

Merge "Ensure we don't send more packets than firmware allows"

parents 8de9f59b 3be4e0cf
Loading
Loading
Loading
Loading
+12 −1
Original line number Diff line number Diff line
@@ -546,6 +546,14 @@ typedef struct {

typedef void(tL2C_FCR_MGMT_EVT_HDLR)(uint8_t, tL2C_CCB*);

/* Necessary info for postponed TX completion callback
*/
typedef struct {
  uint16_t local_cid;
  uint16_t num_sdu;
  tL2CA_TX_COMPLETE_CB* cb;
} tL2C_TX_COMPLETE_CB_INFO;

/* The offset in a buffer that L2CAP will use when building commands.
*/
#define L2CAP_SEND_CMD_OFFSET 0
@@ -631,6 +639,8 @@ extern void l2cu_set_acl_hci_header(BT_HDR* p_buf, tL2C_CCB* p_ccb);
extern void l2cu_check_channel_congestion(tL2C_CCB* p_ccb);
extern void l2cu_disconnect_chnl(tL2C_CCB* p_ccb);

extern void l2cu_tx_complete(tL2C_TX_COMPLETE_CB_INFO* p_cbi);

#if (L2CAP_NON_FLUSHABLE_PB_INCLUDED == TRUE)
extern void l2cu_set_non_flushable_pbf(bool);
#endif
@@ -701,7 +711,8 @@ extern bool l2cu_create_conn(tL2C_LCB* p_lcb, tBT_TRANSPORT transport);
extern bool l2cu_create_conn(tL2C_LCB* p_lcb, tBT_TRANSPORT transport,
                             uint8_t initiating_phys);
extern bool l2cu_create_conn_after_switch(tL2C_LCB* p_lcb);
extern BT_HDR* l2cu_get_next_buffer_to_send(tL2C_LCB* p_lcb);
extern BT_HDR* l2cu_get_next_buffer_to_send(tL2C_LCB* p_lcb,
                                            tL2C_TX_COMPLETE_CB_INFO* p_cbi);
extern void l2cu_resubmit_pending_sec_req(BD_ADDR p_bda);
extern void l2cu_initialize_amp_ccb(tL2C_LCB* p_lcb);
extern void l2cu_adjust_out_mps(tL2C_CCB* p_ccb);
+17 −11
Original line number Diff line number Diff line
@@ -45,7 +45,8 @@

extern fixed_queue_t* btu_general_alarm_queue;

static bool l2c_link_send_to_lower(tL2C_LCB* p_lcb, BT_HDR* p_buf);
static bool l2c_link_send_to_lower(tL2C_LCB* p_lcb, BT_HDR* p_buf,
                                   tL2C_TX_COMPLETE_CB_INFO* p_cbi);

/*******************************************************************************
 *
@@ -992,6 +993,9 @@ void l2c_link_check_send_pkts(tL2C_LCB* p_lcb, tL2C_CCB* p_ccb, BT_HDR* p_buf) {

    /* Loop through, starting at the next */
    for (xx = 0; xx < MAX_L2CAP_LINKS; xx++, p_lcb++) {
      /* Check for wraparound */
      if (p_lcb == &l2cb.lcb_pool[MAX_L2CAP_LINKS]) p_lcb = &l2cb.lcb_pool[0];

      /* If controller window is full, nothing to do */
      if (((l2cb.controller_xmit_window == 0 ||
            (l2cb.round_robin_unacked >= l2cb.round_robin_quota)) &&
@@ -1001,9 +1005,6 @@ void l2c_link_check_send_pkts(tL2C_LCB* p_lcb, tL2C_CCB* p_ccb, BT_HDR* p_buf) {
            l2cb.controller_le_xmit_window == 0)))
        continue;

      /* Check for wraparound */
      if (p_lcb == &l2cb.lcb_pool[MAX_L2CAP_LINKS]) p_lcb = &l2cb.lcb_pool[0];

      if ((!p_lcb->in_use) || (p_lcb->partial_segment_being_sent) ||
          (p_lcb->link_state != LST_CONNECTED) ||
          (p_lcb->link_xmit_quota != 0) || (L2C_LINK_CHECK_POWER_MODE(p_lcb)))
@@ -1013,16 +1014,17 @@ void l2c_link_check_send_pkts(tL2C_LCB* p_lcb, tL2C_CCB* p_ccb, BT_HDR* p_buf) {
      if (!list_is_empty(p_lcb->link_xmit_data_q)) {
        p_buf = (BT_HDR*)list_front(p_lcb->link_xmit_data_q);
        list_remove(p_lcb->link_xmit_data_q, p_buf);
        l2c_link_send_to_lower(p_lcb, p_buf);
        l2c_link_send_to_lower(p_lcb, p_buf, NULL);
      } else if (single_write) {
        /* If only doing one write, break out */
        break;
      }
      /* If nothing on the link queue, check the channel queue */
      else {
        p_buf = l2cu_get_next_buffer_to_send(p_lcb);
        tL2C_TX_COMPLETE_CB_INFO cbi;
        p_buf = l2cu_get_next_buffer_to_send(p_lcb, &cbi);
        if (p_buf != NULL) {
          l2c_link_send_to_lower(p_lcb, p_buf);
          l2c_link_send_to_lower(p_lcb, p_buf, &cbi);
        }
      }
    }
@@ -1055,7 +1057,7 @@ void l2c_link_check_send_pkts(tL2C_LCB* p_lcb, tL2C_CCB* p_ccb, BT_HDR* p_buf) {

      p_buf = (BT_HDR*)list_front(p_lcb->link_xmit_data_q);
      list_remove(p_lcb->link_xmit_data_q, p_buf);
      if (!l2c_link_send_to_lower(p_lcb, p_buf)) break;
      if (!l2c_link_send_to_lower(p_lcb, p_buf, NULL)) break;
    }

    if (!single_write) {
@@ -1065,10 +1067,11 @@ void l2c_link_check_send_pkts(tL2C_LCB* p_lcb, tL2C_CCB* p_ccb, BT_HDR* p_buf) {
              (l2cb.controller_le_xmit_window != 0 &&
               (p_lcb->transport == BT_TRANSPORT_LE))) &&
             (p_lcb->sent_not_acked < p_lcb->link_xmit_quota)) {
        p_buf = l2cu_get_next_buffer_to_send(p_lcb);
        tL2C_TX_COMPLETE_CB_INFO cbi;
        p_buf = l2cu_get_next_buffer_to_send(p_lcb, &cbi);
        if (p_buf == NULL) break;

        if (!l2c_link_send_to_lower(p_lcb, p_buf)) break;
        if (!l2c_link_send_to_lower(p_lcb, p_buf, &cbi)) break;
      }
    }

@@ -1093,7 +1096,7 @@ void l2c_link_check_send_pkts(tL2C_LCB* p_lcb, tL2C_CCB* p_ccb, BT_HDR* p_buf) {
 * Returns          true for success, false for fail
 *
 ******************************************************************************/
static bool l2c_link_send_to_lower(tL2C_LCB* p_lcb, BT_HDR* p_buf) {
static bool l2c_link_send_to_lower(tL2C_LCB* p_lcb, BT_HDR* p_buf, tL2C_TX_COMPLETE_CB_INFO* p_cbi) {
  uint16_t num_segs;
  uint16_t xmit_window, acl_data_size;
  const controller_t* controller = controller_get_interface();
@@ -1183,6 +1186,9 @@ static bool l2c_link_send_to_lower(tL2C_LCB* p_lcb, BT_HDR* p_buf) {
  }
#endif

  if (p_cbi)
    l2cu_tx_complete(p_cbi);

  return true;
}

+14 −5
Original line number Diff line number Diff line
@@ -3241,6 +3241,11 @@ static tL2C_CCB* l2cu_get_next_channel(tL2C_LCB* p_lcb) {
}
#endif /* (L2CAP_ROUND_ROBIN_CHANNEL_SERVICE == TRUE) */

void l2cu_tx_complete(tL2C_TX_COMPLETE_CB_INFO* p_cbi) {
  if (p_cbi->cb != NULL)
      p_cbi->cb(p_cbi->local_cid, p_cbi->num_sdu);
}

/******************************************************************************
 *
 * Function         l2cu_get_next_buffer_to_send
@@ -3251,7 +3256,7 @@ static tL2C_CCB* l2cu_get_next_channel(tL2C_LCB* p_lcb) {
 * Returns          pointer to buffer or NULL
 *
 ******************************************************************************/
BT_HDR* l2cu_get_next_buffer_to_send(tL2C_LCB* p_lcb) {
BT_HDR* l2cu_get_next_buffer_to_send(tL2C_LCB* p_lcb, tL2C_TX_COMPLETE_CB_INFO* p_cbi) {
  tL2C_CCB* p_ccb;
  BT_HDR* p_buf;

@@ -3259,6 +3264,8 @@ BT_HDR* l2cu_get_next_buffer_to_send(tL2C_LCB* p_lcb) {
#if (L2CAP_NUM_FIXED_CHNLS > 0)
  int xx;

  p_cbi->cb = NULL;

  for (xx = 0; xx < L2CAP_NUM_FIXED_CHNLS; xx++) {
    p_ccb = p_lcb->p_fixed_ccbs[xx];
    if (p_ccb == NULL) continue;
@@ -3287,12 +3294,14 @@ BT_HDR* l2cu_get_next_buffer_to_send(tL2C_LCB* p_lcb) {
      if (!fixed_queue_is_empty(p_ccb->xmit_hold_q)) {
        p_buf = (BT_HDR*)fixed_queue_try_dequeue(p_ccb->xmit_hold_q);
        if (NULL == p_buf) {
          L2CAP_TRACE_ERROR("l2cu_get_buffer_to_send: No data to be sent");
          L2CAP_TRACE_ERROR("%s: No data to be sent", __func__);
          return (NULL);
        }
        /* send tx complete */
        if (l2cb.fixed_reg[xx].pL2CA_FixedTxComplete_Cb)
          (*l2cb.fixed_reg[xx].pL2CA_FixedTxComplete_Cb)(p_ccb->local_cid, 1);

        /* Prepare callback info for TX completion */
        p_cbi->cb = l2cb.fixed_reg[xx].pL2CA_FixedTxComplete_Cb;
        p_cbi->local_cid = p_ccb->local_cid;
        p_cbi->num_sdu = 1;

        l2cu_check_channel_congestion(p_ccb);
        l2cu_set_acl_hci_header(p_buf, p_ccb);