iwlwifi: disable FAT channel when not permitted
[safe/jmp/linux-2.6] / drivers / net / wireless / iwlwifi / iwl4965-base.c
index 40616db..676d043 100644 (file)
@@ -87,12 +87,6 @@ MODULE_VERSION(DRV_VERSION);
 MODULE_AUTHOR(DRV_COPYRIGHT);
 MODULE_LICENSE("GPL");
 
-static const struct ieee80211_supported_band *iwl_get_hw_mode(
-               struct iwl_priv *priv, enum ieee80211_band band)
-{
-       return priv->hw->wiphy->bands[band];
-}
-
 static int iwl4965_is_empty_essid(const char *essid, int essid_len)
 {
        /* Single white space is for Linksys APs */
@@ -140,49 +134,6 @@ static const char *iwl4965_escape_essid(const char *essid, u8 essid_len)
 
 /**************************************************************/
 
-#if 0 /* temporary disable till we add real remove station */
-/**
- * iwl4965_remove_station - Remove driver's knowledge of station.
- *
- * NOTE:  This does not remove station from device's station table.
- */
-static u8 iwl4965_remove_station(struct iwl_priv *priv, const u8 *addr, int is_ap)
-{
-       int index = IWL_INVALID_STATION;
-       int i;
-       unsigned long flags;
-
-       spin_lock_irqsave(&priv->sta_lock, flags);
-
-       if (is_ap)
-               index = IWL_AP_ID;
-       else if (is_broadcast_ether_addr(addr))
-               index = priv->hw_params.bcast_sta_id;
-       else
-               for (i = IWL_STA_ID; i < priv->hw_params.max_stations; i++)
-                       if (priv->stations[i].used &&
-                           !compare_ether_addr(priv->stations[i].sta.sta.addr,
-                                               addr)) {
-                               index = i;
-                               break;
-                       }
-
-       if (unlikely(index == IWL_INVALID_STATION))
-               goto out;
-
-       if (priv->stations[index].used) {
-               priv->stations[index].used = 0;
-               priv->num_stations--;
-       }
-
-       BUG_ON(priv->num_stations < 0);
-
-out:
-       spin_unlock_irqrestore(&priv->sta_lock, flags);
-       return 0;
-}
-#endif
-
 
 
 static void iwl4965_set_rxon_hwcrypto(struct iwl_priv *priv, int hw_decrypt)
@@ -404,6 +355,7 @@ static int iwl4965_commit_rxon(struct iwl_priv *priv)
                return rc;
        }
 
+       iwl_remove_station(priv, iwl_bcast_addr, 0);
        iwlcore_clear_stations_table(priv);
 
        if (!priv->error_recovering)
@@ -957,33 +909,7 @@ int iwl4965_is_network_packet(struct iwl_priv *priv, struct ieee80211_hdr *heade
        return 1;
 }
 
-#define TX_STATUS_ENTRY(x) case TX_STATUS_FAIL_ ## x: return #x
-
-static const char *iwl4965_get_tx_fail_reason(u32 status)
-{
-       switch (status & TX_STATUS_MSK) {
-       case TX_STATUS_SUCCESS:
-               return "SUCCESS";
-               TX_STATUS_ENTRY(SHORT_LIMIT);
-               TX_STATUS_ENTRY(LONG_LIMIT);
-               TX_STATUS_ENTRY(FIFO_UNDERRUN);
-               TX_STATUS_ENTRY(MGMNT_ABORT);
-               TX_STATUS_ENTRY(NEXT_FRAG);
-               TX_STATUS_ENTRY(LIFE_EXPIRE);
-               TX_STATUS_ENTRY(DEST_PS);
-               TX_STATUS_ENTRY(ABORTED);
-               TX_STATUS_ENTRY(BT_RETRY);
-               TX_STATUS_ENTRY(STA_INVALID);
-               TX_STATUS_ENTRY(FRAG_DROPPED);
-               TX_STATUS_ENTRY(TID_DISABLE);
-               TX_STATUS_ENTRY(FRAME_FLUSHED);
-               TX_STATUS_ENTRY(INSUFFICIENT_CF_POLL);
-               TX_STATUS_ENTRY(TX_LOCKED);
-               TX_STATUS_ENTRY(NO_BEACON_ON_RADAR);
-       }
 
-       return "UNKNOWN";
-}
 
 /**
  * iwl4965_scan_cancel - Cancel any currently executing HW scan
@@ -1603,343 +1529,16 @@ static int iwl4965_get_measurement(struct iwl_priv *priv,
 }
 #endif
 
-static void iwl4965_txstatus_to_ieee(struct iwl_priv *priv,
-                                    struct iwl_tx_info *tx_sta)
-{
-
-       tx_sta->status.ack_signal = 0;
-       tx_sta->status.excessive_retries = 0;
-
-       if (in_interrupt())
-               ieee80211_tx_status_irqsafe(priv->hw,
-                                           tx_sta->skb[0], &(tx_sta->status));
-       else
-               ieee80211_tx_status(priv->hw,
-                                   tx_sta->skb[0], &(tx_sta->status));
-
-       tx_sta->skb[0] = NULL;
-}
-
-/**
- * iwl4965_tx_queue_reclaim - Reclaim Tx queue entries already Tx'd
- *
- * When FW advances 'R' index, all entries between old and new 'R' index
- * need to be reclaimed. As result, some free space forms.  If there is
- * enough free space (> low mark), wake the stack that feeds us.
- */
-int iwl4965_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index)
-{
-       struct iwl_tx_queue *txq = &priv->txq[txq_id];
-       struct iwl_queue *q = &txq->q;
-       int nfreed = 0;
-
-       if ((index >= q->n_bd) || (iwl_queue_used(q, index) == 0)) {
-               IWL_ERROR("Read index for DMA queue txq id (%d), index %d, "
-                         "is out of range [0-%d] %d %d.\n", txq_id,
-                         index, q->n_bd, q->write_ptr, q->read_ptr);
-               return 0;
-       }
-
-       for (index = iwl_queue_inc_wrap(index, q->n_bd);
-               q->read_ptr != index;
-               q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) {
-               if (txq_id != IWL_CMD_QUEUE_NUM) {
-                       iwl4965_txstatus_to_ieee(priv,
-                                       &(txq->txb[txq->q.read_ptr]));
-                       iwl_hw_txq_free_tfd(priv, txq);
-               } else if (nfreed > 1) {
-                       IWL_ERROR("HCMD skipped: index (%d) %d %d\n", index,
-                                       q->write_ptr, q->read_ptr);
-                       queue_work(priv->workqueue, &priv->restart);
-               }
-               nfreed++;
-       }
-
-       return nfreed;
-}
-
-static int iwl4965_is_tx_success(u32 status)
-{
-       status &= TX_STATUS_MSK;
-       return (status == TX_STATUS_SUCCESS)
-           || (status == TX_STATUS_DIRECT_DONE);
-}
-
 /******************************************************************************
  *
  * Generic RX handler implementations
  *
  ******************************************************************************/
