/alps/pcitool

To get this branch, use:
bzr branch http://darksoft.org/webbzr/alps/pcitool

« back to all changes in this revision

Viewing changes to driver/sysfs.c

  • Committer: Suren A. Chilingaryan
  • Date: 2011-02-13 02:07:11 UTC
  • Revision ID: csa@dside.dyndns.org-20110213020711-y9bjh3n4ke6p4t4n
Initial import

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/**
 
2
 *
 
3
 * @file sysfs.c
 
4
 * @brief This file contains the functions providing the SysFS-interface.
 
5
 * @author Guillermo Marcus
 
6
 * @date 2010-03-01
 
7
 *
 
8
 */
 
9
#include <linux/version.h>
 
10
#include <linux/string.h>
 
11
#include <linux/types.h>
 
12
#include <linux/list.h>
 
13
#include <linux/interrupt.h>
 
14
#include <linux/pci.h>
 
15
#include <linux/cdev.h>
 
16
#include <linux/wait.h>
 
17
#include <linux/mm.h>
 
18
#include <linux/pagemap.h>
 
19
#include <linux/kernel.h>
 
20
 
 
21
#include "compat.h"
 
22
#include "config.h"
 
23
#include "pciDriver.h"
 
24
#include "common.h"
 
25
#include "umem.h"
 
26
#include "kmem.h"
 
27
#include "sysfs.h"
 
28
 
 
29
static SYSFS_GET_FUNCTION(pcidriver_show_kmem_entry);
 
30
static SYSFS_GET_FUNCTION(pcidriver_show_umem_entry);
 
31
 
 
32
/**
 
33
 *
 
34
 * Initializes the sysfs attributes for an kmem/umem-entry
 
35
 *
 
36
 */
 
37
static int _pcidriver_sysfs_initialize(pcidriver_privdata_t *privdata,
 
38
                                        int id,
 
39
                                        struct class_device_attribute *sysfs_attr,
 
40
                                        const char *fmtstring,
 
41
                                        SYSFS_GET_FUNCTION((*callback)))
 
42
{
 
43
        /* sysfs attributes for kmem buffers don’t make sense before 2.6.13, as
 
44
           we have no mmap support before */
 
45
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,13)
 
46
        char namebuffer[16];
 
47
 
 
48
        /* allocate space for the name of the attribute */
 
49
        snprintf(namebuffer, sizeof(namebuffer), fmtstring, id);
 
50
 
 
51
        if ((sysfs_attr->attr.name = kstrdup(namebuffer, GFP_KERNEL)) == NULL)
 
52
                return -ENOMEM;
 
53
 
 
54
        sysfs_attr->attr.mode = S_IRUGO;
 
55
        sysfs_attr->attr.owner = THIS_MODULE;
 
56
        sysfs_attr->show = callback;
 
57
        sysfs_attr->store = NULL;
 
58
                        
 
59
        /* name and add attribute */
 
60
        if (class_device_create_file(privdata->class_dev, sysfs_attr) != 0)
 
61
                return -ENXIO; /* Device not configured. Not the really best choice, but hm. */
 
62
#endif
 
63
 
 
64
        return 0;
 
65
}
 
66
 
 
67
int pcidriver_sysfs_initialize_kmem(pcidriver_privdata_t *privdata, int id, struct class_device_attribute *sysfs_attr)
 
68
{
 
69
        return _pcidriver_sysfs_initialize(privdata, id, sysfs_attr, "kbuf%d", pcidriver_show_kmem_entry);
 
70
}
 
71
 
 
72
int pcidriver_sysfs_initialize_umem(pcidriver_privdata_t *privdata, int id, struct class_device_attribute *sysfs_attr)
 
73
{
 
74
        return _pcidriver_sysfs_initialize(privdata, id, sysfs_attr, "umem%d", pcidriver_show_umem_entry);
 
75
}
 
76
 
 
77
/**
 
78
 *
 
79
 * Removes the file from sysfs and frees the allocated (kstrdup()) memory.
 
80
 *
 
81
 */
 
82
void pcidriver_sysfs_remove(pcidriver_privdata_t *privdata, struct class_device_attribute *sysfs_attr)
 
83
{
 
84
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,13)
 
85
        class_device_remove_file(privdata->class_dev, sysfs_attr);
 
86
        kfree(sysfs_attr->attr.name);
 
87
#endif
 
88
}
 
89
 
 
90
static SYSFS_GET_FUNCTION(pcidriver_show_kmem_entry)
 
91
{
 
92
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,13)
 
93
//      pcidriver_privdata_t *privdata = (pcidriver_privdata_t *)cls->class_data;
 
94
 
 
95
        /* As we can be sure that attr.name contains a filename which we
 
96
         * created (see _pcidriver_sysfs_initialize), we do not need to have
 
97
         * sanity checks but can directly call simple_strtol() */
 
98
        int id = simple_strtol(attr->attr.name + strlen("kbuf"), NULL, 10);
 
99
 
 
100
        return snprintf(buf, PAGE_SIZE, "I am in the kmem_entry show function for buffer %d\n", id);
 
101
#else
 
102
        return 0;
 
103
#endif
 
104
}
 
105
 
 
106
static SYSFS_GET_FUNCTION(pcidriver_show_umem_entry)
 
107
{
 
108
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,13)
 
109
#if 0
 
110
        pcidriver_privdata_t *privdata = (pcidriver_privdata_t *)cls->class_data;
 
111
 
 
112
        return snprintf(buf, PAGE_SIZE, "I am in the umem_entry show function, class_device_kobj_name: %s\n", cls->kobj.name);
 
113
#endif
 
114
        return 0;
 
115
#else
 
116
        return 0;
 
117
#endif
 
118
}
 
119
 
 
120
#ifdef ENABLE_IRQ
 
121
SYSFS_GET_FUNCTION(pcidriver_show_irq_count)
 
122
{
 
123
        pcidriver_privdata_t *privdata = SYSFS_GET_PRIVDATA;
 
124
 
 
125
        return snprintf(buf, PAGE_SIZE, "%d\n", privdata->irq_count);
 
126
}
 
127
 
 
128
SYSFS_GET_FUNCTION(pcidriver_show_irq_queues)
 
129
{
 
130
        pcidriver_privdata_t *privdata = SYSFS_GET_PRIVDATA;
 
131
        int i, offset;
 
132
 
 
133
        /* output will be truncated to PAGE_SIZE */
 
134
        offset = snprintf(buf, PAGE_SIZE, "Queue\tOutstanding IRQs\n");
 
135
        for (i = 0; i < PCIDRIVER_INT_MAXSOURCES; i++)
 
136
                offset += snprintf(buf+offset, PAGE_SIZE-offset, "%d\t%d\n", i, atomic_read(&(privdata->irq_outstanding[i])) );
 
137
 
 
138
        return (offset > PAGE_SIZE ? PAGE_SIZE : offset+1);
 
139
}
 
140
#endif
 
141
 
 
142
SYSFS_GET_FUNCTION(pcidriver_show_mmap_mode)
 
143
{
 
144
        pcidriver_privdata_t *privdata = SYSFS_GET_PRIVDATA;
 
145
 
 
146
        return snprintf(buf, PAGE_SIZE, "%d\n", privdata->mmap_mode);
 
147
}
 
148
 
 
149
SYSFS_SET_FUNCTION(pcidriver_store_mmap_mode)
 
150
{
 
151
        pcidriver_privdata_t *privdata = SYSFS_GET_PRIVDATA;
 
152
        int mode = -1;
 
153
 
 
154
        /* Set the mmap-mode if it is either PCIDRIVER_MMAP_PCI or PCIDRIVER_MMAP_KMEM */
 
155
        if (sscanf(buf, "%d", &mode) == 1 &&
 
156
            (mode == PCIDRIVER_MMAP_PCI || mode == PCIDRIVER_MMAP_KMEM))
 
157
                privdata->mmap_mode = mode;
 
158
 
 
159
        return strlen(buf);
 
160
}
 
161
 
 
162
SYSFS_GET_FUNCTION(pcidriver_show_mmap_area)
 
163
{
 
164
        pcidriver_privdata_t *privdata = SYSFS_GET_PRIVDATA;
 
165
 
 
166
        return snprintf(buf, PAGE_SIZE, "%d\n", privdata->mmap_area);
 
167
}
 
168
 
 
169
SYSFS_SET_FUNCTION(pcidriver_store_mmap_area)
 
170
{
 
171
        pcidriver_privdata_t *privdata = SYSFS_GET_PRIVDATA;
 
172
        int temp = -1;
 
173
 
 
174
        sscanf(buf, "%d", &temp);
 
175
 
 
176
        if ((temp >= PCIDRIVER_BAR0) && (temp <= PCIDRIVER_BAR5))
 
177
                privdata->mmap_area = temp;
 
178
 
 
179
        return strlen(buf);
 
180
}
 
181
 
 
182
SYSFS_GET_FUNCTION(pcidriver_show_kmem_count)
 
183
{
 
184
        pcidriver_privdata_t *privdata = SYSFS_GET_PRIVDATA;
 
185
 
 
186
        return snprintf(buf, PAGE_SIZE, "%d\n", atomic_read(&(privdata->kmem_count)));
 
187
}
 
188
 
 
189
SYSFS_SET_FUNCTION(pcidriver_store_kmem_alloc)
 
190
{
 
191
        pcidriver_privdata_t *privdata = SYSFS_GET_PRIVDATA;
 
192
        kmem_handle_t kmem_handle;
 
193
 
 
194
        /* FIXME: guillermo: is validation of parsing an unsigned int enough? */
 
195
        if (sscanf(buf, "%lu", &kmem_handle.size) == 1)
 
196
                pcidriver_kmem_alloc(privdata, &kmem_handle);
 
197
 
 
198
        return strlen(buf);
 
199
}
 
