iwlagn: keep track of failure tx status
authorWey-Yi Guy <wey-yi.w.guy@intel.com>
Sun, 5 Sep 2010 17:49:42 +0000 (10:49 -0700)
committerWey-Yi Guy <wey-yi.w.guy@intel.com>
Fri, 17 Sep 2010 20:17:36 +0000 (13:17 -0700)
Tx command response sent to host by uCode after completed
the transmission attempt. The status parameter indicates
whether the transmission was successful, or else why if failed.

Here we keep the counters to help understand the different failure
cases.

Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
drivers/net/wireless/iwlwifi/iwl-1000.c
drivers/net/wireless/iwlwifi/iwl-4965.c
drivers/net/wireless/iwlwifi/iwl-5000.c
drivers/net/wireless/iwlwifi/iwl-6000.c
drivers/net/wireless/iwlwifi/iwl-agn-debugfs.c
drivers/net/wireless/iwlwifi/iwl-agn-debugfs.h
drivers/net/wireless/iwlwifi/iwl-core.h
drivers/net/wireless/iwlwifi/iwl-debugfs.c

index 674fb93ae17f0829d02906173326f7b59e98e15c..56ef4ed0db476a7c6560d5b4d7f297e21cfbb5ac 100644 (file)
@@ -223,6 +223,7 @@ static struct iwl_lib_ops iwl1000_lib = {
                .tx_stats_read = iwl_ucode_tx_stats_read,
                .general_stats_read = iwl_ucode_general_stats_read,
                .bt_stats_read = iwl_ucode_bt_stats_read,
+               .reply_tx_error = iwl_reply_tx_error_read,
        },
        .recover_from_tx_stall = iwl_bg_monitor_recover,
        .check_plcp_health = iwl_good_plcp_health,
index 1d6a46d4db594dbf9fe8ae34f4dc702ebb05063f..943a9c7bfa7fdeeb71fce24dba5cee3734a68946 100644 (file)
@@ -2289,6 +2289,7 @@ static struct iwl_lib_ops iwl4965_lib = {
                .tx_stats_read = iwl_ucode_tx_stats_read,
                .general_stats_read = iwl_ucode_general_stats_read,
                .bt_stats_read = iwl_ucode_bt_stats_read,
+               .reply_tx_error = iwl_reply_tx_error_read,
        },
        .recover_from_tx_stall = iwl_bg_monitor_recover,
        .check_plcp_health = iwl_good_plcp_health,
index b9399fbcee97fb95f847c757530946f61b63474f..21b4b23368e6e7129820f3d55427cee01059c534 100644 (file)
@@ -404,6 +404,7 @@ static struct iwl_lib_ops iwl5000_lib = {
                .tx_stats_read = iwl_ucode_tx_stats_read,
                .general_stats_read = iwl_ucode_general_stats_read,
                .bt_stats_read = iwl_ucode_bt_stats_read,
+               .reply_tx_error = iwl_reply_tx_error_read,
        },
        .recover_from_tx_stall = iwl_bg_monitor_recover,
        .check_plcp_health = iwl_good_plcp_health,
@@ -475,6 +476,7 @@ static struct iwl_lib_ops iwl5150_lib = {
                .tx_stats_read = iwl_ucode_tx_stats_read,
                .general_stats_read = iwl_ucode_general_stats_read,
                .bt_stats_read = iwl_ucode_bt_stats_read,
+               .reply_tx_error = iwl_reply_tx_error_read,
        },
        .recover_from_tx_stall = iwl_bg_monitor_recover,
        .check_plcp_health = iwl_good_plcp_health,
index 2fdba088bd276d5c3ef5fb7f31b6944a0be4e911..9f43f2770c96897e39fed5118abdf311af5731bb 100644 (file)
@@ -329,6 +329,7 @@ static struct iwl_lib_ops iwl6000_lib = {
                .tx_stats_read = iwl_ucode_tx_stats_read,
                .general_stats_read = iwl_ucode_general_stats_read,
                .bt_stats_read = iwl_ucode_bt_stats_read,
+               .reply_tx_error = iwl_reply_tx_error_read,
        },
        .recover_from_tx_stall = iwl_bg_monitor_recover,
        .check_plcp_health = iwl_good_plcp_health,
@@ -404,6 +405,7 @@ static struct iwl_lib_ops iwl6000g2b_lib = {
                .tx_stats_read = iwl_ucode_tx_stats_read,
                .general_stats_read = iwl_ucode_general_stats_read,
                .bt_stats_read = iwl_ucode_bt_stats_read,
+               .reply_tx_error = iwl_reply_tx_error_read,
        },
        .recover_from_tx_stall = iwl_bg_monitor_recover,
        .check_plcp_health = iwl_good_plcp_health,
