Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  debug.c   Sprache: C

 
/*
 * Atheros CARL9170 driver
 *
 * debug(fs) probing
 *
 * Copyright 2008, Johannes Berg <johannes@sipsolutions.net>
 * Copyright 2009, 2010, Christian Lamparter <chunkeey@googlemail.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; see the file COPYING.  If not, see
 * http://www.gnu.org/licenses/.
 *
 * This file incorporates work covered by the following copyright and
 * permission notice:
 *    Copyright (c) 2008-2009 Atheros Communications, Inc.
 *
 *    Permission to use, copy, modify, and/or distribute this software for any
 *    purpose with or without fee is hereby granted, provided that the above
 *    copyright notice and this permission notice appear in all copies.
 *
 *    THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 *    WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 *    MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 *    ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 *    WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 *    ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 *    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */


#include <linux/slab.h>
#include <linux/module.h>
#include <linux/seq_file.h>
#include <linux/vmalloc.h>
#include "carl9170.h"
#include "cmd.h"

#define ADD(buf, off, max, fmt, args...)    \
 off += scnprintf(&buf[off], max - off, fmt, ##args)


struct carl9170_debugfs_fops {
 unsigned int read_bufsize;
 umode_t attr;
 char *(*read)(struct ar9170 *ar, char *buf, size_t bufsize,
        ssize_t *len);
 ssize_t (*write)(struct ar9170 *aru, const char *buf, size_t size);

 enum carl9170_device_state req_dev_state;
};

static ssize_t carl9170_debugfs_read(struct file *file, char __user *userbuf,
         size_t count, loff_t *ppos)
{
 const struct carl9170_debugfs_fops *dfops;
 struct ar9170 *ar;
 char *buf = NULL, *res_buf = NULL;
 ssize_t ret = 0;
 int err = 0;

 if (!count)
  return 0;

 ar = file->private_data;

 if (!ar)
  return -ENODEV;
 dfops = debugfs_get_aux(file);

 if (!dfops->read)
  return -ENOSYS;

 if (dfops->read_bufsize) {
  buf = vmalloc(dfops->read_bufsize);
  if (!buf)
   return -ENOMEM;
 }

 mutex_lock(&ar->mutex);
 if (!CHK_DEV_STATE(ar, dfops->req_dev_state)) {
  err = -ENODEV;
  res_buf = buf;
  goto out_free;
 }

 res_buf = dfops->read(ar, buf, dfops->read_bufsize, &ret);

 if (ret > 0)
  err = simple_read_from_buffer(userbuf, count, ppos,
           res_buf, ret);
 else
  err = ret;

 WARN_ON_ONCE(dfops->read_bufsize && (res_buf != buf));

out_free:
 vfree(res_buf);
 mutex_unlock(&ar->mutex);
 return err;
}

static ssize_t carl9170_debugfs_write(struct file *file,
 const char __user *userbuf, size_t count, loff_t *ppos)
{
 const struct carl9170_debugfs_fops *dfops;
 struct ar9170 *ar;
 char *buf = NULL;
 int err = 0;

 if (!count)
  return 0;

 if (count > PAGE_SIZE)
  return -E2BIG;

 ar = file->private_data;

 if (!ar)
  return -ENODEV;
 dfops = debugfs_get_aux(file);

 if (!dfops->write)
  return -ENOSYS;

 buf = vmalloc(count);
 if (!buf)
  return -ENOMEM;

 if (copy_from_user(buf, userbuf, count)) {
  err = -EFAULT;
  goto out_free;
 }

 if (mutex_trylock(&ar->mutex) == 0) {
  err = -EAGAIN;
  goto out_free;
 }

 if (!CHK_DEV_STATE(ar, dfops->req_dev_state)) {
  err = -ENODEV;
  goto out_unlock;
 }

 err = dfops->write(ar, buf, count);
 if (err)
  goto out_unlock;

out_unlock:
 mutex_unlock(&ar->mutex);

out_free:
 vfree(buf);
 return err;
}

static struct debugfs_short_fops debugfs_fops = {
 .read = carl9170_debugfs_read,
 .write = carl9170_debugfs_write,
};

#define __DEBUGFS_DECLARE_FILE(name, _read, _write, _read_bufsize, \
          _attr, _dstate)    \