-#ifdef CONFIG_IWL4965_HT
-
-static inline int iwl4965_get_ra_sta_id(struct iwl_priv *priv,
-                                   struct ieee80211_hdr *hdr)
-{
-       if (priv->iw_mode == IEEE80211_IF_TYPE_STA)
-               return IWL_AP_ID;
-       else {
-               u8 *da = ieee80211_get_DA(hdr);
-               return iwl_find_station(priv, da);
-       }
-}
-
-static struct ieee80211_hdr *iwl4965_tx_queue_get_hdr(
-       struct iwl_priv *priv, int txq_id, int idx)
-{
-       if (priv->txq[txq_id].txb[idx].skb[0])
-               return (struct ieee80211_hdr *)priv->txq[txq_id].
-                               txb[idx].skb[0]->data;
-       return NULL;
-}
-
-static inline u32 iwl4965_get_scd_ssn(struct iwl4965_tx_resp *tx_resp)
-{
-       __le32 *scd_ssn = (__le32 *)((u32 *)&tx_resp->status +
-                               tx_resp->frame_count);
-       return le32_to_cpu(*scd_ssn) & MAX_SN;
-
-}
-
-/**
- * iwl4965_tx_status_reply_tx - Handle Tx rspnse for frames in aggregation queue
- */
-static int iwl4965_tx_status_reply_tx(struct iwl_priv *priv,
-                                     struct iwl_ht_agg *agg,
-                                     struct iwl4965_tx_resp_agg *tx_resp,
-                                     u16 start_idx)
-{
-       u16 status;
-       struct agg_tx_status *frame_status = &tx_resp->status;
-       struct ieee80211_tx_status *tx_status = NULL;
-       struct ieee80211_hdr *hdr = NULL;
-       int i, sh;
-       int txq_id, idx;
-       u16 seq;
-
-       if (agg->wait_for_ba)
-               IWL_DEBUG_TX_REPLY("got tx response w/o block-ack\n");
-
-       agg->frame_count = tx_resp->frame_count;
-       agg->start_idx = start_idx;
-       agg->rate_n_flags = le32_to_cpu(tx_resp->rate_n_flags);
-       agg->bitmap = 0;
-
-       /* # frames attempted by Tx command */
-       if (agg->frame_count == 1) {
-               /* Only one frame was attempted; no block-ack will arrive */
-               status = le16_to_cpu(frame_status[0].status);
-               seq  = le16_to_cpu(frame_status[0].sequence);
-               idx = SEQ_TO_INDEX(seq);
-               txq_id = SEQ_TO_QUEUE(seq);
-
-               /* FIXME: code repetition */
-               IWL_DEBUG_TX_REPLY("FrameCnt = %d, StartIdx=%d idx=%d\n",
-                                  agg->frame_count, agg->start_idx, idx);
-
-               tx_status = &(priv->txq[txq_id].txb[idx].status);
-               tx_status->retry_count = tx_resp->failure_frame;
-               tx_status->control.flags &= ~IEEE80211_TXCTL_AMPDU;
-               tx_status->flags = iwl4965_is_tx_success(status)?
-                       IEEE80211_TX_STATUS_ACK : 0;
-               iwl4965_hwrate_to_tx_control(priv,
-                                            le32_to_cpu(tx_resp->rate_n_flags),
-                                            &tx_status->control);
-               /* FIXME: code repetition end */
-
-               IWL_DEBUG_TX_REPLY("1 Frame 0x%x failure :%d\n",
-                                   status & 0xff, tx_resp->failure_frame);
-               IWL_DEBUG_TX_REPLY("Rate Info rate_n_flags=%x\n",
-                               iwl4965_hw_get_rate_n_flags(tx_resp->rate_n_flags));
-
-               agg->wait_for_ba = 0;
-       } else {
-               /* Two or more frames were attempted; expect block-ack */
-               u64 bitmap = 0;
-               int start = agg->start_idx;
-
-               /* Construct bit-map of pending frames within Tx window */
-               for (i = 0; i < agg->frame_count; i++) {
-                       u16 sc;
-                       status = le16_to_cpu(frame_status[i].status);
-                       seq  = le16_to_cpu(frame_status[i].sequence);
-                       idx = SEQ_TO_INDEX(seq);
-                       txq_id = SEQ_TO_QUEUE(seq);
-
-                       if (status & (AGG_TX_STATE_FEW_BYTES_MSK |
-                                     AGG_TX_STATE_ABORT_MSK))
-                               continue;
-
-                       IWL_DEBUG_TX_REPLY("FrameCnt = %d, txq_id=%d idx=%d\n",
-                                          agg->frame_count, txq_id, idx);
-
-                       hdr = iwl4965_tx_queue_get_hdr(priv, txq_id, idx);
-
-                       sc = le16_to_cpu(hdr->seq_ctrl);
-                       if (idx != (SEQ_TO_SN(sc) & 0xff)) {
-                               IWL_ERROR("BUG_ON idx doesn't match seq control"
-                                         " idx=%d, seq_idx=%d, seq=%d\n",
-                                         idx, SEQ_TO_SN(sc),
-                                         hdr->seq_ctrl);
-                               return -1;
-                       }
-
-                       IWL_DEBUG_TX_REPLY("AGG Frame i=%d idx %d seq=%d\n",
-                                          i, idx, SEQ_TO_SN(sc));
-
-                       sh = idx - start;
-                       if (sh > 64) {
-                               sh = (start - idx) + 0xff;
-                               bitmap = bitmap << sh;
-                               sh = 0;
-                               start = idx;
-                       } else if (sh < -64)
-                               sh  = 0xff - (start - idx);
-                       else if (sh < 0) {
-                               sh = start - idx;
-                               start = idx;
-                               bitmap = bitmap << sh;
-                               sh = 0;
-                       }
-                       bitmap |= (1 << sh);
-                       IWL_DEBUG_TX_REPLY("start=%d bitmap=0x%x\n",
-                                          start, (u32)(bitmap & 0xFFFFFFFF));
-               }
-
-               agg->bitmap = bitmap;
-               agg->start_idx = start;
-               agg->rate_n_flags = le32_to_cpu(tx_resp->rate_n_flags);
-               IWL_DEBUG_TX_REPLY("Frames %d start_idx=%d bitmap=0x%llx\n",
-                                  agg->frame_count, agg->start_idx,
-                                  (unsigned long long)agg->bitmap);
-
-               if (bitmap)
-                       agg->wait_for_ba = 1;
-       }
-       return 0;
-}
-#endif
-
-/**
- * iwl4965_rx_reply_tx - Handle standard (non-aggregation) Tx response
- */
-static void iwl4965_rx_reply_tx(struct iwl_priv *priv,
+static void iwl_rx_reply_alive(struct iwl_priv *priv,
                                struct iwl_rx_mem_buffer *rxb)
 {
        struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
-       u16 sequence = le16_to_cpu(pkt->hdr.sequence);
-       int txq_id = SEQ_TO_QUEUE(sequence);
-       int index = SEQ_TO_INDEX(sequence);
-       struct iwl_tx_queue *txq = &priv->txq[txq_id];
-       struct ieee80211_tx_status *tx_status;
-       struct iwl4965_tx_resp *tx_resp = (void *)&pkt->u.raw[0];
-       u32  status = le32_to_cpu(tx_resp->status);
-#ifdef CONFIG_IWL4965_HT
-       int tid = MAX_TID_COUNT, sta_id = IWL_INVALID_STATION;
-       u16 fc;
-       struct ieee80211_hdr *hdr;
-       u8 *qc = NULL;
-#endif
-
-       if ((index >= txq->q.n_bd) || (iwl_queue_used(&txq->q, index) == 0)) {
-               IWL_ERROR("Read index for DMA queue txq_id (%d) index %d "
-                         "is out of range [0-%d] %d %d\n", txq_id,
-                         index, txq->q.n_bd, txq->q.write_ptr,
-                         txq->q.read_ptr);
-               return;
-       }
-
-#ifdef CONFIG_IWL4965_HT
-       hdr = iwl4965_tx_queue_get_hdr(priv, txq_id, index);
-       fc = le16_to_cpu(hdr->frame_control);
-       if (ieee80211_is_qos_data(fc)) {
-               qc = ieee80211_get_qos_ctrl(hdr, ieee80211_get_hdrlen(fc));
-               tid = qc[0] & 0xf;
-       }
-
-       sta_id = iwl4965_get_ra_sta_id(priv, hdr);
-       if (txq->sched_retry && unlikely(sta_id == IWL_INVALID_STATION)) {
-               IWL_ERROR("Station not known\n");
-               return;
-       }
-
-       if (txq->sched_retry) {
-               const u32 scd_ssn = iwl4965_get_scd_ssn(tx_resp);
-               struct iwl_ht_agg *agg = NULL;
-
-               if (!qc)
-                       return;
-
-               agg = &priv->stations[sta_id].tid[tid].agg;
-
-               iwl4965_tx_status_reply_tx(priv, agg,
-                               (struct iwl4965_tx_resp_agg *)tx_resp, index);
-
-               if ((tx_resp->frame_count == 1) &&
-                   !iwl4965_is_tx_success(status)) {
-                       /* TODO: send BAR */
-               }
-
-               if (txq->q.read_ptr != (scd_ssn & 0xff)) {
-                       int freed, ampdu_q;
-                       index = iwl_queue_dec_wrap(scd_ssn & 0xff, txq->q.n_bd);
-                       IWL_DEBUG_TX_REPLY("Retry scheduler reclaim scd_ssn "
-                                          "%d index %d\n", scd_ssn , index);
-                       freed = iwl4965_tx_queue_reclaim(priv, txq_id, index);
-                       priv->stations[sta_id].tid[tid].tfds_in_queue -= freed;
-
-                       if (iwl_queue_space(&txq->q) > txq->q.low_mark &&
-                           txq_id >= 0 && priv->mac80211_registered &&
-                           agg->state != IWL_EMPTYING_HW_QUEUE_DELBA) {
-                               /* calculate mac80211 ampdu sw queue to wake */
-                               ampdu_q = txq_id - IWL_BACK_QUEUE_FIRST_ID +
-                                         priv->hw->queues;
-                               if (agg->state == IWL_AGG_OFF)
-                                       ieee80211_wake_queue(priv->hw, txq_id);
-                               else
-                                       ieee80211_wake_queue(priv->hw, ampdu_q);
-                       }
-                       iwl4965_check_empty_hw_queue(priv, sta_id, tid, txq_id);
-               }
-       } else {
-#endif /* CONFIG_IWL4965_HT */
-       tx_status = &(txq->txb[txq->q.read_ptr].status);
-
-       tx_status->retry_count = tx_resp->failure_frame;
-       tx_status->flags =
-           iwl4965_is_tx_success(status) ? IEEE80211_TX_STATUS_ACK : 0;
-       iwl4965_hwrate_to_tx_control(priv, le32_to_cpu(tx_resp->rate_n_flags),
-                                    &tx_status->control);
-
-       IWL_DEBUG_TX("Tx queue %d Status %s (0x%08x) rate_n_flags 0x%x "
-                    "retries %d\n", txq_id, iwl4965_get_tx_fail_reason(status),
-                    status, le32_to_cpu(tx_resp->rate_n_flags),
-                    tx_resp->failure_frame);
-
-       IWL_DEBUG_TX_REPLY("Tx queue reclaim %d\n", index);
-#ifdef CONFIG_IWL4965_HT
-       if (index != -1) {
-               int freed = iwl4965_tx_queue_reclaim(priv, txq_id, index);
-               if (tid != MAX_TID_COUNT)
-                       priv->stations[sta_id].tid[tid].tfds_in_queue -= freed;
-               if (iwl_queue_space(&txq->q) > txq->q.low_mark &&
-                       (txq_id >= 0) && priv->mac80211_registered)
-                       ieee80211_wake_queue(priv->hw, txq_id);
-               if (tid != MAX_TID_COUNT)
-                       iwl4965_check_empty_hw_queue(priv, sta_id, tid, txq_id);
-       }
-       }
-#endif /* CONFIG_IWL4965_HT */
-
-       if (iwl_check_bits(status, TX_ABORT_REQUIRED_MSK))
-               IWL_ERROR("TODO:  Implement Tx ABORT REQUIRED!!!\n");
-}
-
-
-static void iwl4965_rx_reply_alive(struct iwl_priv *priv,
-                                  struct iwl_rx_mem_buffer *rxb)
-{
-       struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
-       struct iwl4965_alive_resp *palive;
+       struct iwl_alive_resp *palive;
        struct delayed_work *pwork;
 
        palive = &pkt->u.alive_frame;
@@ -1953,12 +1552,12 @@ static void iwl4965_rx_reply_alive(struct iwl_priv *priv,
                IWL_DEBUG_INFO("Initialization Alive received.\n");
                memcpy(&priv->card_alive_init,
                       &pkt->u.alive_frame,
-                      sizeof(struct iwl4965_init_alive_resp));
+                      sizeof(struct iwl_init_alive_resp));
                pwork = &priv->init_alive_start;
        } else {
                IWL_DEBUG_INFO("Runtime Alive received.\n");
                memcpy(&priv->card_alive, &pkt->u.alive_frame,
-                      sizeof(struct iwl4965_alive_resp));
+                      sizeof(struct iwl_alive_resp));
                pwork = &priv->alive_start;
        }
 