index d706b8afbe5abd7f54b570d1a414a7f9c3c9aac5..de68dde4feee0d81ede6cc10296232acd82d8f40 100644 (file)
@@ -1011,3 +1011,100 @@ ssize_t iwl_ucode_bt_stats_read(struct file *file,
        kfree(buf);
        return ret;
 }
+
+ssize_t iwl_reply_tx_error_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;
+       char *buf;
+       int bufsz = (sizeof(struct reply_tx_error_statistics) * 24) + 200;
+       ssize_t ret;
+
+       if (!iwl_is_alive(priv))
+               return -EAGAIN;
+
+       buf = kzalloc(bufsz, GFP_KERNEL);
+       if (!buf) {
+               IWL_ERR(priv, "Can not allocate Buffer\n");
+               return -ENOMEM;
+       }
+
+       pos += scnprintf(buf + pos, bufsz - pos, "Statistics_TX_Error:\n");
+       pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t\t%u\n",
+                        iwl_get_tx_fail_reason(TX_STATUS_POSTPONE_DELAY),
+                        priv->_agn.reply_tx_stats.pp_delay);
+       pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
+                        iwl_get_tx_fail_reason(TX_STATUS_POSTPONE_FEW_BYTES),
+                        priv->_agn.reply_tx_stats.pp_few_bytes);
+       pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
+                        iwl_get_tx_fail_reason(TX_STATUS_POSTPONE_BT_PRIO),
+                        priv->_agn.reply_tx_stats.pp_bt_prio);
+       pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
+                        iwl_get_tx_fail_reason(TX_STATUS_POSTPONE_QUIET_PERIOD),
+                        priv->_agn.reply_tx_stats.pp_quiet_period);
+       pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
+                        iwl_get_tx_fail_reason(TX_STATUS_POSTPONE_CALC_TTAK),
+                        priv->_agn.reply_tx_stats.pp_calc_ttak);
+       pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t%u\n",
+                        iwl_get_tx_fail_reason(
+                               TX_STATUS_FAIL_INTERNAL_CROSSED_RETRY),
+                        priv->_agn.reply_tx_stats.int_crossed_retry);
+       pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
+                        iwl_get_tx_fail_reason(TX_STATUS_FAIL_SHORT_LIMIT),
+                        priv->_agn.reply_tx_stats.short_limit);
+       pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
+                        iwl_get_tx_fail_reason(TX_STATUS_FAIL_LONG_LIMIT),
+                        priv->_agn.reply_tx_stats.long_limit);
+       pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
+                        iwl_get_tx_fail_reason(TX_STATUS_FAIL_FIFO_UNDERRUN),
+                        priv->_agn.reply_tx_stats.fifo_underrun);
+       pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
+                        iwl_get_tx_fail_reason(TX_STATUS_FAIL_DRAIN_FLOW),
+                        priv->_agn.reply_tx_stats.drain_flow);
+       pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
+                        iwl_get_tx_fail_reason(TX_STATUS_FAIL_RFKILL_FLUSH),
+                        priv->_agn.reply_tx_stats.rfkill_flush);
+       pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
+                        iwl_get_tx_fail_reason(TX_STATUS_FAIL_LIFE_EXPIRE),
+                        priv->_agn.reply_tx_stats.life_expire);
+       pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
+                        iwl_get_tx_fail_reason(TX_STATUS_FAIL_DEST_PS),
+                        priv->_agn.reply_tx_stats.dest_ps);
+       pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
+                        iwl_get_tx_fail_reason(TX_STATUS_FAIL_HOST_ABORTED),
+                        priv->_agn.reply_tx_stats.host_abort);
+       pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
+                        iwl_get_tx_fail_reason(TX_STATUS_FAIL_BT_RETRY),
+                        priv->_agn.reply_tx_stats.pp_delay);
+       pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
+                        iwl_get_tx_fail_reason(TX_STATUS_FAIL_STA_INVALID),
+                        priv->_agn.reply_tx_stats.sta_invalid);
+       pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
+                        iwl_get_tx_fail_reason(TX_STATUS_FAIL_FRAG_DROPPED),
+                        priv->_agn.reply_tx_stats.frag_drop);
+       pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
+                        iwl_get_tx_fail_reason(TX_STATUS_FAIL_TID_DISABLE),
+                        priv->_agn.reply_tx_stats.tid_disable);
+       pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
+                        iwl_get_tx_fail_reason(TX_STATUS_FAIL_FIFO_FLUSHED),
+                        priv->_agn.reply_tx_stats.fifo_flush);
+       pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t%u\n",
+                        iwl_get_tx_fail_reason(
+                               TX_STATUS_FAIL_INSUFFICIENT_CF_POLL),
+                        priv->_agn.reply_tx_stats.insuff_cf_poll);
+       pos += scnprintf(buf + pos, bufsz - pos, "%s:\t\t\t%u\n",
+                        iwl_get_tx_fail_reason(TX_STATUS_FAIL_FW_DROP),
+                        priv->_agn.reply_tx_stats.fail_hw_drop);
+       pos += scnprintf(buf + pos, bufsz - pos, "%s:\t%u\n",
+                        iwl_get_tx_fail_reason(
+                               TX_STATUS_FAIL_STA_COLOR_MISMATCH_DROP),
+                        priv->_agn.reply_tx_stats.sta_color_mismatch);
+       pos += scnprintf(buf + pos, bufsz - pos, "UNKNOWN:\t\t\t%u\n",
+                        priv->_agn.reply_tx_stats.unknown);
+
+       ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+       kfree(buf);
+       return ret;
+}
index bbdce5913ac77a51d52fb02cbef8a587287b6b8e..f2573b5486cd20bc958367c33cf0a9e577ba643a 100644 (file)
@@ -39,6 +39,8 @@ ssize_t iwl_ucode_general_stats_read(struct file *file, char __user *user_buf,
                                     size_t count, loff_t *ppos);
 ssize_t iwl_ucode_bt_stats_read(struct file *file, char __user *user_buf,
                                size_t count, loff_t *ppos);
