Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
at v2.6.26-rc3 460 lines 11 kB view raw
1/* 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 36static irqreturn_t 37scdrv_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 69static int 70scdrv_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 __func__); 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", __func__); 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", __func__, rv); 114 return -EBUSY; 115 } 116 117 return 0; 118} 119 120/* 121 * scdrv_release 122 * 123 * Release a previously-reserved subchannel. 124 */ 125 126static int 127scdrv_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 149static inline int 150read_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 155static ssize_t 156scdrv_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 __func__, (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 */ 241static inline int 242write_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 247static ssize_t 248scdrv_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 321static unsigned int 322scdrv_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 350static 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 359static struct class *snsc_class; 360 361/* 362 * scdrv_init 363 * 364 * Called at boot time to initialize the system controller communication 365 * facility. 366 */ 367int __init 368scdrv_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 __func__); 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", __func__, 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", __func__, 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 __func__, 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 __func__, 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 0 /*ignored */ , 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 460module_init(scdrv_init);