@@ -1971,15 +1570,6 @@ static void iwl4965_rx_reply_alive(struct iwl_priv *priv,
                IWL_WARNING("uCode did not respond OK.\n");
 }
 
-static void iwl4965_rx_reply_add_sta(struct iwl_priv *priv,
-                                    struct iwl_rx_mem_buffer *rxb)
-{
-       struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
-
-       IWL_DEBUG_RX("Received REPLY_ADD_STA: 0x%02X\n", pkt->u.status);
-       return;
-}
-
 static void iwl4965_rx_reply_error(struct iwl_priv *priv,
                                   struct iwl_rx_mem_buffer *rxb)
 {
@@ -2053,7 +1643,7 @@ static void iwl4965_bg_beacon_update(struct work_struct *work)
        struct sk_buff *beacon;
 
        /* Pull updated AP beacon from mac80211. will fail if not in AP mode */
-       beacon = ieee80211_beacon_get(priv->hw, priv->vif, NULL);
+       beacon = ieee80211_beacon_get(priv->hw, priv->vif);
 
        if (!beacon) {
                IWL_ERROR("update beacon failed\n");
@@ -2276,6 +1866,17 @@ static void iwl4965_rx_card_state_notif(struct iwl_priv *priv,
                wake_up_interruptible(&priv->wait_command_queue);
 }
 
+/* Cache phy data (Rx signal strength, etc) for HT frame (REPLY_RX_PHY_CMD).
+ * This will be used later in iwl4965_rx_reply_rx() for REPLY_RX_MPDU_CMD. */
+static void iwl4965_rx_reply_rx_phy(struct iwl_priv *priv,
+                                   struct iwl_rx_mem_buffer *rxb)
+{
+       struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
+       priv->last_phy_res[0] = 1;
+       memcpy(&priv->last_phy_res[1], &(pkt->u.raw[0]),
+              sizeof(struct iwl4965_rx_phy_res));
+}
+
 /**
  * iwl4965_setup_rx_handlers - Initialize Rx handler callbacks
  *
@@ -2287,8 +1888,7 @@ static void iwl4965_rx_card_state_notif(struct iwl_priv *priv,
  */
 static void iwl4965_setup_rx_handlers(struct iwl_priv *priv)
 {
-       priv->rx_handlers[REPLY_ALIVE] = iwl4965_rx_reply_alive;
-       priv->rx_handlers[REPLY_ADD_STA] = iwl4965_rx_reply_add_sta;
+       priv->rx_handlers[REPLY_ALIVE] = iwl_rx_reply_alive;
        priv->rx_handlers[REPLY_ERROR] = iwl4965_rx_reply_error;
        priv->rx_handlers[CHANNEL_SWITCH_NOTIFICATION] = iwl4965_rx_csa;
        priv->rx_handlers[SPECTRUM_MEASURE_NOTIFICATION] =
@@ -2305,66 +1905,25 @@ static void iwl4965_setup_rx_handlers(struct iwl_priv *priv)
         */
        priv->rx_handlers[REPLY_STATISTICS_CMD] = iwl4965_hw_rx_statistics;
        priv->rx_handlers[STATISTICS_NOTIFICATION] = iwl4965_hw_rx_statistics;
-
+       /* scan handlers */
        priv->rx_handlers[REPLY_SCAN_CMD] = iwl4965_rx_reply_scan;
        priv->rx_handlers[SCAN_START_NOTIFICATION] = iwl4965_rx_scan_start_notif;
        priv->rx_handlers[SCAN_RESULTS_NOTIFICATION] =
            iwl4965_rx_scan_results_notif;
        priv->rx_handlers[SCAN_COMPLETE_NOTIFICATION] =
            iwl4965_rx_scan_complete_notif;
+       /* status change handler */
        priv->rx_handlers[CARD_STATE_NOTIFICATION] = iwl4965_rx_card_state_notif;
-       priv->rx_handlers[REPLY_TX] = iwl4965_rx_reply_tx;
 
+       priv->rx_handlers[MISSED_BEACONS_NOTIFICATION] =
+           iwl_rx_missed_beacon_notif;
+       /* Rx handlers */
+       priv->rx_handlers[REPLY_RX_PHY_CMD] = iwl4965_rx_reply_rx_phy;
+       priv->rx_handlers[REPLY_RX_MPDU_CMD] = iwl4965_rx_reply_rx;
        /* Set up hardware specific Rx handlers */
        priv->cfg->ops->lib->rx_handler_setup(priv);
 }
 
-/**
- * iwl4965_tx_cmd_complete - Pull unused buffers off the queue and reclaim them
- * @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
- */
-static void iwl4965_tx_cmd_complete(struct iwl_priv *priv,
-                                   struct iwl_rx_mem_buffer *rxb)
-{
-       struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
-       u16 sequence = le16_to_cpu(pkt->hdr.sequence);
-       int txq_id = SEQ_TO_QUEUE(sequence);
-       int index = SEQ_TO_INDEX(sequence);
-       int huge = sequence & SEQ_HUGE_FRAME;
-       int cmd_index;
-       struct iwl_cmd *cmd;
-
-       /* If a Tx command is being handled and it isn't in the actual
-        * command queue then there a command routing bug has been introduced
-        * in the queue management code. */
-       if (txq_id != IWL_CMD_QUEUE_NUM)
-               IWL_ERROR("Error wrong command queue %d command id 0x%X\n",
-                         txq_id, pkt->hdr.cmd);
-       BUG_ON(txq_id != IWL_CMD_QUEUE_NUM);
-
-       cmd_index = get_cmd_index(&priv->txq[IWL_CMD_QUEUE_NUM].q, index, huge);
-       cmd = &priv->txq[IWL_CMD_QUEUE_NUM].cmd[cmd_index];
-
-       /* Input error checking is done when commands are added to queue. */
-       if (cmd->meta.flags & CMD_WANT_SKB) {
-               cmd->meta.source->u.skb = rxb->skb;
-               rxb->skb = NULL;
-       } else if (cmd->meta.u.callback &&
-                  !cmd->meta.u.callback(priv, cmd, rxb->skb))
-               rxb->skb = NULL;
-
-       iwl4965_tx_queue_reclaim(priv, txq_id, index);
-
-       if (!(cmd->meta.flags & CMD_ASYNC)) {
-               clear_bit(STATUS_HCMD_ACTIVE, &priv->status);
-               wake_up_interruptible(&priv->wait_command_queue);
-       }
-}
-
 /*
  * this should be called while priv->lock is locked
 */
@@ -2453,7 +2012,7 @@ void iwl_rx_handle(struct iwl_priv *priv)
                         * fire off the (possibly) blocking iwl_send_cmd()
                         * as we reclaim the driver command queue */
                        if (rxb && rxb->skb)
-                               iwl4965_tx_cmd_complete(priv, rxb);
+                               iwl_tx_cmd_complete(priv, rxb);
                        else
                                IWL_WARNING("Claim null rxb?\n");
                }
@@ -2621,173 +2180,6 @@ static inline void iwl4965_disable_interrupts(struct iwl_priv *priv)
        IWL_DEBUG_ISR("Disabled interrupts\n");
 }
 
