OpenCores
URL https://opencores.org/ocsvn/test_project/test_project/trunk

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [drivers/] [char/] [snsc.c] - Blame information for rev 65

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 62 marcus.erl
/*
2
 * SN Platform system controller communication support
3
 *
4
 * This file is subject to the terms and conditions of the GNU General Public
5
 * License.  See the file "COPYING" in the main directory of this archive
6
 * for more details.
7
 *
8
 * Copyright (C) 2004, 2006 Silicon Graphics, Inc. All rights reserved.
9
 */
10
 
11
/*
12
 * System controller communication driver
13
 *
14
 * This driver allows a user process to communicate with the system
15
 * controller (a.k.a. "IRouter") network in an SGI SN system.
16
 */
17
 
18
#include <linux/interrupt.h>
19
#include <linux/sched.h>
20
#include <linux/device.h>
21
#include <linux/poll.h>
22
#include <linux/module.h>
23
#include <linux/slab.h>
24
#include <asm/sn/io.h>
25
#include <asm/sn/sn_sal.h>
26
#include <asm/sn/module.h>
27
#include <asm/sn/geo.h>
28
#include <asm/sn/nodepda.h>
29
#include "snsc.h"
30
 
31
#define SYSCTL_BASENAME "snsc"
32
 
33
#define SCDRV_BUFSZ     2048
34
#define SCDRV_TIMEOUT   1000
35
 
36
static irqreturn_t
37
scdrv_interrupt(int irq, void *subch_data)
38
{
39
        struct subch_data_s *sd = subch_data;
40
        unsigned long flags;
41
        int status;
42
 
43
        spin_lock_irqsave(&sd->sd_rlock, flags);
44
        spin_lock(&sd->sd_wlock);
45
        status = ia64_sn_irtr_intr(sd->sd_nasid, sd->sd_subch);
46
 
47
        if (status > 0) {
48
                if (status & SAL_IROUTER_INTR_RECV) {
49
                        wake_up(&sd->sd_rq);
50
                }
51
                if (status & SAL_IROUTER_INTR_XMIT) {
52
                        ia64_sn_irtr_intr_disable
53
                            (sd->sd_nasid, sd->sd_subch,
54
                             SAL_IROUTER_INTR_XMIT);
55
                        wake_up(&sd->sd_wq);
56
                }
57
        }
58
        spin_unlock(&sd->sd_wlock);
59
        spin_unlock_irqrestore(&sd->sd_rlock, flags);
60
        return IRQ_HANDLED;
61
}
62
 
63
/*
64
 * scdrv_open
65
 *
66
 * Reserve a subchannel for system controller communication.
67
 */
68
 
69
static int
70
scdrv_open(struct inode *inode, struct file *file)
71
{
72
        struct sysctl_data_s *scd;
73
        struct subch_data_s *sd;
74
        int rv;
75
 
76
        /* look up device info for this device file */
77
        scd = container_of(inode->i_cdev, struct sysctl_data_s, scd_cdev);
78
 
79
        /* allocate memory for subchannel data */
80
        sd = kzalloc(sizeof (struct subch_data_s), GFP_KERNEL);
81
        if (sd == NULL) {
82
                printk("%s: couldn't allocate subchannel data\n",
83
                       __FUNCTION__);
84
                return -ENOMEM;
85
        }
86
 
87
        /* initialize subch_data_s fields */
88
        sd->sd_nasid = scd->scd_nasid;
89
        sd->sd_subch = ia64_sn_irtr_open(scd->scd_nasid);
90
 
91
        if (sd->sd_subch < 0) {
92
                kfree(sd);
93
                printk("%s: couldn't allocate subchannel\n", __FUNCTION__);
94
                return -EBUSY;
95
        }
96
 
97
        spin_lock_init(&sd->sd_rlock);
98
        spin_lock_init(&sd->sd_wlock);
99
        init_waitqueue_head(&sd->sd_rq);
100
        init_waitqueue_head(&sd->sd_wq);
101
        sema_init(&sd->sd_rbs, 1);
102
        sema_init(&sd->sd_wbs, 1);
103
 
104
        file->private_data = sd;
105
 
106
        /* hook this subchannel up to the system controller interrupt */
107
        rv = request_irq(SGI_UART_VECTOR, scdrv_interrupt,
108
                         IRQF_SHARED | IRQF_DISABLED,
109
                         SYSCTL_BASENAME, sd);
110
        if (rv) {
111
                ia64_sn_irtr_close(sd->sd_nasid, sd->sd_subch);
112
                kfree(sd);
113
                printk("%s: irq request failed (%d)\n", __FUNCTION__, rv);
114
                return -EBUSY;
115
        }
116
 
117
        return 0;
118
}
119
 