200
 
 
201
SYSFS_SET_FUNCTION(pcidriver_store_kmem_free)
 
202
{
 
203
        pcidriver_privdata_t *privdata = SYSFS_GET_PRIVDATA;
 
204
        unsigned int id;
 
205
        pcidriver_kmem_entry_t *kmem_entry;
 
206
 
 
207
        /* Parse the ID of the kernel memory to be freed, check bounds */
 
208
        if (sscanf(buf, "%u", &id) != 1 ||
 
209
            (id >= atomic_read(&(privdata->kmem_count))))
 
210
                goto err;
 
211
 
 
212
        if ((kmem_entry = pcidriver_kmem_find_entry_id(privdata,id)) == NULL)
 
213
                goto err;
 
214
 
 
215
        pcidriver_kmem_free_entry(privdata, kmem_entry );
 
216
err:
 
217
        return strlen(buf);
 
218
}
 
219
 
 
220
SYSFS_GET_FUNCTION(pcidriver_show_kbuffers)
 
221
{
 
222
        pcidriver_privdata_t *privdata = SYSFS_GET_PRIVDATA;
 
223
        int offset = 0;
 
224
        struct list_head *ptr;
 
225
        pcidriver_kmem_entry_t *entry;
 
226
 
 
227
        /* print the header */
 
228
        offset += snprintf(buf, PAGE_SIZE, "kbuf#\tcpu addr\tsize\n");
 
229
 
 
230
        spin_lock(&(privdata->kmemlist_lock));
 
231
        list_for_each(ptr, &(privdata->kmem_list)) {
 
232
                entry = list_entry(ptr, pcidriver_kmem_entry_t, list);
 
233
 
 
234
                /* print entry info */
 
235
                if (offset > PAGE_SIZE) {
 
236
                        spin_unlock( &(privdata->kmemlist_lock) );
 
237
                        return PAGE_SIZE;
 
238
                }
 
239
 
 
240
                offset += snprintf(buf+offset, PAGE_SIZE-offset, "%3d\t%08lx\t%lu\n", entry->id, (unsigned long)(entry->dma_handle), entry->size );
 
241
        }
 
242
 
 
243
        spin_unlock(&(privdata->kmemlist_lock));
 
244
 
 
245
        /* output will be truncated to PAGE_SIZE */
 
246
        return (offset > PAGE_SIZE ? PAGE_SIZE : offset+1);
 
247
}
 
248
 
 
249
SYSFS_GET_FUNCTION(pcidriver_show_umappings)
 
250
{
 
251
        int offset = 0;
 
252
        pcidriver_privdata_t *privdata = SYSFS_GET_PRIVDATA;
 
253
        struct list_head *ptr;
 
254
        pcidriver_umem_entry_t *entry;
 
255
 
 
256
        /* print the header */
 
257
        offset += snprintf(buf, PAGE_SIZE, "umap#\tn_pages\tsg_ents\n");
 
258
 
 
259
        spin_lock( &(privdata->umemlist_lock) );
 
260
        list_for_each( ptr, &(privdata->umem_list) ) {
 
261
                entry = list_entry(ptr, pcidriver_umem_entry_t, list );
 
262
 
 
263
                /* print entry info */
 
264
                if (offset > PAGE_SIZE) {
 
265
                        spin_unlock( &(privdata->umemlist_lock) );
 
266
                        return PAGE_SIZE;
 
267
                }
 
268
 
 
269
                offset += snprintf(buf+offset, PAGE_SIZE-offset, "%3d\t%lu\t%lu\n", entry->id,
 
270
                                (unsigned long)(entry->nr_pages), (unsigned long)(entry->nents));
 
271
        }
 
272
 
 
273
        spin_unlock( &(privdata->umemlist_lock) );
 
274
 
 
275
        /* output will be truncated to PAGE_SIZE */
 
276
        return (offset > PAGE_SIZE ? PAGE_SIZE : offset+1);
 
277
}
 
278
 
 
279
SYSFS_SET_FUNCTION(pcidriver_store_umem_unmap)
 
280
{
 
281
        pcidriver_privdata_t *privdata = SYSFS_GET_PRIVDATA;
 
282
        pcidriver_umem_entry_t *umem_entry;
 
283
        unsigned int id;
 
284
 
 
285
        if (sscanf(buf, "%u", &id) != 1 ||
 
286
            (id >= atomic_read(&(privdata->umem_count))))
 
287
                goto err;
 
288
 
 
289
        if ((umem_entry = pcidriver_umem_find_entry_id(privdata, id)) == NULL)
 
290
                goto err;
 
291
 
 
292
        pcidriver_umem_sgunmap(privdata, umem_entry);
 
293
err:
 
294
        return strlen(buf);
 
295
}