Merge branch 'devicetree/next' of git://git.secretlab.ca/git/linux-2.6
[pandora-kernel.git] / drivers / net / wireless / iwlwifi / iwl-rx.c
index 3efa706..f3f3efe 100644 (file)
@@ -134,7 +134,6 @@ int iwl_rx_queue_space(const struct iwl_rx_queue *q)
 void iwl_rx_queue_update_write_ptr(struct iwl_priv *priv, struct iwl_rx_queue *q)
 {
        unsigned long flags;
-       u32 rx_wrt_ptr_reg = priv->hw_params.rx_wrt_ptr_reg;
        u32 reg;
 
        spin_lock_irqsave(&q->lock, flags);
@@ -146,7 +145,7 @@ void iwl_rx_queue_update_write_ptr(struct iwl_priv *priv, struct iwl_rx_queue *q
                /* shadow register enabled */
                /* Device expects a multiple of 8 */
                q->write_actual = (q->write & ~0x7);
-               iwl_write32(priv, rx_wrt_ptr_reg, q->write_actual);
+               iwl_write32(priv, FH_RSCSR_CHNL0_WPTR, q->write_actual);
        } else {
                /* If power-saving is in use, make sure device is awake */
                if (test_bit(STATUS_POWER_PMI, &priv->status)) {
@@ -162,14 +161,14 @@ void iwl_rx_queue_update_write_ptr(struct iwl_priv *priv, struct iwl_rx_queue *q
                        }
 
                        q->write_actual = (q->write & ~0x7);
-                       iwl_write_direct32(priv, rx_wrt_ptr_reg,
+                       iwl_write_direct32(priv, FH_RSCSR_CHNL0_WPTR,
                                        q->write_actual);
 
                /* Else device is assumed to be awake */
                } else {
                        /* Device expects a multiple of 8 */
                        q->write_actual = (q->write & ~0x7);
-                       iwl_write_direct32(priv, rx_wrt_ptr_reg,
+                       iwl_write_direct32(priv, FH_RSCSR_CHNL0_WPTR,
                                q->write_actual);
                }
        }
@@ -179,46 +178,6 @@ void iwl_rx_queue_update_write_ptr(struct iwl_priv *priv, struct iwl_rx_queue *q
        spin_unlock_irqrestore(&q->lock, flags);
 }
 
-int iwl_rx_queue_alloc(struct iwl_priv *priv)
-{
-       struct iwl_rx_queue *rxq = &priv->rxq;
-       struct device *dev = priv->bus.dev;
-       int i;
-
-       spin_lock_init(&rxq->lock);
-       INIT_LIST_HEAD(&rxq->rx_free);
-       INIT_LIST_HEAD(&rxq->rx_used);
-
-       /* Alloc the circular buffer of Read Buffer Descriptors (RBDs) */
-       rxq->bd = dma_alloc_coherent(dev, 4 * RX_QUEUE_SIZE, &rxq->bd_dma,
-                                    GFP_KERNEL);
-       if (!rxq->bd)
-               goto err_bd;
-
-       rxq->rb_stts = dma_alloc_coherent(dev, sizeof(struct iwl_rb_status),
-                                         &rxq->rb_stts_dma, GFP_KERNEL);
-       if (!rxq->rb_stts)
-               goto err_rb;
-
-       /* Fill the rx_used queue with _all_ of the Rx buffers */
-       for (i = 0; i < RX_FREE_BUFFERS + RX_QUEUE_SIZE; i++)
-               list_add_tail(&rxq->pool[i].list, &rxq->rx_used);
-
-       /* Set us so that we have processed and used all buffers, but have
-        * not restocked the Rx queue with fresh buffers */
-       rxq->read = rxq->write = 0;
-       rxq->write_actual = 0;
-       rxq->free_count = 0;
-       rxq->need_update = 0;
-       return 0;
-
-err_rb:
-       dma_free_coherent(dev, 4 * RX_QUEUE_SIZE, rxq->bd,
-                         rxq->bd_dma);
-err_bd:
-       return -ENOMEM;
-}
-
 /******************************************************************************
  *
  * Generic RX handler implementations
@@ -665,8 +624,8 @@ static void iwl_rx_statistics(struct iwl_priv *priv,
                iwl_rx_calc_noise(priv);
                queue_work(priv->workqueue, &priv->run_time_calib_work);
        }
-       if (priv->cfg->ops->lib->temp_ops.temperature && change)
-               priv->cfg->ops->lib->temp_ops.temperature(priv);
+       if (priv->cfg->ops->lib->temperature && change)
+               priv->cfg->ops->lib->temperature(priv);
 }
 
 static void iwl_rx_reply_statistics(struct iwl_priv *priv,
@@ -943,6 +902,47 @@ static u32 iwl_translate_rx_status(struct iwl_priv *priv, u32 decrypt_in)
        return decrypt_out;
 }
 
+/* Calc max signal level (dBm) among 3 possible receivers */
+static int iwlagn_calc_rssi(struct iwl_priv *priv,
+                            struct iwl_rx_phy_res *rx_resp)
+{
+       /* data from PHY/DSP regarding signal strength, etc.,
+        *   contents are always there, not configurable by host
+        */
+       struct iwlagn_non_cfg_phy *ncphy =
+               (struct iwlagn_non_cfg_phy *)rx_resp->non_cfg_phy_buf;
+       u32 val, rssi_a, rssi_b, rssi_c, max_rssi;
+       u8 agc;
+
+       val  = le32_to_cpu(ncphy->non_cfg_phy[IWLAGN_RX_RES_AGC_IDX]);
+       agc = (val & IWLAGN_OFDM_AGC_MSK) >> IWLAGN_OFDM_AGC_BIT_POS;
+
+       /* Find max rssi among 3 possible receivers.
+        * These values are measured by the digital signal processor (DSP).
+        * They should stay fairly constant even as the signal strength varies,
+        *   if the radio's automatic gain control (AGC) is working right.
+        * AGC value (see below) will provide the "interesting" info.
+        */
+       val = le32_to_cpu(ncphy->non_cfg_phy[IWLAGN_RX_RES_RSSI_AB_IDX]);
+       rssi_a = (val & IWLAGN_OFDM_RSSI_INBAND_A_BITMSK) >>
+               IWLAGN_OFDM_RSSI_A_BIT_POS;
+       rssi_b = (val & IWLAGN_OFDM_RSSI_INBAND_B_BITMSK) >>
+               IWLAGN_OFDM_RSSI_B_BIT_POS;
+       val = le32_to_cpu(ncphy->non_cfg_phy[IWLAGN_RX_RES_RSSI_C_IDX]);
+       rssi_c = (val & IWLAGN_OFDM_RSSI_INBAND_C_BITMSK) >>
+               IWLAGN_OFDM_RSSI_C_BIT_POS;
+
+       max_rssi = max_t(u32, rssi_a, rssi_b);
+       max_rssi = max_t(u32, max_rssi, rssi_c);
+
+       IWL_DEBUG_STATS(priv, "Rssi In A %d B %d C %d Max %d AGC dB %d\n",
+               rssi_a, rssi_b, rssi_c, max_rssi, agc);
+
+       /* dBm = max_rssi dB - agc dB - constant.
+        * Higher AGC (higher radio gain) means lower signal. */
+       return max_rssi - agc - IWLAGN_RSSI_OFFSET;
+}
+
 /* Called for REPLY_RX (legacy ABG frames), or
  * REPLY_RX_MPDU_CMD (HT high-throughput N frames). */
 static void iwl_rx_reply_rx(struct iwl_priv *priv,
@@ -1024,7 +1024,7 @@ static void iwl_rx_reply_rx(struct iwl_priv *priv,
        priv->ucode_beacon_time = le32_to_cpu(phy_res->beacon_time_stamp);
 
        /* Find max signal strength (dBm) among 3 antenna/receiver chains */
-       rx_status.signal = priv->cfg->ops->utils->calc_rssi(priv, phy_res);
+       rx_status.signal = iwlagn_calc_rssi(priv, phy_res);
 
        iwl_dbg_log_rx_data_frame(priv, len, header);
        IWL_DEBUG_STATS_LIMIT(priv, "Rssi %d, TSF %llu\n",