+ssize_t iwl_reply_tx_error_read(struct file *file, char __user *user_buf,
+                               size_t count, loff_t *ppos);
 #else
 static ssize_t iwl_ucode_rx_stats_read(struct file *file, char __user *user_buf,
                                       size_t count, loff_t *ppos)
@@ -60,4 +62,9 @@ static ssize_t iwl_ucode_bt_stats_read(struct file *file, char __user *user_buf,
 {
        return 0;
 }
+static ssize_t iwl_reply_tx_error_read(struct file *file, char __user *user_buf,
+                                      size_t count, loff_t *ppos)
+{
+       return 0;
+}
 #endif
index f1d40c6173c1d0d585bfbac41567c94d4045189d..f0302bfe85f55c46eee85bcbafc48c93270a8c7d 100644 (file)
@@ -130,6 +130,8 @@ struct iwl_debugfs_ops {
                                      size_t count, loff_t *ppos);
        ssize_t (*bt_stats_read)(struct file *file, char __user *user_buf,
                                 size_t count, loff_t *ppos);
+       ssize_t (*reply_tx_error)(struct file *file, char __user *user_buf,
+                                size_t count, loff_t *ppos);
 };
 
 struct iwl_temp_ops {
index e0b31a2a1dacd05abad93db536115f0ad63abf43..265ad01a443f9adb887fe7c606098e5bf94f8ecd 100644 (file)
@@ -1642,6 +1642,18 @@ static ssize_t iwl_dbgfs_protection_mode_write(struct file *file,
        return count;
 }
 
+static ssize_t iwl_dbgfs_reply_tx_error_read(struct file *file,
+                                       char __user *user_buf,
+                                       size_t count, loff_t *ppos)
+{
+       struct iwl_priv *priv = file->private_data;
+
+       if (priv->cfg->ops->lib->debugfs_ops.reply_tx_error)
+               return priv->cfg->ops->lib->debugfs_ops.reply_tx_error(
+                       file, user_buf, count, ppos);
+       else
+               return -ENODATA;
+}
 DEBUGFS_READ_FILE_OPS(rx_statistics);
 DEBUGFS_READ_FILE_OPS(tx_statistics);
 DEBUGFS_READ_WRITE_FILE_OPS(traffic_log);
@@ -1668,6 +1680,7 @@ DEBUGFS_READ_FILE_OPS(ucode_bt_stats);
 DEBUGFS_WRITE_FILE_OPS(monitor_period);
 DEBUGFS_READ_FILE_OPS(bt_traffic);
 DEBUGFS_READ_WRITE_FILE_OPS(protection_mode);
+DEBUGFS_READ_FILE_OPS(reply_tx_error);
 
 /*
  * Create the debugfs files and directories
@@ -1738,6 +1751,7 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name)
                DEBUGFS_ADD_FILE(ucode_tracing, dir_debug, S_IWUSR | S_IRUSR);
        if (priv->cfg->bt_statistics)
                DEBUGFS_ADD_FILE(ucode_bt_stats, dir_debug, S_IRUSR);
+       DEBUGFS_ADD_FILE(reply_tx_error, dir_debug, S_IRUSR);
        DEBUGFS_ADD_FILE(rxon_flags, dir_debug, S_IWUSR);
        DEBUGFS_ADD_FILE(rxon_filter_flags, dir_debug, S_IWUSR);
        DEBUGFS_ADD_FILE(monitor_period, dir_debug, S_IWUSR);