Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wirel...
[pandora-kernel.git] / drivers / net / wireless / ath / ath9k / htc_drv_init.c
index 8776f49..a7bc26d 100644 (file)
@@ -142,9 +142,6 @@ static void ath9k_deinit_priv(struct ath9k_htc_priv *priv)
 {
        ath9k_htc_exit_debug(priv->ah);
        ath9k_hw_deinit(priv->ah);
-       tasklet_kill(&priv->wmi_tasklet);
-       tasklet_kill(&priv->rx_tasklet);
-       tasklet_kill(&priv->tx_tasklet);
        kfree(priv->ah);
        priv->ah = NULL;
 }
@@ -181,7 +178,8 @@ static inline int ath9k_htc_connect_svc(struct ath9k_htc_priv *priv,
        return htc_connect_service(priv->htc, &req, ep_id);
 }
 
-static int ath9k_init_htc_services(struct ath9k_htc_priv *priv, u16 devid)
+static int ath9k_init_htc_services(struct ath9k_htc_priv *priv, u16 devid,
+                                  u32 drv_info)
 {
        int ret;
 
@@ -245,17 +243,10 @@ static int ath9k_init_htc_services(struct ath9k_htc_priv *priv, u16 devid)
         * the HIF layer, shouldn't matter much.
         */
 
-       switch(devid) {
-       case 0x7010:
-       case 0x7015:
-       case 0x9018:
-       case 0xA704:
-       case 0x1200:
+       if (IS_AR7010_DEVICE(drv_info))
                priv->htc->credits = 45;
-               break;
-       default:
+       else
                priv->htc->credits = 33;
-       }
 
        ret = htc_init(priv->htc);
        if (ret)
@@ -294,21 +285,49 @@ static unsigned int ath9k_regread(void *hw_priv, u32 reg_offset)
                          (u8 *) &val, sizeof(val),
                          100);
        if (unlikely(r)) {
-               ath_print(common, ATH_DBG_WMI,
-                         "REGISTER READ FAILED: (0x%04x, %d)\n",
-                          reg_offset, r);
+               ath_dbg(common, ATH_DBG_WMI,
+                       "REGISTER READ FAILED: (0x%04x, %d)\n",
+                       reg_offset, r);
                return -EIO;
        }
 
        return be32_to_cpu(val);
 }
 
+static void ath9k_multi_regread(void *hw_priv, u32 *addr,
+                               u32 *val, u16 count)
+{
+       struct ath_hw *ah = (struct ath_hw *) hw_priv;
+       struct ath_common *common = ath9k_hw_common(ah);
+       struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv;
+       __be32 tmpaddr[8];
+       __be32 tmpval[8];
+       int i, ret;
+
+       for (i = 0; i < count; i++) {
+              tmpaddr[i] = cpu_to_be32(addr[i]);
+       }
+
+       ret = ath9k_wmi_cmd(priv->wmi, WMI_REG_READ_CMDID,
+                          (u8 *)tmpaddr , sizeof(u32) * count,
+                          (u8 *)tmpval, sizeof(u32) * count,
+                          100);
+       if (unlikely(ret)) {
+               ath_dbg(common, ATH_DBG_WMI,
+                       "Multiple REGISTER READ FAILED (count: %d)\n", count);
+       }
+
+       for (i = 0; i < count; i++) {
+              val[i] = be32_to_cpu(tmpval[i]);
+       }
+}
+
 static void ath9k_regwrite_single(void *hw_priv, u32 val, u32 reg_offset)
 {
        struct ath_hw *ah = (struct ath_hw *) hw_priv;
        struct ath_common *common = ath9k_hw_common(ah);
        struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv;
-       __be32 buf[2] = {
+       const __be32 buf[2] = {
                cpu_to_be32(reg_offset),
                cpu_to_be32(val),
        };
@@ -319,9 +338,9 @@ static void ath9k_regwrite_single(void *hw_priv, u32 val, u32 reg_offset)
                          (u8 *) &val, sizeof(val),
                          100);
        if (unlikely(r)) {
-               ath_print(common, ATH_DBG_WMI,
-                         "REGISTER WRITE FAILED:(0x%04x, %d)\n",
-                         reg_offset, r);
+               ath_dbg(common, ATH_DBG_WMI,
+                       "REGISTER WRITE FAILED:(0x%04x, %d)\n",
+                       reg_offset, r);
        }
 }
 
@@ -351,9 +370,9 @@ static void ath9k_regwrite_buffer(void *hw_priv, u32 val, u32 reg_offset)
                          (u8 *) &rsp_status, sizeof(rsp_status),
                          100);
                if (unlikely(r)) {
-                       ath_print(common, ATH_DBG_WMI,
-                                 "REGISTER WRITE FAILED, multi len: %d\n",
-                                 priv->wmi->multi_write_idx);
+                       ath_dbg(common, ATH_DBG_WMI,
+                               "REGISTER WRITE FAILED, multi len: %d\n",
+                               priv->wmi->multi_write_idx);
                }
                priv->wmi->multi_write_idx = 0;
        }
