priv->mac80211_registered and priv->hw needed to move to shared.
stop_queue API was added in order to allow the upper layer to stop
the SW queues for regulatory purposes.
Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
{
if (stop) {
IWL_DEBUG_TEMP(priv, "Stop all queues\n");
- if (priv->mac80211_registered)
+ if (priv->shrd->mac80211_registered)
ieee80211_stop_queues(priv->hw);
IWL_DEBUG_TEMP(priv,
"Schedule 5 seconds CT_KILL Timer\n");
jiffies + CT_KILL_EXIT_DURATION * HZ);
} else {
IWL_DEBUG_TEMP(priv, "Wake all queues\n");
- if (priv->mac80211_registered)
+ if (priv->shrd->mac80211_registered)
ieee80211_wake_queues(priv->hw);
}
}
iwl_is_associated_ctx(ctx) && ctx->vif &&
ctx->vif->type == NL80211_IFTYPE_STATION) {
ctx->last_tx_rejected = true;
- iwl_stop_queue(priv, &priv->txq[txq_id]);
+ iwl_trans_stop_queue(trans(priv), txq_id);
IWL_DEBUG_TX_REPLY(priv,
"TXQ %d status %s (0x%08x) "
if (!exit_pending)
clear_bit(STATUS_EXIT_PENDING, &priv->shrd->status);
- if (priv->mac80211_registered)
+ if (priv->shrd->mac80211_registered)
ieee80211_stop_queues(priv->hw);
/* Clear out all status bits but a few that are stable across reset */
IWL_ERR(priv, "Failed to register hw (error %d)\n", ret);
return ret;
}
- priv->mac80211_registered = 1;
+ priv->shrd->mac80211_registered = 1;
return 0;
}
priv->shrd = &priv->_shrd;
priv->shrd->bus = bus;
priv->shrd->priv = priv;
+ priv->shrd->hw = hw;
bus_set_drv_data(priv->bus, priv->shrd);
priv->shrd->trans = trans_ops->alloc(priv->shrd);
iwl_testmode_cleanup(priv);
iwl_leds_exit(priv);
- if (priv->mac80211_registered) {
+ if (priv->shrd->mac80211_registered) {
ieee80211_unregister_hw(priv->hw);
- priv->mac80211_registered = 0;
+ priv->shrd->mac80211_registered = 0;
}
iwl_tt_exit(priv);
/* Indication if ieee80211_ops->open has been called */
u8 is_open;
- u8 mac80211_registered;
-
/* eeprom -- this is in the card's little endian byte order */
u8 *eeprom;
int nvm_device_type;
return --index & (n_bd - 1);
}
-/*
- * we have 8 bits used like this:
- *
- * 7 6 5 4 3 2 1 0
- * | | | | | | | |
- * | | | | | | +-+-------- AC queue (0-3)
- * | | | | | |
- * | +-+-+-+-+------------ HW queue ID
- * |
- * +---------------------- unused
- */
-static inline void iwl_set_swq_id(struct iwl_tx_queue *txq, u8 ac, u8 hwq)
-{
- BUG_ON(ac > 3); /* only have 2 bits */
- BUG_ON(hwq > 31); /* only use 5 bits */
-
- txq->swq_id = (hwq << 2) | ac;
-}
-
-static inline void iwl_wake_queue(struct iwl_priv *priv,
- struct iwl_tx_queue *txq)
-{
- u8 queue = txq->swq_id;
- u8 ac = queue & 3;
- u8 hwq = (queue >> 2) & 0x1f;
-
- if (unlikely(!priv->mac80211_registered))
- return;
-
- if (test_and_clear_bit(hwq, priv->queue_stopped))
- if (atomic_dec_return(&priv->queue_stop_count[ac]) <= 0)
- ieee80211_wake_queue(priv->hw, ac);
-}
-
-static inline void iwl_stop_queue(struct iwl_priv *priv,
- struct iwl_tx_queue *txq)
-{
- u8 queue = txq->swq_id;
- u8 ac = queue & 3;
- u8 hwq = (queue >> 2) & 0x1f;
-
- if (unlikely(!priv->mac80211_registered))
- return;
-
- if (!test_and_set_bit(hwq, priv->queue_stopped))
- if (atomic_inc_return(&priv->queue_stop_count[ac]) > 0)
- ieee80211_stop_queue(priv->hw, ac);
-}
-
-#ifdef ieee80211_stop_queue
-#undef ieee80211_stop_queue
-#endif
-
-#define ieee80211_stop_queue DO_NOT_USE_ieee80211_stop_queue
-
-#ifdef ieee80211_wake_queue
-#undef ieee80211_wake_queue
-#endif
-
-#define ieee80211_wake_queue DO_NOT_USE_ieee80211_wake_queue
-
static inline void iwl_enable_rfkill_int(struct iwl_priv *priv)
{
IWL_DEBUG_ISR(priv, "Enabling rfkill interrupt\n");
spinlock_t sta_lock;
struct mutex mutex;
+ /*these 2 shouldn't really be here, but they are needed for
+ * iwl_queue_stop, which is called from the upper layer too
+ */
+ u8 mac80211_registered;
+ struct ieee80211_hw *hw;
+
struct iwl_tid_data tid_data[IWLAGN_STATION_COUNT][IWL_MAX_TID_COUNT];
};
iwl_write32(bus(trans), CSR_INT_MASK, trans_pcie->inta_mask);
}
+/*
+ * we have 8 bits used like this:
+ *
+ * 7 6 5 4 3 2 1 0
+ * | | | | | | | |
+ * | | | | | | +-+-------- AC queue (0-3)
+ * | | | | | |
+ * | +-+-+-+-+------------ HW queue ID
+ * |
+ * +---------------------- unused
+ */
+static inline void iwl_set_swq_id(struct iwl_tx_queue *txq, u8 ac, u8 hwq)
+{
+ BUG_ON(ac > 3); /* only have 2 bits */
+ BUG_ON(hwq > 31); /* only use 5 bits */
+
+ txq->swq_id = (hwq << 2) | ac;
+}
+
+static inline void iwl_wake_queue(struct iwl_trans *trans,
+ struct iwl_tx_queue *txq)
+{
+ u8 queue = txq->swq_id;
+ u8 ac = queue & 3;
+ u8 hwq = (queue >> 2) & 0x1f;
+
+ if (unlikely(!trans->shrd->mac80211_registered))
+ return;
+
+ if (test_and_clear_bit(hwq, priv(trans)->queue_stopped))
+ if (atomic_dec_return(&priv(trans)->queue_stop_count[ac]) <= 0)
+ ieee80211_wake_queue(trans->shrd->hw, ac);
+}
+
+static inline void iwl_stop_queue(struct iwl_trans *trans,
+ struct iwl_tx_queue *txq)
+{
+ u8 queue = txq->swq_id;
+ u8 ac = queue & 3;
+ u8 hwq = (queue >> 2) & 0x1f;
+
+ if (unlikely(!trans->shrd->mac80211_registered))
+ return;
+
+ if (!test_and_set_bit(hwq, priv(trans)->queue_stopped))
+ if (atomic_inc_return(&priv(trans)->queue_stop_count[ac]) > 0)
+ ieee80211_stop_queue(trans->shrd->hw, ac);
+}
+
+#ifdef ieee80211_stop_queue
+#undef ieee80211_stop_queue
+#endif
+
+#define ieee80211_stop_queue DO_NOT_USE_ieee80211_stop_queue
+
+#ifdef ieee80211_wake_queue
+#undef ieee80211_wake_queue
+#endif
+
+#define ieee80211_wake_queue DO_NOT_USE_ieee80211_wake_queue
+
#endif /* __iwl_trans_int_pcie_h__ */
txq->need_update = 1;
iwl_txq_update_write_ptr(trans, txq);
} else {
- iwl_stop_queue(priv(trans), txq);
+ iwl_stop_queue(trans, txq);
}
}
return 0;
iwl_stop_tx_ba_trans_ready(priv(trans),
NUM_IWL_RXON_CTX,
sta_id, tid);
- iwl_wake_queue(priv(trans), &priv(trans)->txq[txq_id]);
+ iwl_wake_queue(trans, &priv(trans)->txq[txq_id]);
}
break;
case IWL_EMPTYING_HW_QUEUE_ADDBA:
ssn , tfd_num, txq_id, txq->swq_id);
freed = iwl_tx_queue_reclaim(trans, txq_id, tfd_num, skbs);
if (iwl_queue_space(&txq->q) > txq->q.low_mark && cond)
- iwl_wake_queue(priv(trans), txq);
+ iwl_wake_queue(trans, txq);
}
iwl_free_tfds_in_queue(trans, sta_id, tid, freed);
ac,
(atomic_read(&priv(trans)->queue_stop_count[ac]) > 0)
? "stopped" : "awake");
- iwl_wake_queue(priv(trans), &priv(trans)->txq[txq_id]);
+ iwl_wake_queue(trans, &priv(trans)->txq[txq_id]);
}
}
return iwl_trans;
}
+static void iwl_trans_pcie_stop_queue(struct iwl_trans *trans, int txq_id)
+{
+ iwl_stop_queue(trans, &priv(trans)->txq[txq_id]);
+}
+
#define IWL_FLUSH_WAIT_MS 2000
static int iwl_trans_pcie_wait_tx_queue_empty(struct iwl_trans *trans)
.kick_nic = iwl_trans_pcie_kick_nic,
.free = iwl_trans_pcie_free,
+ .stop_queue = iwl_trans_pcie_stop_queue,
.dbgfs_register = iwl_trans_pcie_dbgfs_register,
* @kick_nic: remove the RESET from the embedded CPU and let it run
* @free: release all the ressource for the transport layer itself such as
* irq, tasklet etc...
+ * @stop_queue: stop a specific queue
* @check_stuck_queue: check if a specific queue is stuck
* @wait_tx_queue_empty: wait until all tx queues are empty
* @dbgfs_register: add the dbgfs files under this directory. Files will be
void (*free)(struct iwl_trans *trans);
+ void (*stop_queue)(struct iwl_trans *trans, int q);
+
int (*dbgfs_register)(struct iwl_trans *trans, struct dentry* dir);
int (*check_stuck_queue)(struct iwl_trans *trans, int q);
int (*wait_tx_queue_empty)(struct iwl_trans *trans);
trans->ops->free(trans);
}
+static inline void iwl_trans_stop_queue(struct iwl_trans *trans, int q)
+{
+ trans->ops->stop_queue(trans, q);
+}
+
static inline int iwl_trans_wait_tx_queue_empty(struct iwl_trans *trans)
{
return trans->ops->wait_tx_queue_empty(trans);