@@ -894,6 +894,7 @@ struct iwl_pcie_first_tb_buf {
* @read_ptr: last used entry (index) host_r
* @dma_addr: physical addr for BD's
* @n_window: safe queue window
+ * @n_reduced_win: reduced @n_window in case of HW allocation workarounds
* @id: queue id
* @low_mark: low watermark, resume queue if free space more than this
* @high_mark: high watermark, stop queue if free space less than this
@@ -936,6 +937,7 @@ struct iwl_txq {
int read_ptr;
dma_addr_t dma_addr;
int n_window;
+ int n_reduced_win;
u32 id;
int low_mark;
int high_mark;
@@ -685,8 +685,8 @@ int iwl_txq_space(struct iwl_trans *trans, const struct iwl_txq *q)
* If q->n_window is smaller than max_tfd_queue_size, there is no need
* to reserve any queue entries for this purpose.
*/
- if (q->n_window < trans->trans_cfg->base_params->max_tfd_queue_size)
- max = q->n_window;
+ if (q->n_reduced_win < trans->trans_cfg->base_params->max_tfd_queue_size)
+ max = q->n_reduced_win;
else
max = trans->trans_cfg->base_params->max_tfd_queue_size - 1;
@@ -899,6 +899,7 @@ static void iwl_txq_gen2_free(struct iwl_trans *trans, int txq_id)
static int iwl_queue_init(struct iwl_txq *q, int slots_num)
{
q->n_window = slots_num;
+ q->n_reduced_win = slots_num;
/* slots_num must be power-of-two size, otherwise
* iwl_txq_get_cmd_index is broken. */
@@ -1037,6 +1038,7 @@ int iwl_txq_alloc(struct iwl_trans *trans, struct iwl_txq *txq, int slots_num,
txq->trans = trans;
txq->n_window = slots_num;
+ txq->n_reduced_win = slots_num;
txq->entries = kcalloc(slots_num,
sizeof(struct iwl_pcie_txq_entry),
@@ -1197,16 +1199,31 @@ int iwl_txq_dyn_alloc(struct iwl_trans *trans, u32 flags, u32 sta_mask,
struct iwl_host_cmd hcmd = {
.flags = CMD_WANT_SKB,
};
+ int org_size = 0;
int ret;
if (trans->trans_cfg->device_family == IWL_DEVICE_FAMILY_BZ &&
- trans->hw_rev_step == SILICON_A_STEP)
+ trans->hw_rev_step == SILICON_A_STEP) {
+ org_size = size;
size = 4096;
+ }
txq = iwl_txq_dyn_alloc_dma(trans, size, timeout);
if (IS_ERR(txq))
return PTR_ERR(txq);
+ if (org_size) {
+ txq->n_reduced_win = org_size;
+
+ txq->low_mark = org_size / 4;
+ if (txq->low_mark < 4)
+ txq->low_mark = 4;
+
+ txq->high_mark = org_size / 8;
+ if (txq->high_mark < 2)
+ txq->high_mark = 2;
+ }
+
if (trans->txqs.queue_alloc_cmd_ver == 0) {
memset(&cmd.old, 0, sizeof(cmd.old));
cmd.old.tfdq_addr = cpu_to_le64(txq->dma_addr);