mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-12-04 08:26:55 +07:00
ath10k: make WMI commands block by design
This will be necessary for further changes in command submission scheme. Once HTC is cleaned up WMI commands will finally block. This requires for SWBA to be processed in a non-atomic context for now. Once other necessary changes are in this will be reverted. Signed-off-by: Michal Kazior <michal.kazior@tieto.com> Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
This commit is contained in:
parent
88e65fc337
commit
be8b394390
@ -114,6 +114,7 @@ struct ath10k_wmi {
|
||||
struct completion unified_ready;
|
||||
atomic_t pending_tx_count;
|
||||
wait_queue_head_t wq;
|
||||
wait_queue_head_t tx_credits_wq;
|
||||
|
||||
struct sk_buff_head wmi_event_list;
|
||||
struct work_struct wmi_event_work;
|
||||
|
@ -111,26 +111,29 @@ TRACE_EVENT(ath10k_log_dbg_dump,
|
||||
);
|
||||
|
||||
TRACE_EVENT(ath10k_wmi_cmd,
|
||||
TP_PROTO(int id, void *buf, size_t buf_len),
|
||||
TP_PROTO(int id, void *buf, size_t buf_len, int ret),
|
||||
|
||||
TP_ARGS(id, buf, buf_len),
|
||||
TP_ARGS(id, buf, buf_len, ret),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__field(unsigned int, id)
|
||||
__field(size_t, buf_len)
|
||||
__dynamic_array(u8, buf, buf_len)
|
||||
__field(int ret)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__entry->id = id;
|
||||
__entry->buf_len = buf_len;
|
||||
__entry->ret = ret;
|
||||
memcpy(__get_dynamic_array(buf), buf, buf_len);
|
||||
),
|
||||
|
||||
TP_printk(
|
||||
"id %d len %zu",
|
||||
"id %d len %zu ret %d",
|
||||
__entry->id,
|
||||
__entry->buf_len
|
||||
__entry->buf_len,
|
||||
__entry->ret
|
||||
)
|
||||
);
|
||||
|
||||
|
@ -90,13 +90,12 @@ static void ath10k_wmi_htc_tx_complete(struct ath10k *ar, struct sk_buff *skb)
|
||||
wake_up(&ar->wmi.wq);
|
||||
}
|
||||
|
||||
/* WMI command API */
|
||||
static int ath10k_wmi_cmd_send(struct ath10k *ar, struct sk_buff *skb,
|
||||
enum wmi_cmd_id cmd_id)
|
||||
static int ath10k_wmi_cmd_send_nowait(struct ath10k *ar, struct sk_buff *skb,
|
||||
enum wmi_cmd_id cmd_id)
|
||||
{
|
||||
struct ath10k_skb_cb *skb_cb = ATH10K_SKB_CB(skb);
|
||||
struct wmi_cmd_hdr *cmd_hdr;
|
||||
int status;
|
||||
int ret;
|
||||
u32 cmd = 0;
|
||||
|
||||
if (skb_push(skb, sizeof(struct wmi_cmd_hdr)) == NULL)
|
||||
@ -107,26 +106,40 @@ static int ath10k_wmi_cmd_send(struct ath10k *ar, struct sk_buff *skb,
|
||||
cmd_hdr = (struct wmi_cmd_hdr *)skb->data;
|
||||
cmd_hdr->cmd_id = __cpu_to_le32(cmd);
|
||||
|
||||
if (atomic_add_return(1, &ar->wmi.pending_tx_count) >
|
||||
WMI_MAX_PENDING_TX_COUNT) {
|
||||
/* avoid using up memory when FW hangs */
|
||||
dev_kfree_skb(skb);
|
||||
atomic_dec(&ar->wmi.pending_tx_count);
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
memset(skb_cb, 0, sizeof(*skb_cb));
|
||||
ret = ath10k_htc_send(&ar->htc, ar->wmi.eid, skb);
|
||||
trace_ath10k_wmi_cmd(cmd_id, skb->data, skb->len, ret);
|
||||
|
||||
trace_ath10k_wmi_cmd(cmd_id, skb->data, skb->len);
|
||||
|
||||
status = ath10k_htc_send(&ar->htc, ar->wmi.eid, skb);
|
||||
if (status) {
|
||||
dev_kfree_skb_any(skb);
|
||||
atomic_dec(&ar->wmi.pending_tx_count);
|
||||
return status;
|
||||
}
|
||||
if (ret)
|
||||
goto err_pull;
|
||||
|
||||
return 0;
|
||||
|
||||
err_pull:
|
||||
skb_pull(skb, sizeof(struct wmi_cmd_hdr));
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void ath10k_wmi_op_ep_tx_credits(struct ath10k *ar,
|
||||
enum ath10k_htc_ep_id eid)
|
||||
{
|
||||
wake_up(&ar->wmi.tx_credits_wq);
|
||||
}
|
||||
|
||||
static int ath10k_wmi_cmd_send(struct ath10k *ar, struct sk_buff *skb,
|
||||
enum wmi_cmd_id cmd_id)
|
||||
{
|
||||
int ret = -EINVAL;
|
||||
|
||||
wait_event_timeout(ar->wmi.tx_credits_wq, ({
|
||||
ret = ath10k_wmi_cmd_send_nowait(ar, skb, cmd_id);
|
||||
(ret != -EAGAIN);
|
||||
}), 3*HZ);
|
||||
|
||||
if (ret)
|
||||
dev_kfree_skb_any(skb);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ath10k_wmi_event_scan(struct ath10k *ar, struct sk_buff *skb)
|
||||
@ -1168,7 +1181,6 @@ static void ath10k_wmi_process_rx(struct ath10k *ar, struct sk_buff *skb)
|
||||
/* some events require to be handled ASAP
|
||||
* thus can't be defered to a worker thread */
|
||||
switch (event_id) {
|
||||
case WMI_HOST_SWBA_EVENTID:
|
||||
case WMI_MGMT_RX_EVENTID:
|
||||
ath10k_wmi_event_process(ar, skb);
|
||||
return;
|
||||
@ -1186,6 +1198,7 @@ int ath10k_wmi_attach(struct ath10k *ar)
|
||||
init_completion(&ar->wmi.service_ready);
|
||||
init_completion(&ar->wmi.unified_ready);
|
||||
init_waitqueue_head(&ar->wmi.wq);
|
||||
init_waitqueue_head(&ar->wmi.tx_credits_wq);
|
||||
|
||||
skb_queue_head_init(&ar->wmi.wmi_event_list);
|
||||
INIT_WORK(&ar->wmi.wmi_event_work, ath10k_wmi_event_work);
|
||||
@ -1215,6 +1228,7 @@ int ath10k_wmi_connect_htc_service(struct ath10k *ar)
|
||||
/* these fields are the same for all service endpoints */
|
||||
conn_req.ep_ops.ep_tx_complete = ath10k_wmi_htc_tx_complete;
|
||||
conn_req.ep_ops.ep_rx_complete = ath10k_wmi_process_rx;
|
||||
conn_req.ep_ops.ep_tx_credits = ath10k_wmi_op_ep_tx_credits;
|
||||
|
||||
/* connect to control service */
|
||||
conn_req.service_id = ATH10K_HTC_SVC_ID_WMI_CONTROL;
|
||||
|
Loading…
Reference in New Issue
Block a user