add some debug counters master-2011-01-17
authorGrazvydas Ignotas <notasas@gmail.com>
Sun, 31 Oct 2010 17:01:30 +0000 (19:01 +0200)
committerGrazvydas Ignotas <notasas@gmail.com>
Mon, 17 Jan 2011 17:19:43 +0000 (19:19 +0200)
drivers/net/wireless/wl12xx/wl1251.h
drivers/net/wireless/wl12xx/wl1251_acx.c
drivers/net/wireless/wl12xx/wl1251_acx.h
drivers/net/wireless/wl12xx/wl1251_main.c
drivers/net/wireless/wl12xx/wl1251_tx.c

index 5e6cbb5..52f92af 100644 (file)
@@ -150,6 +150,10 @@ struct wl1251_stats {
 
        unsigned int retry_count;
        unsigned int excessive_retries;
+
+       unsigned int tx_to_fw;
+       unsigned int tx_timeouts;
+       unsigned int tx_other_err;
 };
 
 struct wl1251_debugfs {
index 87e0af4..f1508a4 100644 (file)
@@ -870,6 +870,22 @@ int wl1251_acx_statistics(struct wl1251 *wl, struct acx_statistics *stats)
        return 0;
 }
 
+int wl1251_acx_error_counters(struct wl1251 *wl, struct acx_error_counters *counts)
+{
+       int ret;
+
+       wl1251_debug(DEBUG_ACX, "acx error counters");
+
+       ret = wl1251_cmd_interrogate(wl, ACX_ERROR_CNT, counts,
+                                    sizeof(*counts));
+       if (ret < 0) {
+               wl1251_warning("acx error counters failed: %d", ret);
+               return -ENOMEM;
+       }
+
+       return 0;
+}
+
 int wl1251_acx_rate_policies(struct wl1251 *wl)
 {
        struct acx_rate_policy *acx;
index a8845b8..7ecd0ee 100644 (file)
@@ -1046,6 +1046,17 @@ struct acx_statistics {
        struct acx_rxpipe_statistics rxpipe;
 } __packed;
 
+struct acx_error_counters
+{
+       struct acx_header header;
+       u32 plcp_error_count;   /* PLCP error count, clears on read */
+       u32 fcs_error_count;    /* FCS error count, clears on read */
+       u32 valid_frame_count;  /* number of MPDUs without PLCP header errors */
+                               /* auto clear */
+       u32 seq_num_miss_count; /* missed sequence numbers in the squentially */
+                               /* values of frames seq numbers */
+} __packed;
+
 #define ACX_MAX_RATE_CLASSES       8
 #define ACX_RATE_MASK_UNSPECIFIED  0
 #define ACX_RATE_RETRY_LIMIT      10
@@ -1399,6 +1410,7 @@ int wl1251_acx_set_preamble(struct wl1251 *wl, enum acx_preamble_type preamble);
 int wl1251_acx_cts_protect(struct wl1251 *wl,
                            enum acx_ctsprotect_type ctsprotect);
 int wl1251_acx_statistics(struct wl1251 *wl, struct acx_statistics *stats);
+int wl1251_acx_error_counters(struct wl1251 *wl, struct acx_error_counters *counts);
 int wl1251_acx_tsf_info(struct wl1251 *wl, u64 *mactime);
 int wl1251_acx_rate_policies(struct wl1251 *wl);
 int wl1251_acx_mem_cfg(struct wl1251 *wl);
index bb8133a..8f5a632 100644 (file)
@@ -1308,6 +1308,50 @@ static int wl1251_register_hw(struct wl1251 *wl)
        return 0;
 }
 
+static ssize_t wl1251_sysfs_show_wl_stats(struct device *dev,
+                                             struct device_attribute *attr,
+                                             char *buf)
+{
+       struct wl1251 *wl = dev_get_drvdata(dev);
+       struct acx_error_counters counts;
+       struct acx_statistics stats;
+       ssize_t len;
+       int ret;
+
+       memset(&counts, 0, sizeof(counts));
+       memset(&stats, 0, sizeof(stats));
+
+       mutex_lock(&wl->mutex);
+
+       if (wl->state != WL1251_STATE_ON)
+               goto out;
+
+       ret = wl1251_ps_elp_wakeup(wl);
+       if (ret < 0)
+               goto out;
+
+       wl1251_acx_error_counters(wl, &counts);
+       //wl1251_acx_statistics(wl, &stats);
+
+       wl1251_ps_elp_sleep(wl);
+
+out:
+       mutex_unlock(&wl->mutex);
+
+       len = snprintf(buf, PAGE_SIZE, "%u %u %u %u "
+                                      "%u %u %u %u\n",
+                       counts.fcs_error_count, counts.plcp_error_count,
+                       counts.seq_num_miss_count, counts.valid_frame_count,
+                       wl->stats.retry_count, wl->stats.tx_timeouts,
+                       wl->stats.tx_other_err, wl->stats.tx_to_fw);
+
+       return len;
+}
+
+static DEVICE_ATTR(wl_stats, S_IRUGO | S_IWUSR,
+                  wl1251_sysfs_show_wl_stats,
+                  NULL);
+
 int wl1251_init_ieee80211(struct wl1251 *wl)
 {
        int ret;
@@ -1339,6 +1383,10 @@ int wl1251_init_ieee80211(struct wl1251 *wl)
        if (ret)
                goto out;
 
+       ret = device_create_file(wiphy_dev(wl->hw->wiphy), &dev_attr_wl_stats);
+       if (ret < 0)
+               wl1251_error("failed to create sysfs file");
+
        wl1251_debugfs_init(wl);
        wl1251_notice("initialized");
 
@@ -1428,6 +1476,7 @@ EXPORT_SYMBOL_GPL(wl1251_alloc_hw);
 
 int wl1251_free_hw(struct wl1251 *wl)
 {
+       device_remove_file(wiphy_dev(wl->hw->wiphy), &dev_attr_wl_stats);
        ieee80211_unregister_hw(wl->hw);
 
        wl1251_debugfs_exit(wl);
index 30b9a6f..41cb141 100644 (file)
@@ -297,6 +297,8 @@ static int wl1251_tx_frame(struct wl1251 *wl, struct sk_buff *skb)
 
        wl1251_tx_trigger(wl);
 
+       wl->stats.tx_to_fw++;
+
        return ret;
 }
 
@@ -388,6 +390,13 @@ static void wl1251_tx_packet_cb(struct wl1251 *wl,
        info->status.rates[0].count = result->ack_failures + 1;
        wl->stats.retry_count += result->ack_failures;
 
+       if (result->status != TX_SUCCESS) {
+               if (result->status & TX_TIMEOUT)
+                       wl->stats.tx_timeouts++;
+               else
+                       wl->stats.tx_other_err++;
+       }
+
        /*
         * We have to remove our private TX header before pushing
         * the skb back to mac80211.