iwlwifi: change struct iwl_fw
[deliverable/linux.git] / drivers / net / wireless / iwlwifi / iwl-testmode.c
index 5f00a371270708d0b0749fabc49db4afb122630b..76f7f925143614c351c45bfc0e590809dcc4e638 100644 (file)
@@ -70,7 +70,6 @@
 #include <net/mac80211.h>
 #include <net/netlink.h>
 
-#include "iwl-wifi.h"
 #include "iwl-dev.h"
 #include "iwl-core.h"
 #include "iwl-debug.h"
@@ -78,8 +77,8 @@
 #include "iwl-agn.h"
 #include "iwl-testmode.h"
 #include "iwl-trans.h"
-#include "iwl-bus.h"
 #include "iwl-fh.h"
+#include "iwl-prph.h"
 
 
 /* Periphery registers absolute lower bound. This is used in order to
@@ -126,13 +125,15 @@ struct nla_policy iwl_testmode_gnl_msg_policy[IWL_TM_ATTR_MAX] = {
        [IWL_TM_ATTR_FW_TYPE] = { .type = NLA_U32, },
        [IWL_TM_ATTR_FW_INST_SIZE] = { .type = NLA_U32, },
        [IWL_TM_ATTR_FW_DATA_SIZE] = { .type = NLA_U32, },
+
+       [IWL_TM_ATTR_ENABLE_NOTIFICATION] = {.type = NLA_FLAG, },
 };
 
 /*
  * See the struct iwl_rx_packet in iwl-commands.h for the format of the
  * received events from the device
  */
-static inline int get_event_length(struct iwl_rx_mem_buffer *rxb)
+static inline int get_event_length(struct iwl_rx_cmd_buffer *rxb)
 {
        struct iwl_rx_packet *pkt = rxb_addr(rxb);
        if (pkt)
@@ -163,7 +164,7 @@ static inline int get_event_length(struct iwl_rx_mem_buffer *rxb)
  */
 
 static void iwl_testmode_ucode_rx_pkt(struct iwl_priv *priv,
-                               struct iwl_rx_mem_buffer *rxb)
+                                     struct iwl_rx_cmd_buffer *rxb)
 {
        struct ieee80211_hw *hw = priv->hw;
        struct sk_buff *skb;
@@ -184,7 +185,8 @@ static void iwl_testmode_ucode_rx_pkt(struct iwl_priv *priv,
                return;
        }
        NLA_PUT_U32(skb, IWL_TM_ATTR_COMMAND, IWL_TM_CMD_DEV2APP_UCODE_RX_PKT);
-       NLA_PUT(skb, IWL_TM_ATTR_UCODE_RX_PKT, length, data);
+       /* the length doesn't include len_n_flags field, so add it manually */
+       NLA_PUT(skb, IWL_TM_ATTR_UCODE_RX_PKT, length + sizeof(__le32), data);
        cfg80211_testmode_event(skb, GFP_ATOMIC);
        return;
 
@@ -195,7 +197,7 @@ nla_put_failure:
 
 void iwl_testmode_init(struct iwl_priv *priv)
 {
-       priv->pre_rx_handler = iwl_testmode_ucode_rx_pkt;
+       priv->pre_rx_handler = NULL;
        priv->testmode_trace.trace_enabled = false;
        priv->testmode_mem.read_in_progress = false;
 }
@@ -255,7 +257,7 @@ void iwl_testmode_cleanup(struct iwl_priv *priv)
  */
 static int iwl_testmode_ucode(struct ieee80211_hw *hw, struct nlattr **tb)
 {
-       struct iwl_priv *priv = hw->priv;
+       struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
        struct iwl_host_cmd cmd;
        struct iwl_rx_packet *pkt;
        struct sk_buff *skb;
@@ -284,7 +286,7 @@ static int iwl_testmode_ucode(struct ieee80211_hw *hw, struct nlattr **tb)
        IWL_DEBUG_INFO(priv, "testmode ucode command ID 0x%x, flags 0x%x,"
                                " len %d\n", cmd.id, cmd.flags, cmd.len[0]);
 
-       ret = iwl_trans_send_cmd(trans(priv), &cmd);
+       ret = iwl_dvm_send_cmd(priv, &cmd);
        if (ret) {
                IWL_ERR(priv, "Failed to send hcmd\n");
                return ret;
@@ -293,7 +295,7 @@ static int iwl_testmode_ucode(struct ieee80211_hw *hw, struct nlattr **tb)
                return ret;
 
        /* Handling return of SKB to the user */
-       pkt = (struct iwl_rx_packet *)cmd.reply_page;
+       pkt = cmd.resp_pkt;
        if (!pkt) {
                IWL_ERR(priv, "HCMD received a null response packet\n");
                return ret;
@@ -309,8 +311,8 @@ static int iwl_testmode_ucode(struct ieee80211_hw *hw, struct nlattr **tb)
        }
 
        /* The reply is in a page, that we cannot send to user space. */
-       memcpy(reply_buf, &(pkt->u), reply_len);
-       iwl_free_pages(priv->shrd, cmd.reply_page);
+       memcpy(reply_buf, &(pkt->hdr), reply_len);
+       iwl_free_resp(&cmd);
 
        NLA_PUT_U32(skb, IWL_TM_ATTR_COMMAND, IWL_TM_CMD_DEV2APP_UCODE_RX_PKT);
        NLA_PUT(skb, IWL_TM_ATTR_UCODE_RX_PKT, reply_len, reply_buf);
@@ -341,7 +343,7 @@ nla_put_failure:
  */
 static int iwl_testmode_reg(struct ieee80211_hw *hw, struct nlattr **tb)
 {
-       struct iwl_priv *priv = hw->priv;
+       struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
        u32 ofs, val32, cmd;
        u8 val8;
        struct sk_buff *skb;
@@ -420,23 +422,23 @@ static int iwl_testmode_cfg_init_calib(struct iwl_priv *priv)
        struct iwl_notification_wait calib_wait;
        int ret;
 
-       iwl_init_notification_wait(priv->shrd, &calib_wait,
-                                     CALIBRATION_COMPLETE_NOTIFICATION,
-                                     NULL, NULL);
-       ret = iwl_init_alive_start(trans(priv));
+       iwl_init_notification_wait(&priv->notif_wait, &calib_wait,
+                                  CALIBRATION_COMPLETE_NOTIFICATION,
+                                  NULL, NULL);
+       ret = iwl_init_alive_start(priv);
        if (ret) {
                IWL_ERR(priv, "Fail init calibration: %d\n", ret);
                goto cfg_init_calib_error;
        }
 
-       ret = iwl_wait_notification(priv->shrd, &calib_wait, 2 * HZ);
+       ret = iwl_wait_notification(&priv->notif_wait, &calib_wait, 2 * HZ);
        if (ret)
                IWL_ERR(priv, "Error detecting"
                        " CALIBRATION_COMPLETE_NOTIFICATION: %d\n", ret);
        return ret;
 
 cfg_init_calib_error:
-       iwl_remove_notification(priv->shrd, &calib_wait);
+       iwl_remove_notification(&priv->notif_wait, &calib_wait);
        return ret;
 }
 
@@ -458,12 +460,13 @@ cfg_init_calib_error:
  */
 static int iwl_testmode_driver(struct ieee80211_hw *hw, struct nlattr **tb)
 {
-       struct iwl_priv *priv = hw->priv;
+       struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
        struct iwl_trans *trans = trans(priv);
        struct sk_buff *skb;
        unsigned char *rsp_data_ptr = NULL;
        int status = 0, rsp_data_len = 0;
        u32 devid, inst_size = 0, data_size = 0;
+       const struct fw_img *img;
 
        switch (nla_get_u32(tb[IWL_TM_ATTR_COMMAND])) {
        case IWL_TM_CMD_APP2DEV_GET_DEVICENAME:
@@ -485,18 +488,19 @@ static int iwl_testmode_driver(struct ieee80211_hw *hw, struct nlattr **tb)
                break;
 
        case IWL_TM_CMD_APP2DEV_LOAD_INIT_FW:
-               status = iwl_load_ucode_wait_alive(trans, IWL_UCODE_INIT);
+               status = iwl_load_ucode_wait_alive(priv, IWL_UCODE_INIT);
                if (status)
                        IWL_ERR(priv, "Error loading init ucode: %d\n", status);
                break;
 
        case IWL_TM_CMD_APP2DEV_CFG_INIT_CALIB:
                iwl_testmode_cfg_init_calib(priv);
+               priv->ucode_loaded = false;
                iwl_trans_stop_device(trans);
                break;
 
        case IWL_TM_CMD_APP2DEV_LOAD_RUNTIME_FW:
-               status = iwl_load_ucode_wait_alive(trans, IWL_UCODE_REGULAR);
+               status = iwl_load_ucode_wait_alive(priv, IWL_UCODE_REGULAR);
                if (status) {
                        IWL_ERR(priv,
                                "Error loading runtime ucode: %d\n", status);
@@ -510,8 +514,9 @@ static int iwl_testmode_driver(struct ieee80211_hw *hw, struct nlattr **tb)
 
        case IWL_TM_CMD_APP2DEV_LOAD_WOWLAN_FW:
                iwl_scan_cancel_timeout(priv, 200);
+               priv->ucode_loaded = false;
                iwl_trans_stop_device(trans);
-               status = iwl_load_ucode_wait_alive(trans, IWL_UCODE_WOWLAN);
+               status = iwl_load_ucode_wait_alive(priv, IWL_UCODE_WOWLAN);
                if (status) {
                        IWL_ERR(priv,
                                "Error loading WOWLAN ucode: %d\n", status);
@@ -554,7 +559,7 @@ static int iwl_testmode_driver(struct ieee80211_hw *hw, struct nlattr **tb)
 
        case IWL_TM_CMD_APP2DEV_GET_FW_VERSION:
                IWL_INFO(priv, "uCode version raw: 0x%x\n",
-                        nic(priv)->fw.ucode_ver);
+                        priv->fw->ucode_ver);
 
                skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, 20);
                if (!skb) {
@@ -562,7 +567,7 @@ static int iwl_testmode_driver(struct ieee80211_hw *hw, struct nlattr **tb)
                        return -ENOMEM;
                }
                NLA_PUT_U32(skb, IWL_TM_ATTR_FW_VERSION,
-                           nic(priv)->fw.ucode_ver);
+                           priv->fw->ucode_ver);
                status = cfg80211_testmode_reply(skb);
                if (status < 0)
                        IWL_ERR(priv, "Error sending msg : %d\n", status);
@@ -589,25 +594,13 @@ static int iwl_testmode_driver(struct ieee80211_hw *hw, struct nlattr **tb)
                        IWL_ERR(priv, "Memory allocation fail\n");
                        return -ENOMEM;
                }
-               switch (priv->shrd->ucode_type) {
-               case IWL_UCODE_REGULAR:
-                       inst_size = nic(priv)->fw.ucode_rt.code.len;
-                       data_size = nic(priv)->fw.ucode_rt.data.len;
-                       break;
-               case IWL_UCODE_INIT:
-                       inst_size = nic(priv)->fw.ucode_init.code.len;
-                       data_size = nic(priv)->fw.ucode_init.data.len;
-                       break;
-               case IWL_UCODE_WOWLAN:
-                       inst_size = nic(priv)->fw.ucode_wowlan.code.len;
-                       data_size = nic(priv)->fw.ucode_wowlan.data.len;
-                       break;
-               case IWL_UCODE_NONE:
+               if (!priv->ucode_loaded) {
                        IWL_ERR(priv, "No uCode has not been loaded\n");
-                       break;
-               default:
-                       IWL_ERR(priv, "Unsupported uCode type\n");
-                       break;
+                       return -EINVAL;
+               } else {
+                       img = &priv->fw->img[priv->shrd->ucode_type];
+                       inst_size = img->sec[IWL_UCODE_SECTION_INST].len;
+                       data_size = img->sec[IWL_UCODE_SECTION_DATA].len;
                }
                NLA_PUT_U32(skb, IWL_TM_ATTR_FW_TYPE, priv->shrd->ucode_type);
                NLA_PUT_U32(skb, IWL_TM_ATTR_FW_INST_SIZE, inst_size);
@@ -643,7 +636,7 @@ nla_put_failure:
  */
 static int iwl_testmode_trace(struct ieee80211_hw *hw, struct nlattr **tb)
 {
-       struct iwl_priv *priv = hw->priv;
+       struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
        struct sk_buff *skb;
        int status = 0;
        struct device *dev = trans(priv)->dev;
@@ -714,11 +707,11 @@ nla_put_failure:
        return -EMSGSIZE;
 }
 
-static int iwl_testmode_trace_dump(struct ieee80211_hw *hw, struct nlattr **tb,
+static int iwl_testmode_trace_dump(struct ieee80211_hw *hw,
                                   struct sk_buff *skb,
                                   struct netlink_callback *cb)
 {
-       struct iwl_priv *priv = hw->priv;
+       struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
        int idx, length;
 
        if (priv->testmode_trace.trace_enabled &&
@@ -762,7 +755,7 @@ static int iwl_testmode_trace_dump(struct ieee80211_hw *hw, struct nlattr **tb,
  */
 static int iwl_testmode_ownership(struct ieee80211_hw *hw, struct nlattr **tb)
 {
-       struct iwl_priv *priv = hw->priv;
+       struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
        u8 owner;
 
        if (!tb[IWL_TM_ATTR_UCODE_OWNER]) {
@@ -771,9 +764,13 @@ static int iwl_testmode_ownership(struct ieee80211_hw *hw, struct nlattr **tb)
        }
 
        owner = nla_get_u8(tb[IWL_TM_ATTR_UCODE_OWNER]);
-       if ((owner == IWL_OWNERSHIP_DRIVER) || (owner == IWL_OWNERSHIP_TM))
-               priv->shrd->ucode_owner = owner;
-       else {
+       if (owner == IWL_OWNERSHIP_DRIVER) {
+               priv->ucode_owner = owner;
+               priv->pre_rx_handler = NULL;
+       } else if (owner == IWL_OWNERSHIP_TM) {
+               priv->pre_rx_handler = iwl_testmode_ucode_rx_pkt;
+               priv->ucode_owner = owner;
+       } else {
                IWL_ERR(priv, "Invalid owner\n");
                return -EINVAL;
        }
@@ -799,9 +796,10 @@ static int iwl_testmode_indirect_read(struct iwl_priv *priv, u32 addr, u32 size)
                addr < IWL_TM_ABS_PRPH_START + PRPH_END) {
                        spin_lock_irqsave(&trans->reg_lock, flags);
                        iwl_grab_nic_access(trans);
-                       iwl_write32(trans, HBUS_TARG_PRPH_RADDR, addr);
+                       iwl_write32(trans, HBUS_TARG_PRPH_RADDR,
+                               addr | (3 << 24));
                        for (i = 0; i < size; i += 4)
-                               priv->testmode_mem.buff_addr[i] =
+                               *(u32 *)(priv->testmode_mem.buff_addr + i) =
                                        iwl_read32(trans, HBUS_TARG_PRPH_RDAT);
                        iwl_release_nic_access(trans);
                        spin_unlock_irqrestore(&trans->reg_lock, flags);
@@ -833,7 +831,8 @@ static int iwl_testmode_indirect_write(struct iwl_priv *priv, u32 addr,
                                spin_lock_irqsave(&trans->reg_lock, flags);
                                iwl_grab_nic_access(trans);
                                iwl_write32(trans, HBUS_TARG_PRPH_WADDR,
-                                           (addr & 0x0000FFFF) | (size << 24));
+                                           (addr & 0x0000FFFF) |
+                                           ((size - 1) << 24));
                                iwl_write32(trans, HBUS_TARG_PRPH_WDAT, val);
                                iwl_release_nic_access(trans);
                                /* needed after consecutive writes w/o read */
@@ -844,7 +843,7 @@ static int iwl_testmode_indirect_write(struct iwl_priv *priv, u32 addr,
                                        return -EINVAL;
                                for (i = 0; i < size; i += 4)
                                        iwl_write_prph(trans, addr+i,
-                                               *(u32 *)buf+i);
+                                               *(u32 *)(buf+i));
                        }
        } else if (iwlagn_hw_valid_rtc_data_addr(addr) ||
                (IWLAGN_RTC_INST_LOWER_BOUND <= addr &&
@@ -874,7 +873,7 @@ static int iwl_testmode_indirect_write(struct iwl_priv *priv, u32 addr,
 static int iwl_testmode_indirect_mem(struct ieee80211_hw *hw,
        struct nlattr **tb)
 {
-       struct iwl_priv *priv = hw->priv;
+       struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
        u32 addr, size, cmd;
        unsigned char *buf;
 
@@ -904,11 +903,11 @@ static int iwl_testmode_indirect_mem(struct ieee80211_hw *hw,
        }
 }
 
-static int iwl_testmode_buffer_dump(struct ieee80211_hw *hw, struct nlattr **tb,
-                                  struct sk_buff *skb,
-                                  struct netlink_callback *cb)
+static int iwl_testmode_buffer_dump(struct ieee80211_hw *hw,
+                                   struct sk_buff *skb,
+                                   struct netlink_callback *cb)
 {
-       struct iwl_priv *priv = hw->priv;
+       struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
        int idx, length;
 
        if (priv->testmode_mem.read_in_progress) {
@@ -936,6 +935,20 @@ static int iwl_testmode_buffer_dump(struct ieee80211_hw *hw, struct nlattr **tb,
        return -ENOBUFS;
 }
 
+static int iwl_testmode_notifications(struct ieee80211_hw *hw,
+       struct nlattr **tb)
+{
+       struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
+       bool enable;
+
+       enable = nla_get_flag(tb[IWL_TM_ATTR_ENABLE_NOTIFICATION]);
+       if (enable)
+               priv->pre_rx_handler = iwl_testmode_ucode_rx_pkt;
+       else
+               priv->pre_rx_handler = NULL;
+       return 0;
+}
+
 
 /* The testmode gnl message handler that takes the gnl message from the
  * user space and parses it per the policy iwl_testmode_gnl_msg_policy, then
@@ -959,7 +972,7 @@ static int iwl_testmode_buffer_dump(struct ieee80211_hw *hw, struct nlattr **tb,
 int iwlagn_mac_testmode_cmd(struct ieee80211_hw *hw, void *data, int len)
 {
        struct nlattr *tb[IWL_TM_ATTR_MAX];
-       struct iwl_priv *priv = hw->priv;
+       struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
        int result;
 
        result = nla_parse(tb, IWL_TM_ATTR_MAX - 1, data, len,
@@ -975,7 +988,7 @@ int iwlagn_mac_testmode_cmd(struct ieee80211_hw *hw, void *data, int len)
                return -ENOMSG;
        }
        /* in case multiple accesses to the device happens */
-       mutex_lock(&priv->shrd->mutex);
+       mutex_lock(&priv->mutex);
 
        switch (nla_get_u32(tb[IWL_TM_ATTR_COMMAND])) {
        case IWL_TM_CMD_APP2DEV_UCODE:
@@ -1021,13 +1034,19 @@ int iwlagn_mac_testmode_cmd(struct ieee80211_hw *hw, void *data, int len)
                result = iwl_testmode_indirect_mem(hw, tb);
                break;
 
+       case IWL_TM_CMD_APP2DEV_NOTIFICATIONS:
+               IWL_DEBUG_INFO(priv, "testmode notifications cmd "
+                       "to driver\n");
+               result = iwl_testmode_notifications(hw, tb);
+               break;
+
        default:
                IWL_ERR(priv, "Unknown testmode command\n");
                result = -ENOSYS;
                break;
        }
 
-       mutex_unlock(&priv->shrd->mutex);
+       mutex_unlock(&priv->mutex);
        return result;
 }
 
@@ -1036,7 +1055,7 @@ int iwlagn_mac_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *skb,
                      void *data, int len)
 {
        struct nlattr *tb[IWL_TM_ATTR_MAX];
-       struct iwl_priv *priv = hw->priv;
+       struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
        int result;
        u32 cmd;
 
@@ -1062,21 +1081,21 @@ int iwlagn_mac_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *skb,
        }
 
        /* in case multiple accesses to the device happens */
-       mutex_lock(&priv->shrd->mutex);
+       mutex_lock(&priv->mutex);
        switch (cmd) {
        case IWL_TM_CMD_APP2DEV_READ_TRACE:
                IWL_DEBUG_INFO(priv, "uCode trace cmd to driver\n");
-               result = iwl_testmode_trace_dump(hw, tb, skb, cb);
+               result = iwl_testmode_trace_dump(hw, skb, cb);
                break;
        case IWL_TM_CMD_APP2DEV_INDIRECT_BUFFER_DUMP:
                IWL_DEBUG_INFO(priv, "testmode sram dump cmd to driver\n");
-               result = iwl_testmode_buffer_dump(hw, tb, skb, cb);
+               result = iwl_testmode_buffer_dump(hw, skb, cb);
                break;
        default:
                result = -EINVAL;
                break;
        }
 
-       mutex_unlock(&priv->shrd->mutex);
+       mutex_unlock(&priv->mutex);
        return result;
 }
This page took 0.030572 seconds and 5 git commands to generate.