@@ -401,9 +420,9 @@ static void ath9k_regwrite_flush(void *hw_priv)
                          (u8 *) &rsp_status, sizeof(rsp_status),
                          100);
                if (unlikely(r)) {
-                       ath_print(common, ATH_DBG_WMI,
-                                 "REGISTER WRITE FAILED, multi len: %d\n",
-                                 priv->wmi->multi_write_idx);
+                       ath_dbg(common, ATH_DBG_WMI,
+                               "REGISTER WRITE FAILED, multi len: %d\n",
+                               priv->wmi->multi_write_idx);
                }
                priv->wmi->multi_write_idx = 0;
        }
@@ -413,6 +432,7 @@ static void ath9k_regwrite_flush(void *hw_priv)
 
 static const struct ath_ops ath9k_common_ops = {
        .read = ath9k_regread,
+       .multi_read = ath9k_multi_regread,
        .write = ath9k_regwrite,
        .enable_write_buffer = ath9k_enable_regwrite_buffer,
        .write_flush = ath9k_regwrite_flush,
@@ -475,9 +495,9 @@ static void setup_ht_cap(struct ath9k_htc_priv *priv,
        tx_streams = ath9k_cmn_count_streams(common->tx_chainmask, 2);
        rx_streams = ath9k_cmn_count_streams(common->rx_chainmask, 2);
 
-       ath_print(common, ATH_DBG_CONFIG,
-                 "TX streams %d, RX streams: %d\n",
-                 tx_streams, rx_streams);
+       ath_dbg(common, ATH_DBG_CONFIG,
+               "TX streams %d, RX streams: %d\n",
+               tx_streams, rx_streams);
 
        if (tx_streams != rx_streams) {
                ht_info->mcs.tx_params |= IEEE80211_HT_MCS_TX_RX_DIFF;
@@ -501,37 +521,31 @@ static int ath9k_init_queues(struct ath9k_htc_priv *priv)
 
        priv->beaconq = ath9k_hw_beaconq_setup(priv->ah);
        if (priv->beaconq == -1) {
-               ath_print(common, ATH_DBG_FATAL,
-                         "Unable to setup BEACON xmit queue\n");
+               ath_err(common, "Unable to setup BEACON xmit queue\n");
                goto err;
        }
 
        priv->cabq = ath9k_htc_cabq_setup(priv);
        if (priv->cabq == -1) {
-               ath_print(common, ATH_DBG_FATAL,
-                         "Unable to setup CAB xmit queue\n");
+               ath_err(common, "Unable to setup CAB xmit queue\n");
                goto err;
        }
 
        if (!ath9k_htc_txq_setup(priv, WME_AC_BE)) {
-               ath_print(common, ATH_DBG_FATAL,
-                         "Unable to setup xmit queue for BE traffic\n");
+               ath_err(common, "Unable to setup xmit queue for BE traffic\n");
                goto err;
        }
 
        if (!ath9k_htc_txq_setup(priv, WME_AC_BK)) {
-               ath_print(common, ATH_DBG_FATAL,
-                         "Unable to setup xmit queue for BK traffic\n");
+               ath_err(common, "Unable to setup xmit queue for BK traffic\n");
                goto err;
        }
        if (!ath9k_htc_txq_setup(priv, WME_AC_VI)) {
-               ath_print(common, ATH_DBG_FATAL,
-                         "Unable to setup xmit queue for VI traffic\n");
+               ath_err(common, "Unable to setup xmit queue for VI traffic\n");
                goto err;
        }
        if (!ath9k_htc_txq_setup(priv, WME_AC_VO)) {
-               ath_print(common, ATH_DBG_FATAL,
-                         "Unable to setup xmit queue for VO traffic\n");
+               ath_err(common, "Unable to setup xmit queue for VO traffic\n");
                goto err;
        }
 
@@ -549,9 +563,9 @@ static void ath9k_init_crypto(struct ath9k_htc_priv *priv)
        /* Get the hardware key cache size. */
        common->keymax = priv->ah->caps.keycache_size;
        if (common->keymax > ATH_KEYMAX) {
-               ath_print(common, ATH_DBG_ANY,
-                         "Warning, using only %u entries in %u key cache\n",
-                         ATH_KEYMAX, common->keymax);
+               ath_dbg(common, ATH_DBG_ANY,
+                       "Warning, using only %u entries in %u key cache\n",
+                       ATH_KEYMAX, common->keymax);
                common->keymax = ATH_KEYMAX;
        }
 
@@ -627,7 +641,8 @@ static void ath9k_init_btcoex(struct ath9k_htc_priv *priv)
 }
 
 static int ath9k_init_priv(struct ath9k_htc_priv *priv,
-                          u16 devid, char *product)
+                          u16 devid, char *product,
+                          u32 drv_info)
 {
        struct ath_hw *ah = NULL;
        struct ath_common *common;
@@ -641,6 +656,8 @@ static int ath9k_init_priv(struct ath9k_htc_priv *priv,
 
        ah->hw_version.devid = devid;
        ah->hw_version.subsysid = 0; /* FIXME */
+       ah->hw_version.usbdev = drv_info;
+       ah->ah_flags |= AH_USE_EEPROM;
        priv->ah = ah;
 
        common = ath9k_hw_common(ah);
@@ -656,13 +673,15 @@ static int ath9k_init_priv(struct ath9k_htc_priv *priv,
        spin_lock_init(&priv->tx_lock);
        mutex_init(&priv->mutex);
        mutex_init(&priv->htc_pm_lock);
-       tasklet_init(&priv->wmi_tasklet, ath9k_wmi_tasklet,
+       tasklet_init(&priv->swba_tasklet, ath9k_swba_tasklet,
                     (unsigned long)priv);
        tasklet_init(&priv->rx_tasklet, ath9k_rx_tasklet,
                     (unsigned long)priv);
-       tasklet_init(&priv->tx_tasklet, ath9k_tx_tasklet, (unsigned long)priv);
+       tasklet_init(&priv->tx_tasklet, ath9k_tx_tasklet,
+                    (unsigned long)priv);
        INIT_DELAYED_WORK(&priv->ath9k_ani_work, ath9k_ani_work);
        INIT_WORK(&priv->ps_work, ath9k_ps_work);
+       INIT_WORK(&priv->fatal_work, ath9k_fatal_work);
 
        /*
         * Cache line size is used to size and align various
@@ -673,16 +692,15 @@ static int ath9k_init_priv(struct ath9k_htc_priv *priv,
 
        ret = ath9k_hw_init(ah);
        if (ret) {
-               ath_print(common, ATH_DBG_FATAL,
-                         "Unable to initialize hardware; "
-                         "initialization status: %d\n", ret);
+               ath_err(common,
+                       "Unable to initialize hardware; initialization status: %d\n",
+                       ret);
                goto err_hw;
        }
 
        ret = ath9k_htc_init_debug(ah);
        if (ret) {
-               ath_print(common, ATH_DBG_FATAL,
-                         "Unable to create debugfs files\n");
+               ath_err(common, "Unable to create debugfs files\n");
                goto err_debug;
        }
 
@@ -762,7 +780,7 @@ static void ath9k_set_hw_capab(struct ath9k_htc_priv *priv,
 }
 
 static int ath9k_init_device(struct ath9k_htc_priv *priv,
-                            u16 devid, char *product)
+                            u16 devid, char *product, u32 drv_info)
 {
        struct ieee80211_hw *hw = priv->hw;
        struct ath_common *common;
@@ -771,7 +789,7 @@ static int ath9k_init_device(struct ath9k_htc_priv *priv,
        struct ath_regulatory *reg;
 
        /* Bring up device */
-       error = ath9k_init_priv(priv, devid, product);
+       error = ath9k_init_priv(priv, devid, product, drv_info);
        if (error != 0)
                goto err_init;
 
@@ -829,7 +847,7 @@ err_init:
 }
 
 int ath9k_htc_probe_device(struct htc_target *htc_handle, struct device *dev,
-                          u16 devid, char *product)
+                          u16 devid, char *product, u32 drv_info)
 {
        struct ieee80211_hw *hw;
        struct ath9k_htc_priv *priv;
@@ -856,14 +874,11 @@ int ath9k_htc_probe_device(struct htc_target *htc_handle, struct device *dev,
                goto err_free;
        }
 
-       ret = ath9k_init_htc_services(priv, devid);
+       ret = ath9k_init_htc_services(priv, devid, drv_info);
        if (ret)
                goto err_init;
 
-       /* The device may have been unplugged earlier. */
-       priv->op_flags &= ~OP_UNPLUGGED;
-
-       ret = ath9k_init_device(priv, devid, product);
+       ret = ath9k_init_device(priv, devid, product, drv_info);
        if (ret)
                goto err_init;
 
@@ -882,7 +897,7 @@ void ath9k_htc_disconnect_device(struct htc_target *htc_handle, bool hotunplug)
 
                /* Check if the device has been yanked out. */
                if (hotunplug)
-                       htc_handle->drv_priv->op_flags |= OP_UNPLUGGED;
+                       htc_handle->drv_priv->ah->ah_flags |= AH_UNPLUGGED;
 
                ath9k_deinit_device(htc_handle->drv_priv);
                ath9k_deinit_wmi(htc_handle->drv_priv);
@@ -899,14 +914,15 @@ void ath9k_htc_suspend(struct htc_target *htc_handle)
 
 int ath9k_htc_resume(struct htc_target *htc_handle)
 {
+       struct ath9k_htc_priv *priv = htc_handle->drv_priv;
        int ret;
 
-       ret = ath9k_htc_wait_for_target(htc_handle->drv_priv);
+       ret = ath9k_htc_wait_for_target(priv);
        if (ret)
                return ret;
 
-       ret = ath9k_init_htc_services(htc_handle->drv_priv,
-                             htc_handle->drv_priv->ah->hw_version.devid);
+       ret = ath9k_init_htc_services(priv, priv->ah->hw_version.devid,
+                                     priv->ah->hw_version.usbdev);
        return ret;
 }
 #endif