120
/*
121
 * scdrv_release
122
 *
123
 * Release a previously-reserved subchannel.
124
 */
125
 
126
static int
127
scdrv_release(struct inode *inode, struct file *file)
128
{
129
        struct subch_data_s *sd = (struct subch_data_s *) file->private_data;
130
        int rv;
131
 
132
        /* free the interrupt */
133
        free_irq(SGI_UART_VECTOR, sd);
134
 
135
        /* ask SAL to close the subchannel */
136
        rv = ia64_sn_irtr_close(sd->sd_nasid, sd->sd_subch);
137
 
138
        kfree(sd);
139
        return rv;
140
}
141
 
142
/*
143
 * scdrv_read
144
 *
145
 * Called to read bytes from the open IRouter pipe.
146
 *
147
 */
148
 
149
static inline int
150
read_status_check(struct subch_data_s *sd, int *len)
151
{
152
        return ia64_sn_irtr_recv(sd->sd_nasid, sd->sd_subch, sd->sd_rb, len);
153
}
154
 
155
static ssize_t
156
scdrv_read(struct file *file, char __user *buf, size_t count, loff_t *f_pos)
157
{
158
        int status;
159
        int len;
160
        unsigned long flags;
161
        struct subch_data_s *sd = (struct subch_data_s *) file->private_data;
162
 
163
        /* try to get control of the read buffer */
164
        if (down_trylock(&sd->sd_rbs)) {
165
                /* somebody else has it now;
166
                 * if we're non-blocking, then exit...
167
                 */
168
                if (file->f_flags & O_NONBLOCK) {
169
                        return -EAGAIN;
170
                }
171
                /* ...or if we want to block, then do so here */
172
                if (down_interruptible(&sd->sd_rbs)) {
173
                        /* something went wrong with wait */
174
                        return -ERESTARTSYS;
175
                }
176
        }
177
 
178
        /* anything to read? */
179
        len = CHUNKSIZE;
180
        spin_lock_irqsave(&sd->sd_rlock, flags);
181
        status = read_status_check(sd, &len);
182
 
183
        /* if not, and we're blocking I/O, loop */
184
        while (status < 0) {
185
                DECLARE_WAITQUEUE(wait, current);
186
 
187
                if (file->f_flags & O_NONBLOCK) {
188
                        spin_unlock_irqrestore(&sd->sd_rlock, flags);
189
                        up(&sd->sd_rbs);
190
                        return -EAGAIN;
191
                }
192
 
193
                len = CHUNKSIZE;
194
                set_current_state(TASK_INTERRUPTIBLE);
195
                add_wait_queue(&sd->sd_rq, &wait);
196
                spin_unlock_irqrestore(&sd->sd_rlock, flags);
197
 
198
                schedule_timeout(SCDRV_TIMEOUT);
199
 
200
                remove_wait_queue(&sd->sd_rq, &wait);
201
                if (signal_pending(current)) {
202
                        /* wait was interrupted */
203
                        up(&sd->sd_rbs);
204
                        return -ERESTARTSYS;
205
                }
206
 
207
                spin_lock_irqsave(&sd->sd_rlock, flags);
208
                status = read_status_check(sd, &len);
209
        }
210
        spin_unlock_irqrestore(&sd->sd_rlock, flags);
211
 
212
        if (len > 0) {
213
                /* we read something in the last read_status_check(); copy
214
                 * it out to user space
215
                 */
216
                if (count < len) {
217
                        pr_debug("%s: only accepting %d of %d bytes\n",
218
                                 __FUNCTION__, (int) count, len);
219
                }
220
                len = min((int) count, len);
221
                if (copy_to_user(buf, sd->sd_rb, len))
222
                        len = -EFAULT;
223
        }
224
 
225
        /* release the read buffer and wake anyone who might be
226
         * waiting for it
227
         */
228
        up(&sd->sd_rbs);
229
 
230
        /* return the number of characters read in */
231
        return len;
232
}
233
 