static const struct carl9170_debugfs_fops carl_debugfs_##name ##_ops = {\
 .read_bufsize = _read_bufsize,     \
 .read = _read,       \
 .write = _write,      \
 .attr = _attr,       \
 .req_dev_state = _dstate,     \
}

#define DEBUGFS_DECLARE_FILE(name, _read, _write, _read_bufsize, _attr) \
 __DEBUGFS_DECLARE_FILE(name, _read, _write, _read_bufsize, \
          _attr, CARL9170_STARTED)   \

#define DEBUGFS_DECLARE_RO_FILE(name, _read_bufsize)   \
 DEBUGFS_DECLARE_FILE(name, carl9170_debugfs_##name ##_read, \
        NULL, _read_bufsize, 0400)

#define DEBUGFS_DECLARE_WO_FILE(name)     \
 DEBUGFS_DECLARE_FILE(name, NULL, carl9170_debugfs_##name ##_write,\
        0, 0200)

#define DEBUGFS_DECLARE_RW_FILE(name, _read_bufsize)   \
 DEBUGFS_DECLARE_FILE(name, carl9170_debugfs_##name ##_read, \
        carl9170_debugfs_##name ##_write,  \
        _read_bufsize, 0600)

#define __DEBUGFS_DECLARE_RW_FILE(name, _read_bufsize, _dstate)  \
 __DEBUGFS_DECLARE_FILE(name, carl9170_debugfs_##name ##_read, \
        carl9170_debugfs_##name ##_write,  \
        _read_bufsize, 0600, _dstate)

