~ubuntu-branches/ubuntu/precise/linux-lowlatency/precise

« back to all changes in this revision

Viewing changes to net/mac80211/rc80211_pid_debugfs.c

  • Committer: Package Import Robot
  • Author(s): Alessio Igor Bogani
  • Date: 2011-10-26 11:13:05 UTC
  • Revision ID: package-import@ubuntu.com-20111026111305-tz023xykf0i6eosh
Tags: upstream-3.2.0
ImportĀ upstreamĀ versionĀ 3.2.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright 2007, Mattias Nissler <mattias.nissler@gmx.de>
 
3
 *
 
4
 * This program is free software; you can redistribute it and/or modify
 
5
 * it under the terms of the GNU General Public License version 2 as
 
6
 * published by the Free Software Foundation.
 
7
 */
 
8
 
 
9
#include <linux/sched.h>
 
10
#include <linux/spinlock.h>
 
11
#include <linux/poll.h>
 
12
#include <linux/netdevice.h>
 
13
#include <linux/types.h>
 
14
#include <linux/skbuff.h>
 
15
#include <linux/slab.h>
 
16
#include <linux/export.h>
 
17
 
 
18
#include <net/mac80211.h>
 
19
#include "rate.h"
 
20
 
 
21
#include "rc80211_pid.h"
 
22
 
 
23
static void rate_control_pid_event(struct rc_pid_event_buffer *buf,
 
24
                                   enum rc_pid_event_type type,
 
25
                                   union rc_pid_event_data *data)
 
26
{
 
27
        struct rc_pid_event *ev;
 
28
        unsigned long status;
 
29
 
 
30
        spin_lock_irqsave(&buf->lock, status);
 
31
        ev = &(buf->ring[buf->next_entry]);
 
32
        buf->next_entry = (buf->next_entry + 1) % RC_PID_EVENT_RING_SIZE;
 
33
 
 
34
        ev->timestamp = jiffies;
 
35
        ev->id = buf->ev_count++;
 
36
        ev->type = type;
 
37
        ev->data = *data;
 
38
 
 
39
        spin_unlock_irqrestore(&buf->lock, status);
 
40
 
 
41
        wake_up_all(&buf->waitqueue);
 
42
}
 
43
 
 
44
void rate_control_pid_event_tx_status(struct rc_pid_event_buffer *buf,
 
45
                                      struct ieee80211_tx_info *stat)
 
46
{
 
47
        union rc_pid_event_data evd;
 
48
 
 
49
        evd.flags = stat->flags;
 
50
        memcpy(&evd.tx_status, stat, sizeof(struct ieee80211_tx_info));
 
51
        rate_control_pid_event(buf, RC_PID_EVENT_TYPE_TX_STATUS, &evd);
 
52
}
 
53
 
 
54
void rate_control_pid_event_rate_change(struct rc_pid_event_buffer *buf,
 
55
                                               int index, int rate)
 
56
{
 
57
        union rc_pid_event_data evd;
 
58
 
 
59
        evd.index = index;
 
60
        evd.rate = rate;
 
61
        rate_control_pid_event(buf, RC_PID_EVENT_TYPE_RATE_CHANGE, &evd);
 
62
}
 
63
 
 
64
void rate_control_pid_event_tx_rate(struct rc_pid_event_buffer *buf,
 
65
                                           int index, int rate)
 
66
{
 
67
        union rc_pid_event_data evd;
 
68
 
 
69
        evd.index = index;
 
70
        evd.rate = rate;
 
71
        rate_control_pid_event(buf, RC_PID_EVENT_TYPE_TX_RATE, &evd);
 
72
}
 
73
 
 
74
void rate_control_pid_event_pf_sample(struct rc_pid_event_buffer *buf,
 
75
                                             s32 pf_sample, s32 prop_err,
 
76
                                             s32 int_err, s32 der_err)
 
77
{
 
78
        union rc_pid_event_data evd;
 
79
 
 
80
        evd.pf_sample = pf_sample;
 
81
        evd.prop_err = prop_err;
 
82
        evd.int_err = int_err;
 
83
        evd.der_err = der_err;
 
84
        rate_control_pid_event(buf, RC_PID_EVENT_TYPE_PF_SAMPLE, &evd);
 
85
}
 
86
 
 
87
static int rate_control_pid_events_open(struct inode *inode, struct file *file)
 
88
{
 
89
        struct rc_pid_sta_info *sinfo = inode->i_private;
 
90
        struct rc_pid_event_buffer *events = &sinfo->events;
 
91
        struct rc_pid_events_file_info *file_info;
 
92
        unsigned long status;
 
93
 
 
94
        /* Allocate a state struct */
 
95
        file_info = kmalloc(sizeof(*file_info), GFP_KERNEL);
 
96
        if (file_info == NULL)
 
97
                return -ENOMEM;
 
98
 
 
99
        spin_lock_irqsave(&events->lock, status);
 
100
 
 
101
        file_info->next_entry = events->next_entry;
 
102
        file_info->events = events;
 
103
 
 
104
        spin_unlock_irqrestore(&events->lock, status);
 
105
 
 
106
        file->private_data = file_info;
 
107
 
 
108
        return 0;
 
109
}
 
110
 
 
111
static int rate_control_pid_events_release(struct inode *inode,
 
112
                                           struct file *file)
 