234
/*
235
 * scdrv_write
236
 *
237
 * Writes a chunk of an IRouter packet (or other system controller data)
238
 * to the system controller.
239
 *
240
 */
241
static inline int
242
write_status_check(struct subch_data_s *sd, int count)
243
{
244
        return ia64_sn_irtr_send(sd->sd_nasid, sd->sd_subch, sd->sd_wb, count);
245
}
246
 
247
static ssize_t
248
scdrv_write(struct file *file, const char __user *buf,
249
            size_t count, loff_t *f_pos)
250
{
251
        unsigned long flags;
252
        int status;
253
        struct subch_data_s *sd = (struct subch_data_s *) file->private_data;
254
 
255
        /* try to get control of the write buffer */
256
        if (down_trylock(&sd->sd_wbs)) {
257
                /* somebody else has it now;
258
                 * if we're non-blocking, then exit...
259
                 */
260
                if (file->f_flags & O_NONBLOCK) {
261
                        return -EAGAIN;
262
                }
263
                /* ...or if we want to block, then do so here */
264
                if (down_interruptible(&sd->sd_wbs)) {
265
                        /* something went wrong with wait */
266
                        return -ERESTARTSYS;
267
                }
268
        }
269
 
270
        count = min((int) count, CHUNKSIZE);
271
        if (copy_from_user(sd->sd_wb, buf, count)) {
272
                up(&sd->sd_wbs);
273
                return -EFAULT;
274
        }
275
 
276
        /* try to send the buffer */
277
        spin_lock_irqsave(&sd->sd_wlock, flags);
278
        status = write_status_check(sd, count);
279
 
280
        /* if we failed, and we want to block, then loop */
281
        while (status <= 0) {
282
                DECLARE_WAITQUEUE(wait, current);
283
 
284
                if (file->f_flags & O_NONBLOCK) {
285
                        spin_unlock(&sd->sd_wlock);
286
                        up(&sd->sd_wbs);
287
                        return -EAGAIN;
288
                }
289
 
290
                set_current_state(TASK_INTERRUPTIBLE);
291
                add_wait_queue(&sd->sd_wq, &wait);
292
                spin_unlock_irqrestore(&sd->sd_wlock, flags);
293
 
294
                schedule_timeout(SCDRV_TIMEOUT);
295
 
296
                remove_wait_queue(&sd->sd_wq, &wait);
297
                if (signal_pending(current)) {
298
                        /* wait was interrupted */
299
                        up(&sd->sd_wbs);
300
                        return -ERESTARTSYS;
301
                }
302
 
303
                spin_lock_irqsave(&sd->sd_wlock, flags);
304
                status = write_status_check(sd, count);
305
        }
306
        spin_unlock_irqrestore(&sd->sd_wlock, flags);
307
 
308
        /* release the write buffer and wake anyone who's waiting for it */
309
        up(&sd->sd_wbs);
310
 
311
        /* return the number of characters accepted (should be the complete
312
         * "chunk" as requested)
313
         */
314
        if ((status >= 0) && (status < count)) {
315
                pr_debug("Didn't accept the full chunk; %d of %d\n",
316
                         status, (int) count);
317
        }
318
        return status;
319
}
320
 
321
static unsigned int
322
scdrv_poll(struct file *file, struct poll_table_struct *wait)
323
{
324
        unsigned int mask = 0;
325
        int status = 0;
326
        struct subch_data_s *sd = (struct subch_data_s *) file->private_data;
327
        unsigned long flags;
328
 
329
        poll_wait(file, &sd->sd_rq, wait);
330
        poll_wait(file, &sd->sd_wq, wait);
331
 
332
        spin_lock_irqsave(&sd->sd_rlock, flags);
333
        spin_lock(&sd->sd_wlock);
334
        status = ia64_sn_irtr_intr(sd->sd_nasid, sd->sd_subch);
335
        spin_unlock(&sd->sd_wlock);
336
        spin_unlock_irqrestore(&sd->sd_rlock, flags);
337
 
338
        if (status > 0) {
339
                if (status & SAL_IROUTER_INTR_RECV) {
340
                        mask |= POLLIN | POLLRDNORM;
341
                }
342
                if (status & SAL_IROUTER_INTR_XMIT) {
343
                        mask |= POLLOUT | POLLWRNORM;
344
                }
345
        }
346
 
347
        return mask;
348
}
349
 