#define DEBUGFS_READONLY_FILE(name, _read_bufsize, fmt, value...) \
static char *carl9170_debugfs_ ##name ## _read(struct ar9170 *ar, \
          char *buf, size_t buf_size,\
          ssize_t *len)  \
{         \
 ADD(buf, *len, buf_size, fmt "\n"##value);   \
 return buf;       \
}         \
DEBUGFS_DECLARE_RO_FILE(name, _read_bufsize)

static char *carl9170_debugfs_mem_usage_read(struct ar9170 *ar, char *buf,
          size_t bufsize, ssize_t *len)
{
 spin_lock_bh(&ar->mem_lock);

 ADD(buf, *len, bufsize, "jar: [%*pb]\n",
     ar->fw.mem_blocks, ar->mem_bitmap);

 ADD(buf, *len, bufsize, "cookies: used:%3d / total:%3d, allocs:%d\n",
     bitmap_weight(ar->mem_bitmap, ar->fw.mem_blocks),
     ar->fw.mem_blocks, atomic_read(&ar->mem_allocs));

 ADD(buf, *len, bufsize, "memory: free:%3d (%3d KiB) / total:%3d KiB)\n",
     atomic_read(&ar->mem_free_blocks),
     (atomic_read(&ar->mem_free_blocks) * ar->fw.mem_block_size) / 1024,
     (ar->fw.mem_blocks * ar->fw.mem_block_size) / 1024);

 spin_unlock_bh(&ar->mem_lock);

 return buf;
}
DEBUGFS_DECLARE_RO_FILE(mem_usage, 512);

static char *carl9170_debugfs_qos_stat_read(struct ar9170 *ar, char *buf,
         size_t bufsize, ssize_t *len)
{
 ADD(buf, *len, bufsize, "%s QoS AC\n", modparam_noht ? "Hardware" :
     "Software");

 ADD(buf, *len, bufsize, "[ VO VI "
     " BE BK ]\n");

 spin_lock_bh(&ar->tx_stats_lock);
 ADD(buf, *len, bufsize, "[length/limit length/limit "
     "length/limit length/limit ]\n"
    "[ %3d/%3d %3d/%3d "
     " %3d/%3d %3d/%3d ]\n\n",
     ar->tx_stats[0].len, ar->tx_stats[0].limit,
     ar->tx_stats[1].len, ar->tx_stats[1].limit,
     ar->tx_stats[2].len, ar->tx_stats[2].limit,
     ar->tx_stats[3].len, ar->tx_stats[3].limit);

 ADD(buf, *len, bufsize, "[ total total "
     " total total ]\n"
    "[%10d %10d %10d %10d ]\n\n",
     ar->tx_stats[0].count, ar->tx_stats[1].count,
     ar->tx_stats[2].count, ar->tx_stats[3].count);

 spin_unlock_bh(&ar->tx_stats_lock);

 ADD(buf, *len, bufsize, "[ pend/waittx pend/waittx "
     " pend/waittx pend/waittx]\n"
    "[ %3d/%3d %3d/%3d "
     " %3d/%3d %3d/%3d ]\n\n",
     skb_queue_len(&ar->tx_pending[0]),
     skb_queue_len(&ar->tx_status[0]),
     skb_queue_len(&ar->tx_pending[1]),
     skb_queue_len(&ar->tx_status[1]),
     skb_queue_len(&ar->tx_pending[2]),
     skb_queue_len(&ar->tx_status[2]),
     skb_queue_len(&ar->tx_pending[3]),
     skb_queue_len(&ar->tx_status[3]));

 return buf;
}
DEBUGFS_DECLARE_RO_FILE(qos_stat, 512);

static void carl9170_debugfs_format_frame(struct ar9170 *ar,
 struct sk_buff *skb, const char *prefix, char *buf,
 ssize_t *off, ssize_t bufsize)
{
 struct _carl9170_tx_superframe *txc = (void *) skb->data;
 struct ieee80211_tx_info *txinfo = IEEE80211_SKB_CB(skb);
 struct carl9170_tx_info *arinfo = (void *) txinfo->rate_driver_data;
 struct ieee80211_hdr *hdr = (void *) txc->frame_data;

 ADD(buf, *off, bufsize, "%s %p, c:%2x, DA:%pM, sq:%4d, mc:%.4x, "
     "pc:%.8x, to:%d ms\n", prefix, skb, txc->s.cookie,
     ieee80211_get_DA(hdr), get_seq_h(hdr),
     le16_to_cpu(txc->f.mac_control), le32_to_cpu(txc->f.phy_control),
     jiffies_to_msecs(jiffies - arinfo->timeout));
}


static char *carl9170_debugfs_ampdu_state_read(struct ar9170 *ar, char *buf,
            size_t bufsize, ssize_t *len)
{
 struct carl9170_sta_tid *iter;
 struct sk_buff *skb;
 int cnt = 0, fc;
 int offset;

 rcu_read_lock();
 list_for_each_entry_rcu(iter, &ar->tx_ampdu_list, list) {

  spin_lock_bh(&iter->lock);
  ADD(buf, *len, bufsize, "Entry: #%2d TID:%1d, BSN:%4d, "
      "SNX:%4d, HSN:%4d, BAW:%2d, state:%1d, toggles:%d\n",
      cnt, iter->tid, iter->bsn, iter->snx, iter->hsn,
      iter->max, iter->state, iter->counter);

  ADD(buf, *len, bufsize, "\tWindow: [%*pb,W]\n",
      CARL9170_BAW_BITS, iter->bitmap);

#define BM_STR_OFF(offset)     \
 ((CARL9170_BAW_BITS - (offset) - 1) / 4 +  \
  (CARL9170_BAW_BITS - (offset) - 1) / 32 + 1)

  offset = BM_STR_OFF(0);
  ADD(buf, *len, bufsize, "\tBase Seq: %*s\n", offset, "T");

  offset = BM_STR_OFF(SEQ_DIFF(iter->snx, iter->bsn));
  ADD(buf, *len, bufsize, "\tNext Seq: %*s\n", offset, "W");

  offset = BM_STR_OFF(((int)iter->hsn - (int)iter->bsn) %
         CARL9170_BAW_BITS);
  ADD(buf, *len, bufsize, "\tLast Seq: %*s\n", offset, "N");

  ADD(buf, *len, bufsize, "\tPre-Aggregation reorder buffer: "
      " currently queued:%d\n", skb_queue_len(&iter->queue));

  fc = 0;
  skb_queue_walk(&iter->queue, skb) {
   char prefix[32];

   snprintf(prefix, sizeof(prefix), "\t\t%3d :", fc);
   carl9170_debugfs_format_frame(ar, skb, prefix, buf,
            len, bufsize);

   fc++;
  }
  spin_unlock_bh(&iter->lock);
  cnt++;
 }
 rcu_read_unlock();

 return buf;
}
DEBUGFS_DECLARE_RO_FILE(ampdu_state, 8000);

static void carl9170_debugfs_queue_dump(struct ar9170 *ar, char *buf,
 ssize_t *len, size_t bufsize, struct sk_buff_head *queue)
{
 struct sk_buff *skb;
 char prefix[16];
 int fc = 0;

 spin_lock_bh(&queue->lock);
 skb_queue_walk(queue, skb) {
  snprintf(prefix, sizeof(prefix), "%3d :", fc);
  carl9170_debugfs_format_frame(ar, skb, prefix, buf,
           len, bufsize);
  fc++;
 }
 spin_unlock_bh(&queue->lock);
}

#define DEBUGFS_QUEUE_DUMP(q, qi)     \
static char *carl9170_debugfs_####_##qi ##_read(struct ar9170 *ar, \
 char *buf, size_t bufsize, ssize_t *len)   \
{         \
 carl9170_debugfs_queue_dump(ar, buf, len, bufsize, &ar->q[qi]); \
 return buf;       \
}         \
DEBUGFS_DECLARE_RO_FILE(q##_##qi, 8000);

static char *carl9170_debugfs_sta_psm_read(struct ar9170 *ar, char *buf,
        size_t bufsize, ssize_t *len)
{
 ADD(buf, *len, bufsize, "psm state: %s\n", (ar->ps.off_override ?
     "FORCE CAM" : (ar->ps.state ? "PSM" : "CAM")));

 ADD(buf, *len, bufsize, "sleep duration: %d ms.\n", ar->ps.sleep_ms);
 ADD(buf, *len, bufsize, "last power-state transition: %d ms ago.\n",
     jiffies_to_msecs(jiffies - ar->ps.last_action));
 ADD(buf, *len, bufsize, "last CAM->PSM transition: %d ms ago.\n",
     jiffies_to_msecs(jiffies - ar->ps.last_slept));

 return buf;
}
DEBUGFS_DECLARE_RO_FILE(sta_psm, 160);

static char *carl9170_debugfs_tx_stuck_read(struct ar9170 *ar, char *buf,
         size_t bufsize, ssize_t *len)
{
 int i;

 for (i = 0; i < ar->hw->queues; i++) {
  ADD(buf, *len, bufsize, "TX queue [%d]: %10d max:%10d ms.\n",
      i, ieee80211_queue_stopped(ar->hw, i) ?
      jiffies_to_msecs(jiffies - ar->queue_stop_timeout[i]) : 0,
      jiffies_to_msecs(ar->max_queue_stop_timeout[i]));

  ar->max_queue_stop_timeout[i] = 0;
 }

 return buf;
}
DEBUGFS_DECLARE_RO_FILE(tx_stuck, 180);

static char *carl9170_debugfs_phy_noise_read(struct ar9170 *ar, char *buf,
          size_t bufsize, ssize_t *len)
{
 int err;

 err = carl9170_get_noisefloor(ar);
 if (err) {
  *len = err;
  return buf;
 }

 ADD(buf, *len, bufsize, "Chain 0: %10d dBm, ext. chan.:%10d dBm\n",
     ar->noise[0], ar->noise[2]);
 ADD(buf, *len, bufsize, "Chain 2: %10d dBm, ext. chan.:%10d dBm\n",
     ar->noise[1], ar->noise[3]);

 return buf;
}
DEBUGFS_DECLARE_RO_FILE(phy_noise, 180);

static char *carl9170_debugfs_vif_dump_read(struct ar9170 *ar, char *buf,
         size_t bufsize, ssize_t *len)
{
 struct carl9170_vif_info *iter;
 int i = 0;

 ADD(buf, *len, bufsize, "registered VIFs:%d \\ %d\n",
     ar->vifs, ar->fw.vif_num);

 ADD(buf, *len, bufsize, "VIF bitmap: [%*pb]\n",
     ar->fw.vif_num, &ar->vif_bitmap);

 rcu_read_lock();
 list_for_each_entry_rcu(iter, &ar->vif_list, list) {
  struct ieee80211_vif *vif = carl9170_get_vif(iter);
  ADD(buf, *len, bufsize, "\t%d = [%s VIF, id:%d, type:%x "
      " mac:%pM %s]\n", i, (carl9170_get_main_vif(ar) == vif ?
      "Master" : " Slave"), iter->id, vif->type, vif->addr,
      iter->enable_beacon ? "beaconing " : "");
  i++;
 }
 rcu_read_unlock();

 return buf;
}
DEBUGFS_DECLARE_RO_FILE(vif_dump, 8000);

#define UPDATE_COUNTER(ar, name) ({    \
 u32 __tmp[ARRAY_SIZE(name##_regs)];    \
 unsigned int __i, __err = -ENODEV;    \
         \
 for (__i = 0; __i < ARRAY_SIZE(name##_regs); __i++) {  \
  __tmp[__i] = name##_regs[__i].reg;   \
  ar->debug.stats.name##_counter[__i] = 0;  \
 }        \
         \
 if (IS_STARTED(ar))      \
  __err = carl9170_read_mreg(ar, ARRAY_SIZE(name##_regs), \
   __tmp, ar->debug.stats.name##_counter);  \
 (__err); })

#define TALLY_SUM_UP(ar, name) do {     \
 unsigned int __i;      \
         \
 for (__i = 0; __i < ARRAY_SIZE(name##_regs); __i++) {  \
  ar->debug.stats.name##_sum[__i] +=   \
   ar->debug.stats.name##_counter[__i];  \
 }        \
while (0)

#define DEBUGFS_HW_TALLY_FILE(name, f)     \
static char *carl9170_debugfs_##name ## _read(struct ar9170 *ar, \
  char *dum, size_t bufsize, ssize_t *ret)   \
{         \
 char *buf;       \
 int i, max_len, err;      \
         \
 max_len = ARRAY_SIZE(name##_regs) * 80;    \
 buf = vmalloc(max_len);      \
 if (!buf)       \
  return NULL;      \
         \
 err = UPDATE_COUNTER(ar, name);     \
 if (err) {       \
  *ret = err;      \
  return buf;      \
 }        \
         \
 TALLY_SUM_UP(ar, name);      \
         \
 for (i = 0; i < ARRAY_SIZE(name##_regs); i++) {   \
  ADD(buf, *ret, max_len, "%22s = %" f "[+%" f "]\n", \
      name##_regs[i].nreg, ar->debug.stats.name ##_sum[i],\
      ar->debug.stats.name ##_counter[i]);  \
 }        \
         \
 return buf;       \
}         \
DEBUGFS_DECLARE_RO_FILE(name, 0);

#define DEBUGFS_HW_REG_FILE(name, f)     \
static char *carl9170_debugfs_##name ## _read(struct ar9170 *ar, \
 char *dum, size_t bufsize, ssize_t *ret)   \
{         \
 char *buf;       \
 int i, max_len, err;      \
         \
 max_len = ARRAY_SIZE(name##_regs) * 80;    \
 buf = vmalloc(max_len);      \
 if (!buf)       \
  return NULL;      \
         \
 err = UPDATE_COUNTER(ar, name);     \
 if (err) {       \
  *ret = err;      \
  return buf;      \
 }        \
         \
 for (i = 0; i < ARRAY_SIZE(name##_regs); i++) {   \
  ADD(buf, *ret, max_len, "%22s = %" f "\n",  \
      name##_regs[i].nreg,    \
      ar->debug.stats.name##_counter[i]);   \
 }        \
         \
 return buf;       \
}         \
DEBUGFS_DECLARE_RO_FILE(name, 0);

static ssize_t carl9170_debugfs_hw_ioread32_write(struct ar9170 *ar,
 const char *buf, size_t count)
{
 int err = 0, i, n = 0, max_len = 32, res;
 unsigned int reg, tmp;

 if (!count)
  return 0;

 if (count > max_len)
  return -E2BIG;

 res = sscanf(buf, "0x%X %d", ®, &n);
 if (res < 1) {
  err = -EINVAL;
  goto out;
 }

 if (res == 1)
  n = 1;

 if (n > 15) {
  err = -EMSGSIZE;
  goto out;
 }

 if ((reg >= 0x280000) || ((reg + (n << 2)) >= 0x280000)) {
  err = -EADDRNOTAVAIL;
  goto out;
 }

 if (reg & 3) {
  err = -EINVAL;
  goto out;
 }

 for (i = 0; i < n; i++) {
  err = carl9170_read_reg(ar, reg + (i << 2), &tmp);
  if (err)
   goto out;

  ar->debug.ring[ar->debug.ring_tail].reg = reg + (i << 2);
  ar->debug.ring[ar->debug.ring_tail].value = tmp;
  ar->debug.ring_tail++;
  ar->debug.ring_tail %= CARL9170_DEBUG_RING_SIZE;
 }

out:
 return err ? err : count;
}

static char *carl9170_debugfs_hw_ioread32_read(struct ar9170 *ar, char *buf,
            size_t bufsize, ssize_t *ret)
{
 int i = 0;

 while (ar->debug.ring_head != ar->debug.ring_tail) {
  ADD(buf, *ret, bufsize, "%.8x = %.8x\n",
      ar->debug.ring[ar->debug.ring_head].reg,
      ar->debug.ring[ar->debug.ring_head].value);

  ar->debug.ring_head++;
  ar->debug.ring_head %= CARL9170_DEBUG_RING_SIZE;

  if (i++ == 64)
   break;
 }
 ar->debug.ring_head = ar->debug.ring_tail;
 return buf;
}
DEBUGFS_DECLARE_RW_FILE(hw_ioread32, CARL9170_DEBUG_RING_SIZE * 40);

static ssize_t carl9170_debugfs_bug_write(struct ar9170 *ar, const char *buf,
       size_t count)
{
 int err;

 if (count < 1)
  return -EINVAL;

 switch (buf[0]) {
 case 'F':
  ar->needs_full_reset = true;
  break;

 case 'R':
  if (!IS_STARTED(ar)) {
   err = -EAGAIN;
   goto out;
  }

  ar->needs_full_reset = false;
  break;

 case 'M':
  err = carl9170_mac_reset(ar);
  if (err < 0)
   count = err;

  goto out;

 case 'P':
  err = carl9170_set_channel(ar, ar->hw->conf.chandef.chan,
   cfg80211_get_chandef_type(&ar->hw->conf.chandef));
  if (err < 0)
   count = err;

  goto out;

 default:
  return -EINVAL;
 }

 carl9170_restart(ar, CARL9170_RR_USER_REQUEST);

out:
 return count;
}

static char *carl9170_debugfs_bug_read(struct ar9170 *ar, char *buf,
           size_t bufsize, ssize_t *ret)
{
 ADD(buf, *ret, bufsize, "[P]hy reinit, [R]estart, [F]ull usb reset, "
     "[M]ac reset\n");
 ADD(buf, *ret, bufsize, "firmware restarts:%d, last reason:%d\n",
  ar->restart_counter, ar->last_reason);
 ADD(buf, *ret, bufsize, "phy reinit errors:%d (%d)\n",
  ar->total_chan_fail, ar->chan_fail);
 ADD(buf, *ret, bufsize, "reported firmware errors:%d\n",
  ar->fw.err_counter);
 ADD(buf, *ret, bufsize, "reported firmware BUGs:%d\n",
  ar->fw.bug_counter);
 ADD(buf, *ret, bufsize, "pending restart requests:%d\n",
  atomic_read(&ar->pending_restarts));
 return buf;
}
__DEBUGFS_DECLARE_RW_FILE(bug, 400, CARL9170_STOPPED);

static const char *const erp_modes[] = {
 [CARL9170_ERP_INVALID] = "INVALID",
 [CARL9170_ERP_AUTO] = "Automatic",
 [CARL9170_ERP_MAC80211] = "Set by MAC80211",
 [CARL9170_ERP_OFF] = "Force Off",
 [CARL9170_ERP_RTS] = "Force RTS",
 [CARL9170_ERP_CTS] = "Force CTS"
};

static char *carl9170_debugfs_erp_read(struct ar9170 *ar, char *buf,
           size_t bufsize, ssize_t *ret)
{
 ADD(buf, *ret, bufsize, "ERP Setting: (%d) -> %s\n", ar->erp_mode,
     erp_modes[ar->erp_mode]);
 return buf;
}

static ssize_t carl9170_debugfs_erp_write(struct ar9170 *ar, const char *buf,
       size_t count)
{
 int res, val;

 if (count < 1)
  return -EINVAL;

 res = sscanf(buf, "%d", &val);
 if (res != 1)
  return -EINVAL;

 if (!((val > CARL9170_ERP_INVALID) &&
       (val < __CARL9170_ERP_NUM)))
  return -EINVAL;

 ar->erp_mode = val;
 return count;
}

DEBUGFS_DECLARE_RW_FILE(erp, 80);

static ssize_t carl9170_debugfs_hw_iowrite32_write(struct ar9170 *ar,
 const char *buf, size_t count)
{
 int err = 0, max_len = 22, res;
 u32 reg, val;

 if (!count)
  return 0;

 if (count > max_len)
  return -E2BIG;

 res = sscanf(buf, "0x%X 0x%X", ®, &val);
 if (res != 2) {
  err = -EINVAL;
  goto out;
 }

 if (reg <= 0x100000 || reg >= 0x280000) {
  err = -EADDRNOTAVAIL;
  goto out;
 }

 if (reg & 3) {
  err = -EINVAL;
  goto out;
 }

 err = carl9170_write_reg(ar, reg, val);
 if (err)
  goto out;

out:
 return err ? err : count;
}
DEBUGFS_DECLARE_WO_FILE(hw_iowrite32);

DEBUGFS_HW_TALLY_FILE(hw_tx_tally, "u");
DEBUGFS_HW_TALLY_FILE(hw_rx_tally, "u");
DEBUGFS_HW_TALLY_FILE(hw_phy_errors, "u");
DEBUGFS_HW_REG_FILE(hw_wlan_queue, ".8x");
DEBUGFS_HW_REG_FILE(hw_pta_queue, ".8x");
DEBUGFS_HW_REG_FILE(hw_ampdu_info, ".8x");
DEBUGFS_QUEUE_DUMP(tx_status, 0);
DEBUGFS_QUEUE_DUMP(tx_status, 1);
DEBUGFS_QUEUE_DUMP(tx_status, 2);
DEBUGFS_QUEUE_DUMP(tx_status, 3);
DEBUGFS_QUEUE_DUMP(tx_pending, 0);
DEBUGFS_QUEUE_DUMP(tx_pending, 1);
DEBUGFS_QUEUE_DUMP(tx_pending, 2);
DEBUGFS_QUEUE_DUMP(tx_pending, 3);
DEBUGFS_READONLY_FILE(usb_tx_anch_urbs, 20, "%d",
        atomic_read(&ar->tx_anch_urbs));
DEBUGFS_READONLY_FILE(usb_rx_anch_urbs, 20, "%d",
        atomic_read(&ar->rx_anch_urbs));
DEBUGFS_READONLY_FILE(usb_rx_work_urbs, 20, "%d",
        atomic_read(&ar->rx_work_urbs));
DEBUGFS_READONLY_FILE(usb_rx_pool_urbs, 20, "%d",
        atomic_read(&ar->rx_pool_urbs));

DEBUGFS_READONLY_FILE(tx_total_queued, 20, "%d",
        atomic_read(&ar->tx_total_queued));
DEBUGFS_READONLY_FILE(tx_ampdu_scheduler, 20, "%d",
        atomic_read(&ar->tx_ampdu_scheduler));

DEBUGFS_READONLY_FILE(tx_total_pending, 20, "%d",
        atomic_read(&ar->tx_total_pending));

DEBUGFS_READONLY_FILE(tx_ampdu_list_len, 20, "%d",
        ar->tx_ampdu_list_len);

DEBUGFS_READONLY_FILE(tx_ampdu_upload, 20, "%d",
        atomic_read(&ar->tx_ampdu_upload));

DEBUGFS_READONLY_FILE(tx_janitor_last_run, 64, "last run:%d ms ago",
 jiffies_to_msecs(jiffies - ar->tx_janitor_last_run));

DEBUGFS_READONLY_FILE(tx_dropped, 20, "%d", ar->tx_dropped);

DEBUGFS_READONLY_FILE(rx_dropped, 20, "%d", ar->rx_dropped);

DEBUGFS_READONLY_FILE(sniffer_enabled, 20, "%d", ar->sniffer_enabled);
DEBUGFS_READONLY_FILE(rx_software_decryption, 20, "%d",
        ar->rx_software_decryption);
DEBUGFS_READONLY_FILE(ampdu_factor, 20, "%d",
        ar->current_factor);
DEBUGFS_READONLY_FILE(ampdu_density, 20, "%d",
        ar->current_density);

DEBUGFS_READONLY_FILE(beacon_int, 20, "%d TU", ar->global_beacon_int);
DEBUGFS_READONLY_FILE(pretbtt, 20, "%d TU", ar->global_pretbtt);

void carl9170_debugfs_register(struct ar9170 *ar)
{
 ar->debug_dir = debugfs_create_dir(KBUILD_MODNAME,
  ar->hw->wiphy->debugfsdir);

#define DEBUGFS_ADD(name)      \
 debugfs_create_file_aux(#name, carl_debugfs_##name ##_ops.attr, \
       ar->debug_dir, ar, &carl_debugfs_##name ## _ops, \
       &debugfs_fops)

 DEBUGFS_ADD(usb_tx_anch_urbs);
 DEBUGFS_ADD(usb_rx_pool_urbs);
 DEBUGFS_ADD(usb_rx_anch_urbs);
 DEBUGFS_ADD(usb_rx_work_urbs);

 DEBUGFS_ADD(tx_total_queued);
 DEBUGFS_ADD(tx_total_pending);
 DEBUGFS_ADD(tx_dropped);
 DEBUGFS_ADD(tx_stuck);
 DEBUGFS_ADD(tx_ampdu_upload);
 DEBUGFS_ADD(tx_ampdu_scheduler);
 DEBUGFS_ADD(tx_ampdu_list_len);

 DEBUGFS_ADD(rx_dropped);
 DEBUGFS_ADD(sniffer_enabled);
 DEBUGFS_ADD(rx_software_decryption);

 DEBUGFS_ADD(mem_usage);
 DEBUGFS_ADD(qos_stat);
 DEBUGFS_ADD(sta_psm);
 DEBUGFS_ADD(ampdu_state);

 DEBUGFS_ADD(hw_tx_tally);
 DEBUGFS_ADD(hw_rx_tally);
 DEBUGFS_ADD(hw_phy_errors);
 DEBUGFS_ADD(phy_noise);

 DEBUGFS_ADD(hw_wlan_queue);
 DEBUGFS_ADD(hw_pta_queue);
 DEBUGFS_ADD(hw_ampdu_info);

 DEBUGFS_ADD(ampdu_density);
 DEBUGFS_ADD(ampdu_factor);

 DEBUGFS_ADD(tx_janitor_last_run);

 DEBUGFS_ADD(tx_status_0);
 DEBUGFS_ADD(tx_status_1);
 DEBUGFS_ADD(tx_status_2);
 DEBUGFS_ADD(tx_status_3);

 DEBUGFS_ADD(tx_pending_0);
 DEBUGFS_ADD(tx_pending_1);
 DEBUGFS_ADD(tx_pending_2);
 DEBUGFS_ADD(tx_pending_3);

 DEBUGFS_ADD(hw_ioread32);
 DEBUGFS_ADD(hw_iowrite32);
 DEBUGFS_ADD(bug);

 DEBUGFS_ADD(erp);

 DEBUGFS_ADD(vif_dump);

 DEBUGFS_ADD(beacon_int);
 DEBUGFS_ADD(pretbtt);

#undef DEBUGFS_ADD
}

void carl9170_debugfs_unregister(struct ar9170 *ar)
{
 debugfs_remove_recursive(ar->debug_dir);
}

Messung V0.5
C=98 H=90 G=94

¤ Dauer der Verarbeitung: 0.10 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge