ath10k: htc: rx trailer lookahead support
The RX trailer parsing is now capable of parsing lookahead reports. A lookahead contains the first 4 bytes of the next HTC message (that will be read in the next SDIO read operation). Lookaheads are used by the SDIO/mbox HIF layer to determine if the next message is part of a bundle, which endpoint it belongs to and how long it is. Signed-off-by: Erik Stromdahl <erik.stromdahl@gmail.com> Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
This commit is contained in:
parent
3e0dd820f0
commit
680ebb4e79
|
@ -231,11 +231,78 @@ ath10k_htc_process_credit_report(struct ath10k_htc *htc,
|
|||
spin_unlock_bh(&htc->tx_lock);
|
||||
}
|
||||
|
||||
static int
|
||||
ath10k_htc_process_lookahead(struct ath10k_htc *htc,
|
||||
const struct ath10k_htc_lookahead_report *report,
|
||||
int len,
|
||||
enum ath10k_htc_ep_id eid,
|
||||
void *next_lookaheads,
|
||||
int *next_lookaheads_len)
|
||||
{
|
||||
struct ath10k *ar = htc->ar;
|
||||
|
||||
/* Invalid lookahead flags are actually transmitted by
|
||||
* the target in the HTC control message.
|
||||
* Since this will happen at every boot we silently ignore
|
||||
* the lookahead in this case
|
||||
*/
|
||||
if (report->pre_valid != ((~report->post_valid) & 0xFF))
|
||||
return 0;
|
||||
|
||||
if (next_lookaheads && next_lookaheads_len) {
|
||||
ath10k_dbg(ar, ATH10K_DBG_HTC,
|
||||
"htc rx lookahead found pre_valid 0x%x post_valid 0x%x\n",
|
||||
report->pre_valid, report->post_valid);
|
||||
|
||||
/* look ahead bytes are valid, copy them over */
|
||||
memcpy((u8 *)next_lookaheads, report->lookahead, 4);
|
||||
|
||||
*next_lookaheads_len = 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
ath10k_htc_process_lookahead_bundle(struct ath10k_htc *htc,
|
||||
const struct ath10k_htc_lookahead_bundle *report,
|
||||
int len,
|
||||
enum ath10k_htc_ep_id eid,
|
||||
void *next_lookaheads,
|
||||
int *next_lookaheads_len)
|
||||
{
|
||||
struct ath10k *ar = htc->ar;
|
||||
int bundle_cnt = len / sizeof(*report);
|
||||
|
||||
if (!bundle_cnt || (bundle_cnt > HTC_HOST_MAX_MSG_PER_BUNDLE)) {
|
||||
ath10k_warn(ar, "Invalid lookahead bundle count: %d\n",
|
||||
bundle_cnt);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (next_lookaheads && next_lookaheads_len) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < bundle_cnt; i++) {
|
||||
memcpy(((u8 *)next_lookaheads) + 4 * i,
|
||||
report->lookahead, 4);
|
||||
report++;
|
||||
}
|
||||
|
||||
*next_lookaheads_len = bundle_cnt;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ath10k_htc_process_trailer(struct ath10k_htc *htc,
|
||||
u8 *buffer,
|
||||
int length,
|
||||
enum ath10k_htc_ep_id src_eid)
|
||||
enum ath10k_htc_ep_id src_eid,
|
||||
void *next_lookaheads,
|
||||
int *next_lookaheads_len)
|
||||
{
|
||||
struct ath10k_htc_lookahead_bundle *bundle;
|
||||
struct ath10k *ar = htc->ar;
|
||||
int status = 0;
|
||||
struct ath10k_htc_record *record;
|
||||
|
@ -275,6 +342,29 @@ int ath10k_htc_process_trailer(struct ath10k_htc *htc,
|
|||
record->hdr.len,
|
||||
src_eid);
|
||||
break;
|
||||
case ATH10K_HTC_RECORD_LOOKAHEAD:
|
||||
len = sizeof(struct ath10k_htc_lookahead_report);
|
||||
if (record->hdr.len < len) {
|
||||
ath10k_warn(ar, "Lookahead report too long\n");
|
||||
status = -EINVAL;
|
||||
break;
|
||||
}
|
||||
status = ath10k_htc_process_lookahead(htc,
|
||||
record->lookahead_report,
|
||||
record->hdr.len,
|
||||
src_eid,
|
||||
next_lookaheads,
|
||||
next_lookaheads_len);
|
||||
break;
|
||||
case ATH10K_HTC_RECORD_LOOKAHEAD_BUNDLE:
|
||||
bundle = record->lookahead_bundle;
|
||||
status = ath10k_htc_process_lookahead_bundle(htc,
|
||||
bundle,
|
||||
record->hdr.len,
|
||||
src_eid,
|
||||
next_lookaheads,
|
||||
next_lookaheads_len);
|
||||
break;
|
||||
default:
|
||||
ath10k_warn(ar, "Unhandled record: id:%d length:%d\n",
|
||||
record->hdr.id, record->hdr.len);
|
||||
|
@ -362,7 +452,8 @@ void ath10k_htc_rx_completion_handler(struct ath10k *ar, struct sk_buff *skb)
|
|||
trailer += payload_len;
|
||||
trailer -= trailer_len;
|
||||
status = ath10k_htc_process_trailer(htc, trailer,
|
||||
trailer_len, hdr->eid);
|
||||
trailer_len, hdr->eid,
|
||||
NULL, NULL);
|
||||
if (status)
|
||||
goto out;
|
||||
|
||||
|
|
|
@ -50,6 +50,8 @@ struct ath10k;
|
|||
* 4-byte aligned.
|
||||
*/
|
||||
|
||||
#define HTC_HOST_MAX_MSG_PER_BUNDLE 8
|
||||
|
||||
enum ath10k_htc_tx_flags {
|
||||
ATH10K_HTC_FLAG_NEED_CREDIT_UPDATE = 0x01,
|
||||
ATH10K_HTC_FLAG_SEND_BUNDLE = 0x02
|
||||
|
@ -174,8 +176,10 @@ struct ath10k_htc_msg {
|
|||
} __packed __aligned(4);
|
||||
|
||||
enum ath10k_ath10k_htc_record_id {
|
||||
ATH10K_HTC_RECORD_NULL = 0,
|
||||
ATH10K_HTC_RECORD_CREDITS = 1
|
||||
ATH10K_HTC_RECORD_NULL = 0,
|
||||
ATH10K_HTC_RECORD_CREDITS = 1,
|
||||
ATH10K_HTC_RECORD_LOOKAHEAD = 2,
|
||||
ATH10K_HTC_RECORD_LOOKAHEAD_BUNDLE = 3,
|
||||
};
|
||||
|
||||
struct ath10k_ath10k_htc_record_hdr {
|
||||
|
@ -192,10 +196,28 @@ struct ath10k_htc_credit_report {
|
|||
u8 pad1;
|
||||
} __packed;
|
||||
|
||||
struct ath10k_htc_lookahead_report {
|
||||
u8 pre_valid;
|
||||
u8 pad0;
|
||||
u8 pad1;
|
||||
u8 pad2;
|
||||
u8 lookahead[4];
|
||||
u8 post_valid;
|
||||
u8 pad3;
|
||||
u8 pad4;
|
||||
u8 pad5;
|
||||
} __packed;
|
||||
|
||||
struct ath10k_htc_lookahead_bundle {
|
||||
u8 lookahead[4];
|
||||
} __packed;
|
||||
|
||||
struct ath10k_htc_record {
|
||||
struct ath10k_ath10k_htc_record_hdr hdr;
|
||||
union {
|
||||
struct ath10k_htc_credit_report credit_report[0];
|
||||
struct ath10k_htc_lookahead_report lookahead_report[0];
|
||||
struct ath10k_htc_lookahead_bundle lookahead_bundle[0];
|
||||
u8 pauload[0];
|
||||
};
|
||||
} __packed __aligned(4);
|
||||
|
@ -356,6 +378,8 @@ void ath10k_htc_notify_tx_completion(struct ath10k_htc_ep *ep,
|
|||
int ath10k_htc_process_trailer(struct ath10k_htc *htc,
|
||||
u8 *buffer,
|
||||
int length,
|
||||
enum ath10k_htc_ep_id src_eid);
|
||||
enum ath10k_htc_ep_id src_eid,
|
||||
void *next_lookaheads,
|
||||
int *next_lookaheads_len);
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue