0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062 #include <linux/fs.h>
0063 #include <linux/fs_context.h>
0064 #include <linux/pagemap.h>
0065 #include <linux/slab.h>
0066 #include <linux/uaccess.h>
0067 #include <asm/io.h>
0068 #include "ibmasm.h"
0069 #include "remote.h"
0070 #include "dot_command.h"
0071
0072 #define IBMASMFS_MAGIC 0x66726f67
0073
0074 static LIST_HEAD(service_processors);
0075
0076 static struct inode *ibmasmfs_make_inode(struct super_block *sb, int mode);
0077 static void ibmasmfs_create_files (struct super_block *sb);
0078 static int ibmasmfs_fill_super(struct super_block *sb, struct fs_context *fc);
0079
0080 static int ibmasmfs_get_tree(struct fs_context *fc)
0081 {
0082 return get_tree_single(fc, ibmasmfs_fill_super);
0083 }
0084
0085 static const struct fs_context_operations ibmasmfs_context_ops = {
0086 .get_tree = ibmasmfs_get_tree,
0087 };
0088
0089 static int ibmasmfs_init_fs_context(struct fs_context *fc)
0090 {
0091 fc->ops = &ibmasmfs_context_ops;
0092 return 0;
0093 }
0094
0095 static const struct super_operations ibmasmfs_s_ops = {
0096 .statfs = simple_statfs,
0097 .drop_inode = generic_delete_inode,
0098 };
0099
0100 static const struct file_operations *ibmasmfs_dir_ops = &simple_dir_operations;
0101
0102 static struct file_system_type ibmasmfs_type = {
0103 .owner = THIS_MODULE,
0104 .name = "ibmasmfs",
0105 .init_fs_context = ibmasmfs_init_fs_context,
0106 .kill_sb = kill_litter_super,
0107 };
0108 MODULE_ALIAS_FS("ibmasmfs");
0109
0110 static int ibmasmfs_fill_super(struct super_block *sb, struct fs_context *fc)
0111 {
0112 struct inode *root;
0113
0114 sb->s_blocksize = PAGE_SIZE;
0115 sb->s_blocksize_bits = PAGE_SHIFT;
0116 sb->s_magic = IBMASMFS_MAGIC;
0117 sb->s_op = &ibmasmfs_s_ops;
0118 sb->s_time_gran = 1;
0119
0120 root = ibmasmfs_make_inode (sb, S_IFDIR | 0500);
0121 if (!root)
0122 return -ENOMEM;
0123
0124 root->i_op = &simple_dir_inode_operations;
0125 root->i_fop = ibmasmfs_dir_ops;
0126
0127 sb->s_root = d_make_root(root);
0128 if (!sb->s_root)
0129 return -ENOMEM;
0130
0131 ibmasmfs_create_files(sb);
0132 return 0;
0133 }
0134
0135 static struct inode *ibmasmfs_make_inode(struct super_block *sb, int mode)
0136 {
0137 struct inode *ret = new_inode(sb);
0138
0139 if (ret) {
0140 ret->i_ino = get_next_ino();
0141 ret->i_mode = mode;
0142 ret->i_atime = ret->i_mtime = ret->i_ctime = current_time(ret);
0143 }
0144 return ret;
0145 }
0146
0147 static struct dentry *ibmasmfs_create_file(struct dentry *parent,
0148 const char *name,
0149 const struct file_operations *fops,
0150 void *data,
0151 int mode)
0152 {
0153 struct dentry *dentry;
0154 struct inode *inode;
0155
0156 dentry = d_alloc_name(parent, name);
0157 if (!dentry)
0158 return NULL;
0159
0160 inode = ibmasmfs_make_inode(parent->d_sb, S_IFREG | mode);
0161 if (!inode) {
0162 dput(dentry);
0163 return NULL;
0164 }
0165
0166 inode->i_fop = fops;
0167 inode->i_private = data;
0168
0169 d_add(dentry, inode);
0170 return dentry;
0171 }
0172
0173 static struct dentry *ibmasmfs_create_dir(struct dentry *parent,
0174 const char *name)
0175 {
0176 struct dentry *dentry;
0177 struct inode *inode;
0178
0179 dentry = d_alloc_name(parent, name);
0180 if (!dentry)
0181 return NULL;
0182
0183 inode = ibmasmfs_make_inode(parent->d_sb, S_IFDIR | 0500);
0184 if (!inode) {
0185 dput(dentry);
0186 return NULL;
0187 }
0188
0189 inode->i_op = &simple_dir_inode_operations;
0190 inode->i_fop = ibmasmfs_dir_ops;
0191
0192 d_add(dentry, inode);
0193 return dentry;
0194 }
0195
0196 int ibmasmfs_register(void)
0197 {
0198 return register_filesystem(&ibmasmfs_type);
0199 }
0200
0201 void ibmasmfs_unregister(void)
0202 {
0203 unregister_filesystem(&ibmasmfs_type);
0204 }
0205
0206 void ibmasmfs_add_sp(struct service_processor *sp)
0207 {
0208 list_add(&sp->node, &service_processors);
0209 }
0210
0211
0212 struct ibmasmfs_command_data {
0213 struct service_processor *sp;
0214 struct command *command;
0215 };
0216
0217
0218 struct ibmasmfs_event_data {
0219 struct service_processor *sp;
0220 struct event_reader reader;
0221 int active;
0222 };
0223
0224
0225 struct ibmasmfs_heartbeat_data {
0226 struct service_processor *sp;
0227 struct reverse_heartbeat heartbeat;
0228 int active;
0229 };
0230
0231 static int command_file_open(struct inode *inode, struct file *file)
0232 {
0233 struct ibmasmfs_command_data *command_data;
0234
0235 if (!inode->i_private)
0236 return -ENODEV;
0237
0238 command_data = kmalloc(sizeof(struct ibmasmfs_command_data), GFP_KERNEL);
0239 if (!command_data)
0240 return -ENOMEM;
0241
0242 command_data->command = NULL;
0243 command_data->sp = inode->i_private;
0244 file->private_data = command_data;
0245 return 0;
0246 }
0247
0248 static int command_file_close(struct inode *inode, struct file *file)
0249 {
0250 struct ibmasmfs_command_data *command_data = file->private_data;
0251
0252 if (command_data->command)
0253 command_put(command_data->command);
0254
0255 kfree(command_data);
0256 return 0;
0257 }
0258
0259 static ssize_t command_file_read(struct file *file, char __user *buf, size_t count, loff_t *offset)
0260 {
0261 struct ibmasmfs_command_data *command_data = file->private_data;
0262 struct command *cmd;
0263 int len;
0264 unsigned long flags;
0265
0266 if (*offset < 0)
0267 return -EINVAL;
0268 if (count == 0 || count > IBMASM_CMD_MAX_BUFFER_SIZE)
0269 return 0;
0270 if (*offset != 0)
0271 return 0;
0272
0273 spin_lock_irqsave(&command_data->sp->lock, flags);
0274 cmd = command_data->command;
0275 if (cmd == NULL) {
0276 spin_unlock_irqrestore(&command_data->sp->lock, flags);
0277 return 0;
0278 }
0279 command_data->command = NULL;
0280 spin_unlock_irqrestore(&command_data->sp->lock, flags);
0281
0282 if (cmd->status != IBMASM_CMD_COMPLETE) {
0283 command_put(cmd);
0284 return -EIO;
0285 }
0286 len = min(count, cmd->buffer_size);
0287 if (copy_to_user(buf, cmd->buffer, len)) {
0288 command_put(cmd);
0289 return -EFAULT;
0290 }
0291 command_put(cmd);
0292
0293 return len;
0294 }
0295
0296 static ssize_t command_file_write(struct file *file, const char __user *ubuff, size_t count, loff_t *offset)
0297 {
0298 struct ibmasmfs_command_data *command_data = file->private_data;
0299 struct command *cmd;
0300 unsigned long flags;
0301
0302 if (*offset < 0)
0303 return -EINVAL;
0304 if (count == 0 || count > IBMASM_CMD_MAX_BUFFER_SIZE)
0305 return 0;
0306 if (*offset != 0)
0307 return 0;
0308
0309
0310 if (command_data->command)
0311 return -EAGAIN;
0312
0313 cmd = ibmasm_new_command(command_data->sp, count);
0314 if (!cmd)
0315 return -ENOMEM;
0316
0317 if (copy_from_user(cmd->buffer, ubuff, count)) {
0318 command_put(cmd);
0319 return -EFAULT;
0320 }
0321
0322 spin_lock_irqsave(&command_data->sp->lock, flags);
0323 if (command_data->command) {
0324 spin_unlock_irqrestore(&command_data->sp->lock, flags);
0325 command_put(cmd);
0326 return -EAGAIN;
0327 }
0328 command_data->command = cmd;
0329 spin_unlock_irqrestore(&command_data->sp->lock, flags);
0330
0331 ibmasm_exec_command(command_data->sp, cmd);
0332 ibmasm_wait_for_response(cmd, get_dot_command_timeout(cmd->buffer));
0333
0334 return count;
0335 }
0336
0337 static int event_file_open(struct inode *inode, struct file *file)
0338 {
0339 struct ibmasmfs_event_data *event_data;
0340 struct service_processor *sp;
0341
0342 if (!inode->i_private)
0343 return -ENODEV;
0344
0345 sp = inode->i_private;
0346
0347 event_data = kmalloc(sizeof(struct ibmasmfs_event_data), GFP_KERNEL);
0348 if (!event_data)
0349 return -ENOMEM;
0350
0351 ibmasm_event_reader_register(sp, &event_data->reader);
0352
0353 event_data->sp = sp;
0354 event_data->active = 0;
0355 file->private_data = event_data;
0356 return 0;
0357 }
0358
0359 static int event_file_close(struct inode *inode, struct file *file)
0360 {
0361 struct ibmasmfs_event_data *event_data = file->private_data;
0362
0363 ibmasm_event_reader_unregister(event_data->sp, &event_data->reader);
0364 kfree(event_data);
0365 return 0;
0366 }
0367
0368 static ssize_t event_file_read(struct file *file, char __user *buf, size_t count, loff_t *offset)
0369 {
0370 struct ibmasmfs_event_data *event_data = file->private_data;
0371 struct event_reader *reader = &event_data->reader;
0372 struct service_processor *sp = event_data->sp;
0373 int ret;
0374 unsigned long flags;
0375
0376 if (*offset < 0)
0377 return -EINVAL;
0378 if (count == 0 || count > IBMASM_EVENT_MAX_SIZE)
0379 return 0;
0380 if (*offset != 0)
0381 return 0;
0382
0383 spin_lock_irqsave(&sp->lock, flags);
0384 if (event_data->active) {
0385 spin_unlock_irqrestore(&sp->lock, flags);
0386 return -EBUSY;
0387 }
0388 event_data->active = 1;
0389 spin_unlock_irqrestore(&sp->lock, flags);
0390
0391 ret = ibmasm_get_next_event(sp, reader);
0392 if (ret <= 0)
0393 goto out;
0394
0395 if (count < reader->data_size) {
0396 ret = -EINVAL;
0397 goto out;
0398 }
0399
0400 if (copy_to_user(buf, reader->data, reader->data_size)) {
0401 ret = -EFAULT;
0402 goto out;
0403 }
0404 ret = reader->data_size;
0405
0406 out:
0407 event_data->active = 0;
0408 return ret;
0409 }
0410
0411 static ssize_t event_file_write(struct file *file, const char __user *buf, size_t count, loff_t *offset)
0412 {
0413 struct ibmasmfs_event_data *event_data = file->private_data;
0414
0415 if (*offset < 0)
0416 return -EINVAL;
0417 if (count != 1)
0418 return 0;
0419 if (*offset != 0)
0420 return 0;
0421
0422 ibmasm_cancel_next_event(&event_data->reader);
0423 return 0;
0424 }
0425
0426 static int r_heartbeat_file_open(struct inode *inode, struct file *file)
0427 {
0428 struct ibmasmfs_heartbeat_data *rhbeat;
0429
0430 if (!inode->i_private)
0431 return -ENODEV;
0432
0433 rhbeat = kmalloc(sizeof(struct ibmasmfs_heartbeat_data), GFP_KERNEL);
0434 if (!rhbeat)
0435 return -ENOMEM;
0436
0437 rhbeat->sp = inode->i_private;
0438 rhbeat->active = 0;
0439 ibmasm_init_reverse_heartbeat(rhbeat->sp, &rhbeat->heartbeat);
0440 file->private_data = rhbeat;
0441 return 0;
0442 }
0443
0444 static int r_heartbeat_file_close(struct inode *inode, struct file *file)
0445 {
0446 struct ibmasmfs_heartbeat_data *rhbeat = file->private_data;
0447
0448 kfree(rhbeat);
0449 return 0;
0450 }
0451
0452 static ssize_t r_heartbeat_file_read(struct file *file, char __user *buf, size_t count, loff_t *offset)
0453 {
0454 struct ibmasmfs_heartbeat_data *rhbeat = file->private_data;
0455 unsigned long flags;
0456 int result;
0457
0458 if (*offset < 0)
0459 return -EINVAL;
0460 if (count == 0 || count > 1024)
0461 return 0;
0462 if (*offset != 0)
0463 return 0;
0464
0465
0466 spin_lock_irqsave(&rhbeat->sp->lock, flags);
0467 if (rhbeat->active) {
0468 spin_unlock_irqrestore(&rhbeat->sp->lock, flags);
0469 return -EBUSY;
0470 }
0471 rhbeat->active = 1;
0472 spin_unlock_irqrestore(&rhbeat->sp->lock, flags);
0473
0474 result = ibmasm_start_reverse_heartbeat(rhbeat->sp, &rhbeat->heartbeat);
0475 rhbeat->active = 0;
0476
0477 return result;
0478 }
0479
0480 static ssize_t r_heartbeat_file_write(struct file *file, const char __user *buf, size_t count, loff_t *offset)
0481 {
0482 struct ibmasmfs_heartbeat_data *rhbeat = file->private_data;
0483
0484 if (*offset < 0)
0485 return -EINVAL;
0486 if (count != 1)
0487 return 0;
0488 if (*offset != 0)
0489 return 0;
0490
0491 if (rhbeat->active)
0492 ibmasm_stop_reverse_heartbeat(&rhbeat->heartbeat);
0493
0494 return 1;
0495 }
0496
0497 static int remote_settings_file_close(struct inode *inode, struct file *file)
0498 {
0499 return 0;
0500 }
0501
0502 static ssize_t remote_settings_file_read(struct file *file, char __user *buf, size_t count, loff_t *offset)
0503 {
0504 void __iomem *address = (void __iomem *)file->private_data;
0505 int len = 0;
0506 unsigned int value;
0507 char lbuf[20];
0508
0509 value = readl(address);
0510 len = snprintf(lbuf, sizeof(lbuf), "%d\n", value);
0511
0512 return simple_read_from_buffer(buf, count, offset, lbuf, len);
0513 }
0514
0515 static ssize_t remote_settings_file_write(struct file *file, const char __user *ubuff, size_t count, loff_t *offset)
0516 {
0517 void __iomem *address = (void __iomem *)file->private_data;
0518 char *buff;
0519 unsigned int value;
0520
0521 if (*offset < 0)
0522 return -EINVAL;
0523 if (count == 0 || count > 1024)
0524 return 0;
0525 if (*offset != 0)
0526 return 0;
0527
0528 buff = kzalloc (count + 1, GFP_KERNEL);
0529 if (!buff)
0530 return -ENOMEM;
0531
0532
0533 if (copy_from_user(buff, ubuff, count)) {
0534 kfree(buff);
0535 return -EFAULT;
0536 }
0537
0538 value = simple_strtoul(buff, NULL, 10);
0539 writel(value, address);
0540 kfree(buff);
0541
0542 return count;
0543 }
0544
0545 static const struct file_operations command_fops = {
0546 .open = command_file_open,
0547 .release = command_file_close,
0548 .read = command_file_read,
0549 .write = command_file_write,
0550 .llseek = generic_file_llseek,
0551 };
0552
0553 static const struct file_operations event_fops = {
0554 .open = event_file_open,
0555 .release = event_file_close,
0556 .read = event_file_read,
0557 .write = event_file_write,
0558 .llseek = generic_file_llseek,
0559 };
0560
0561 static const struct file_operations r_heartbeat_fops = {
0562 .open = r_heartbeat_file_open,
0563 .release = r_heartbeat_file_close,
0564 .read = r_heartbeat_file_read,
0565 .write = r_heartbeat_file_write,
0566 .llseek = generic_file_llseek,
0567 };
0568
0569 static const struct file_operations remote_settings_fops = {
0570 .open = simple_open,
0571 .release = remote_settings_file_close,
0572 .read = remote_settings_file_read,
0573 .write = remote_settings_file_write,
0574 .llseek = generic_file_llseek,
0575 };
0576
0577
0578 static void ibmasmfs_create_files (struct super_block *sb)
0579 {
0580 struct list_head *entry;
0581 struct service_processor *sp;
0582
0583 list_for_each(entry, &service_processors) {
0584 struct dentry *dir;
0585 struct dentry *remote_dir;
0586 sp = list_entry(entry, struct service_processor, node);
0587 dir = ibmasmfs_create_dir(sb->s_root, sp->dirname);
0588 if (!dir)
0589 continue;
0590
0591 ibmasmfs_create_file(dir, "command", &command_fops, sp, S_IRUSR|S_IWUSR);
0592 ibmasmfs_create_file(dir, "event", &event_fops, sp, S_IRUSR|S_IWUSR);
0593 ibmasmfs_create_file(dir, "reverse_heartbeat", &r_heartbeat_fops, sp, S_IRUSR|S_IWUSR);
0594
0595 remote_dir = ibmasmfs_create_dir(dir, "remote_video");
0596 if (!remote_dir)
0597 continue;
0598
0599 ibmasmfs_create_file(remote_dir, "width", &remote_settings_fops, (void *)display_width(sp), S_IRUSR|S_IWUSR);
0600 ibmasmfs_create_file(remote_dir, "height", &remote_settings_fops, (void *)display_height(sp), S_IRUSR|S_IWUSR);
0601 ibmasmfs_create_file(remote_dir, "depth", &remote_settings_fops, (void *)display_depth(sp), S_IRUSR|S_IWUSR);
0602 }
0603 }