-static const char *desc_lookup(int i)
-{
-       switch (i) {
-       case 1:
-               return "FAIL";
-       case 2:
-               return "BAD_PARAM";
-       case 3:
-               return "BAD_CHECKSUM";
-       case 4:
-               return "NMI_INTERRUPT";
-       case 5:
-               return "SYSASSERT";
-       case 6:
-               return "FATAL_ERROR";
-       }
-
-       return "UNKNOWN";
-}
-
-#define ERROR_START_OFFSET  (1 * sizeof(u32))
-#define ERROR_ELEM_SIZE     (7 * sizeof(u32))
-
-static void iwl4965_dump_nic_error_log(struct iwl_priv *priv)
-{
-       u32 data2, line;
-       u32 desc, time, count, base, data1;
-       u32 blink1, blink2, ilink1, ilink2;
-       int rc;
-
-       base = le32_to_cpu(priv->card_alive.error_event_table_ptr);
-
-       if (!priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) {
-               IWL_ERROR("Not valid error log pointer 0x%08X\n", base);
-               return;
-       }
-
-       rc = iwl_grab_nic_access(priv);
-       if (rc) {
-               IWL_WARNING("Can not read from adapter at this time.\n");
-               return;
-       }
-
-       count = iwl_read_targ_mem(priv, base);
-
-       if (ERROR_START_OFFSET <= count * ERROR_ELEM_SIZE) {
-               IWL_ERROR("Start IWL Error Log Dump:\n");
-               IWL_ERROR("Status: 0x%08lX, count: %d\n", priv->status, count);
-       }
-
-       desc = iwl_read_targ_mem(priv, base + 1 * sizeof(u32));
-       blink1 = iwl_read_targ_mem(priv, base + 3 * sizeof(u32));
-       blink2 = iwl_read_targ_mem(priv, base + 4 * sizeof(u32));
-       ilink1 = iwl_read_targ_mem(priv, base + 5 * sizeof(u32));
-       ilink2 = iwl_read_targ_mem(priv, base + 6 * sizeof(u32));
-       data1 = iwl_read_targ_mem(priv, base + 7 * sizeof(u32));
-       data2 = iwl_read_targ_mem(priv, base + 8 * sizeof(u32));
-       line = iwl_read_targ_mem(priv, base + 9 * sizeof(u32));
-       time = iwl_read_targ_mem(priv, base + 11 * sizeof(u32));
-
-       IWL_ERROR("Desc               Time       "
-                 "data1      data2      line\n");
-       IWL_ERROR("%-13s (#%d) %010u 0x%08X 0x%08X %u\n",
-                 desc_lookup(desc), desc, time, data1, data2, line);
-       IWL_ERROR("blink1  blink2  ilink1  ilink2\n");
-       IWL_ERROR("0x%05X 0x%05X 0x%05X 0x%05X\n", blink1, blink2,
-                 ilink1, ilink2);
-
-       iwl_release_nic_access(priv);
-}
-
-#define EVENT_START_OFFSET  (4 * sizeof(u32))
-
-/**
- * iwl4965_print_event_log - Dump error event log to syslog
- *
- * NOTE: Must be called with iwl_grab_nic_access() already obtained!
- */
-static void iwl4965_print_event_log(struct iwl_priv *priv, u32 start_idx,
-                               u32 num_events, u32 mode)
-{
-       u32 i;
-       u32 base;       /* SRAM byte address of event log header */
-       u32 event_size; /* 2 u32s, or 3 u32s if timestamp recorded */
-       u32 ptr;        /* SRAM byte address of log data */
-       u32 ev, time, data; /* event log data */
-
-       if (num_events == 0)
-               return;
-
-       base = le32_to_cpu(priv->card_alive.log_event_table_ptr);
-
-       if (mode == 0)
-               event_size = 2 * sizeof(u32);
-       else
-               event_size = 3 * sizeof(u32);
-
-       ptr = base + EVENT_START_OFFSET + (start_idx * event_size);
-
-       /* "time" is actually "data" for mode 0 (no timestamp).
-        * place event id # at far right for easier visual parsing. */
-       for (i = 0; i < num_events; i++) {
-               ev = iwl_read_targ_mem(priv, ptr);
-               ptr += sizeof(u32);
-               time = iwl_read_targ_mem(priv, ptr);
-               ptr += sizeof(u32);
-               if (mode == 0)
-                       IWL_ERROR("0x%08x\t%04u\n", time, ev); /* data, ev */
-               else {
-                       data = iwl_read_targ_mem(priv, ptr);
-                       ptr += sizeof(u32);
-                       IWL_ERROR("%010u\t0x%08x\t%04u\n", time, data, ev);
-               }
-       }
-}
-
-static void iwl4965_dump_nic_event_log(struct iwl_priv *priv)
-{
-       int rc;
-       u32 base;       /* SRAM byte address of event log header */
-       u32 capacity;   /* event log capacity in # entries */
-       u32 mode;       /* 0 - no timestamp, 1 - timestamp recorded */
-       u32 num_wraps;  /* # times uCode wrapped to top of log */
-       u32 next_entry; /* index of next entry to be written by uCode */
-       u32 size;       /* # entries that we'll print */
-
-       base = le32_to_cpu(priv->card_alive.log_event_table_ptr);
-       if (!priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) {
-               IWL_ERROR("Invalid event log pointer 0x%08X\n", base);
-               return;
-       }
-
-       rc = iwl_grab_nic_access(priv);
-       if (rc) {
-               IWL_WARNING("Can not read from adapter at this time.\n");
-               return;
-       }
-
-       /* event log header */
-       capacity = iwl_read_targ_mem(priv, base);
-       mode = iwl_read_targ_mem(priv, base + (1 * sizeof(u32)));
-       num_wraps = iwl_read_targ_mem(priv, base + (2 * sizeof(u32)));
-       next_entry = iwl_read_targ_mem(priv, base + (3 * sizeof(u32)));
-
-       size = num_wraps ? capacity : next_entry;
-
-       /* bail out if nothing in log */
-       if (size == 0) {
-               IWL_ERROR("Start IWL Event Log Dump: nothing in log\n");
-               iwl_release_nic_access(priv);
-               return;
-       }
-
-       IWL_ERROR("Start IWL Event Log Dump: display count %d, wraps %d\n",
-                 size, num_wraps);
-
-       /* if uCode has wrapped back to top of log, start at the oldest entry,
-        * i.e the next one that uCode would fill. */
-       if (num_wraps)
-               iwl4965_print_event_log(priv, next_entry,
-                                   capacity - next_entry, mode);
-
-       /* (then/else) start at top of log */
-       iwl4965_print_event_log(priv, 0, next_entry, mode);
-
-       iwl_release_nic_access(priv);
-}
 
 /**
  * iwl4965_irq_handle_error - called for HW or SW error interrupt from card
@@ -2802,8 +2194,8 @@ static void iwl4965_irq_handle_error(struct iwl_priv *priv)
 
 #ifdef CONFIG_IWLWIFI_DEBUG
        if (priv->debug_level & IWL_DL_FW_ERRORS) {
-               iwl4965_dump_nic_error_log(priv);
-               iwl4965_dump_nic_event_log(priv);
+               iwl_dump_nic_error_log(priv);
+               iwl_dump_nic_event_log(priv);
                iwl4965_print_rx_config_cmd(priv);
        }
 #endif
@@ -2978,6 +2370,9 @@ static void iwl4965_irq_tasklet(struct iwl_priv *priv)
        if (inta & CSR_INT_BIT_FH_TX) {
                IWL_DEBUG_ISR("Tx interrupt\n");
                handled |= CSR_INT_BIT_FH_TX;
+               /* FH finished to write, send event */
+               priv->ucode_write_complete = 1;
+               wake_up_interruptible(&priv->wait_command_queue);
        }
 
        if (inta & ~handled)
