aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorTomas Winkler <tomas.winkler@intel.com>2008-03-06 20:36:55 -0500
committerJohn W. Linville <linville@tuxdriver.com>2008-03-07 16:03:02 -0500
commit91c066f27b6dacb6589fb5190af373fb9f993397 (patch)
tree0e89811d45705907265c01c49c715b6446529e9e /drivers
parent28447f3cfdf72f6ea97b50cc1eefe35602107dff (diff)
iwlwifi: 3945 split tx_complete to command and packet function
This patch 1. removes cmd completion from iwl3945_tx_queue_reclaim and creates iwl3945_cmd_queue_reclaim. 1. removes 11n relevant elements from this function 2. removes call to ieee80211_tx_status_irqsafe and uses ieee80211_tx_status only Signed-off-by: Tomas Winkler <tomas.winkler@intel.com> Signed-off-by: Reinette Chatre <reinette.chatre@intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-3945.c117
-rw-r--r--drivers/net/wireless/iwlwifi/iwl3945-base.c188
2 files changed, 148 insertions, 157 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c
index 49b78110432..dc3d695bf09 100644
--- a/drivers/net/wireless/iwlwifi/iwl-3945.c
+++ b/drivers/net/wireless/iwlwifi/iwl-3945.c
@@ -227,14 +227,126 @@ __le32 iwl3945_get_antenna_flags(const struct iwl3945_priv *priv)
227 return 0; /* "diversity" is default if error */ 227 return 0; /* "diversity" is default if error */
228} 228}
229 229
230#ifdef CONFIG_IWL3945_DEBUG
231#define TX_STATUS_ENTRY(x) case TX_STATUS_FAIL_ ## x: return #x
232
233static const char *iwl3945_get_tx_fail_reason(u32 status)
234{
235 switch (status & TX_STATUS_MSK) {
236 case TX_STATUS_SUCCESS:
237 return "SUCCESS";
238 TX_STATUS_ENTRY(SHORT_LIMIT);
239 TX_STATUS_ENTRY(LONG_LIMIT);
240 TX_STATUS_ENTRY(FIFO_UNDERRUN);
241 TX_STATUS_ENTRY(MGMNT_ABORT);
242 TX_STATUS_ENTRY(NEXT_FRAG);
243 TX_STATUS_ENTRY(LIFE_EXPIRE);
244 TX_STATUS_ENTRY(DEST_PS);
245 TX_STATUS_ENTRY(ABORTED);
246 TX_STATUS_ENTRY(BT_RETRY);
247 TX_STATUS_ENTRY(STA_INVALID);
248 TX_STATUS_ENTRY(FRAG_DROPPED);
249 TX_STATUS_ENTRY(TID_DISABLE);
250 TX_STATUS_ENTRY(FRAME_FLUSHED);
251 TX_STATUS_ENTRY(INSUFFICIENT_CF_POLL);
252 TX_STATUS_ENTRY(TX_LOCKED);
253 TX_STATUS_ENTRY(NO_BEACON_ON_RADAR);
254 }
255
256 return "UNKNOWN";
257}
258#else
259static inline const char *iwl3945_get_tx_fail_reason(u32 status)
260{
261 return "";
262}
263#endif
264
265
266/**
267 * iwl3945_tx_queue_reclaim - Reclaim Tx queue entries already Tx'd
268 *
269 * When FW advances 'R' index, all entries between old and new 'R' index
270 * need to be reclaimed. As result, some free space forms. If there is
271 * enough free space (> low mark), wake the stack that feeds us.
272 */
273static void iwl3945_tx_queue_reclaim(struct iwl3945_priv *priv,
274 int txq_id, int index)
275{
276 struct iwl3945_tx_queue *txq = &priv->txq[txq_id];
277 struct iwl3945_queue *q = &txq->q;
278 struct iwl3945_tx_info *tx_info;
279
280 BUG_ON(txq_id == IWL_CMD_QUEUE_NUM);
281
282 for (index = iwl_queue_inc_wrap(index, q->n_bd); q->read_ptr != index;
283 q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) {
284
285 tx_info = &txq->txb[txq->q.read_ptr];
286 ieee80211_tx_status(priv->hw, tx_info->skb[0],
287 &tx_info->status);
288 tx_info->skb[0] = NULL;
289 iwl3945_hw_txq_free_tfd(priv, txq);
290 }
291
292 if (iwl3945_queue_space(q) > q->low_mark && (txq_id >= 0) &&
293 (txq_id != IWL_CMD_QUEUE_NUM) &&
294 priv->mac80211_registered)
295 ieee80211_wake_queue(priv->hw, txq_id);
296}
297
298/**
299 * iwl3945_rx_reply_tx - Handle Tx response
300 */
301static void iwl3945_rx_reply_tx(struct iwl3945_priv *priv,
302 struct iwl3945_rx_mem_buffer *rxb)
303{
304 struct iwl3945_rx_packet *pkt = (void *)rxb->skb->data;
305 u16 sequence = le16_to_cpu(pkt->hdr.sequence);
306 int txq_id = SEQ_TO_QUEUE(sequence);
307 int index = SEQ_TO_INDEX(sequence);
308 struct iwl3945_tx_queue *txq = &priv->txq[txq_id];
309 struct ieee80211_tx_status *tx_status;
310 struct iwl3945_tx_resp *tx_resp = (void *)&pkt->u.raw[0];
311 u32 status = le32_to_cpu(tx_resp->status);
312 int rate_idx;
313
314 if ((index >= txq->q.n_bd) || (iwl3945_x2_queue_used(&txq->q, index) == 0)) {
315 IWL_ERROR("Read index for DMA queue txq_id (%d) index %d "
316 "is out of range [0-%d] %d %d\n", txq_id,
317 index, txq->q.n_bd, txq->q.write_ptr,
318 txq->q.read_ptr);
319 return;
320 }
321
322 tx_status = &(txq->txb[txq->q.read_ptr].status);
323
324 tx_status->retry_count = tx_resp->failure_frame;
325 /* tx_status->rts_retry_count = tx_resp->failure_rts; */
326 tx_status->flags = ((status & TX_STATUS_MSK) == TX_STATUS_SUCCESS) ?
327 IEEE80211_TX_STATUS_ACK : 0;
328
329 IWL_DEBUG_TX("Tx queue %d Status %s (0x%08x) plcp rate %d retries %d\n",
330 txq_id, iwl3945_get_tx_fail_reason(status), status,
331 tx_resp->rate, tx_resp->failure_frame);
332
333 rate_idx = iwl3945_hwrate_to_plcp_idx(tx_resp->rate);
334 tx_status->control.tx_rate = &priv->ieee_rates[rate_idx];
335 IWL_DEBUG_TX_REPLY("Tx queue reclaim %d\n", index);
336 iwl3945_tx_queue_reclaim(priv, txq_id, index);
337
338 if (iwl_check_bits(status, TX_ABORT_REQUIRED_MSK))
339 IWL_ERROR("TODO: Implement Tx ABORT REQUIRED!!!\n");
340}
341
342
343
230/***************************************************************************** 344/*****************************************************************************
231 * 345 *
232 * Intel PRO/Wireless 3945ABG/BG Network Connection 346 * Intel PRO/Wireless 3945ABG/BG Network Connection
233 * 347 *
234 * RX handler implementations 348 * RX handler implementations
235 * 349 *
236 * Used by iwl-base.c
237 *
238 *****************************************************************************/ 350 *****************************************************************************/
239 351
240void iwl3945_hw_rx_statistics(struct iwl3945_priv *priv, struct iwl3945_rx_mem_buffer *rxb) 352void iwl3945_hw_rx_statistics(struct iwl3945_priv *priv, struct iwl3945_rx_mem_buffer *rxb)
@@ -2510,6 +2622,7 @@ unsigned int iwl3945_hw_get_beacon_cmd(struct iwl3945_priv *priv,
2510 2622
2511void iwl3945_hw_rx_handler_setup(struct iwl3945_priv *priv) 2623void iwl3945_hw_rx_handler_setup(struct iwl3945_priv *priv)
2512{ 2624{
2625 priv->rx_handlers[REPLY_TX] = iwl3945_rx_reply_tx;
2513 priv->rx_handlers[REPLY_3945_RX] = iwl3945_rx_reply_rx; 2626 priv->rx_handlers[REPLY_3945_RX] = iwl3945_rx_reply_rx;
2514} 2627}
2515 2628
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c
index 39fd5440a24..ecf749c2dc0 100644
--- a/drivers/net/wireless/iwlwifi/iwl3945-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c
@@ -2063,34 +2063,6 @@ int iwl3945_is_network_packet(struct iwl3945_priv *priv, struct ieee80211_hdr *h
2063 return 1; 2063 return 1;
2064} 2064}
2065 2065
2066#define TX_STATUS_ENTRY(x) case TX_STATUS_FAIL_ ## x: return #x
2067
2068static const char *iwl3945_get_tx_fail_reason(u32 status)
2069{
2070 switch (status & TX_STATUS_MSK) {
2071 case TX_STATUS_SUCCESS:
2072 return "SUCCESS";
2073 TX_STATUS_ENTRY(SHORT_LIMIT);
2074 TX_STATUS_ENTRY(LONG_LIMIT);
2075 TX_STATUS_ENTRY(FIFO_UNDERRUN);
2076 TX_STATUS_ENTRY(MGMNT_ABORT);
2077 TX_STATUS_ENTRY(NEXT_FRAG);
2078 TX_STATUS_ENTRY(LIFE_EXPIRE);
2079 TX_STATUS_ENTRY(DEST_PS);
2080 TX_STATUS_ENTRY(ABORTED);
2081 TX_STATUS_ENTRY(BT_RETRY);
2082 TX_STATUS_ENTRY(STA_INVALID);
2083 TX_STATUS_ENTRY(FRAG_DROPPED);
2084 TX_STATUS_ENTRY(TID_DISABLE);
2085 TX_STATUS_ENTRY(FRAME_FLUSHED);
2086 TX_STATUS_ENTRY(INSUFFICIENT_CF_POLL);
2087 TX_STATUS_ENTRY(TX_LOCKED);
2088 TX_STATUS_ENTRY(NO_BEACON_ON_RADAR);
2089 }
2090
2091 return "UNKNOWN";
2092}
2093
2094/** 2066/**
2095 * iwl3945_scan_cancel - Cancel any currently executing HW scan 2067 * iwl3945_scan_cancel - Cancel any currently executing HW scan
2096 * 2068 *
@@ -3138,125 +3110,6 @@ static int iwl3945_get_measurement(struct iwl3945_priv *priv,
3138} 3110}
3139#endif 3111#endif
3140 3112
3141static void iwl3945_txstatus_to_ieee(struct iwl3945_priv *priv,
3142 struct iwl3945_tx_info *tx_sta)
3143{
3144
3145 tx_sta->status.ack_signal = 0;
3146 tx_sta->status.excessive_retries = 0;
3147 tx_sta->status.queue_length = 0;
3148 tx_sta->status.queue_number = 0;
3149
3150 if (in_interrupt())
3151 ieee80211_tx_status_irqsafe(priv->hw,
3152 tx_sta->skb[0], &(tx_sta->status));
3153 else
3154 ieee80211_tx_status(priv->hw,
3155 tx_sta->skb[0], &(tx_sta->status));
3156
3157 tx_sta->skb[0] = NULL;
3158}
3159
3160/**
3161 * iwl3945_tx_queue_reclaim - Reclaim Tx queue entries already Tx'd
3162 *
3163 * When FW advances 'R' index, all entries between old and new 'R' index
3164 * need to be reclaimed. As result, some free space forms. If there is
3165 * enough free space (> low mark), wake the stack that feeds us.
3166 */
3167static int iwl3945_tx_queue_reclaim(struct iwl3945_priv *priv, int txq_id, int index)
3168{
3169 struct iwl3945_tx_queue *txq = &priv->txq[txq_id];
3170 struct iwl3945_queue *q = &txq->q;
3171 int nfreed = 0;
3172
3173 if ((index >= q->n_bd) || (iwl3945_x2_queue_used(q, index) == 0)) {
3174 IWL_ERROR("Read index for DMA queue txq id (%d), index %d, "
3175 "is out of range [0-%d] %d %d.\n", txq_id,
3176 index, q->n_bd, q->write_ptr, q->read_ptr);
3177 return 0;
3178 }
3179
3180 for (index = iwl_queue_inc_wrap(index, q->n_bd);
3181 q->read_ptr != index;
3182 q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) {
3183 if (txq_id != IWL_CMD_QUEUE_NUM) {
3184 iwl3945_txstatus_to_ieee(priv,
3185 &(txq->txb[txq->q.read_ptr]));
3186 iwl3945_hw_txq_free_tfd(priv, txq);
3187 } else if (nfreed > 1) {
3188 IWL_ERROR("HCMD skipped: index (%d) %d %d\n", index,
3189 q->write_ptr, q->read_ptr);
3190 queue_work(priv->workqueue, &priv->restart);
3191 }
3192 nfreed++;
3193 }
3194
3195 if (iwl3945_queue_space(q) > q->low_mark && (txq_id >= 0) &&
3196 (txq_id != IWL_CMD_QUEUE_NUM) &&
3197 priv->mac80211_registered)
3198 ieee80211_wake_queue(priv->hw, txq_id);
3199
3200
3201 return nfreed;
3202}
3203
3204static int iwl3945_is_tx_success(u32 status)
3205{
3206 return (status & 0xFF) == 0x1;
3207}
3208
3209/******************************************************************************
3210 *
3211 * Generic RX handler implementations
3212 *
3213 ******************************************************************************/
3214/**
3215 * iwl3945_rx_reply_tx - Handle Tx response
3216 */
3217static void iwl3945_rx_reply_tx(struct iwl3945_priv *priv,
3218 struct iwl3945_rx_mem_buffer *rxb)
3219{
3220 struct iwl3945_rx_packet *pkt = (void *)rxb->skb->data;
3221 u16 sequence = le16_to_cpu(pkt->hdr.sequence);
3222 int txq_id = SEQ_TO_QUEUE(sequence);
3223 int index = SEQ_TO_INDEX(sequence);
3224 struct iwl3945_tx_queue *txq = &priv->txq[txq_id];
3225 struct ieee80211_tx_status *tx_status;
3226 struct iwl3945_tx_resp *tx_resp = (void *)&pkt->u.raw[0];
3227 u32 status = le32_to_cpu(tx_resp->status);
3228
3229 if ((index >= txq->q.n_bd) || (iwl3945_x2_queue_used(&txq->q, index) == 0)) {
3230 IWL_ERROR("Read index for DMA queue txq_id (%d) index %d "
3231 "is out of range [0-%d] %d %d\n", txq_id,
3232 index, txq->q.n_bd, txq->q.write_ptr,
3233 txq->q.read_ptr);
3234 return;
3235 }
3236
3237 tx_status = &(txq->txb[txq->q.read_ptr].status);
3238
3239 tx_status->retry_count = tx_resp->failure_frame;
3240 tx_status->queue_number = status;
3241 tx_status->queue_length = tx_resp->bt_kill_count;
3242 tx_status->queue_length |= tx_resp->failure_rts;
3243
3244 tx_status->flags =
3245 iwl3945_is_tx_success(status) ? IEEE80211_TX_STATUS_ACK : 0;
3246
3247 IWL_DEBUG_TX("Tx queue %d Status %s (0x%08x) plcp rate %d retries %d\n",
3248 txq_id, iwl3945_get_tx_fail_reason(status), status,
3249 tx_resp->rate, tx_resp->failure_frame);
3250
3251 IWL_DEBUG_TX_REPLY("Tx queue reclaim %d\n", index);
3252 if (index != -1)
3253 iwl3945_tx_queue_reclaim(priv, txq_id, index);
3254
3255 if (iwl_check_bits(status, TX_ABORT_REQUIRED_MSK))
3256 IWL_ERROR("TODO: Implement Tx ABORT REQUIRED!!!\n");
3257}
3258
3259
3260static void iwl3945_rx_reply_alive(struct iwl3945_priv *priv, 3113static void iwl3945_rx_reply_alive(struct iwl3945_priv *priv,
3261 struct iwl3945_rx_mem_buffer *rxb) 3114 struct iwl3945_rx_mem_buffer *rxb)
3262{ 3115{
@@ -3603,13 +3456,44 @@ static void iwl3945_setup_rx_handlers(struct iwl3945_priv *priv)
3603 priv->rx_handlers[SCAN_COMPLETE_NOTIFICATION] = 3456 priv->rx_handlers[SCAN_COMPLETE_NOTIFICATION] =
3604 iwl3945_rx_scan_complete_notif; 3457 iwl3945_rx_scan_complete_notif;
3605 priv->rx_handlers[CARD_STATE_NOTIFICATION] = iwl3945_rx_card_state_notif; 3458 priv->rx_handlers[CARD_STATE_NOTIFICATION] = iwl3945_rx_card_state_notif;
3606 priv->rx_handlers[REPLY_TX] = iwl3945_rx_reply_tx;
3607 3459
3608 /* Set up hardware specific Rx handlers */ 3460 /* Set up hardware specific Rx handlers */
3609 iwl3945_hw_rx_handler_setup(priv); 3461 iwl3945_hw_rx_handler_setup(priv);
3610} 3462}
3611 3463
3612/** 3464/**
3465 * iwl3945_cmd_queue_reclaim - Reclaim CMD queue entries
3466 * When FW advances 'R' index, all entries between old and new 'R' index
3467 * need to be reclaimed.
3468 */
3469static void iwl3945_cmd_queue_reclaim(struct iwl3945_priv *priv,
3470 int txq_id, int index)
3471{
3472 struct iwl3945_tx_queue *txq = &priv->txq[txq_id];
3473 struct iwl3945_queue *q = &txq->q;
3474 int nfreed = 0;
3475
3476 if ((index >= q->n_bd) || (iwl3945_x2_queue_used(q, index) == 0)) {
3477 IWL_ERROR("Read index for DMA queue txq id (%d), index %d, "
3478 "is out of range [0-%d] %d %d.\n", txq_id,
3479 index, q->n_bd, q->write_ptr, q->read_ptr);
3480 return;
3481 }
3482
3483 for (index = iwl_queue_inc_wrap(index, q->n_bd); q->read_ptr != index;
3484 q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) {
3485 if (nfreed > 1) {
3486 IWL_ERROR("HCMD skipped: index (%d) %d %d\n", index,
3487 q->write_ptr, q->read_ptr);
3488 queue_work(priv->workqueue, &priv->restart);
3489 break;
3490 }
3491 nfreed++;
3492 }
3493}
3494
3495
3496/**
3613 * iwl3945_tx_cmd_complete - Pull unused buffers off the queue and reclaim them 3497 * iwl3945_tx_cmd_complete - Pull unused buffers off the queue and reclaim them
3614 * @rxb: Rx buffer to reclaim 3498 * @rxb: Rx buffer to reclaim
3615 * 3499 *
@@ -3628,12 +3512,6 @@ static void iwl3945_tx_cmd_complete(struct iwl3945_priv *priv,
3628 int cmd_index; 3512 int cmd_index;
3629 struct iwl3945_cmd *cmd; 3513 struct iwl3945_cmd *cmd;
3630 3514
3631 /* If a Tx command is being handled and it isn't in the actual
3632 * command queue then there a command routing bug has been introduced
3633 * in the queue management code. */
3634 if (txq_id != IWL_CMD_QUEUE_NUM)
3635 IWL_ERROR("Error wrong command queue %d command id 0x%X\n",
3636 txq_id, pkt->hdr.cmd);
3637 BUG_ON(txq_id != IWL_CMD_QUEUE_NUM); 3515 BUG_ON(txq_id != IWL_CMD_QUEUE_NUM);
3638 3516
3639 cmd_index = get_cmd_index(&priv->txq[IWL_CMD_QUEUE_NUM].q, index, huge); 3517 cmd_index = get_cmd_index(&priv->txq[IWL_CMD_QUEUE_NUM].q, index, huge);
@@ -3647,7 +3525,7 @@ static void iwl3945_tx_cmd_complete(struct iwl3945_priv *priv,
3647 !cmd->meta.u.callback(priv, cmd, rxb->skb)) 3525 !cmd->meta.u.callback(priv, cmd, rxb->skb))
3648 rxb->skb = NULL; 3526 rxb->skb = NULL;
3649 3527
3650 iwl3945_tx_queue_reclaim(priv, txq_id, index); 3528 iwl3945_cmd_queue_reclaim(priv, txq_id, index);
3651 3529
3652 if (!(cmd->meta.flags & CMD_ASYNC)) { 3530 if (!(cmd->meta.flags & CMD_ASYNC)) {
3653 clear_bit(STATUS_HCMD_ACTIVE, &priv->status); 3531 clear_bit(STATUS_HCMD_ACTIVE, &priv->status);