350
static const struct file_operations scdrv_fops = {
351
        .owner =        THIS_MODULE,
352
        .read =         scdrv_read,
353
        .write =        scdrv_write,
354
        .poll =         scdrv_poll,
355
        .open =         scdrv_open,
356
        .release =      scdrv_release,
357
};
358
 
359
static struct class *snsc_class;
360
 
361
/*
362
 * scdrv_init
363
 *
364
 * Called at boot time to initialize the system controller communication
365
 * facility.
366
 */
367
int __init
368
scdrv_init(void)
369
{
370
        geoid_t geoid;
371
        cnodeid_t cnode;
372
        char devname[32];
373
        char *devnamep;
374
        struct sysctl_data_s *scd;
375
        void *salbuf;
376
        dev_t first_dev, dev;
377
        nasid_t event_nasid;
378
 
379
        if (!ia64_platform_is("sn2"))
380
                return -ENODEV;
381
 
382
        event_nasid = ia64_sn_get_console_nasid();
383
 
384
        if (alloc_chrdev_region(&first_dev, 0, num_cnodes,
385
                                SYSCTL_BASENAME) < 0) {
386
                printk("%s: failed to register SN system controller device\n",
387
                       __FUNCTION__);
388
                return -ENODEV;
389
        }
390
        snsc_class = class_create(THIS_MODULE, SYSCTL_BASENAME);
391
 
392
        for (cnode = 0; cnode < num_cnodes; cnode++) {
393
                        geoid = cnodeid_get_geoid(cnode);
394
                        devnamep = devname;
395
                        format_module_id(devnamep, geo_module(geoid),
396
                                         MODULE_FORMAT_BRIEF);
397
                        devnamep = devname + strlen(devname);
398
                        sprintf(devnamep, "^%d#%d", geo_slot(geoid),
399
                                geo_slab(geoid));
400
 
401
                        /* allocate sysctl device data */
402
                        scd = kzalloc(sizeof (struct sysctl_data_s),
403
                                      GFP_KERNEL);
404
                        if (!scd) {
405
                                printk("%s: failed to allocate device info"
406
                                       "for %s/%s\n", __FUNCTION__,
407
                                       SYSCTL_BASENAME, devname);
408
                                continue;
409
                        }
410
 
411
                        /* initialize sysctl device data fields */
412
                        scd->scd_nasid = cnodeid_to_nasid(cnode);
413
                        if (!(salbuf = kmalloc(SCDRV_BUFSZ, GFP_KERNEL))) {
414
                                printk("%s: failed to allocate driver buffer"
415
                                       "(%s%s)\n", __FUNCTION__,
416
                                       SYSCTL_BASENAME, devname);
417
                                kfree(scd);
418
                                continue;
419
                        }
420
 
421
                        if (ia64_sn_irtr_init(scd->scd_nasid, salbuf,
422
                                              SCDRV_BUFSZ) < 0) {
423
                                printk
424
                                    ("%s: failed to initialize SAL for"
425
                                     " system controller communication"
426
                                     " (%s/%s): outdated PROM?\n",
427
                                     __FUNCTION__, SYSCTL_BASENAME, devname);
428
                                kfree(scd);
429
                                kfree(salbuf);
430
                                continue;
431
                        }
432
 
433
                        dev = first_dev + cnode;
434
                        cdev_init(&scd->scd_cdev, &scdrv_fops);
435
                        if (cdev_add(&scd->scd_cdev, dev, 1)) {
436
                                printk("%s: failed to register system"
437
                                       " controller device (%s%s)\n",
438
                                       __FUNCTION__, SYSCTL_BASENAME, devname);
439
                                kfree(scd);
440
                                kfree(salbuf);
441
                                continue;
442
                        }
443
 
444
                        device_create(snsc_class, NULL, dev, "%s", devname);
445
 
446
                        ia64_sn_irtr_intr_enable(scd->scd_nasid,
447
 
448
                                                 SAL_IROUTER_INTR_RECV);
449
 
450
                        /* on the console nasid, prepare to receive
451
                         * system controller environmental events
452
                         */
453
                        if(scd->scd_nasid == event_nasid) {
454
                                scdrv_event_init(scd);
455
                        }
456
        }
457
        return 0;
458
}
459
 
460
module_init(scdrv_init);

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.