| | 939 | #ifdef CONFIG_SYSCTL |
|---|
| | 940 | static int |
|---|
| | 941 | proc_read_nodes(struct ieee80211vap *vap, const int size, char *buf, int space) |
|---|
| | 942 | { |
|---|
| | 943 | char *p = buf; |
|---|
| | 944 | struct ieee80211_node *ni; |
|---|
| | 945 | struct ath_node *an; |
|---|
| | 946 | struct sample_node *sn; |
|---|
| | 947 | struct ieee80211_node_table *nt = |
|---|
| | 948 | (struct ieee80211_node_table *) &vap->iv_ic->ic_sta; |
|---|
| | 949 | int x = 0; |
|---|
| | 950 | int size_bin = 0; |
|---|
| | 951 | |
|---|
| | 952 | TAILQ_FOREACH(ni, &nt->nt_node, ni_list) { |
|---|
| | 953 | /* Assume each node needs 500 bytes */ |
|---|
| | 954 | if (buf + space < p + 500) |
|---|
| | 955 | break; |
|---|
| | 956 | an = ATH_NODE(ni); |
|---|
| | 957 | sn = ATH_NODE_SAMPLE(an); |
|---|
| | 958 | /* Skip ourself */ |
|---|
| | 959 | if (memcmp(vap->iv_myaddr, ni->ni_macaddr, |
|---|
| | 960 | IEEE80211_ADDR_LEN)==0) { |
|---|
| | 961 | continue; |
|---|
| | 962 | } |
|---|
| | 963 | |
|---|
| | 964 | size_bin = size_to_bin(size); |
|---|
| | 965 | p += sprintf(p, "%s\n", ether_sprintf(ni->ni_macaddr)); |
|---|
| | 966 | p += sprintf(p, |
|---|
| | 967 | "rate\ttt\tperfect\tfailed\tpkts\tavg_tries\tlast_tx\n"); |
|---|
| | 968 | for (x = 0; x < sn->num_rates; x++) { |
|---|
| | 969 | int a = 1; |
|---|
| | 970 | int t = 1; |
|---|
| | 971 | |
|---|
| | 972 | p += sprintf(p, "%s", |
|---|
| | 973 | (x == sn->current_rate[size_bin]) ? "*" : " "); |
|---|
| | 974 | |
|---|
| | 975 | p += sprintf(p, "%3d%s", |
|---|
| | 976 | sn->rates[x].rate/2, |
|---|
| | 977 | (sn->rates[x].rate & 0x1) != 0 ? ".5" : " "); |
|---|
| | 978 | |
|---|
| | 979 | p += sprintf(p, "\t%4d\t%4d\t%2d\t%3d", |
|---|
| | 980 | sn->stats[size_bin][x].average_tx_time, |
|---|
| | 981 | sn->stats[size_bin][x].perfect_tx_time, |
|---|
| | 982 | sn->stats[size_bin][x].successive_failures, |
|---|
| | 983 | sn->stats[size_bin][x].total_packets); |
|---|
| | 984 | |
|---|
| | 985 | if (sn->stats[size_bin][x].total_packets) { |
|---|
| | 986 | a = sn->stats[size_bin][x].total_packets; |
|---|
| | 987 | t = sn->stats[size_bin][x].tries; |
|---|
| | 988 | } |
|---|
| | 989 | p += sprintf(p, "\t%d.%02d\t", t/a, (t*100/a) % 100); |
|---|
| | 990 | if (sn->stats[size_bin][x].last_tx) { |
|---|
| | 991 | unsigned d = jiffies - |
|---|
| | 992 | sn->stats[size_bin][x].last_tx; |
|---|
| | 993 | p += sprintf(p, "%d.%02d", d / HZ, d % HZ); |
|---|
| | 994 | } else { |
|---|
| | 995 | p += sprintf(p, "-"); |
|---|
| | 996 | } |
|---|
| | 997 | p += sprintf(p, "\n"); |
|---|
| | 998 | } |
|---|
| | 999 | printk("\n"); |
|---|
| | 1000 | } |
|---|
| | 1001 | |
|---|
| | 1002 | return (p - buf); |
|---|
| | 1003 | } |
|---|
| | 1004 | |
|---|
| | 1005 | int |
|---|
| | 1006 | proc_ratesample_open(struct inode *inode, struct file *file) |
|---|
| | 1007 | { |
|---|
| | 1008 | struct proc_ieee80211_priv *pv = NULL; |
|---|
| | 1009 | struct proc_dir_entry *dp = PDE(inode); |
|---|
| | 1010 | struct ieee80211vap *vap = dp->data; |
|---|
| | 1011 | int size = 0; |
|---|
| | 1012 | |
|---|
| | 1013 | if (!(file->private_data = kmalloc(sizeof(struct proc_ieee80211_priv), |
|---|
| | 1014 | GFP_KERNEL))) |
|---|
| | 1015 | return -ENOMEM; |
|---|
| | 1016 | |
|---|
| | 1017 | /* intially allocate both read and write buffers */ |
|---|
| | 1018 | pv = (struct proc_ieee80211_priv *) file->private_data; |
|---|
| | 1019 | memset(pv, 0, sizeof(struct proc_ieee80211_priv)); |
|---|
| | 1020 | pv->rbuf = vmalloc(MAX_PROC_IEEE80211_SIZE); |
|---|
| | 1021 | if (!pv->rbuf) { |
|---|
| | 1022 | kfree(pv); |
|---|
| | 1023 | return -ENOMEM; |
|---|
| | 1024 | } |
|---|
| | 1025 | pv->wbuf = vmalloc(MAX_PROC_IEEE80211_SIZE); |
|---|
| | 1026 | if (!pv->wbuf) { |
|---|
| | 1027 | vfree(pv->rbuf); |
|---|
| | 1028 | kfree(pv); |
|---|
| | 1029 | return -ENOMEM; |
|---|
| | 1030 | } |
|---|
| | 1031 | memset(pv->wbuf, 0, MAX_PROC_IEEE80211_SIZE); |
|---|
| | 1032 | memset(pv->rbuf, 0, MAX_PROC_IEEE80211_SIZE); |
|---|
| | 1033 | pv->max_wlen = MAX_PROC_IEEE80211_SIZE; |
|---|
| | 1034 | pv->max_rlen = MAX_PROC_IEEE80211_SIZE; |
|---|
| | 1035 | |
|---|
| | 1036 | /* Determine what size packets to get stats for based on proc filename */ |
|---|
| | 1037 | size = (int)simple_strtol(dp->name + 10, NULL, 0); |
|---|
| | 1038 | |
|---|
| | 1039 | /* now read the data into the buffer */ |
|---|
| | 1040 | pv->rlen = proc_read_nodes(vap, size, pv->rbuf, MAX_PROC_IEEE80211_SIZE); |
|---|
| | 1041 | return 0; |
|---|
| | 1042 | } |
|---|
| | 1043 | |
|---|
| | 1044 | static struct file_operations proc_ratesample_ops = { |
|---|
| | 1045 | .read = NULL, |
|---|
| | 1046 | .write = NULL, |
|---|
| | 1047 | .open = proc_ratesample_open, |
|---|
| | 1048 | .release = NULL, |
|---|
| | 1049 | }; |
|---|
| | 1050 | |
|---|
| | 1051 | void |
|---|
| | 1052 | ath_rate_dynamic_proc_register(struct ieee80211vap *vap) |
|---|
| | 1053 | { |
|---|
| | 1054 | /* Create proc entries for the rate control algorithm */ |
|---|
| | 1055 | ieee80211_proc_vcreate(vap, &proc_ratesample_ops, "ratestats_250"); |
|---|
| | 1056 | ieee80211_proc_vcreate(vap, &proc_ratesample_ops, "ratestats_1600"); |
|---|
| | 1057 | ieee80211_proc_vcreate(vap, &proc_ratesample_ops, "ratestats_3000"); |
|---|
| | 1058 | } |
|---|
| | 1059 | EXPORT_SYMBOL(ath_rate_dynamic_proc_register); |
|---|
| | 1060 | #endif /* CONFIG_SYSCTL */ |
|---|
| | 1061 | |
|---|