Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Copyright (c) 2010-2011 Atheros Communications Inc.
0003  *
0004  * Permission to use, copy, modify, and/or distribute this software for any
0005  * purpose with or without fee is hereby granted, provided that the above
0006  * copyright notice and this permission notice appear in all copies.
0007  *
0008  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
0009  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
0010  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
0011  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
0012  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
0013  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
0014  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
0015  */
0016 
0017 #include "htc.h"
0018 
0019 static ssize_t read_file_tgt_int_stats(struct file *file, char __user *user_buf,
0020                        size_t count, loff_t *ppos)
0021 {
0022     struct ath9k_htc_priv *priv = file->private_data;
0023     struct ath9k_htc_target_int_stats cmd_rsp;
0024     char buf[512];
0025     unsigned int len = 0;
0026     int ret = 0;
0027 
0028     memset(&cmd_rsp, 0, sizeof(cmd_rsp));
0029 
0030     ath9k_htc_ps_wakeup(priv);
0031 
0032     WMI_CMD(WMI_INT_STATS_CMDID);
0033     if (ret) {
0034         ath9k_htc_ps_restore(priv);
0035         return -EINVAL;
0036     }
0037 
0038     ath9k_htc_ps_restore(priv);
0039 
0040     len += scnprintf(buf + len, sizeof(buf) - len,
0041              "%20s : %10u\n", "RX",
0042              be32_to_cpu(cmd_rsp.rx));
0043 
0044     len += scnprintf(buf + len, sizeof(buf) - len,
0045              "%20s : %10u\n", "RXORN",
0046              be32_to_cpu(cmd_rsp.rxorn));
0047 
0048     len += scnprintf(buf + len, sizeof(buf) - len,
0049              "%20s : %10u\n", "RXEOL",
0050              be32_to_cpu(cmd_rsp.rxeol));
0051 
0052     len += scnprintf(buf + len, sizeof(buf) - len,
0053              "%20s : %10u\n", "TXURN",
0054              be32_to_cpu(cmd_rsp.txurn));
0055 
0056     len += scnprintf(buf + len, sizeof(buf) - len,
0057              "%20s : %10u\n", "TXTO",
0058              be32_to_cpu(cmd_rsp.txto));
0059 
0060     len += scnprintf(buf + len, sizeof(buf) - len,
0061              "%20s : %10u\n", "CST",
0062              be32_to_cpu(cmd_rsp.cst));
0063 
0064     if (len > sizeof(buf))
0065         len = sizeof(buf);
0066 
0067     return simple_read_from_buffer(user_buf, count, ppos, buf, len);
0068 }
0069 
0070 static const struct file_operations fops_tgt_int_stats = {
0071     .read = read_file_tgt_int_stats,
0072     .open = simple_open,
0073     .owner = THIS_MODULE,
0074     .llseek = default_llseek,
0075 };
0076 
0077 static ssize_t read_file_tgt_tx_stats(struct file *file, char __user *user_buf,
0078                       size_t count, loff_t *ppos)
0079 {
0080     struct ath9k_htc_priv *priv = file->private_data;
0081     struct ath9k_htc_target_tx_stats cmd_rsp;
0082     char buf[512];
0083     unsigned int len = 0;
0084     int ret = 0;
0085 
0086     memset(&cmd_rsp, 0, sizeof(cmd_rsp));
0087 
0088     ath9k_htc_ps_wakeup(priv);
0089 
0090     WMI_CMD(WMI_TX_STATS_CMDID);
0091     if (ret) {
0092         ath9k_htc_ps_restore(priv);
0093         return -EINVAL;
0094     }
0095 
0096     ath9k_htc_ps_restore(priv);
0097 
0098     len += scnprintf(buf + len, sizeof(buf) - len,
0099              "%20s : %10u\n", "Xretries",
0100              be32_to_cpu(cmd_rsp.xretries));
0101 
0102     len += scnprintf(buf + len, sizeof(buf) - len,
0103              "%20s : %10u\n", "FifoErr",
0104              be32_to_cpu(cmd_rsp.fifoerr));
0105 
0106     len += scnprintf(buf + len, sizeof(buf) - len,
0107              "%20s : %10u\n", "Filtered",
0108              be32_to_cpu(cmd_rsp.filtered));
0109 
0110     len += scnprintf(buf + len, sizeof(buf) - len,
0111              "%20s : %10u\n", "TimerExp",
0112              be32_to_cpu(cmd_rsp.timer_exp));
0113 
0114     len += scnprintf(buf + len, sizeof(buf) - len,
0115              "%20s : %10u\n", "ShortRetries",
0116              be32_to_cpu(cmd_rsp.shortretries));
0117 
0118     len += scnprintf(buf + len, sizeof(buf) - len,
0119              "%20s : %10u\n", "LongRetries",
0120              be32_to_cpu(cmd_rsp.longretries));
0121 
0122     len += scnprintf(buf + len, sizeof(buf) - len,
0123              "%20s : %10u\n", "QueueNull",
0124              be32_to_cpu(cmd_rsp.qnull));
0125 
0126     len += scnprintf(buf + len, sizeof(buf) - len,
0127              "%20s : %10u\n", "EncapFail",
0128              be32_to_cpu(cmd_rsp.encap_fail));
0129 
0130     len += scnprintf(buf + len, sizeof(buf) - len,
0131              "%20s : %10u\n", "NoBuf",
0132              be32_to_cpu(cmd_rsp.nobuf));
0133 
0134     if (len > sizeof(buf))
0135         len = sizeof(buf);
0136 
0137     return simple_read_from_buffer(user_buf, count, ppos, buf, len);
0138 }
0139 
0140 static const struct file_operations fops_tgt_tx_stats = {
0141     .read = read_file_tgt_tx_stats,
0142     .open = simple_open,
0143     .owner = THIS_MODULE,
0144     .llseek = default_llseek,
0145 };
0146 
0147 static ssize_t read_file_tgt_rx_stats(struct file *file, char __user *user_buf,
0148                       size_t count, loff_t *ppos)
0149 {
0150     struct ath9k_htc_priv *priv = file->private_data;
0151     struct ath9k_htc_target_rx_stats cmd_rsp;
0152     char buf[512];
0153     unsigned int len = 0;
0154     int ret = 0;
0155 
0156     memset(&cmd_rsp, 0, sizeof(cmd_rsp));
0157 
0158     ath9k_htc_ps_wakeup(priv);
0159 
0160     WMI_CMD(WMI_RX_STATS_CMDID);
0161     if (ret) {
0162         ath9k_htc_ps_restore(priv);
0163         return -EINVAL;
0164     }
0165 
0166     ath9k_htc_ps_restore(priv);
0167 
0168     len += scnprintf(buf + len, sizeof(buf) - len,
0169              "%20s : %10u\n", "NoBuf",
0170              be32_to_cpu(cmd_rsp.nobuf));
0171 
0172     len += scnprintf(buf + len, sizeof(buf) - len,
0173              "%20s : %10u\n", "HostSend",
0174              be32_to_cpu(cmd_rsp.host_send));
0175 
0176     len += scnprintf(buf + len, sizeof(buf) - len,
0177              "%20s : %10u\n", "HostDone",
0178              be32_to_cpu(cmd_rsp.host_done));
0179 
0180     if (len > sizeof(buf))
0181         len = sizeof(buf);
0182 
0183     return simple_read_from_buffer(user_buf, count, ppos, buf, len);
0184 }
0185 
0186 static const struct file_operations fops_tgt_rx_stats = {
0187     .read = read_file_tgt_rx_stats,
0188     .open = simple_open,
0189     .owner = THIS_MODULE,
0190     .llseek = default_llseek,
0191 };
0192 
0193 static ssize_t read_file_xmit(struct file *file, char __user *user_buf,
0194                   size_t count, loff_t *ppos)
0195 {
0196     struct ath9k_htc_priv *priv = file->private_data;
0197     char buf[512];
0198     unsigned int len = 0;
0199 
0200     len += scnprintf(buf + len, sizeof(buf) - len,
0201              "%20s : %10u\n", "Buffers queued",
0202              priv->debug.tx_stats.buf_queued);
0203     len += scnprintf(buf + len, sizeof(buf) - len,
0204              "%20s : %10u\n", "Buffers completed",
0205              priv->debug.tx_stats.buf_completed);
0206     len += scnprintf(buf + len, sizeof(buf) - len,
0207              "%20s : %10u\n", "SKBs queued",
0208              priv->debug.tx_stats.skb_queued);
0209     len += scnprintf(buf + len, sizeof(buf) - len,
0210              "%20s : %10u\n", "SKBs success",
0211              priv->debug.tx_stats.skb_success);
0212     len += scnprintf(buf + len, sizeof(buf) - len,
0213              "%20s : %10u\n", "SKBs failed",
0214              priv->debug.tx_stats.skb_failed);
0215     len += scnprintf(buf + len, sizeof(buf) - len,
0216              "%20s : %10u\n", "CAB queued",
0217              priv->debug.tx_stats.cab_queued);
0218 
0219     len += scnprintf(buf + len, sizeof(buf) - len,
0220              "%20s : %10u\n", "BE queued",
0221              priv->debug.tx_stats.queue_stats[IEEE80211_AC_BE]);
0222     len += scnprintf(buf + len, sizeof(buf) - len,
0223              "%20s : %10u\n", "BK queued",
0224              priv->debug.tx_stats.queue_stats[IEEE80211_AC_BK]);
0225     len += scnprintf(buf + len, sizeof(buf) - len,
0226              "%20s : %10u\n", "VI queued",
0227              priv->debug.tx_stats.queue_stats[IEEE80211_AC_VI]);
0228     len += scnprintf(buf + len, sizeof(buf) - len,
0229              "%20s : %10u\n", "VO queued",
0230              priv->debug.tx_stats.queue_stats[IEEE80211_AC_VO]);
0231 
0232     if (len > sizeof(buf))
0233         len = sizeof(buf);
0234 
0235     return simple_read_from_buffer(user_buf, count, ppos, buf, len);
0236 }
0237 
0238 static const struct file_operations fops_xmit = {
0239     .read = read_file_xmit,
0240     .open = simple_open,
0241     .owner = THIS_MODULE,
0242     .llseek = default_llseek,
0243 };
0244 
0245 void ath9k_htc_err_stat_rx(struct ath9k_htc_priv *priv,
0246                  struct ath_rx_status *rs)
0247 {
0248     ath9k_cmn_debug_stat_rx(&priv->debug.rx_stats, rs);
0249 }
0250 
0251 static ssize_t read_file_skb_rx(struct file *file, char __user *user_buf,
0252                   size_t count, loff_t *ppos)
0253 {
0254     struct ath9k_htc_priv *priv = file->private_data;
0255     char *buf;
0256     unsigned int len = 0, size = 1500;
0257     ssize_t retval = 0;
0258 
0259     buf = kzalloc(size, GFP_KERNEL);
0260     if (buf == NULL)
0261         return -ENOMEM;
0262 
0263     len += scnprintf(buf + len, size - len,
0264              "%20s : %10u\n", "SKBs allocated",
0265              priv->debug.skbrx_stats.skb_allocated);
0266     len += scnprintf(buf + len, size - len,
0267              "%20s : %10u\n", "SKBs completed",
0268              priv->debug.skbrx_stats.skb_completed);
0269     len += scnprintf(buf + len, size - len,
0270              "%20s : %10u\n", "SKBs Dropped",
0271              priv->debug.skbrx_stats.skb_dropped);
0272 
0273     if (len > size)
0274         len = size;
0275 
0276     retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
0277     kfree(buf);
0278 
0279     return retval;
0280 }
0281 
0282 static const struct file_operations fops_skb_rx = {
0283     .read = read_file_skb_rx,
0284     .open = simple_open,
0285     .owner = THIS_MODULE,
0286     .llseek = default_llseek,
0287 };
0288 
0289 static ssize_t read_file_slot(struct file *file, char __user *user_buf,
0290                   size_t count, loff_t *ppos)
0291 {
0292     struct ath9k_htc_priv *priv = file->private_data;
0293     char buf[512];
0294     unsigned int len;
0295 
0296     spin_lock_bh(&priv->tx.tx_lock);
0297     len = scnprintf(buf, sizeof(buf),
0298             "TX slot bitmap : %*pb\n"
0299             "Used slots     : %d\n",
0300             MAX_TX_BUF_NUM, priv->tx.tx_slot,
0301             bitmap_weight(priv->tx.tx_slot, MAX_TX_BUF_NUM));
0302     spin_unlock_bh(&priv->tx.tx_lock);
0303     return simple_read_from_buffer(user_buf, count, ppos, buf, len);
0304 }
0305 
0306 static const struct file_operations fops_slot = {
0307     .read = read_file_slot,
0308     .open = simple_open,
0309     .owner = THIS_MODULE,
0310     .llseek = default_llseek,
0311 };
0312 
0313 static ssize_t read_file_queue(struct file *file, char __user *user_buf,
0314                    size_t count, loff_t *ppos)
0315 {
0316     struct ath9k_htc_priv *priv = file->private_data;
0317     char buf[512];
0318     unsigned int len = 0;
0319 
0320     len += scnprintf(buf + len, sizeof(buf) - len, "%20s : %10u\n",
0321              "Mgmt endpoint", skb_queue_len(&priv->tx.mgmt_ep_queue));
0322 
0323     len += scnprintf(buf + len, sizeof(buf) - len, "%20s : %10u\n",
0324              "Cab endpoint", skb_queue_len(&priv->tx.cab_ep_queue));
0325 
0326     len += scnprintf(buf + len, sizeof(buf) - len, "%20s : %10u\n",
0327              "Data BE endpoint", skb_queue_len(&priv->tx.data_be_queue));
0328 
0329     len += scnprintf(buf + len, sizeof(buf) - len, "%20s : %10u\n",
0330              "Data BK endpoint", skb_queue_len(&priv->tx.data_bk_queue));
0331 
0332     len += scnprintf(buf + len, sizeof(buf) - len, "%20s : %10u\n",
0333              "Data VI endpoint", skb_queue_len(&priv->tx.data_vi_queue));
0334 
0335     len += scnprintf(buf + len, sizeof(buf) - len, "%20s : %10u\n",
0336              "Data VO endpoint", skb_queue_len(&priv->tx.data_vo_queue));
0337 
0338     len += scnprintf(buf + len, sizeof(buf) - len, "%20s : %10u\n",
0339              "Failed queue", skb_queue_len(&priv->tx.tx_failed));
0340 
0341     spin_lock_bh(&priv->tx.tx_lock);
0342     len += scnprintf(buf + len, sizeof(buf) - len, "%20s : %10u\n",
0343              "Queued count", priv->tx.queued_cnt);
0344     spin_unlock_bh(&priv->tx.tx_lock);
0345 
0346     if (len > sizeof(buf))
0347         len = sizeof(buf);
0348 
0349     return simple_read_from_buffer(user_buf, count, ppos, buf, len);
0350 
0351 }
0352 
0353 static const struct file_operations fops_queue = {
0354     .read = read_file_queue,
0355     .open = simple_open,
0356     .owner = THIS_MODULE,
0357     .llseek = default_llseek,
0358 };
0359 
0360 static ssize_t read_file_debug(struct file *file, char __user *user_buf,
0361                    size_t count, loff_t *ppos)
0362 {
0363     struct ath9k_htc_priv *priv = file->private_data;
0364     struct ath_common *common = ath9k_hw_common(priv->ah);
0365     char buf[32];
0366     unsigned int len;
0367 
0368     len = sprintf(buf, "0x%08x\n", common->debug_mask);
0369     return simple_read_from_buffer(user_buf, count, ppos, buf, len);
0370 }
0371 
0372 static ssize_t write_file_debug(struct file *file, const char __user *user_buf,
0373                 size_t count, loff_t *ppos)
0374 {
0375     struct ath9k_htc_priv *priv = file->private_data;
0376     struct ath_common *common = ath9k_hw_common(priv->ah);
0377     unsigned long mask;
0378     char buf[32];
0379     ssize_t len;
0380 
0381     len = min(count, sizeof(buf) - 1);
0382     if (copy_from_user(buf, user_buf, len))
0383         return -EFAULT;
0384 
0385     buf[len] = '\0';
0386     if (kstrtoul(buf, 0, &mask))
0387         return -EINVAL;
0388 
0389     common->debug_mask = mask;
0390     return count;
0391 }
0392 
0393 static const struct file_operations fops_debug = {
0394     .read = read_file_debug,
0395     .write = write_file_debug,
0396     .open = simple_open,
0397     .owner = THIS_MODULE,
0398     .llseek = default_llseek,
0399 };
0400 
0401 /* Ethtool support for get-stats */
0402 #define AMKSTR(nm) #nm "_BE", #nm "_BK", #nm "_VI", #nm "_VO"
0403 static const char ath9k_htc_gstrings_stats[][ETH_GSTRING_LEN] = {
0404     "tx_pkts_nic",
0405     "tx_bytes_nic",
0406     "rx_pkts_nic",
0407     "rx_bytes_nic",
0408 
0409     AMKSTR(d_tx_pkts),
0410 
0411     "d_rx_crc_err",
0412     "d_rx_decrypt_crc_err",
0413     "d_rx_phy_err",
0414     "d_rx_mic_err",
0415     "d_rx_pre_delim_crc_err",
0416     "d_rx_post_delim_crc_err",
0417     "d_rx_decrypt_busy_err",
0418 
0419     "d_rx_phyerr_radar",
0420     "d_rx_phyerr_ofdm_timing",
0421     "d_rx_phyerr_cck_timing",
0422 
0423 };
0424 #define ATH9K_HTC_SSTATS_LEN ARRAY_SIZE(ath9k_htc_gstrings_stats)
0425 
0426 void ath9k_htc_get_et_strings(struct ieee80211_hw *hw,
0427                   struct ieee80211_vif *vif,
0428                   u32 sset, u8 *data)
0429 {
0430     if (sset == ETH_SS_STATS)
0431         memcpy(data, *ath9k_htc_gstrings_stats,
0432                sizeof(ath9k_htc_gstrings_stats));
0433 }
0434 
0435 int ath9k_htc_get_et_sset_count(struct ieee80211_hw *hw,
0436                 struct ieee80211_vif *vif, int sset)
0437 {
0438     if (sset == ETH_SS_STATS)
0439         return ATH9K_HTC_SSTATS_LEN;
0440     return 0;
0441 }
0442 
0443 #define STXBASE priv->debug.tx_stats
0444 #define SRXBASE priv->debug.rx_stats
0445 #define SKBTXBASE priv->debug.tx_stats
0446 #define SKBRXBASE priv->debug.skbrx_stats
0447 #define ASTXQ(a)                    \
0448     data[i++] = STXBASE.a[IEEE80211_AC_BE];     \
0449     data[i++] = STXBASE.a[IEEE80211_AC_BK];     \
0450     data[i++] = STXBASE.a[IEEE80211_AC_VI];     \
0451     data[i++] = STXBASE.a[IEEE80211_AC_VO]
0452 
0453 void ath9k_htc_get_et_stats(struct ieee80211_hw *hw,
0454                 struct ieee80211_vif *vif,
0455                 struct ethtool_stats *stats, u64 *data)
0456 {
0457     struct ath9k_htc_priv *priv = hw->priv;
0458     int i = 0;
0459 
0460     data[i++] = SKBTXBASE.skb_success;
0461     data[i++] = SKBTXBASE.skb_success_bytes;
0462     data[i++] = SKBRXBASE.skb_completed;
0463     data[i++] = SKBRXBASE.skb_completed_bytes;
0464 
0465     ASTXQ(queue_stats);
0466 
0467     data[i++] = SRXBASE.crc_err;
0468     data[i++] = SRXBASE.decrypt_crc_err;
0469     data[i++] = SRXBASE.phy_err;
0470     data[i++] = SRXBASE.mic_err;
0471     data[i++] = SRXBASE.pre_delim_crc_err;
0472     data[i++] = SRXBASE.post_delim_crc_err;
0473     data[i++] = SRXBASE.decrypt_busy_err;
0474 
0475     data[i++] = SRXBASE.phy_err_stats[ATH9K_PHYERR_RADAR];
0476     data[i++] = SRXBASE.phy_err_stats[ATH9K_PHYERR_OFDM_TIMING];
0477     data[i++] = SRXBASE.phy_err_stats[ATH9K_PHYERR_CCK_TIMING];
0478 
0479     WARN_ON(i != ATH9K_HTC_SSTATS_LEN);
0480 }
0481 
0482 void ath9k_htc_deinit_debug(struct ath9k_htc_priv *priv)
0483 {
0484     ath9k_cmn_spectral_deinit_debug(&priv->spec_priv);
0485 }
0486 
0487 int ath9k_htc_init_debug(struct ath_hw *ah)
0488 {
0489     struct ath_common *common = ath9k_hw_common(ah);
0490     struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv;
0491 
0492     priv->debug.debugfs_phy = debugfs_create_dir(KBUILD_MODNAME,
0493                          priv->hw->wiphy->debugfsdir);
0494     if (!priv->debug.debugfs_phy)
0495         return -ENOMEM;
0496 
0497     ath9k_cmn_spectral_init_debug(&priv->spec_priv, priv->debug.debugfs_phy);
0498 
0499     debugfs_create_file("tgt_int_stats", 0400, priv->debug.debugfs_phy,
0500                 priv, &fops_tgt_int_stats);
0501     debugfs_create_file("tgt_tx_stats", 0400, priv->debug.debugfs_phy,
0502                 priv, &fops_tgt_tx_stats);
0503     debugfs_create_file("tgt_rx_stats", 0400, priv->debug.debugfs_phy,
0504                 priv, &fops_tgt_rx_stats);
0505     debugfs_create_file("xmit", 0400, priv->debug.debugfs_phy,
0506                 priv, &fops_xmit);
0507     debugfs_create_file("skb_rx", 0400, priv->debug.debugfs_phy,
0508                 priv, &fops_skb_rx);
0509 
0510     ath9k_cmn_debug_recv(priv->debug.debugfs_phy, &priv->debug.rx_stats);
0511     ath9k_cmn_debug_phy_err(priv->debug.debugfs_phy, &priv->debug.rx_stats);
0512 
0513     debugfs_create_file("slot", 0400, priv->debug.debugfs_phy,
0514                 priv, &fops_slot);
0515     debugfs_create_file("queue", 0400, priv->debug.debugfs_phy,
0516                 priv, &fops_queue);
0517     debugfs_create_file("debug", 0600, priv->debug.debugfs_phy,
0518                 priv, &fops_debug);
0519 
0520     ath9k_cmn_debug_base_eeprom(priv->debug.debugfs_phy, priv->ah);
0521     ath9k_cmn_debug_modal_eeprom(priv->debug.debugfs_phy, priv->ah);
0522 
0523     return 0;
0524 }