113
{
 
114
        struct rc_pid_events_file_info *file_info = file->private_data;
 
115
 
 
116
        kfree(file_info);
 
117
 
 
118
        return 0;
 
119
}
 
120
 
 
121
static unsigned int rate_control_pid_events_poll(struct file *file,
 
122
                                                 poll_table *wait)
 
123
{
 
124
        struct rc_pid_events_file_info *file_info = file->private_data;
 
125
 
 
126
        poll_wait(file, &file_info->events->waitqueue, wait);
 
127
 
 
128
        return POLLIN | POLLRDNORM;
 
129
}
 
130
 
 
131
#define RC_PID_PRINT_BUF_SIZE 64
 
132
 
 
133
static ssize_t rate_control_pid_events_read(struct file *file, char __user *buf,
 
134
                                            size_t length, loff_t *offset)
 
135
{
 
136
        struct rc_pid_events_file_info *file_info = file->private_data;
 
137
        struct rc_pid_event_buffer *events = file_info->events;
 
138
        struct rc_pid_event *ev;
 
139
        char pb[RC_PID_PRINT_BUF_SIZE];
 
140
        int ret;
 
141
        int p;
 
142
        unsigned long status;
 
143
 
 
144
        /* Check if there is something to read. */
 
145
        if (events->next_entry == file_info->next_entry) {
 
146
                if (file->f_flags & O_NONBLOCK)
 
147
                        return -EAGAIN;
 
148
 
 
149
                /* Wait */
 
150
                ret = wait_event_interruptible(events->waitqueue,
 
151
                                events->next_entry != file_info->next_entry);
 
152
 
 
153
                if (ret)
 
154
                        return ret;
 
155
        }
 
156
 
 
157
        /* Write out one event per call. I don't care whether it's a little
 
158
         * inefficient, this is debugging code anyway. */
 
159
        spin_lock_irqsave(&events->lock, status);
 
160
 
 
161
        /* Get an event */
 
162
        ev = &(events->ring[file_info->next_entry]);
 
163
        file_info->next_entry = (file_info->next_entry + 1) %
 
164
                                RC_PID_EVENT_RING_SIZE;
 
165
 
 
166
        /* Print information about the event. Note that userspace needs to
 
167
         * provide large enough buffers. */
 
168
        length = length < RC_PID_PRINT_BUF_SIZE ?
 
169
                 length : RC_PID_PRINT_BUF_SIZE;
 
170
        p = snprintf(pb, length, "%u %lu ", ev->id, ev->timestamp);
 
171
        switch (ev->type) {
 
172
        case RC_PID_EVENT_TYPE_TX_STATUS:
 
173
                p += snprintf(pb + p, length - p, "tx_status %u %u",
 
174
                              !(ev->data.flags & IEEE80211_TX_STAT_ACK),
 
175
                              ev->data.tx_status.status.rates[0].idx);
 
176
                break;
 
177
        case RC_PID_EVENT_TYPE_RATE_CHANGE:
 
178
                p += snprintf(pb + p, length - p, "rate_change %d %d",
 
179
                              ev->data.index, ev->data.rate);
 
180
                break;
 
181
        case RC_PID_EVENT_TYPE_TX_RATE:
 
182
                p += snprintf(pb + p, length - p, "tx_rate %d %d",
 
183
                              ev->data.index, ev->data.rate);
 
184
                break;
 
185
        case RC_PID_EVENT_TYPE_PF_SAMPLE:
 
186
                p += snprintf(pb + p, length - p,
 
187
                              "pf_sample %d %d %d %d",
 
188
                              ev->data.pf_sample, ev->data.prop_err,
 
189
                              ev->data.int_err, ev->data.der_err);
 
190
                break;
 
191
        }
 
192
        p += snprintf(pb + p, length - p, "\n");
 
193
 
 
194
        spin_unlock_irqrestore(&events->lock, status);
 
195
 
 
196
        if (copy_to_user(buf, pb, p))
 
197
                return -EFAULT;
 
198
 
 
199
        return p;
 
200
}
 
201
 
 
202
#undef RC_PID_PRINT_BUF_SIZE
 
203
 
 
204
static const struct file_operations rc_pid_fop_events = {
 
205
        .owner = THIS_MODULE,
 
206
        .read = rate_control_pid_events_read,
 
207
        .poll = rate_control_pid_events_poll,
 
208
        .open = rate_control_pid_events_open,
 
209
        .release = rate_control_pid_events_release,
 
210
        .llseek = noop_llseek,
 
211
};
 
212
 
 
213
void rate_control_pid_add_sta_debugfs(void *priv, void *priv_sta,
 
214
                                             struct dentry *dir)
 
215
{
 
216
        struct rc_pid_sta_info *spinfo = priv_sta;
 
217
 
 
218
        spinfo->events_entry = debugfs_create_file("rc_pid_events", S_IRUGO,
 
219
                                                   dir, spinfo,
 
220
                                                   &rc_pid_fop_events);
 
221
}
 
222
 
 
223
void rate_control_pid_remove_sta_debugfs(void *priv, void *priv_sta)
 
224
{
 
225
        struct rc_pid_sta_info *spinfo = priv_sta;
 
226
 
 
227
        debugfs_remove(spinfo->events_entry);
 
228
}