@@ -3416,11 +2811,11 @@ static int iwl4965_read_ucode(struct iwl_priv *priv)
 }
 
 /**
- * iwl4965_alive_start - called after REPLY_ALIVE notification received
+ * iwl_alive_start - called after REPLY_ALIVE notification received
  *                   from protocol/runtime uCode (initialization uCode's
- *                   Alive gets handled by iwl4965_init_alive_start()).
+ *                   Alive gets handled by iwl_init_alive_start()).
  */
-static void iwl4965_alive_start(struct iwl_priv *priv)
+static void iwl_alive_start(struct iwl_priv *priv)
 {
        int ret = 0;
 
@@ -3444,7 +2839,6 @@ static void iwl4965_alive_start(struct iwl_priv *priv)
        }
 
        iwlcore_clear_stations_table(priv);
-
        ret = priv->cfg->ops->lib->alive_notify(priv);
        if (ret) {
                IWL_WARNING("Could not complete ALIVE transition [ntf]: %d\n",
@@ -3461,7 +2855,7 @@ static void iwl4965_alive_start(struct iwl_priv *priv)
        if (iwl_is_rfkill(priv))
                return;
 
-       ieee80211_start_queues(priv->hw);
+       ieee80211_wake_queues(priv->hw);
 
        priv->active_rate = priv->rates_mask;
        priv->active_rate_basic = priv->rates_mask & IWL_BASIC_RATES_MASK;
@@ -3482,12 +2876,12 @@ static void iwl4965_alive_start(struct iwl_priv *priv)
        /* Configure Bluetooth device coexistence support */
        iwl4965_send_bt_config(priv);
 
+       iwl_reset_run_time_calib(priv);
+
        /* Configure the adapter for unassociated operation */
        iwl4965_commit_rxon(priv);
 
        /* At this point, the NIC is initialized and operational */
-       priv->notif_missed_beacons = 0;
-
        iwl4965_rf_kill_ct_config(priv);
 
        iwl_leds_register(priv);
@@ -3513,12 +2907,9 @@ static void __iwl4965_down(struct iwl_priv *priv)
 {
        unsigned long flags;
        int exit_pending = test_bit(STATUS_EXIT_PENDING, &priv->status);
-       struct ieee80211_conf *conf = NULL;
 
        IWL_DEBUG_INFO(DRV_NAME " is going down\n");
 
-       conf = ieee80211_get_hw_conf(priv->hw);
-
        if (!exit_pending)
                set_bit(STATUS_EXIT_PENDING, &priv->status);
 
@@ -3580,8 +2971,8 @@ static void __iwl4965_down(struct iwl_priv *priv)
                         CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
        spin_unlock_irqrestore(&priv->lock, flags);
 
-       iwl4965_hw_txq_ctx_stop(priv);
-       iwl4965_hw_rxq_stop(priv);
+       iwl_txq_ctx_stop(priv);
+       iwl_rxq_stop(priv);
 
        spin_lock_irqsave(&priv->lock, flags);
        if (!iwl_grab_nic_access(priv)) {
@@ -3593,13 +2984,12 @@ static void __iwl4965_down(struct iwl_priv *priv)
 
        udelay(5);
 
-       iwl4965_hw_nic_stop_master(priv);
-       iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET);
-       iwl4965_hw_nic_reset(priv);
+       /* FIXME: apm_ops.suspend(priv) */
+       priv->cfg->ops->lib->apm_ops.reset(priv);
        priv->cfg->ops->lib->free_shared_mem(priv);
 
  exit:
-       memset(&priv->card_alive, 0, sizeof(struct iwl4965_alive_resp));
+       memset(&priv->card_alive, 0, sizeof(struct iwl_alive_resp));
 
        if (priv->ibss_beacon)
                dev_kfree_skb(priv->ibss_beacon);
@@ -3731,7 +3121,7 @@ static int __iwl4965_up(struct iwl_priv *priv)
  *
  *****************************************************************************/
 
-static void iwl4965_bg_init_alive_start(struct work_struct *data)
+static void iwl_bg_init_alive_start(struct work_struct *data)
 {
        struct iwl_priv *priv =
            container_of(data, struct iwl_priv, init_alive_start.work);
@@ -3744,7 +3134,7 @@ static void iwl4965_bg_init_alive_start(struct work_struct *data)
        mutex_unlock(&priv->mutex);
 }
 
-static void iwl4965_bg_alive_start(struct work_struct *data)
+static void iwl_bg_alive_start(struct work_struct *data)
 {
        struct iwl_priv *priv =
            container_of(data, struct iwl_priv, alive_start.work);
@@ -3753,7 +3143,7 @@ static void iwl4965_bg_alive_start(struct work_struct *data)
                return;
 
        mutex_lock(&priv->mutex);
-       iwl4965_alive_start(priv);
+       iwl_alive_start(priv);
        mutex_unlock(&priv->mutex);
 }
 
@@ -4300,21 +3690,23 @@ static int iwl4965_mac_start(struct ieee80211_hw *hw)
        if (test_bit(STATUS_IN_SUSPEND, &priv->status))
                return 0;
 
-       /* Wait for START_ALIVE from ucode. Otherwise callbacks from
+       /* Wait for START_ALIVE from Run Time ucode. Otherwise callbacks from
         * mac80211 will not be run successfully. */
-       ret = wait_event_interruptible_timeout(priv->wait_command_queue,
-                       test_bit(STATUS_READY, &priv->status),
-                       UCODE_READY_TIMEOUT);
-       if (!ret) {
-               if (!test_bit(STATUS_READY, &priv->status)) {
-                       IWL_ERROR("Wait for START_ALIVE timeout after %dms.\n",
-                                 jiffies_to_msecs(UCODE_READY_TIMEOUT));
-                       ret = -ETIMEDOUT;
-                       goto out_release_irq;
+       if (priv->ucode_type == UCODE_RT) {
+               ret = wait_event_interruptible_timeout(priv->wait_command_queue,
+                               test_bit(STATUS_READY, &priv->status),
+                               UCODE_READY_TIMEOUT);
+               if (!ret) {
+                       if (!test_bit(STATUS_READY, &priv->status)) {
+                               IWL_ERROR("START_ALIVE timeout after %dms.\n",
+                                       jiffies_to_msecs(UCODE_READY_TIMEOUT));
+                               ret = -ETIMEDOUT;
+                               goto out_release_irq;
+                       }
                }
-       }
 
-       priv->is_open = 1;
+               priv->is_open = 1;
+       }
        IWL_DEBUG_MAC80211("leave\n");
        return 0;
 
@@ -4362,8 +3754,7 @@ static void iwl4965_mac_stop(struct ieee80211_hw *hw)
        IWL_DEBUG_MAC80211("leave\n");
 }
 
-static int iwl4965_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb,
-                     struct ieee80211_tx_control *ctl)
+static int iwl4965_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
 {
        struct iwl_priv *priv = hw->priv;
 
@@ -4375,9 +3766,9 @@ static int iwl4965_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb,
        }
 
        IWL_DEBUG_TX("dev->xmit(%d bytes) at rate 0x%02x\n", skb->len,
-                    ctl->tx_rate->bitrate);
+                    ieee80211_get_tx_rate(hw, IEEE80211_SKB_CB(skb))->bitrate);
 
-       if (iwl_tx_skb(priv, skb, ctl))
+       if (iwl_tx_skb(priv, skb))
                dev_kfree_skb_any(skb);
 
        IWL_DEBUG_MAC80211("leave\n");
@@ -5159,8 +4550,7 @@ static void iwl4965_mac_reset_tsf(struct ieee80211_hw *hw)
        IWL_DEBUG_MAC80211("leave\n");
 }
 
-static int iwl4965_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb,
-                                struct ieee80211_tx_control *control)
+static int iwl4965_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb)
 {
        struct iwl_priv *priv = hw->priv;
        unsigned long flags;
@@ -5253,7 +4643,7 @@ static ssize_t show_version(struct device *d,
                                struct device_attribute *attr, char *buf)
 {
        struct iwl_priv *priv = d->driver_data;
-       struct iwl4965_alive_resp *palive = &priv->card_alive;
+       struct iwl_alive_resp *palive = &priv->card_alive;
 
        if (palive->is_valid)
                return sprintf(buf, "fw version: 0x%01X.0x%01X.0x%01X.0x%01X\n"
@@ -5623,34 +5013,6 @@ static ssize_t show_status(struct device *d,
 
 static DEVICE_ATTR(status, S_IRUGO, show_status, NULL);
 
-static ssize_t dump_error_log(struct device *d,
-                             struct device_attribute *attr,
-                             const char *buf, size_t count)
-{
-       char *p = (char *)buf;
-
-       if (p[0] == '1')
-               iwl4965_dump_nic_error_log((struct iwl_priv *)d->driver_data);
-
-       return strnlen(buf, count);
-}
-
-static DEVICE_ATTR(dump_errors, S_IWUSR, NULL, dump_error_log);
-
-static ssize_t dump_event_log(struct device *d,
-                             struct device_attribute *attr,
-                             const char *buf, size_t count)
-{
-       char *p = (char *)buf;
-
-       if (p[0] == '1')
-               iwl4965_dump_nic_event_log((struct iwl_priv *)d->driver_data);
-
-       return strnlen(buf, count);
-}
-
-static DEVICE_ATTR(dump_events, S_IWUSR, NULL, dump_event_log);
-
 /*****************************************************************************
  *
  * driver setup and teardown
@@ -5673,8 +5035,8 @@ static void iwl4965_setup_deferred_work(struct iwl_priv *priv)
        INIT_WORK(&priv->beacon_update, iwl4965_bg_beacon_update);
        INIT_WORK(&priv->set_monitor, iwl4965_bg_set_monitor);
        INIT_DELAYED_WORK(&priv->post_associate, iwl4965_bg_post_associate);
-       INIT_DELAYED_WORK(&priv->init_alive_start, iwl4965_bg_init_alive_start);
-       INIT_DELAYED_WORK(&priv->alive_start, iwl4965_bg_alive_start);
+       INIT_DELAYED_WORK(&priv->init_alive_start, iwl_bg_init_alive_start);
+       INIT_DELAYED_WORK(&priv->alive_start, iwl_bg_alive_start);
        INIT_DELAYED_WORK(&priv->scan_check, iwl4965_bg_scan_check);
 
        iwl4965_hw_setup_deferred_work(priv);
@@ -5696,8 +5058,6 @@ static void iwl4965_cancel_deferred_work(struct iwl_priv *priv)
 
 static struct attribute *iwl4965_sysfs_entries[] = {
        &dev_attr_channels.attr,
-       &dev_attr_dump_errors.attr,
-       &dev_attr_dump_events.attr,
        &dev_attr_flags.attr,
        &dev_attr_filter_flags.attr,
 #ifdef CONFIG_IWL4965_SPECTRUM_MEASUREMENT
@@ -5875,10 +5235,10 @@ static int iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
        }
 
        /*******************
-        * 6. Setup hw/priv
+        * 6. Setup priv
         *******************/
 
-       err = iwl_setup(priv);
+       err = iwl_init_drv(priv);
        if (err)
                goto out_free_eeprom;
        /* At this point both hw and priv are initialized. */
@@ -5893,9 +5253,6 @@ static int iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
                IWL_DEBUG_INFO("Radio disabled.\n");
        }
 
-       if (priv->cfg->mod_params->enable_qos)
-               priv->qos_data.qos_enable = 1;
-
        /********************
         * 8. Setup services
         ********************/
@@ -5906,14 +5263,9 @@ static int iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
        err = sysfs_create_group(&pdev->dev.kobj, &iwl4965_attribute_group);
        if (err) {
                IWL_ERROR("failed to create sysfs device attributes\n");
-               goto out_free_eeprom;
+               goto out_uninit_drv;
        }
 
-       err = iwl_dbgfs_register(priv, DRV_NAME);
-       if (err) {
-               IWL_ERROR("failed to create debugfs files\n");
-               goto out_remove_sysfs;
-       }
 
        iwl4965_setup_deferred_work(priv);
        iwl4965_setup_rx_handlers(priv);
@@ -5924,12 +5276,26 @@ static int iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
        pci_save_state(pdev);
        pci_disable_device(pdev);
 
+       /**********************************
+        * 10. Setup and register mac80211
+        **********************************/
+
+       err = iwl_setup_mac(priv);
+       if (err)
+               goto out_remove_sysfs;
+
+       err = iwl_dbgfs_register(priv, DRV_NAME);
+       if (err)
+               IWL_ERROR("failed to create debugfs files\n");
+
        /* notify iwlcore to init */
        iwlcore_low_level_notify(priv, IWLCORE_INIT_EVT);
        return 0;
 
  out_remove_sysfs:
        sysfs_remove_group(&pdev->dev.kobj, &iwl4965_attribute_group);
+ out_uninit_drv:
+       iwl_uninit_drv(priv);
  out_free_eeprom:
        iwl_eeprom_free(priv);
  out_iounmap:
@@ -6011,8 +5377,7 @@ static void __devexit iwl4965_pci_remove(struct pci_dev *pdev)
        pci_disable_device(pdev);
        pci_set_drvdata(pdev, NULL);
 
-       iwl_free_channel_map(priv);
-       iwlcore_free_geos(priv);
+       iwl_uninit_drv(priv);
 
        if (priv->ibss_beacon)
                dev_kfree_skb(priv->ibss_beacon);