1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * IBM ASM Service Processor Device Driver
5 * Copyright (C) IBM Corporation, 2004
7 * Author: Max Asböck <amax@us.ibm.com>
11 * Parts of this code are based on an article by Jonathan Corbet
12 * that appeared in Linux Weekly News.
17 * The IBMASM file virtual filesystem. It creates the following hierarchy
18 * dynamically when mounted from user space:
24 * | |-- reverse_heartbeat
35 * |-- reverse_heartbeat
41 * For each service processor the following files are created:
43 * command: execute dot commands
44 * write: execute a dot command on the service processor
45 * read: return the result of a previously executed dot command
47 * events: listen for service processor events
48 * read: sleep (interruptible) until an event occurs
49 * write: wakeup sleeping event listener
51 * reverse_heartbeat: send a heartbeat to the service processor
52 * read: sleep (interruptible) until the reverse heartbeat fails
53 * write: wakeup sleeping heartbeat listener
57 * remote_video/width: control remote display settings
63 #include <linux/fs_context.h>
64 #include <linux/pagemap.h>
65 #include <linux/slab.h>
66 #include <linux/uaccess.h>
70 #include "dot_command.h"
72 #define IBMASMFS_MAGIC 0x66726f67
74 static LIST_HEAD(service_processors
);
76 static struct inode
*ibmasmfs_make_inode(struct super_block
*sb
, int mode
);
77 static void ibmasmfs_create_files (struct super_block
*sb
);
78 static int ibmasmfs_fill_super(struct super_block
*sb
, struct fs_context
*fc
);
80 static int ibmasmfs_get_tree(struct fs_context
*fc
)
82 return get_tree_single(fc
, ibmasmfs_fill_super
);
85 static const struct fs_context_operations ibmasmfs_context_ops
= {
86 .get_tree
= ibmasmfs_get_tree
,
89 static int ibmasmfs_init_fs_context(struct fs_context
*fc
)
91 fc
->ops
= &ibmasmfs_context_ops
;
95 static const struct super_operations ibmasmfs_s_ops
= {
96 .statfs
= simple_statfs
,
97 .drop_inode
= generic_delete_inode
,
100 static const struct file_operations
*ibmasmfs_dir_ops
= &simple_dir_operations
;
102 static struct file_system_type ibmasmfs_type
= {
103 .owner
= THIS_MODULE
,
105 .init_fs_context
= ibmasmfs_init_fs_context
,
106 .kill_sb
= kill_litter_super
,
108 MODULE_ALIAS_FS("ibmasmfs");
110 static int ibmasmfs_fill_super(struct super_block
*sb
, struct fs_context
*fc
)
114 sb
->s_blocksize
= PAGE_SIZE
;
115 sb
->s_blocksize_bits
= PAGE_SHIFT
;
116 sb
->s_magic
= IBMASMFS_MAGIC
;
117 sb
->s_op
= &ibmasmfs_s_ops
;
120 root
= ibmasmfs_make_inode (sb
, S_IFDIR
| 0500);
124 root
->i_op
= &simple_dir_inode_operations
;
125 root
->i_fop
= ibmasmfs_dir_ops
;
127 sb
->s_root
= d_make_root(root
);
131 ibmasmfs_create_files(sb
);
135 static struct inode
*ibmasmfs_make_inode(struct super_block
*sb
, int mode
)
137 struct inode
*ret
= new_inode(sb
);
140 ret
->i_ino
= get_next_ino();
142 ret
->i_atime
= ret
->i_mtime
= ret
->i_ctime
= current_time(ret
);
147 static struct dentry
*ibmasmfs_create_file(struct dentry
*parent
,
149 const struct file_operations
*fops
,
153 struct dentry
*dentry
;
156 dentry
= d_alloc_name(parent
, name
);
160 inode
= ibmasmfs_make_inode(parent
->d_sb
, S_IFREG
| mode
);
167 inode
->i_private
= data
;
169 d_add(dentry
, inode
);
173 static struct dentry
*ibmasmfs_create_dir(struct dentry
*parent
,
176 struct dentry
*dentry
;
179 dentry
= d_alloc_name(parent
, name
);
183 inode
= ibmasmfs_make_inode(parent
->d_sb
, S_IFDIR
| 0500);
189 inode
->i_op
= &simple_dir_inode_operations
;
190 inode
->i_fop
= ibmasmfs_dir_ops
;
192 d_add(dentry
, inode
);
196 int ibmasmfs_register(void)
198 return register_filesystem(&ibmasmfs_type
);
201 void ibmasmfs_unregister(void)
203 unregister_filesystem(&ibmasmfs_type
);
206 void ibmasmfs_add_sp(struct service_processor
*sp
)
208 list_add(&sp
->node
, &service_processors
);
211 /* struct to save state between command file operations */
212 struct ibmasmfs_command_data
{
213 struct service_processor
*sp
;
214 struct command
*command
;
217 /* struct to save state between event file operations */
218 struct ibmasmfs_event_data
{
219 struct service_processor
*sp
;
220 struct event_reader reader
;
224 /* struct to save state between reverse heartbeat file operations */
225 struct ibmasmfs_heartbeat_data
{
226 struct service_processor
*sp
;
227 struct reverse_heartbeat heartbeat
;
231 static int command_file_open(struct inode
*inode
, struct file
*file
)
233 struct ibmasmfs_command_data
*command_data
;
235 if (!inode
->i_private
)
238 command_data
= kmalloc(sizeof(struct ibmasmfs_command_data
), GFP_KERNEL
);
242 command_data
->command
= NULL
;
243 command_data
->sp
= inode
->i_private
;
244 file
->private_data
= command_data
;
248 static int command_file_close(struct inode
*inode
, struct file
*file
)
250 struct ibmasmfs_command_data
*command_data
= file
->private_data
;
252 if (command_data
->command
)
253 command_put(command_data
->command
);
259 static ssize_t
command_file_read(struct file
*file
, char __user
*buf
, size_t count
, loff_t
*offset
)
261 struct ibmasmfs_command_data
*command_data
= file
->private_data
;
268 if (count
== 0 || count
> IBMASM_CMD_MAX_BUFFER_SIZE
)
273 spin_lock_irqsave(&command_data
->sp
->lock
, flags
);
274 cmd
= command_data
->command
;
276 spin_unlock_irqrestore(&command_data
->sp
->lock
, flags
);
279 command_data
->command
= NULL
;
280 spin_unlock_irqrestore(&command_data
->sp
->lock
, flags
);
282 if (cmd
->status
!= IBMASM_CMD_COMPLETE
) {
286 len
= min(count
, cmd
->buffer_size
);
287 if (copy_to_user(buf
, cmd
->buffer
, len
)) {
296 static ssize_t
command_file_write(struct file
*file
, const char __user
*ubuff
, size_t count
, loff_t
*offset
)
298 struct ibmasmfs_command_data
*command_data
= file
->private_data
;
304 if (count
== 0 || count
> IBMASM_CMD_MAX_BUFFER_SIZE
)
309 /* commands are executed sequentially, only one command at a time */
310 if (command_data
->command
)
313 cmd
= ibmasm_new_command(command_data
->sp
, count
);
317 if (copy_from_user(cmd
->buffer
, ubuff
, count
)) {
322 spin_lock_irqsave(&command_data
->sp
->lock
, flags
);
323 if (command_data
->command
) {
324 spin_unlock_irqrestore(&command_data
->sp
->lock
, flags
);
328 command_data
->command
= cmd
;
329 spin_unlock_irqrestore(&command_data
->sp
->lock
, flags
);
331 ibmasm_exec_command(command_data
->sp
, cmd
);
332 ibmasm_wait_for_response(cmd
, get_dot_command_timeout(cmd
->buffer
));
337 static int event_file_open(struct inode
*inode
, struct file
*file
)
339 struct ibmasmfs_event_data
*event_data
;
340 struct service_processor
*sp
;
342 if (!inode
->i_private
)
345 sp
= inode
->i_private
;
347 event_data
= kmalloc(sizeof(struct ibmasmfs_event_data
), GFP_KERNEL
);
351 ibmasm_event_reader_register(sp
, &event_data
->reader
);
354 event_data
->active
= 0;
355 file
->private_data
= event_data
;
359 static int event_file_close(struct inode
*inode
, struct file
*file
)
361 struct ibmasmfs_event_data
*event_data
= file
->private_data
;
363 ibmasm_event_reader_unregister(event_data
->sp
, &event_data
->reader
);
368 static ssize_t
event_file_read(struct file
*file
, char __user
*buf
, size_t count
, loff_t
*offset
)
370 struct ibmasmfs_event_data
*event_data
= file
->private_data
;
371 struct event_reader
*reader
= &event_data
->reader
;
372 struct service_processor
*sp
= event_data
->sp
;
378 if (count
== 0 || count
> IBMASM_EVENT_MAX_SIZE
)
383 spin_lock_irqsave(&sp
->lock
, flags
);
384 if (event_data
->active
) {
385 spin_unlock_irqrestore(&sp
->lock
, flags
);
388 event_data
->active
= 1;
389 spin_unlock_irqrestore(&sp
->lock
, flags
);
391 ret
= ibmasm_get_next_event(sp
, reader
);
395 if (count
< reader
->data_size
) {
400 if (copy_to_user(buf
, reader
->data
, reader
->data_size
)) {
404 ret
= reader
->data_size
;
407 event_data
->active
= 0;
411 static ssize_t
event_file_write(struct file
*file
, const char __user
*buf
, size_t count
, loff_t
*offset
)
413 struct ibmasmfs_event_data
*event_data
= file
->private_data
;
422 ibmasm_cancel_next_event(&event_data
->reader
);
426 static int r_heartbeat_file_open(struct inode
*inode
, struct file
*file
)
428 struct ibmasmfs_heartbeat_data
*rhbeat
;
430 if (!inode
->i_private
)
433 rhbeat
= kmalloc(sizeof(struct ibmasmfs_heartbeat_data
), GFP_KERNEL
);
437 rhbeat
->sp
= inode
->i_private
;
439 ibmasm_init_reverse_heartbeat(rhbeat
->sp
, &rhbeat
->heartbeat
);
440 file
->private_data
= rhbeat
;
444 static int r_heartbeat_file_close(struct inode
*inode
, struct file
*file
)
446 struct ibmasmfs_heartbeat_data
*rhbeat
= file
->private_data
;
452 static ssize_t
r_heartbeat_file_read(struct file
*file
, char __user
*buf
, size_t count
, loff_t
*offset
)
454 struct ibmasmfs_heartbeat_data
*rhbeat
= file
->private_data
;
460 if (count
== 0 || count
> 1024)
465 /* allow only one reverse heartbeat per process */
466 spin_lock_irqsave(&rhbeat
->sp
->lock
, flags
);
467 if (rhbeat
->active
) {
468 spin_unlock_irqrestore(&rhbeat
->sp
->lock
, flags
);
472 spin_unlock_irqrestore(&rhbeat
->sp
->lock
, flags
);
474 result
= ibmasm_start_reverse_heartbeat(rhbeat
->sp
, &rhbeat
->heartbeat
);
480 static ssize_t
r_heartbeat_file_write(struct file
*file
, const char __user
*buf
, size_t count
, loff_t
*offset
)
482 struct ibmasmfs_heartbeat_data
*rhbeat
= file
->private_data
;
492 ibmasm_stop_reverse_heartbeat(&rhbeat
->heartbeat
);
497 static int remote_settings_file_close(struct inode
*inode
, struct file
*file
)
502 static ssize_t
remote_settings_file_read(struct file
*file
, char __user
*buf
, size_t count
, loff_t
*offset
)
504 void __iomem
*address
= (void __iomem
*)file
->private_data
;
509 value
= readl(address
);
510 len
= snprintf(lbuf
, sizeof(lbuf
), "%d\n", value
);
512 return simple_read_from_buffer(buf
, count
, offset
, lbuf
, len
);
515 static ssize_t
remote_settings_file_write(struct file
*file
, const char __user
*ubuff
, size_t count
, loff_t
*offset
)
517 void __iomem
*address
= (void __iomem
*)file
->private_data
;
523 if (count
== 0 || count
> 1024)
528 buff
= kzalloc (count
+ 1, GFP_KERNEL
);
533 if (copy_from_user(buff
, ubuff
, count
)) {
538 value
= simple_strtoul(buff
, NULL
, 10);
539 writel(value
, address
);
545 static const struct file_operations command_fops
= {
546 .open
= command_file_open
,
547 .release
= command_file_close
,
548 .read
= command_file_read
,
549 .write
= command_file_write
,
550 .llseek
= generic_file_llseek
,
553 static const struct file_operations event_fops
= {
554 .open
= event_file_open
,
555 .release
= event_file_close
,
556 .read
= event_file_read
,
557 .write
= event_file_write
,
558 .llseek
= generic_file_llseek
,
561 static const struct file_operations r_heartbeat_fops
= {
562 .open
= r_heartbeat_file_open
,
563 .release
= r_heartbeat_file_close
,
564 .read
= r_heartbeat_file_read
,
565 .write
= r_heartbeat_file_write
,
566 .llseek
= generic_file_llseek
,
569 static const struct file_operations remote_settings_fops
= {
571 .release
= remote_settings_file_close
,
572 .read
= remote_settings_file_read
,
573 .write
= remote_settings_file_write
,
574 .llseek
= generic_file_llseek
,
578 static void ibmasmfs_create_files (struct super_block
*sb
)
580 struct list_head
*entry
;
581 struct service_processor
*sp
;
583 list_for_each(entry
, &service_processors
) {
585 struct dentry
*remote_dir
;
586 sp
= list_entry(entry
, struct service_processor
, node
);
587 dir
= ibmasmfs_create_dir(sb
->s_root
, sp
->dirname
);
591 ibmasmfs_create_file(dir
, "command", &command_fops
, sp
, S_IRUSR
|S_IWUSR
);
592 ibmasmfs_create_file(dir
, "event", &event_fops
, sp
, S_IRUSR
|S_IWUSR
);
593 ibmasmfs_create_file(dir
, "reverse_heartbeat", &r_heartbeat_fops
, sp
, S_IRUSR
|S_IWUSR
);
595 remote_dir
= ibmasmfs_create_dir(dir
, "remote_video");
599 ibmasmfs_create_file(remote_dir
, "width", &remote_settings_fops
, (void *)display_width(sp
), S_IRUSR
|S_IWUSR
);
600 ibmasmfs_create_file(remote_dir
, "height", &remote_settings_fops
, (void *)display_height(sp
), S_IRUSR
|S_IWUSR
);
601 ibmasmfs_create_file(remote_dir
, "depth", &remote_settings_fops
, (void *)display_depth(sp
), S_IRUSR
|S_IWUSR
);