iwlwifi: check for valid band for channel info
[pandora-kernel.git] / drivers / net / wireless / iwlwifi / iwl-debugfs.c
index 64eb585..af70229 100644 (file)
@@ -172,7 +172,6 @@ static ssize_t iwl_dbgfs_sram_read(struct file *file,
        struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
        const size_t bufsz = sizeof(buf);
 
-       iwl_grab_nic_access(priv);
        for (i = priv->dbgfs->sram_len; i > 0; i -= 4) {
                val = iwl_read_targ_mem(priv, priv->dbgfs->sram_offset + \
                                        priv->dbgfs->sram_len - i);
@@ -192,7 +191,6 @@ static ssize_t iwl_dbgfs_sram_read(struct file *file,
                pos += scnprintf(buf + pos, bufsz - pos, "0x%08x ", val);
        }
        pos += scnprintf(buf + pos, bufsz - pos, "\n");
-       iwl_release_nic_access(priv);
 
        ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
        return ret;
@@ -292,7 +290,7 @@ static ssize_t iwl_dbgfs_stations_read(struct file *file, char __user *user_buf,
        return ret;
 }
 
-static ssize_t iwl_dbgfs_eeprom_read(struct file *file,
+static ssize_t iwl_dbgfs_nvm_read(struct file *file,
                                       char __user *user_buf,
                                       size_t count,
                                       loff_t *ppos)
@@ -306,7 +304,7 @@ static ssize_t iwl_dbgfs_eeprom_read(struct file *file,
        buf_size = 4 * eeprom_len + 256;
 
        if (eeprom_len % 16) {
-               IWL_ERR(priv, "EEPROM size is not multiple of 16.\n");
+               IWL_ERR(priv, "NVM size is not multiple of 16.\n");
                return -ENODATA;
        }
 
@@ -318,6 +316,13 @@ static ssize_t iwl_dbgfs_eeprom_read(struct file *file,
        }
 
        ptr = priv->eeprom;
+       if (!ptr) {
+               IWL_ERR(priv, "Invalid EEPROM/OTP memory\n");
+               return -ENOMEM;
+       }
+       pos += scnprintf(buf + pos, buf_size - pos, "NVM Type: %s\n",
+                       (priv->nvm_device_type == NVM_DEVICE_TYPE_OTP)
+                       ? "OTP" : "EEPROM");
        for (ofs = 0 ; ofs < eeprom_len ; ofs += 16) {
                pos += scnprintf(buf + pos, buf_size - pos, "0x%.4x ", ofs);
                hex_dump_to_buffer(ptr + ofs, 16 , 16, 2, buf + pos,
@@ -375,51 +380,53 @@ static ssize_t iwl_dbgfs_channels_read(struct file *file, char __user *user_buf,
        }
 
        supp_band = iwl_get_hw_mode(priv, IEEE80211_BAND_2GHZ);
-       channels = supp_band->channels;
-
-       pos += scnprintf(buf + pos, bufsz - pos,
-                       "Displaying %d channels in 2.4GHz band 802.11bg):\n",
-                        supp_band->n_channels);
+       if (supp_band) {
+               channels = supp_band->channels;
 
-       for (i = 0; i < supp_band->n_channels; i++)
                pos += scnprintf(buf + pos, bufsz - pos,
-                               "%d: %ddBm: BSS%s%s, %s.\n",
-                               ieee80211_frequency_to_channel(
-                               channels[i].center_freq),
-                               channels[i].max_power,
-                               channels[i].flags & IEEE80211_CHAN_RADAR ?
-                               " (IEEE 802.11h required)" : "",
-                               (!(channels[i].flags & IEEE80211_CHAN_NO_IBSS)
-                               || (channels[i].flags &
-                               IEEE80211_CHAN_RADAR)) ? "" :
-                               ", IBSS",
-                               channels[i].flags &
-                               IEEE80211_CHAN_PASSIVE_SCAN ?
-                               "passive only" : "active/passive");
+                               "Displaying %d channels in 2.4GHz band 802.11bg):\n",
+                               supp_band->n_channels);
 
+               for (i = 0; i < supp_band->n_channels; i++)
+                       pos += scnprintf(buf + pos, bufsz - pos,
+                                       "%d: %ddBm: BSS%s%s, %s.\n",
+                                       ieee80211_frequency_to_channel(
+                                       channels[i].center_freq),
+                                       channels[i].max_power,
+                                       channels[i].flags & IEEE80211_CHAN_RADAR ?
+                                       " (IEEE 802.11h required)" : "",
+                                       ((channels[i].flags & IEEE80211_CHAN_NO_IBSS)
+                                       || (channels[i].flags &
+                                       IEEE80211_CHAN_RADAR)) ? "" :
+                                       ", IBSS",
+                                       channels[i].flags &
+                                       IEEE80211_CHAN_PASSIVE_SCAN ?
+                                       "passive only" : "active/passive");
+       }
        supp_band = iwl_get_hw_mode(priv, IEEE80211_BAND_5GHZ);
-       channels = supp_band->channels;
-
-       pos += scnprintf(buf + pos, bufsz - pos,
-                       "Displaying %d channels in 5.2GHz band (802.11a)\n",
-                       supp_band->n_channels);
+       if (supp_band) {
+               channels = supp_band->channels;
 
-       for (i = 0; i < supp_band->n_channels; i++)
                pos += scnprintf(buf + pos, bufsz - pos,
-                               "%d: %ddBm: BSS%s%s, %s.\n",
-                               ieee80211_frequency_to_channel(
-                               channels[i].center_freq),
-                               channels[i].max_power,
-                               channels[i].flags & IEEE80211_CHAN_RADAR ?
-                               " (IEEE 802.11h required)" : "",
-                               ((channels[i].flags & IEEE80211_CHAN_NO_IBSS)
-                               || (channels[i].flags &
-                               IEEE80211_CHAN_RADAR)) ? "" :
-                               ", IBSS",
-                               channels[i].flags &
-                               IEEE80211_CHAN_PASSIVE_SCAN ?
-                               "passive only" : "active/passive");
+                               "Displaying %d channels in 5.2GHz band (802.11a)\n",
+                               supp_band->n_channels);
 
+               for (i = 0; i < supp_band->n_channels; i++)
+                       pos += scnprintf(buf + pos, bufsz - pos,
+                                       "%d: %ddBm: BSS%s%s, %s.\n",
+                                       ieee80211_frequency_to_channel(
+                                       channels[i].center_freq),
+                                       channels[i].max_power,
+                                       channels[i].flags & IEEE80211_CHAN_RADAR ?
+                                       " (IEEE 802.11h required)" : "",
+                                       ((channels[i].flags & IEEE80211_CHAN_NO_IBSS)
+                                       || (channels[i].flags &
+                                       IEEE80211_CHAN_RADAR)) ? "" :
+                                       ", IBSS",
+                                       channels[i].flags &
+                                       IEEE80211_CHAN_PASSIVE_SCAN ?
+                                       "passive only" : "active/passive");
+       }
        ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
        kfree(buf);
        return ret;
@@ -456,8 +463,6 @@ static ssize_t iwl_dbgfs_status_read(struct file *file,
                test_bit(STATUS_GEO_CONFIGURED, &priv->status));
        pos += scnprintf(buf + pos, bufsz - pos, "STATUS_EXIT_PENDING:\t %d\n",
                test_bit(STATUS_EXIT_PENDING, &priv->status));
-       pos += scnprintf(buf + pos, bufsz - pos, "STATUS_IN_SUSPEND:\t %d\n",
-               test_bit(STATUS_IN_SUSPEND, &priv->status));
        pos += scnprintf(buf + pos, bufsz - pos, "STATUS_STATISTICS:\t %d\n",
                test_bit(STATUS_STATISTICS, &priv->status));
        pos += scnprintf(buf + pos, bufsz - pos, "STATUS_SCANNING:\t %d\n",
@@ -475,14 +480,104 @@ static ssize_t iwl_dbgfs_status_read(struct file *file,
        return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
 }
 
+static ssize_t iwl_dbgfs_interrupt_read(struct file *file,
+                                       char __user *user_buf,
+                                       size_t count, loff_t *ppos) {
+
+       struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
+       int pos = 0;
+       int cnt = 0;
+       char *buf;
+       int bufsz = 24 * 64; /* 24 items * 64 char per item */
+       ssize_t ret;
+
+       buf = kzalloc(bufsz, GFP_KERNEL);
+       if (!buf) {
+               IWL_ERR(priv, "Can not allocate Buffer\n");
+               return -ENOMEM;
+       }
+
+       pos += scnprintf(buf + pos, bufsz - pos,
+                       "Interrupt Statistics Report:\n");
+
+       pos += scnprintf(buf + pos, bufsz - pos, "HW Error:\t\t\t %u\n",
+               priv->isr_stats.hw);
+       pos += scnprintf(buf + pos, bufsz - pos, "SW Error:\t\t\t %u\n",
+               priv->isr_stats.sw);
+       if (priv->isr_stats.sw > 0) {
+               pos += scnprintf(buf + pos, bufsz - pos,
+                       "\tLast Restarting Code:  0x%X\n",
+                       priv->isr_stats.sw_err);
+       }
+#ifdef CONFIG_IWLWIFI_DEBUG
+       pos += scnprintf(buf + pos, bufsz - pos, "Frame transmitted:\t\t %u\n",
+               priv->isr_stats.sch);
+       pos += scnprintf(buf + pos, bufsz - pos, "Alive interrupt:\t\t %u\n",
+               priv->isr_stats.alive);
+#endif
+       pos += scnprintf(buf + pos, bufsz - pos,
+               "HW RF KILL switch toggled:\t %u\n",
+               priv->isr_stats.rfkill);
+
+       pos += scnprintf(buf + pos, bufsz - pos, "CT KILL:\t\t\t %u\n",
+               priv->isr_stats.ctkill);
+
+       pos += scnprintf(buf + pos, bufsz - pos, "Wakeup Interrupt:\t\t %u\n",
+               priv->isr_stats.wakeup);
+
+       pos += scnprintf(buf + pos, bufsz - pos,
+               "Rx command responses:\t\t %u\n",
+               priv->isr_stats.rx);
+       for (cnt = 0; cnt < REPLY_MAX; cnt++) {
+               if (priv->isr_stats.rx_handlers[cnt] > 0)
+                       pos += scnprintf(buf + pos, bufsz - pos,
+                               "\tRx handler[%36s]:\t\t %u\n",
+                               get_cmd_string(cnt),
+                               priv->isr_stats.rx_handlers[cnt]);
+       }
+
+       pos += scnprintf(buf + pos, bufsz - pos, "Tx/FH interrupt:\t\t %u\n",
+               priv->isr_stats.tx);
+
+       pos += scnprintf(buf + pos, bufsz - pos, "Unexpected INTA:\t\t %u\n",
+               priv->isr_stats.unhandled);
+
+       ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+       kfree(buf);
+       return ret;
+}
+
+static ssize_t iwl_dbgfs_interrupt_write(struct file *file,
+                                        const char __user *user_buf,
+                                        size_t count, loff_t *ppos)
+{
+       struct iwl_priv *priv = file->private_data;
+       char buf[8];
+       int buf_size;
+       u32 reset_flag;
+
+       memset(buf, 0, sizeof(buf));
+       buf_size = min(count, sizeof(buf) -  1);
+       if (copy_from_user(buf, user_buf, buf_size))
+               return -EFAULT;
+       if (sscanf(buf, "%x", &reset_flag) != 1)
+               return -EFAULT;
+       if (reset_flag == 0)
+               iwl_clear_isr_stats(priv);
+
+       return count;
+}
+
+
 DEBUGFS_READ_WRITE_FILE_OPS(sram);
 DEBUGFS_WRITE_FILE_OPS(log_event);
-DEBUGFS_READ_FILE_OPS(eeprom);
+DEBUGFS_READ_FILE_OPS(nvm);
 DEBUGFS_READ_FILE_OPS(stations);
 DEBUGFS_READ_FILE_OPS(rx_statistics);
 DEBUGFS_READ_FILE_OPS(tx_statistics);
 DEBUGFS_READ_FILE_OPS(channels);
 DEBUGFS_READ_FILE_OPS(status);
+DEBUGFS_READ_WRITE_FILE_OPS(interrupt);
 
 /*
  * Create the debugfs files and directories
@@ -510,7 +605,7 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name)
 
        DEBUGFS_ADD_DIR(data, dbgfs->dir_drv);
        DEBUGFS_ADD_DIR(rf, dbgfs->dir_drv);
-       DEBUGFS_ADD_FILE(eeprom, data);
+       DEBUGFS_ADD_FILE(nvm, data);
        DEBUGFS_ADD_FILE(sram, data);
        DEBUGFS_ADD_FILE(log_event, data);
        DEBUGFS_ADD_FILE(stations, data);
@@ -518,6 +613,7 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name)
        DEBUGFS_ADD_FILE(tx_statistics, data);
        DEBUGFS_ADD_FILE(channels, data);
        DEBUGFS_ADD_FILE(status, data);
+       DEBUGFS_ADD_FILE(interrupt, data);
        DEBUGFS_ADD_BOOL(disable_sensitivity, rf, &priv->disable_sens_cal);
        DEBUGFS_ADD_BOOL(disable_chain_noise, rf,
                         &priv->disable_chain_noise_cal);
@@ -540,7 +636,7 @@ void iwl_dbgfs_unregister(struct iwl_priv *priv)
        if (!priv->dbgfs)
                return;
 
-       DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_eeprom);
+       DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_nvm);
        DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_rx_statistics);
        DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_tx_statistics);
        DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_sram);
@@ -548,6 +644,7 @@ void iwl_dbgfs_unregister(struct iwl_priv *priv)
        DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_stations);
        DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_channels);
        DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_status);
+       DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_interrupt);
        DEBUGFS_REMOVE(priv->dbgfs->dir_data);
        DEBUGFS_REMOVE(priv->dbgfs->dbgfs_rf_files.file_disable_sensitivity);
        DEBUGFS_REMOVE(priv->dbgfs->dbgfs_rf_files.file_disable_chain_noise);