Commit dcbb4746 authored by Emmanuel Grumbach's avatar Emmanuel Grumbach

iwlwifi: trans: support a callback for ASYNC commands

This allows the op_mode to request from the transport to
call a callback when an ASYNC commands is completed by
the firmware. The same callback will be called for all the
commands. Pass the command whose response triggers the
callback as a parameter to the callback itself.
Signed-off-by: default avatarEmmanuel Grumbach <emmanuel.grumbach@intel.com>
parent 0cd58eaa
...@@ -123,6 +123,8 @@ struct iwl_cfg; ...@@ -123,6 +123,8 @@ struct iwl_cfg;
* received on the RSS queue(s). The queue parameter indicates which of the * received on the RSS queue(s). The queue parameter indicates which of the
* RSS queues received this frame; it will always be non-zero. * RSS queues received this frame; it will always be non-zero.
* This method must not sleep. * This method must not sleep.
* @async_cb: called when an ASYNC command with CMD_WANT_ASYNC_CALLBACK set
* completes. Must be atomic.
* @queue_full: notifies that a HW queue is full. * @queue_full: notifies that a HW queue is full.
* Must be atomic and called with BH disabled. * Must be atomic and called with BH disabled.
* @queue_not_full: notifies that a HW queue is not full any more. * @queue_not_full: notifies that a HW queue is not full any more.
...@@ -155,6 +157,8 @@ struct iwl_op_mode_ops { ...@@ -155,6 +157,8 @@ struct iwl_op_mode_ops {
struct iwl_rx_cmd_buffer *rxb); struct iwl_rx_cmd_buffer *rxb);
void (*rx_rss)(struct iwl_op_mode *op_mode, struct napi_struct *napi, void (*rx_rss)(struct iwl_op_mode *op_mode, struct napi_struct *napi,
struct iwl_rx_cmd_buffer *rxb, unsigned int queue); struct iwl_rx_cmd_buffer *rxb, unsigned int queue);
void (*async_cb)(struct iwl_op_mode *op_mode,
const struct iwl_device_cmd *cmd);
void (*queue_full)(struct iwl_op_mode *op_mode, int queue); void (*queue_full)(struct iwl_op_mode *op_mode, int queue);
void (*queue_not_full)(struct iwl_op_mode *op_mode, int queue); void (*queue_not_full)(struct iwl_op_mode *op_mode, int queue);
bool (*hw_rf_kill)(struct iwl_op_mode *op_mode, bool state); bool (*hw_rf_kill)(struct iwl_op_mode *op_mode, bool state);
...@@ -203,6 +207,13 @@ static inline void iwl_op_mode_rx_rss(struct iwl_op_mode *op_mode, ...@@ -203,6 +207,13 @@ static inline void iwl_op_mode_rx_rss(struct iwl_op_mode *op_mode,
op_mode->ops->rx_rss(op_mode, napi, rxb, queue); op_mode->ops->rx_rss(op_mode, napi, rxb, queue);
} }
static inline void iwl_op_mode_async_cb(struct iwl_op_mode *op_mode,
const struct iwl_device_cmd *cmd)
{
if (op_mode->ops->async_cb)
op_mode->ops->async_cb(op_mode, cmd);
}
static inline void iwl_op_mode_queue_full(struct iwl_op_mode *op_mode, static inline void iwl_op_mode_queue_full(struct iwl_op_mode *op_mode,
int queue) int queue)
{ {
......
...@@ -248,6 +248,8 @@ static inline u32 iwl_rx_packet_payload_len(const struct iwl_rx_packet *pkt) ...@@ -248,6 +248,8 @@ static inline u32 iwl_rx_packet_payload_len(const struct iwl_rx_packet *pkt)
* @CMD_MAKE_TRANS_IDLE: The command response should mark the trans as idle. * @CMD_MAKE_TRANS_IDLE: The command response should mark the trans as idle.
* @CMD_WAKE_UP_TRANS: The command response should wake up the trans * @CMD_WAKE_UP_TRANS: The command response should wake up the trans
* (i.e. mark it as non-idle). * (i.e. mark it as non-idle).
* @CMD_WANT_ASYNC_CALLBACK: the op_mode's async callback function must be
* called after this command completes. Valid only with CMD_ASYNC.
* @CMD_TB_BITMAP_POS: Position of the first bit for the TB bitmap. We need to * @CMD_TB_BITMAP_POS: Position of the first bit for the TB bitmap. We need to
* check that we leave enough room for the TBs bitmap which needs 20 bits. * check that we leave enough room for the TBs bitmap which needs 20 bits.
*/ */
...@@ -259,6 +261,7 @@ enum CMD_MODE { ...@@ -259,6 +261,7 @@ enum CMD_MODE {
CMD_SEND_IN_IDLE = BIT(4), CMD_SEND_IN_IDLE = BIT(4),
CMD_MAKE_TRANS_IDLE = BIT(5), CMD_MAKE_TRANS_IDLE = BIT(5),
CMD_WAKE_UP_TRANS = BIT(6), CMD_WAKE_UP_TRANS = BIT(6),
CMD_WANT_ASYNC_CALLBACK = BIT(7),
CMD_TB_BITMAP_POS = 11, CMD_TB_BITMAP_POS = 11,
}; };
...@@ -903,6 +906,10 @@ static inline int iwl_trans_send_cmd(struct iwl_trans *trans, ...@@ -903,6 +906,10 @@ static inline int iwl_trans_send_cmd(struct iwl_trans *trans,
return -EIO; return -EIO;
} }
if (WARN_ON((cmd->flags & CMD_WANT_ASYNC_CALLBACK) &&
!(cmd->flags & CMD_ASYNC)))
return -EINVAL;
if (!(cmd->flags & CMD_ASYNC)) if (!(cmd->flags & CMD_ASYNC))
lock_map_acquire_read(&trans->sync_cmd_lockdep_map); lock_map_acquire_read(&trans->sync_cmd_lockdep_map);
......
...@@ -1593,10 +1593,6 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans, ...@@ -1593,10 +1593,6 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans,
/* /*
* iwl_pcie_hcmd_complete - Pull unused buffers off the queue and reclaim them * iwl_pcie_hcmd_complete - Pull unused buffers off the queue and reclaim them
* @rxb: Rx buffer to reclaim * @rxb: Rx buffer to reclaim
*
* If an Rx buffer has an async callback associated with it the callback
* will be executed. The attached skb (if present) will only be freed
* if the callback returns 1
*/ */
void iwl_pcie_hcmd_complete(struct iwl_trans *trans, void iwl_pcie_hcmd_complete(struct iwl_trans *trans,
struct iwl_rx_cmd_buffer *rxb) struct iwl_rx_cmd_buffer *rxb)
...@@ -1640,6 +1636,9 @@ void iwl_pcie_hcmd_complete(struct iwl_trans *trans, ...@@ -1640,6 +1636,9 @@ void iwl_pcie_hcmd_complete(struct iwl_trans *trans,
meta->source->_rx_page_order = trans_pcie->rx_page_order; meta->source->_rx_page_order = trans_pcie->rx_page_order;
} }
if (meta->flags & CMD_WANT_ASYNC_CALLBACK)
iwl_op_mode_async_cb(trans->op_mode, cmd);
iwl_pcie_cmdq_reclaim(trans, txq_id, index); iwl_pcie_cmdq_reclaim(trans, txq_id, index);
if (!(meta->flags & CMD_ASYNC)) { if (!(meta->flags & CMD_ASYNC)) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment