Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
linux
Commits
f92e3618
Commit
f92e3618
authored
Feb 14, 2003
by
Todd Inglett
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
ppc64: new scanlog interface
parent
a2d6e7a2
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
272 additions
and
0 deletions
+272
-0
arch/ppc64/Kconfig
arch/ppc64/Kconfig
+4
-0
arch/ppc64/kernel/Makefile
arch/ppc64/kernel/Makefile
+1
-0
arch/ppc64/kernel/rtas.c
arch/ppc64/kernel/rtas.c
+10
-0
arch/ppc64/kernel/scanlog.c
arch/ppc64/kernel/scanlog.c
+249
-0
include/asm-ppc64/rtas.h
include/asm-ppc64/rtas.h
+8
-0
No files found.
arch/ppc64/Kconfig
View file @
f92e3618
...
...
@@ -128,6 +128,10 @@ config RTAS_FLASH
tristate "Firmware flash interface"
depends on !PPC_ISERIES
config SCANLOG
tristate "Scanlog dump interface"
depends on !PPC_ISERIES
config PPC_RTAS
bool "Proc interface to RTAS"
depends on !PPC_ISERIES
...
...
arch/ppc64/kernel/Makefile
View file @
f92e3618
...
...
@@ -30,3 +30,4 @@ obj-$(CONFIG_SMP) += smp.o
obj-$(CONFIG_PROFILING)
+=
profile.o
obj-$(CONFIG_MODULES)
+=
module.o ppc_ksyms.o
obj-$(CONFIG_PPC_RTAS)
+=
rtas-proc.o
obj-$(CONFIG_SCANLOG)
+=
scanlog.o
arch/ppc64/kernel/rtas.c
View file @
f92e3618
...
...
@@ -56,6 +56,9 @@ struct rtas_t rtas = {
extern
unsigned
long
reloc_offset
(
void
);
spinlock_t
rtas_data_buf_lock
=
SPIN_LOCK_UNLOCKED
;
char
rtas_data_buf
[
RTAS_DATA_BUF_SIZE
];
void
phys_call_rtas
(
int
token
,
int
nargs
,
int
nret
,
...)
{
...
...
@@ -278,3 +281,10 @@ rtas_halt(void)
rtas_flash_bypass_warning
();
rtas_power_off
();
}
EXPORT_SYMBOL
(
rtas_proc_dir
);
EXPORT_SYMBOL
(
rtas_firmware_flash_list
);
EXPORT_SYMBOL
(
rtas_token
);
EXPORT_SYMBOL
(
rtas_call
);
EXPORT_SYMBOL
(
rtas_data_buf
);
EXPORT_SYMBOL
(
rtas_data_buf_lock
);
arch/ppc64/kernel/scanlog.c
0 → 100644
View file @
f92e3618
/*
* c 2001 PPC 64 Team, IBM Corp
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*
* scan-log-data driver for PPC64 Todd Inglett <tinglett@vnet.ibm.com>
*
* When ppc64 hardware fails the service processor dumps internal state
* of the system. After a reboot the operating system can access a dump
* of this data using this driver. A dump exists if the device-tree
* /chosen/ibm,scan-log-data property exists.
*
* This driver exports /proc/ppc64/scan-log-dump which can be read.
* The driver supports only sequential reads.
*
* The driver looks at a write to the driver for the single word "reset".
* If given, the driver will reset the scanlog so the platform can free it.
*/
#include <linux/module.h>
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/proc_fs.h>
#include <linux/init.h>
#include <asm/uaccess.h>
#include <asm/rtas.h>
#include <asm/prom.h>
#define MODULE_VERSION "1.0"
#define MODULE_NAME "scanlog"
/* Status returns from ibm,scan-log-dump */
#define SCANLOG_COMPLETE 0
#define SCANLOG_HWERROR -1
#define SCANLOG_CONTINUE 1
#define DEBUG(A...) do { if (scanlog_debug) printk(KERN_ERR "scanlog: " A); } while (0)
static
int
scanlog_debug
;
static
unsigned
int
ibm_scan_log_dump
;
/* RTAS token */
static
struct
proc_dir_entry
*
proc_ppc64_scan_log_dump
;
/* The proc file */
extern
struct
proc_dir_entry
*
proc_rtas
;
static
ssize_t
scanlog_read
(
struct
file
*
file
,
char
*
buf
,
size_t
count
,
loff_t
*
ppos
)
{
struct
inode
*
inode
=
file
->
f_dentry
->
d_inode
;
struct
proc_dir_entry
*
dp
;
unsigned
int
*
data
;
unsigned
long
status
;
unsigned
long
len
,
off
;
unsigned
int
wait_time
;
dp
=
PDE
(
inode
);
data
=
(
unsigned
int
*
)
dp
->
data
;
if
(
!
data
)
{
printk
(
KERN_ERR
"scanlog: read failed no data
\n
"
);
return
-
EIO
;
}
if
(
count
>
RTAS_DATA_BUF_SIZE
)
count
=
RTAS_DATA_BUF_SIZE
;
if
(
count
<
1024
)
{
/* This is the min supported by this RTAS call. Rather
* than do all the buffering we insist the user code handle
* larger reads. As long as cp works... :)
*/
printk
(
KERN_ERR
"scanlog: cannot perform a small read (%ld)
\n
"
,
count
);
return
-
EINVAL
;
}
if
(
verify_area
(
VERIFY_WRITE
,
buf
,
count
))
return
-
EFAULT
;
for
(;;)
{
wait_time
=
HZ
/
2
;
/* default wait if no data */
spin_lock
(
&
rtas_data_buf_lock
);
memcpy
(
rtas_data_buf
,
data
,
RTAS_DATA_BUF_SIZE
);
status
=
rtas_call
(
ibm_scan_log_dump
,
2
,
1
,
NULL
,
__pa
(
rtas_data_buf
),
count
);
memcpy
(
data
,
rtas_data_buf
,
RTAS_DATA_BUF_SIZE
);
spin_unlock
(
&
rtas_data_buf_lock
);
DEBUG
(
"status=%ld, data[0]=%x, data[1]=%x, data[2]=%x
\n
"
,
status
,
data
[
0
],
data
[
1
],
data
[
2
]);
switch
(
status
)
{
case
SCANLOG_COMPLETE
:
DEBUG
(
"hit eof
\n
"
);
return
0
;
case
SCANLOG_HWERROR
:
DEBUG
(
"hardware error reading scan log data
\n
"
);
return
-
EIO
;
case
SCANLOG_CONTINUE
:
/* We may or may not have data yet */
len
=
data
[
1
];
off
=
data
[
2
];
if
(
len
>
0
)
{
if
(
copy_to_user
(
buf
,
((
char
*
)
data
)
+
off
,
len
))
return
-
EFAULT
;
return
len
;
}
/* Break to sleep default time */
break
;
default:
if
(
status
>
9900
&&
status
<=
9905
)
{
/* No data. RTAS is hinting at a delay required
* between 1-100000 milliseconds
*/
int
ms
=
1
;
for
(;
status
>
9900
;
status
--
)
ms
=
ms
*
10
;
/* Use microseconds for reasonable accuracy */
ms
*=
1000
;
wait_time
=
ms
/
(
1000000
/
HZ
);
/* round down is fine */
/* Fall through to sleep */
}
else
{
printk
(
KERN_ERR
"scanlog: unknown error from rtas: %ld
\n
"
,
status
);
return
-
EIO
;
}
}
/* Apparently no data yet. Wait and try again. */
set_current_state
(
TASK_INTERRUPTIBLE
);
schedule_timeout
(
wait_time
);
}
/*NOTREACHED*/
}
static
ssize_t
scanlog_write
(
struct
file
*
file
,
const
char
*
buf
,
size_t
count
,
loff_t
*
ppos
)
{
unsigned
long
status
;
if
(
buf
)
{
if
(
strncmp
(
buf
,
"reset"
,
5
)
==
0
)
{
DEBUG
(
"reset scanlog
\n
"
);
status
=
rtas_call
(
ibm_scan_log_dump
,
2
,
1
,
NULL
,
NULL
,
0
);
DEBUG
(
"rtas returns %ld
\n
"
,
status
);
}
else
if
(
strncmp
(
buf
,
"debugon"
,
7
)
==
0
)
{
printk
(
KERN_ERR
"scanlog: debug on
\n
"
);
scanlog_debug
=
1
;
}
else
if
(
strncmp
(
buf
,
"debugoff"
,
8
)
==
0
)
{
printk
(
KERN_ERR
"scanlog: debug off
\n
"
);
scanlog_debug
=
0
;
}
}
return
count
;
}
static
int
scanlog_open
(
struct
inode
*
inode
,
struct
file
*
file
)
{
struct
proc_dir_entry
*
dp
=
PDE
(
inode
);
unsigned
int
*
data
=
(
unsigned
int
*
)
dp
->
data
;
if
(
!
data
)
{
printk
(
KERN_ERR
"scanlog: open failed no data
\n
"
);
return
-
EIO
;
}
if
(
data
[
0
]
!=
0
)
{
/* This imperfect test stops a second copy of the
* data (or a reset while data is being copied)
*/
return
-
EBUSY
;
}
data
[
0
]
=
0
;
/* re-init so we restart the scan */
return
0
;
}
static
int
scanlog_release
(
struct
inode
*
inode
,
struct
file
*
file
)
{
struct
proc_dir_entry
*
dp
=
PDE
(
inode
);
unsigned
int
*
data
=
(
unsigned
int
*
)
dp
->
data
;
if
(
!
data
)
{
printk
(
KERN_ERR
"scanlog: release failed no data
\n
"
);
return
-
EIO
;
}
data
[
0
]
=
0
;
return
0
;
}
struct
file_operations
scanlog_fops
=
{
owner:
THIS_MODULE
,
read:
scanlog_read
,
write:
scanlog_write
,
open:
scanlog_open
,
release:
scanlog_release
,
};
int
__init
scanlog_init
(
void
)
{
struct
proc_dir_entry
*
ent
;
ibm_scan_log_dump
=
rtas_token
(
"ibm,scan-log-dump"
);
if
(
ibm_scan_log_dump
==
RTAS_UNKNOWN_SERVICE
)
{
printk
(
KERN_ERR
"scan-log-dump not implemented on this system
\n
"
);
return
-
EIO
;
}
if
(
proc_rtas
==
NULL
)
proc_rtas
=
proc_mkdir
(
"rtas"
,
0
);
if
(
proc_rtas
==
NULL
)
{
printk
(
KERN_ERR
"Failed to create /proc/rtas in scanlog_init
\n
"
);
return
-
EIO
;
}
ent
=
create_proc_entry
(
"scan-log-dump"
,
S_IRUSR
,
proc_rtas
);
if
(
ent
)
{
ent
->
proc_fops
=
&
scanlog_fops
;
/* Ideally we could allocate a buffer < 4G */
ent
->
data
=
kmalloc
(
RTAS_DATA_BUF_SIZE
,
GFP_KERNEL
);
if
(
!
ent
->
data
)
{
printk
(
KERN_ERR
"Failed to allocate a buffer
\n
"
);
remove_proc_entry
(
"scan-log-dump"
,
ent
->
parent
);
return
-
ENOMEM
;
}
((
unsigned
int
*
)
ent
->
data
)[
0
]
=
0
;
}
else
{
printk
(
KERN_ERR
"Failed to create ppc64/scan-log-dump proc entry
\n
"
);
return
-
EIO
;
}
proc_ppc64_scan_log_dump
=
ent
;
return
0
;
}
void
__exit
scanlog_cleanup
(
void
)
{
if
(
proc_ppc64_scan_log_dump
)
{
if
(
proc_ppc64_scan_log_dump
->
data
)
kfree
(
proc_ppc64_scan_log_dump
->
data
);
remove_proc_entry
(
"scan-log-dump"
,
proc_ppc64_scan_log_dump
->
parent
);
}
}
module_init
(
scanlog_init
);
module_exit
(
scanlog_cleanup
);
MODULE_LICENSE
(
"GPL"
);
include/asm-ppc64/rtas.h
View file @
f92e3618
...
...
@@ -168,5 +168,13 @@ extern void rtas_halt(void);
extern
struct
proc_dir_entry
*
rtas_proc_dir
;
/* Some RTAS ops require a data buffer and that buffer must be < 4G.
* Rather than having a memory allocator, just use this buffer
* (get the lock first), make the RTAS call. Copy the data instead
* of holding the buffer for long.
*/
#define RTAS_DATA_BUF_SIZE 1024
extern
spinlock_t
rtas_data_buf_lock
;
extern
char
rtas_data_buf
[
RTAS_DATA_BUF_SIZE
];
#endif
/* _PPC64_RTAS_H */
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment