You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
Merge git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core-2.6: (64 commits)
debugfs: use specified mode to possibly mark files read/write only
debugfs: Fix terminology inconsistency of dir name to mount debugfs filesystem.
xen: remove driver_data direct access of struct device from more drivers
usb: gadget: at91_udc: remove driver_data direct access of struct device
uml: remove driver_data direct access of struct device
block/ps3: remove driver_data direct access of struct device
s390: remove driver_data direct access of struct device
parport: remove driver_data direct access of struct device
parisc: remove driver_data direct access of struct device
of_serial: remove driver_data direct access of struct device
mips: remove driver_data direct access of struct device
ipmi: remove driver_data direct access of struct device
infiniband: ehca: remove driver_data direct access of struct device
ibmvscsi: gadget: at91_udc: remove driver_data direct access of struct device
hvcs: remove driver_data direct access of struct device
xen block: remove driver_data direct access of struct device
thermal: remove driver_data direct access of struct device
scsi: remove driver_data direct access of struct device
pcmcia: remove driver_data direct access of struct device
PCIE: remove driver_data direct access of struct device
...
Manually fix up trivial conflicts due to different direct driver_data
direct access fixups in drivers/block/{ps3disk.c,ps3vram.c}
This commit is contained in:
@@ -106,7 +106,7 @@
|
||||
number of errors are printk'ed including a full stack trace.
|
||||
</para>
|
||||
<para>
|
||||
The statistics are available via debugfs/debug_objects/stats.
|
||||
The statistics are available via /sys/kernel/debug/debug_objects/stats.
|
||||
They provide information about the number of warnings and the
|
||||
number of successful fixups along with information about the
|
||||
usage of the internal tracking objects and the state of the
|
||||
|
||||
@@ -117,7 +117,7 @@ Using the pktcdvd debugfs interface
|
||||
|
||||
To read pktcdvd device infos in human readable form, do:
|
||||
|
||||
# cat /debug/pktcdvd/pktcdvd[0-7]/info
|
||||
# cat /sys/kernel/debug/pktcdvd/pktcdvd[0-7]/info
|
||||
|
||||
For a description of the debugfs interface look into the file:
|
||||
|
||||
|
||||
@@ -162,3 +162,35 @@ device_remove_file(dev,&dev_attr_power);
|
||||
|
||||
The file name will be 'power' with a mode of 0644 (-rw-r--r--).
|
||||
|
||||
Word of warning: While the kernel allows device_create_file() and
|
||||
device_remove_file() to be called on a device at any time, userspace has
|
||||
strict expectations on when attributes get created. When a new device is
|
||||
registered in the kernel, a uevent is generated to notify userspace (like
|
||||
udev) that a new device is available. If attributes are added after the
|
||||
device is registered, then userspace won't get notified and userspace will
|
||||
not know about the new attributes.
|
||||
|
||||
This is important for device driver that need to publish additional
|
||||
attributes for a device at driver probe time. If the device driver simply
|
||||
calls device_create_file() on the device structure passed to it, then
|
||||
userspace will never be notified of the new attributes. Instead, it should
|
||||
probably use class_create() and class->dev_attrs to set up a list of
|
||||
desired attributes in the modules_init function, and then in the .probe()
|
||||
hook, and then use device_create() to create a new device as a child
|
||||
of the probed device. The new device will generate a new uevent and
|
||||
properly advertise the new attributes to userspace.
|
||||
|
||||
For example, if a driver wanted to add the following attributes:
|
||||
struct device_attribute mydriver_attribs[] = {
|
||||
__ATTR(port_count, 0444, port_count_show),
|
||||
__ATTR(serial_number, 0444, serial_number_show),
|
||||
NULL
|
||||
};
|
||||
|
||||
Then in the module init function is would do:
|
||||
mydriver_class = class_create(THIS_MODULE, "my_attrs");
|
||||
mydriver_class.dev_attr = mydriver_attribs;
|
||||
|
||||
And assuming 'dev' is the struct device passed into the probe hook, the driver
|
||||
probe function would do something like:
|
||||
create_device(&mydriver_class, dev, chrdev, &private_data, "my_name");
|
||||
|
||||
@@ -29,16 +29,16 @@ o debugfs entries
|
||||
fault-inject-debugfs kernel module provides some debugfs entries for runtime
|
||||
configuration of fault-injection capabilities.
|
||||
|
||||
- /debug/fail*/probability:
|
||||
- /sys/kernel/debug/fail*/probability:
|
||||
|
||||
likelihood of failure injection, in percent.
|
||||
Format: <percent>
|
||||
|
||||
Note that one-failure-per-hundred is a very high error rate
|
||||
for some testcases. Consider setting probability=100 and configure
|
||||
/debug/fail*/interval for such testcases.
|
||||
/sys/kernel/debug/fail*/interval for such testcases.
|
||||
|
||||
- /debug/fail*/interval:
|
||||
- /sys/kernel/debug/fail*/interval:
|
||||
|
||||
specifies the interval between failures, for calls to
|
||||
should_fail() that pass all the other tests.
|
||||
@@ -46,18 +46,18 @@ configuration of fault-injection capabilities.
|
||||
Note that if you enable this, by setting interval>1, you will
|
||||
probably want to set probability=100.
|
||||
|
||||
- /debug/fail*/times:
|
||||
- /sys/kernel/debug/fail*/times:
|
||||
|
||||
specifies how many times failures may happen at most.
|
||||
A value of -1 means "no limit".
|
||||
|
||||
- /debug/fail*/space:
|
||||
- /sys/kernel/debug/fail*/space:
|
||||
|
||||
specifies an initial resource "budget", decremented by "size"
|
||||
on each call to should_fail(,size). Failure injection is
|
||||
suppressed until "space" reaches zero.
|
||||
|
||||
- /debug/fail*/verbose
|
||||
- /sys/kernel/debug/fail*/verbose
|
||||
|
||||
Format: { 0 | 1 | 2 }
|
||||
specifies the verbosity of the messages when failure is
|
||||
@@ -65,17 +65,17 @@ configuration of fault-injection capabilities.
|
||||
log line per failure; '2' will print a call trace too -- useful
|
||||
to debug the problems revealed by fault injection.
|
||||
|
||||
- /debug/fail*/task-filter:
|
||||
- /sys/kernel/debug/fail*/task-filter:
|
||||
|
||||
Format: { 'Y' | 'N' }
|
||||
A value of 'N' disables filtering by process (default).
|
||||
Any positive value limits failures to only processes indicated by
|
||||
/proc/<pid>/make-it-fail==1.
|
||||
|
||||
- /debug/fail*/require-start:
|
||||
- /debug/fail*/require-end:
|
||||
- /debug/fail*/reject-start:
|
||||
- /debug/fail*/reject-end:
|
||||
- /sys/kernel/debug/fail*/require-start:
|
||||
- /sys/kernel/debug/fail*/require-end:
|
||||
- /sys/kernel/debug/fail*/reject-start:
|
||||
- /sys/kernel/debug/fail*/reject-end:
|
||||
|
||||
specifies the range of virtual addresses tested during
|
||||
stacktrace walking. Failure is injected only if some caller
|
||||
@@ -84,26 +84,26 @@ configuration of fault-injection capabilities.
|
||||
Default required range is [0,ULONG_MAX) (whole of virtual address space).
|
||||
Default rejected range is [0,0).
|
||||
|
||||
- /debug/fail*/stacktrace-depth:
|
||||
- /sys/kernel/debug/fail*/stacktrace-depth:
|
||||
|
||||
specifies the maximum stacktrace depth walked during search
|
||||
for a caller within [require-start,require-end) OR
|
||||
[reject-start,reject-end).
|
||||
|
||||
- /debug/fail_page_alloc/ignore-gfp-highmem:
|
||||
- /sys/kernel/debug/fail_page_alloc/ignore-gfp-highmem:
|
||||
|
||||
Format: { 'Y' | 'N' }
|
||||
default is 'N', setting it to 'Y' won't inject failures into
|
||||
highmem/user allocations.
|
||||
|
||||
- /debug/failslab/ignore-gfp-wait:
|
||||
- /debug/fail_page_alloc/ignore-gfp-wait:
|
||||
- /sys/kernel/debug/failslab/ignore-gfp-wait:
|
||||
- /sys/kernel/debug/fail_page_alloc/ignore-gfp-wait:
|
||||
|
||||
Format: { 'Y' | 'N' }
|
||||
default is 'N', setting it to 'Y' will inject failures
|
||||
only into non-sleep allocations (GFP_ATOMIC allocations).
|
||||
|
||||
- /debug/fail_page_alloc/min-order:
|
||||
- /sys/kernel/debug/fail_page_alloc/min-order:
|
||||
|
||||
specifies the minimum page allocation order to be injected
|
||||
failures.
|
||||
@@ -166,13 +166,13 @@ o Inject slab allocation failures into module init/exit code
|
||||
#!/bin/bash
|
||||
|
||||
FAILTYPE=failslab
|
||||
echo Y > /debug/$FAILTYPE/task-filter
|
||||
echo 10 > /debug/$FAILTYPE/probability
|
||||
echo 100 > /debug/$FAILTYPE/interval
|
||||
echo -1 > /debug/$FAILTYPE/times
|
||||
echo 0 > /debug/$FAILTYPE/space
|
||||
echo 2 > /debug/$FAILTYPE/verbose
|
||||
echo 1 > /debug/$FAILTYPE/ignore-gfp-wait
|
||||
echo Y > /sys/kernel/debug/$FAILTYPE/task-filter
|
||||
echo 10 > /sys/kernel/debug/$FAILTYPE/probability
|
||||
echo 100 > /sys/kernel/debug/$FAILTYPE/interval
|
||||
echo -1 > /sys/kernel/debug/$FAILTYPE/times
|
||||
echo 0 > /sys/kernel/debug/$FAILTYPE/space
|
||||
echo 2 > /sys/kernel/debug/$FAILTYPE/verbose
|
||||
echo 1 > /sys/kernel/debug/$FAILTYPE/ignore-gfp-wait
|
||||
|
||||
faulty_system()
|
||||
{
|
||||
@@ -217,20 +217,20 @@ then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
cat /sys/module/$module/sections/.text > /debug/$FAILTYPE/require-start
|
||||
cat /sys/module/$module/sections/.data > /debug/$FAILTYPE/require-end
|
||||
cat /sys/module/$module/sections/.text > /sys/kernel/debug/$FAILTYPE/require-start
|
||||
cat /sys/module/$module/sections/.data > /sys/kernel/debug/$FAILTYPE/require-end
|
||||
|
||||
echo N > /debug/$FAILTYPE/task-filter
|
||||
echo 10 > /debug/$FAILTYPE/probability
|
||||
echo 100 > /debug/$FAILTYPE/interval
|
||||
echo -1 > /debug/$FAILTYPE/times
|
||||
echo 0 > /debug/$FAILTYPE/space
|
||||
echo 2 > /debug/$FAILTYPE/verbose
|
||||
echo 1 > /debug/$FAILTYPE/ignore-gfp-wait
|
||||
echo 1 > /debug/$FAILTYPE/ignore-gfp-highmem
|
||||
echo 10 > /debug/$FAILTYPE/stacktrace-depth
|
||||
echo N > /sys/kernel/debug/$FAILTYPE/task-filter
|
||||
echo 10 > /sys/kernel/debug/$FAILTYPE/probability
|
||||
echo 100 > /sys/kernel/debug/$FAILTYPE/interval
|
||||
echo -1 > /sys/kernel/debug/$FAILTYPE/times
|
||||
echo 0 > /sys/kernel/debug/$FAILTYPE/space
|
||||
echo 2 > /sys/kernel/debug/$FAILTYPE/verbose
|
||||
echo 1 > /sys/kernel/debug/$FAILTYPE/ignore-gfp-wait
|
||||
echo 1 > /sys/kernel/debug/$FAILTYPE/ignore-gfp-highmem
|
||||
echo 10 > /sys/kernel/debug/$FAILTYPE/stacktrace-depth
|
||||
|
||||
trap "echo 0 > /debug/$FAILTYPE/probability" SIGINT SIGTERM EXIT
|
||||
trap "echo 0 > /sys/kernel/debug/$FAILTYPE/probability" SIGINT SIGTERM EXIT
|
||||
|
||||
echo "Injecting errors into the module $module... (interrupt to stop)"
|
||||
sleep 1000000
|
||||
|
||||
@@ -77,7 +77,8 @@
|
||||
seconds for the whole load operation.
|
||||
|
||||
- request_firmware_nowait() is also provided for convenience in
|
||||
non-user contexts.
|
||||
user contexts to request firmware asynchronously, but can't be called
|
||||
in atomic contexts.
|
||||
|
||||
|
||||
about in-kernel persistence:
|
||||
|
||||
@@ -507,9 +507,9 @@ http://www.linuxsymposium.org/2006/linuxsymposium_procv2.pdf (pages 101-115)
|
||||
Appendix A: The kprobes debugfs interface
|
||||
|
||||
With recent kernels (> 2.6.20) the list of registered kprobes is visible
|
||||
under the /debug/kprobes/ directory (assuming debugfs is mounted at /debug).
|
||||
under the /sys/kernel/debug/kprobes/ directory (assuming debugfs is mounted at //sys/kernel/debug).
|
||||
|
||||
/debug/kprobes/list: Lists all registered probes on the system
|
||||
/sys/kernel/debug/kprobes/list: Lists all registered probes on the system
|
||||
|
||||
c015d71a k vfs_read+0x0
|
||||
c011a316 j do_fork+0x0
|
||||
@@ -525,7 +525,7 @@ virtual addresses that correspond to modules that've been unloaded),
|
||||
such probes are marked with [GONE]. If the probe is temporarily disabled,
|
||||
such probes are marked with [DISABLED].
|
||||
|
||||
/debug/kprobes/enabled: Turn kprobes ON/OFF forcibly.
|
||||
/sys/kernel/debug/kprobes/enabled: Turn kprobes ON/OFF forcibly.
|
||||
|
||||
Provides a knob to globally and forcibly turn registered kprobes ON or OFF.
|
||||
By default, all kprobes are enabled. By echoing "0" to this file, all
|
||||
|
||||
+142
-91
@@ -7,7 +7,6 @@ Copyright 2008 Red Hat Inc.
|
||||
(dual licensed under the GPL v2)
|
||||
Reviewers: Elias Oltmanns, Randy Dunlap, Andrew Morton,
|
||||
John Kacur, and David Teigland.
|
||||
|
||||
Written for: 2.6.28-rc2
|
||||
|
||||
Introduction
|
||||
@@ -33,13 +32,26 @@ The File System
|
||||
Ftrace uses the debugfs file system to hold the control files as
|
||||
well as the files to display output.
|
||||
|
||||
To mount the debugfs system:
|
||||
When debugfs is configured into the kernel (which selecting any ftrace
|
||||
option will do) the directory /sys/kernel/debug will be created. To mount
|
||||
this directory, you can add to your /etc/fstab file:
|
||||
|
||||
# mkdir /debug
|
||||
# mount -t debugfs nodev /debug
|
||||
debugfs /sys/kernel/debug debugfs defaults 0 0
|
||||
|
||||
( Note: it is more common to mount at /sys/kernel/debug, but for
|
||||
simplicity this document will use /debug)
|
||||
Or you can mount it at run time with:
|
||||
|
||||
mount -t debugfs nodev /sys/kernel/debug
|
||||
|
||||
For quicker access to that directory you may want to make a soft link to
|
||||
it:
|
||||
|
||||
ln -s /sys/kernel/debug /debug
|
||||
|
||||
Any selected ftrace option will also create a directory called tracing
|
||||
within the debugfs. The rest of the document will assume that you are in
|
||||
the ftrace directory (cd /sys/kernel/debug/tracing) and will only concentrate
|
||||
on the files within that directory and not distract from the content with
|
||||
the extended "/sys/kernel/debug/tracing" path name.
|
||||
|
||||
That's it! (assuming that you have ftrace configured into your kernel)
|
||||
|
||||
@@ -389,18 +401,18 @@ trace_options
|
||||
The trace_options file is used to control what gets printed in
|
||||
the trace output. To see what is available, simply cat the file:
|
||||
|
||||
cat /debug/tracing/trace_options
|
||||
cat trace_options
|
||||
print-parent nosym-offset nosym-addr noverbose noraw nohex nobin \
|
||||
noblock nostacktrace nosched-tree nouserstacktrace nosym-userobj
|
||||
|
||||
To disable one of the options, echo in the option prepended with
|
||||
"no".
|
||||
|
||||
echo noprint-parent > /debug/tracing/trace_options
|
||||
echo noprint-parent > trace_options
|
||||
|
||||
To enable an option, leave off the "no".
|
||||
|
||||
echo sym-offset > /debug/tracing/trace_options
|
||||
echo sym-offset > trace_options
|
||||
|
||||
Here are the available options:
|
||||
|
||||
@@ -476,11 +488,11 @@ sched_switch
|
||||
This tracer simply records schedule switches. Here is an example
|
||||
of how to use it.
|
||||
|
||||
# echo sched_switch > /debug/tracing/current_tracer
|
||||
# echo 1 > /debug/tracing/tracing_enabled
|
||||
# echo sched_switch > current_tracer
|
||||
# echo 1 > tracing_enabled
|
||||
# sleep 1
|
||||
# echo 0 > /debug/tracing/tracing_enabled
|
||||
# cat /debug/tracing/trace
|
||||
# echo 0 > tracing_enabled
|
||||
# cat trace
|
||||
|
||||
# tracer: sched_switch
|
||||
#
|
||||
@@ -583,13 +595,13 @@ new trace is saved.
|
||||
To reset the maximum, echo 0 into tracing_max_latency. Here is
|
||||
an example:
|
||||
|
||||
# echo irqsoff > /debug/tracing/current_tracer
|
||||
# echo 0 > /debug/tracing/tracing_max_latency
|
||||
# echo 1 > /debug/tracing/tracing_enabled
|
||||
# echo irqsoff > current_tracer
|
||||
# echo 0 > tracing_max_latency
|
||||
# echo 1 > tracing_enabled
|
||||
# ls -ltr
|
||||
[...]
|
||||
# echo 0 > /debug/tracing/tracing_enabled
|
||||
# cat /debug/tracing/latency_trace
|
||||
# echo 0 > tracing_enabled
|
||||
# cat latency_trace
|
||||
# tracer: irqsoff
|
||||
#
|
||||
irqsoff latency trace v1.1.5 on 2.6.26
|
||||
@@ -690,13 +702,13 @@ Like the irqsoff tracer, it records the maximum latency for
|
||||
which preemption was disabled. The control of preemptoff tracer
|
||||
is much like the irqsoff tracer.
|
||||
|
||||
# echo preemptoff > /debug/tracing/current_tracer
|
||||
# echo 0 > /debug/tracing/tracing_max_latency
|
||||
# echo 1 > /debug/tracing/tracing_enabled
|
||||
# echo preemptoff > current_tracer
|
||||
# echo 0 > tracing_max_latency
|
||||
# echo 1 > tracing_enabled
|
||||
# ls -ltr
|
||||
[...]
|
||||
# echo 0 > /debug/tracing/tracing_enabled
|
||||
# cat /debug/tracing/latency_trace
|
||||
# echo 0 > tracing_enabled
|
||||
# cat latency_trace
|
||||
# tracer: preemptoff
|
||||
#
|
||||
preemptoff latency trace v1.1.5 on 2.6.26-rc8
|
||||
@@ -837,13 +849,13 @@ tracer.
|
||||
Again, using this trace is much like the irqsoff and preemptoff
|
||||
tracers.
|
||||
|
||||
# echo preemptirqsoff > /debug/tracing/current_tracer
|
||||
# echo 0 > /debug/tracing/tracing_max_latency
|
||||
# echo 1 > /debug/tracing/tracing_enabled
|
||||
# echo preemptirqsoff > current_tracer
|
||||
# echo 0 > tracing_max_latency
|
||||
# echo 1 > tracing_enabled
|
||||
# ls -ltr
|
||||
[...]
|
||||
# echo 0 > /debug/tracing/tracing_enabled
|
||||
# cat /debug/tracing/latency_trace
|
||||
# echo 0 > tracing_enabled
|
||||
# cat latency_trace
|
||||
# tracer: preemptirqsoff
|
||||
#
|
||||
preemptirqsoff latency trace v1.1.5 on 2.6.26-rc8
|
||||
@@ -999,12 +1011,12 @@ slightly differently than we did with the previous tracers.
|
||||
Instead of performing an 'ls', we will run 'sleep 1' under
|
||||
'chrt' which changes the priority of the task.
|
||||
|
||||
# echo wakeup > /debug/tracing/current_tracer
|
||||
# echo 0 > /debug/tracing/tracing_max_latency
|
||||
# echo 1 > /debug/tracing/tracing_enabled
|
||||
# echo wakeup > current_tracer
|
||||
# echo 0 > tracing_max_latency
|
||||
# echo 1 > tracing_enabled
|
||||
# chrt -f 5 sleep 1
|
||||
# echo 0 > /debug/tracing/tracing_enabled
|
||||
# cat /debug/tracing/latency_trace
|
||||
# echo 0 > tracing_enabled
|
||||
# cat latency_trace
|
||||
# tracer: wakeup
|
||||
#
|
||||
wakeup latency trace v1.1.5 on 2.6.26-rc8
|
||||
@@ -1114,11 +1126,11 @@ can be done from the debug file system. Make sure the
|
||||
ftrace_enabled is set; otherwise this tracer is a nop.
|
||||
|
||||
# sysctl kernel.ftrace_enabled=1
|
||||
# echo function > /debug/tracing/current_tracer
|
||||
# echo 1 > /debug/tracing/tracing_enabled
|
||||
# echo function > current_tracer
|
||||
# echo 1 > tracing_enabled
|
||||
# usleep 1
|
||||
# echo 0 > /debug/tracing/tracing_enabled
|
||||
# cat /debug/tracing/trace
|
||||
# echo 0 > tracing_enabled
|
||||
# cat trace
|
||||
# tracer: function
|
||||
#
|
||||
# TASK-PID CPU# TIMESTAMP FUNCTION
|
||||
@@ -1155,7 +1167,7 @@ int trace_fd;
|
||||
[...]
|
||||
int main(int argc, char *argv[]) {
|
||||
[...]
|
||||
trace_fd = open("/debug/tracing/tracing_enabled", O_WRONLY);
|
||||
trace_fd = open(tracing_file("tracing_enabled"), O_WRONLY);
|
||||
[...]
|
||||
if (condition_hit()) {
|
||||
write(trace_fd, "0", 1);
|
||||
@@ -1163,26 +1175,20 @@ int main(int argc, char *argv[]) {
|
||||
[...]
|
||||
}
|
||||
|
||||
Note: Here we hard coded the path name. The debugfs mount is not
|
||||
guaranteed to be at /debug (and is more commonly at
|
||||
/sys/kernel/debug). For simple one time traces, the above is
|
||||
sufficent. For anything else, a search through /proc/mounts may
|
||||
be needed to find where the debugfs file-system is mounted.
|
||||
|
||||
|
||||
Single thread tracing
|
||||
---------------------
|
||||
|
||||
By writing into /debug/tracing/set_ftrace_pid you can trace a
|
||||
By writing into set_ftrace_pid you can trace a
|
||||
single thread. For example:
|
||||
|
||||
# cat /debug/tracing/set_ftrace_pid
|
||||
# cat set_ftrace_pid
|
||||
no pid
|
||||
# echo 3111 > /debug/tracing/set_ftrace_pid
|
||||
# cat /debug/tracing/set_ftrace_pid
|
||||
# echo 3111 > set_ftrace_pid
|
||||
# cat set_ftrace_pid
|
||||
3111
|
||||
# echo function > /debug/tracing/current_tracer
|
||||
# cat /debug/tracing/trace | head
|
||||
# echo function > current_tracer
|
||||
# cat trace | head
|
||||
# tracer: function
|
||||
#
|
||||
# TASK-PID CPU# TIMESTAMP FUNCTION
|
||||
@@ -1193,8 +1199,8 @@ no pid
|
||||
yum-updatesd-3111 [003] 1637.254683: lock_hrtimer_base <-hrtimer_try_to_cancel
|
||||
yum-updatesd-3111 [003] 1637.254685: fget_light <-do_sys_poll
|
||||
yum-updatesd-3111 [003] 1637.254686: pipe_poll <-do_sys_poll
|
||||
# echo -1 > /debug/tracing/set_ftrace_pid
|
||||
# cat /debug/tracing/trace |head
|
||||
# echo -1 > set_ftrace_pid
|
||||
# cat trace |head
|
||||
# tracer: function
|
||||
#
|
||||
# TASK-PID CPU# TIMESTAMP FUNCTION
|
||||
@@ -1216,6 +1222,51 @@ something like this simple program:
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define _STR(x) #x
|
||||
#define STR(x) _STR(x)
|
||||
#define MAX_PATH 256
|
||||
|
||||
const char *find_debugfs(void)
|
||||
{
|
||||
static char debugfs[MAX_PATH+1];
|
||||
static int debugfs_found;
|
||||
char type[100];
|
||||
FILE *fp;
|
||||
|
||||
if (debugfs_found)
|
||||
return debugfs;
|
||||
|
||||
if ((fp = fopen("/proc/mounts","r")) == NULL) {
|
||||
perror("/proc/mounts");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
while (fscanf(fp, "%*s %"
|
||||
STR(MAX_PATH)
|
||||
"s %99s %*s %*d %*d\n",
|
||||
debugfs, type) == 2) {
|
||||
if (strcmp(type, "debugfs") == 0)
|
||||
break;
|
||||
}
|
||||
fclose(fp);
|
||||
|
||||
if (strcmp(type, "debugfs") != 0) {
|
||||
fprintf(stderr, "debugfs not mounted");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
debugfs_found = 1;
|
||||
|
||||
return debugfs;
|
||||
}
|
||||
|
||||
const char *tracing_file(const char *file_name)
|
||||
{
|
||||
static char trace_file[MAX_PATH+1];
|
||||
snprintf(trace_file, MAX_PATH, "%s/%s", find_debugfs(), file_name);
|
||||
return trace_file;
|
||||
}
|
||||
|
||||
int main (int argc, char **argv)
|
||||
{
|
||||
if (argc < 1)
|
||||
@@ -1226,12 +1277,12 @@ int main (int argc, char **argv)
|
||||
char line[64];
|
||||
int s;
|
||||
|
||||
ffd = open("/debug/tracing/current_tracer", O_WRONLY);
|
||||
ffd = open(tracing_file("current_tracer"), O_WRONLY);
|
||||
if (ffd < 0)
|
||||
exit(-1);
|
||||
write(ffd, "nop", 3);
|
||||
|
||||
fd = open("/debug/tracing/set_ftrace_pid", O_WRONLY);
|
||||
fd = open(tracing_file("set_ftrace_pid"), O_WRONLY);
|
||||
s = sprintf(line, "%d\n", getpid());
|
||||
write(fd, line, s);
|
||||
|
||||
@@ -1383,22 +1434,22 @@ want, depending on your needs.
|
||||
tracing_cpu_mask file) or you might sometimes see unordered
|
||||
function calls while cpu tracing switch.
|
||||
|
||||
hide: echo nofuncgraph-cpu > /debug/tracing/trace_options
|
||||
show: echo funcgraph-cpu > /debug/tracing/trace_options
|
||||
hide: echo nofuncgraph-cpu > trace_options
|
||||
show: echo funcgraph-cpu > trace_options
|
||||
|
||||
- The duration (function's time of execution) is displayed on
|
||||
the closing bracket line of a function or on the same line
|
||||
than the current function in case of a leaf one. It is default
|
||||
enabled.
|
||||
|
||||
hide: echo nofuncgraph-duration > /debug/tracing/trace_options
|
||||
show: echo funcgraph-duration > /debug/tracing/trace_options
|
||||
hide: echo nofuncgraph-duration > trace_options
|
||||
show: echo funcgraph-duration > trace_options
|
||||
|
||||
- The overhead field precedes the duration field in case of
|
||||
reached duration thresholds.
|
||||
|
||||
hide: echo nofuncgraph-overhead > /debug/tracing/trace_options
|
||||
show: echo funcgraph-overhead > /debug/tracing/trace_options
|
||||
hide: echo nofuncgraph-overhead > trace_options
|
||||
show: echo funcgraph-overhead > trace_options
|
||||
depends on: funcgraph-duration
|
||||
|
||||
ie:
|
||||
@@ -1427,8 +1478,8 @@ want, depending on your needs.
|
||||
- The task/pid field displays the thread cmdline and pid which
|
||||
executed the function. It is default disabled.
|
||||
|
||||
hide: echo nofuncgraph-proc > /debug/tracing/trace_options
|
||||
show: echo funcgraph-proc > /debug/tracing/trace_options
|
||||
hide: echo nofuncgraph-proc > trace_options
|
||||
show: echo funcgraph-proc > trace_options
|
||||
|
||||
ie:
|
||||
|
||||
@@ -1451,8 +1502,8 @@ want, depending on your needs.
|
||||
system clock since it started. A snapshot of this time is
|
||||
given on each entry/exit of functions
|
||||
|
||||
hide: echo nofuncgraph-abstime > /debug/tracing/trace_options
|
||||
show: echo funcgraph-abstime > /debug/tracing/trace_options
|
||||
hide: echo nofuncgraph-abstime > trace_options
|
||||
show: echo funcgraph-abstime > trace_options
|
||||
|
||||
ie:
|
||||
|
||||
@@ -1549,7 +1600,7 @@ listed in:
|
||||
|
||||
available_filter_functions
|
||||
|
||||
# cat /debug/tracing/available_filter_functions
|
||||
# cat available_filter_functions
|
||||
put_prev_task_idle
|
||||
kmem_cache_create
|
||||
pick_next_task_rt
|
||||
@@ -1561,12 +1612,12 @@ mutex_lock
|
||||
If I am only interested in sys_nanosleep and hrtimer_interrupt:
|
||||
|
||||
# echo sys_nanosleep hrtimer_interrupt \
|
||||
> /debug/tracing/set_ftrace_filter
|
||||
# echo ftrace > /debug/tracing/current_tracer
|
||||
# echo 1 > /debug/tracing/tracing_enabled
|
||||
> set_ftrace_filter
|
||||
# echo ftrace > current_tracer
|
||||
# echo 1 > tracing_enabled
|
||||
# usleep 1
|
||||
# echo 0 > /debug/tracing/tracing_enabled
|
||||
# cat /debug/tracing/trace
|
||||
# echo 0 > tracing_enabled
|
||||
# cat trace
|
||||
# tracer: ftrace
|
||||
#
|
||||
# TASK-PID CPU# TIMESTAMP FUNCTION
|
||||
@@ -1577,7 +1628,7 @@ If I am only interested in sys_nanosleep and hrtimer_interrupt:
|
||||
|
||||
To see which functions are being traced, you can cat the file:
|
||||
|
||||
# cat /debug/tracing/set_ftrace_filter
|
||||
# cat set_ftrace_filter
|
||||
hrtimer_interrupt
|
||||
sys_nanosleep
|
||||
|
||||
@@ -1597,7 +1648,7 @@ Note: It is better to use quotes to enclose the wild cards,
|
||||
otherwise the shell may expand the parameters into names
|
||||
of files in the local directory.
|
||||
|
||||
# echo 'hrtimer_*' > /debug/tracing/set_ftrace_filter
|
||||
# echo 'hrtimer_*' > set_ftrace_filter
|
||||
|
||||
Produces:
|
||||
|
||||
@@ -1618,7 +1669,7 @@ Produces:
|
||||
|
||||
Notice that we lost the sys_nanosleep.
|
||||
|
||||
# cat /debug/tracing/set_ftrace_filter
|
||||
# cat set_ftrace_filter
|
||||
hrtimer_run_queues
|
||||
hrtimer_run_pending
|
||||
hrtimer_init
|
||||
@@ -1644,17 +1695,17 @@ To append to the filters, use '>>'
|
||||
To clear out a filter so that all functions will be recorded
|
||||
again:
|
||||
|
||||
# echo > /debug/tracing/set_ftrace_filter
|
||||
# cat /debug/tracing/set_ftrace_filter
|
||||
# echo > set_ftrace_filter
|
||||
# cat set_ftrace_filter
|
||||
#
|
||||
|
||||
Again, now we want to append.
|
||||
|
||||
# echo sys_nanosleep > /debug/tracing/set_ftrace_filter
|
||||
# cat /debug/tracing/set_ftrace_filter
|
||||
# echo sys_nanosleep > set_ftrace_filter
|
||||
# cat set_ftrace_filter
|
||||
sys_nanosleep
|
||||
# echo 'hrtimer_*' >> /debug/tracing/set_ftrace_filter
|
||||
# cat /debug/tracing/set_ftrace_filter
|
||||
# echo 'hrtimer_*' >> set_ftrace_filter
|
||||
# cat set_ftrace_filter
|
||||
hrtimer_run_queues
|
||||
hrtimer_run_pending
|
||||
hrtimer_init
|
||||
@@ -1677,7 +1728,7 @@ hrtimer_init_sleeper
|
||||
The set_ftrace_notrace prevents those functions from being
|
||||
traced.
|
||||
|
||||
# echo '*preempt*' '*lock*' > /debug/tracing/set_ftrace_notrace
|
||||
# echo '*preempt*' '*lock*' > set_ftrace_notrace
|
||||
|
||||
Produces:
|
||||
|
||||
@@ -1767,13 +1818,13 @@ the effect on the tracing is different. Every read from
|
||||
trace_pipe is consumed. This means that subsequent reads will be
|
||||
different. The trace is live.
|
||||
|
||||
# echo function > /debug/tracing/current_tracer
|
||||
# cat /debug/tracing/trace_pipe > /tmp/trace.out &
|
||||
# echo function > current_tracer
|
||||
# cat trace_pipe > /tmp/trace.out &
|
||||
[1] 4153
|
||||
# echo 1 > /debug/tracing/tracing_enabled
|
||||
# echo 1 > tracing_enabled
|
||||
# usleep 1
|
||||
# echo 0 > /debug/tracing/tracing_enabled
|
||||
# cat /debug/tracing/trace
|
||||
# echo 0 > tracing_enabled
|
||||
# cat trace
|
||||
# tracer: function
|
||||
#
|
||||
# TASK-PID CPU# TIMESTAMP FUNCTION
|
||||
@@ -1809,7 +1860,7 @@ number listed is the number of entries that can be recorded per
|
||||
CPU. To know the full size, multiply the number of possible CPUS
|
||||
with the number of entries.
|
||||
|
||||
# cat /debug/tracing/buffer_size_kb
|
||||
# cat buffer_size_kb
|
||||
1408 (units kilobytes)
|
||||
|
||||
Note, to modify this, you must have tracing completely disabled.
|
||||
@@ -1817,18 +1868,18 @@ To do that, echo "nop" into the current_tracer. If the
|
||||
current_tracer is not set to "nop", an EINVAL error will be
|
||||
returned.
|
||||
|
||||
# echo nop > /debug/tracing/current_tracer
|
||||
# echo 10000 > /debug/tracing/buffer_size_kb
|
||||
# cat /debug/tracing/buffer_size_kb
|
||||
# echo nop > current_tracer
|
||||
# echo 10000 > buffer_size_kb
|
||||
# cat buffer_size_kb
|
||||
10000 (units kilobytes)
|
||||
|
||||
The number of pages which will be allocated is limited to a
|
||||
percentage of available memory. Allocating too much will produce
|
||||
an error.
|
||||
|
||||
# echo 1000000000000 > /debug/tracing/buffer_size_kb
|
||||
# echo 1000000000000 > buffer_size_kb
|
||||
-bash: echo: write error: Cannot allocate memory
|
||||
# cat /debug/tracing/buffer_size_kb
|
||||
# cat buffer_size_kb
|
||||
85
|
||||
|
||||
-----------
|
||||
|
||||
@@ -32,41 +32,41 @@ is no way to automatically detect if you are losing events due to CPUs racing.
|
||||
Usage Quick Reference
|
||||
---------------------
|
||||
|
||||
$ mount -t debugfs debugfs /debug
|
||||
$ echo mmiotrace > /debug/tracing/current_tracer
|
||||
$ cat /debug/tracing/trace_pipe > mydump.txt &
|
||||
$ mount -t debugfs debugfs /sys/kernel/debug
|
||||
$ echo mmiotrace > /sys/kernel/debug/tracing/current_tracer
|
||||
$ cat /sys/kernel/debug/tracing/trace_pipe > mydump.txt &
|
||||
Start X or whatever.
|
||||
$ echo "X is up" > /debug/tracing/trace_marker
|
||||
$ echo nop > /debug/tracing/current_tracer
|
||||
$ echo "X is up" > /sys/kernel/debug/tracing/trace_marker
|
||||
$ echo nop > /sys/kernel/debug/tracing/current_tracer
|
||||
Check for lost events.
|
||||
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
Make sure debugfs is mounted to /debug. If not, (requires root privileges)
|
||||
$ mount -t debugfs debugfs /debug
|
||||
Make sure debugfs is mounted to /sys/kernel/debug. If not, (requires root privileges)
|
||||
$ mount -t debugfs debugfs /sys/kernel/debug
|
||||
|
||||
Check that the driver you are about to trace is not loaded.
|
||||
|
||||
Activate mmiotrace (requires root privileges):
|
||||
$ echo mmiotrace > /debug/tracing/current_tracer
|
||||
$ echo mmiotrace > /sys/kernel/debug/tracing/current_tracer
|
||||
|
||||
Start storing the trace:
|
||||
$ cat /debug/tracing/trace_pipe > mydump.txt &
|
||||
$ cat /sys/kernel/debug/tracing/trace_pipe > mydump.txt &
|
||||
The 'cat' process should stay running (sleeping) in the background.
|
||||
|
||||
Load the driver you want to trace and use it. Mmiotrace will only catch MMIO
|
||||
accesses to areas that are ioremapped while mmiotrace is active.
|
||||
|
||||
During tracing you can place comments (markers) into the trace by
|
||||
$ echo "X is up" > /debug/tracing/trace_marker
|
||||
$ echo "X is up" > /sys/kernel/debug/tracing/trace_marker
|
||||
This makes it easier to see which part of the (huge) trace corresponds to
|
||||
which action. It is recommended to place descriptive markers about what you
|
||||
do.
|
||||
|
||||
Shut down mmiotrace (requires root privileges):
|
||||
$ echo nop > /debug/tracing/current_tracer
|
||||
$ echo nop > /sys/kernel/debug/tracing/current_tracer
|
||||
The 'cat' process exits. If it does not, kill it by issuing 'fg' command and
|
||||
pressing ctrl+c.
|
||||
|
||||
@@ -78,10 +78,10 @@ to view your kernel log and look for "mmiotrace has lost events" warning. If
|
||||
events were lost, the trace is incomplete. You should enlarge the buffers and
|
||||
try again. Buffers are enlarged by first seeing how large the current buffers
|
||||
are:
|
||||
$ cat /debug/tracing/buffer_size_kb
|
||||
$ cat /sys/kernel/debug/tracing/buffer_size_kb
|
||||
gives you a number. Approximately double this number and write it back, for
|
||||
instance:
|
||||
$ echo 128000 > /debug/tracing/buffer_size_kb
|
||||
$ echo 128000 > /sys/kernel/debug/tracing/buffer_size_kb
|
||||
Then start again from the top.
|
||||
|
||||
If you are doing a trace for a driver project, e.g. Nouveau, you should also
|
||||
|
||||
@@ -38,7 +38,7 @@ int __init sni_eisa_root_init(void)
|
||||
if (!r)
|
||||
return r;
|
||||
|
||||
eisa_root_dev.dev.driver_data = &eisa_bus_root;
|
||||
dev_set_drvdata(&eisa_root_dev.dev, &eisa_bus_root);
|
||||
|
||||
if (eisa_root_register(&eisa_bus_root)) {
|
||||
/* A real bridge may have been registered before
|
||||
|
||||
@@ -360,7 +360,7 @@ static struct platform_driver uml_net_driver = {
|
||||
|
||||
static void net_device_release(struct device *dev)
|
||||
{
|
||||
struct uml_net *device = dev->driver_data;
|
||||
struct uml_net *device = dev_get_drvdata(dev);
|
||||
struct net_device *netdev = device->dev;
|
||||
struct uml_net_private *lp = netdev_priv(netdev);
|
||||
|
||||
@@ -440,7 +440,7 @@ static void eth_configure(int n, void *init, char *mac,
|
||||
device->pdev.id = n;
|
||||
device->pdev.name = DRIVER_NAME;
|
||||
device->pdev.dev.release = net_device_release;
|
||||
device->pdev.dev.driver_data = device;
|
||||
dev_set_drvdata(&device->pdev.dev, device);
|
||||
if (platform_device_register(&device->pdev))
|
||||
goto out_free_netdev;
|
||||
SET_NETDEV_DEV(dev,&device->pdev.dev);
|
||||
|
||||
@@ -778,7 +778,7 @@ static int ubd_open_dev(struct ubd *ubd_dev)
|
||||
|
||||
static void ubd_device_release(struct device *dev)
|
||||
{
|
||||
struct ubd *ubd_dev = dev->driver_data;
|
||||
struct ubd *ubd_dev = dev_get_drvdata(dev);
|
||||
|
||||
blk_cleanup_queue(ubd_dev->queue);
|
||||
*ubd_dev = ((struct ubd) DEFAULT_UBD);
|
||||
@@ -807,7 +807,7 @@ static int ubd_disk_register(int major, u64 size, int unit,
|
||||
ubd_devs[unit].pdev.id = unit;
|
||||
ubd_devs[unit].pdev.name = DRIVER_NAME;
|
||||
ubd_devs[unit].pdev.dev.release = ubd_device_release;
|
||||
ubd_devs[unit].pdev.dev.driver_data = &ubd_devs[unit];
|
||||
dev_set_drvdata(&ubd_devs[unit].pdev.dev, &ubd_devs[unit]);
|
||||
platform_device_register(&ubd_devs[unit].pdev);
|
||||
disk->driverfs_dev = &ubd_devs[unit].pdev.dev;
|
||||
}
|
||||
|
||||
@@ -182,6 +182,11 @@ static struct notifier_block __refdata cpuid_class_cpu_notifier =
|
||||
.notifier_call = cpuid_class_cpu_callback,
|
||||
};
|
||||
|
||||
static char *cpuid_nodename(struct device *dev)
|
||||
{
|
||||
return kasprintf(GFP_KERNEL, "cpu/%u/cpuid", MINOR(dev->devt));
|
||||
}
|
||||
|
||||
static int __init cpuid_init(void)
|
||||
{
|
||||
int i, err = 0;
|
||||
@@ -198,6 +203,7 @@ static int __init cpuid_init(void)
|
||||
err = PTR_ERR(cpuid_class);
|
||||
goto out_chrdev;
|
||||
}
|
||||
cpuid_class->nodename = cpuid_nodename;
|
||||
for_each_online_cpu(i) {
|
||||
err = cpuid_device_create(i);
|
||||
if (err != 0)
|
||||
|
||||
@@ -236,6 +236,7 @@ static const struct file_operations microcode_fops = {
|
||||
static struct miscdevice microcode_dev = {
|
||||
.minor = MICROCODE_MINOR,
|
||||
.name = "microcode",
|
||||
.devnode = "cpu/microcode",
|
||||
.fops = µcode_fops,
|
||||
};
|
||||
|
||||
|
||||
@@ -196,6 +196,11 @@ static struct notifier_block __refdata msr_class_cpu_notifier = {
|
||||
.notifier_call = msr_class_cpu_callback,
|
||||
};
|
||||
|
||||
static char *msr_nodename(struct device *dev)
|
||||
{
|
||||
return kasprintf(GFP_KERNEL, "cpu/%u/msr", MINOR(dev->devt));
|
||||
}
|
||||
|
||||
static int __init msr_init(void)
|
||||
{
|
||||
int i, err = 0;
|
||||
@@ -212,6 +217,7 @@ static int __init msr_init(void)
|
||||
err = PTR_ERR(msr_class);
|
||||
goto out_chrdev;
|
||||
}
|
||||
msr_class->nodename = msr_nodename;
|
||||
for_each_online_cpu(i) {
|
||||
err = msr_device_create(i);
|
||||
if (err != 0)
|
||||
|
||||
@@ -1065,6 +1065,11 @@ EXPORT_SYMBOL_GPL(bsg_register_queue);
|
||||
|
||||
static struct cdev bsg_cdev;
|
||||
|
||||
static char *bsg_nodename(struct device *dev)
|
||||
{
|
||||
return kasprintf(GFP_KERNEL, "bsg/%s", dev_name(dev));
|
||||
}
|
||||
|
||||
static int __init bsg_init(void)
|
||||
{
|
||||
int ret, i;
|
||||
@@ -1085,6 +1090,7 @@ static int __init bsg_init(void)
|
||||
ret = PTR_ERR(bsg_class);
|
||||
goto destroy_kmemcache;
|
||||
}
|
||||
bsg_class->nodename = bsg_nodename;
|
||||
|
||||
ret = alloc_chrdev_region(&devid, 0, BSG_MAX_DEVS, "bsg");
|
||||
if (ret)
|
||||
|
||||
@@ -996,10 +996,20 @@ struct class block_class = {
|
||||
.name = "block",
|
||||
};
|
||||
|
||||
static char *block_nodename(struct device *dev)
|
||||
{
|
||||
struct gendisk *disk = dev_to_disk(dev);
|
||||
|
||||
if (disk->nodename)
|
||||
return disk->nodename(disk);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct device_type disk_type = {
|
||||
.name = "disk",
|
||||
.groups = disk_attr_groups,
|
||||
.release = disk_release,
|
||||
.nodename = block_nodename,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_PROC_FS
|
||||
|
||||
+54
-3
@@ -22,6 +22,7 @@
|
||||
#include <linux/kallsyms.h>
|
||||
#include <linux/semaphore.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/async.h>
|
||||
|
||||
#include "base.h"
|
||||
#include "power/power.h"
|
||||
@@ -161,10 +162,18 @@ static int dev_uevent(struct kset *kset, struct kobject *kobj,
|
||||
struct device *dev = to_dev(kobj);
|
||||
int retval = 0;
|
||||
|
||||
/* add the major/minor if present */
|
||||
/* add device node properties if present */
|
||||
if (MAJOR(dev->devt)) {
|
||||
const char *tmp;
|
||||
const char *name;
|
||||
|
||||
add_uevent_var(env, "MAJOR=%u", MAJOR(dev->devt));
|
||||
add_uevent_var(env, "MINOR=%u", MINOR(dev->devt));
|
||||
name = device_get_nodename(dev, &tmp);
|
||||
if (name) {
|
||||
add_uevent_var(env, "DEVNAME=%s", name);
|
||||
kfree(tmp);
|
||||
}
|
||||
}
|
||||
|
||||
if (dev->type && dev->type->name)
|
||||
@@ -874,7 +883,7 @@ int device_add(struct device *dev)
|
||||
* the name, and force the use of dev_name()
|
||||
*/
|
||||
if (dev->init_name) {
|
||||
dev_set_name(dev, dev->init_name);
|
||||
dev_set_name(dev, "%s", dev->init_name);
|
||||
dev->init_name = NULL;
|
||||
}
|
||||
|
||||
@@ -1127,6 +1136,47 @@ static struct device *next_device(struct klist_iter *i)
|
||||
return dev;
|
||||
}
|
||||
|
||||
/**
|
||||
* device_get_nodename - path of device node file
|
||||
* @dev: device
|
||||
* @tmp: possibly allocated string
|
||||
*
|
||||
* Return the relative path of a possible device node.
|
||||
* Non-default names may need to allocate a memory to compose
|
||||
* a name. This memory is returned in tmp and needs to be
|
||||
* freed by the caller.
|
||||
*/
|
||||
const char *device_get_nodename(struct device *dev, const char **tmp)
|
||||
{
|
||||
char *s;
|
||||
|
||||
*tmp = NULL;
|
||||
|
||||
/* the device type may provide a specific name */
|
||||
if (dev->type && dev->type->nodename)
|
||||
*tmp = dev->type->nodename(dev);
|
||||
if (*tmp)
|
||||
return *tmp;
|
||||
|
||||
/* the class may provide a specific name */
|
||||
if (dev->class && dev->class->nodename)
|
||||
*tmp = dev->class->nodename(dev);
|
||||
if (*tmp)
|
||||
return *tmp;
|
||||
|
||||
/* return name without allocation, tmp == NULL */
|
||||
if (strchr(dev_name(dev), '!') == NULL)
|
||||
return dev_name(dev);
|
||||
|
||||
/* replace '!' in the name with '/' */
|
||||
*tmp = kstrdup(dev_name(dev), GFP_KERNEL);
|
||||
if (!*tmp)
|
||||
return NULL;
|
||||
while ((s = strchr(*tmp, '!')))
|
||||
s[0] = '/';
|
||||
return *tmp;
|
||||
}
|
||||
|
||||
/**
|
||||
* device_for_each_child - device child iterator.
|
||||
* @parent: parent struct device.
|
||||
@@ -1271,7 +1321,7 @@ struct device *__root_device_register(const char *name, struct module *owner)
|
||||
if (!root)
|
||||
return ERR_PTR(err);
|
||||
|
||||
err = dev_set_name(&root->dev, name);
|
||||
err = dev_set_name(&root->dev, "%s", name);
|
||||
if (err) {
|
||||
kfree(root);
|
||||
return ERR_PTR(err);
|
||||
@@ -1665,4 +1715,5 @@ void device_shutdown(void)
|
||||
kobject_put(sysfs_dev_char_kobj);
|
||||
kobject_put(sysfs_dev_block_kobj);
|
||||
kobject_put(dev_kobj);
|
||||
async_synchronize_full();
|
||||
}
|
||||
|
||||
+5
-1
@@ -226,7 +226,7 @@ static int __device_attach(struct device_driver *drv, void *data)
|
||||
* pair is found, break out and return.
|
||||
*
|
||||
* Returns 1 if the device was bound to a driver;
|
||||
* 0 if no matching device was found;
|
||||
* 0 if no matching driver was found;
|
||||
* -ENODEV if the device is not registered.
|
||||
*
|
||||
* When called for a USB interface, @dev->parent->sem must be held.
|
||||
@@ -320,6 +320,10 @@ static void __device_release_driver(struct device *dev)
|
||||
devres_release_all(dev);
|
||||
dev->driver = NULL;
|
||||
klist_remove(&dev->p->knode_driver);
|
||||
if (dev->bus)
|
||||
blocking_notifier_call_chain(&dev->bus->p->bus_notifier,
|
||||
BUS_NOTIFY_UNBOUND_DRIVER,
|
||||
dev);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@ static int loading_timeout = 60; /* In seconds */
|
||||
static DEFINE_MUTEX(fw_lock);
|
||||
|
||||
struct firmware_priv {
|
||||
char fw_id[FIRMWARE_NAME_MAX];
|
||||
char *fw_id;
|
||||
struct completion completion;
|
||||
struct bin_attribute attr_data;
|
||||
struct firmware *fw;
|
||||
@@ -355,8 +355,9 @@ static void fw_dev_release(struct device *dev)
|
||||
for (i = 0; i < fw_priv->nr_pages; i++)
|
||||
__free_page(fw_priv->pages[i]);
|
||||
kfree(fw_priv->pages);
|
||||
kfree(fw_priv->fw_id);
|
||||
kfree(fw_priv);
|
||||
kfree(dev);
|
||||
put_device(dev);
|
||||
|
||||
module_put(THIS_MODULE);
|
||||
}
|
||||
@@ -386,13 +387,19 @@ static int fw_register_device(struct device **dev_p, const char *fw_name,
|
||||
|
||||
init_completion(&fw_priv->completion);
|
||||
fw_priv->attr_data = firmware_attr_data_tmpl;
|
||||
strlcpy(fw_priv->fw_id, fw_name, FIRMWARE_NAME_MAX);
|
||||
fw_priv->fw_id = kstrdup(fw_name, GFP_KERNEL);
|
||||
if (!fw_priv->fw_id) {
|
||||
dev_err(device, "%s: Firmware name allocation failed\n",
|
||||
__func__);
|
||||
retval = -ENOMEM;
|
||||
goto error_kfree;
|
||||
}
|
||||
|
||||
fw_priv->timeout.function = firmware_class_timeout;
|
||||
fw_priv->timeout.data = (u_long) fw_priv;
|
||||
init_timer(&fw_priv->timeout);
|
||||
|
||||
dev_set_name(f_dev, dev_name(device));
|
||||
dev_set_name(f_dev, "%s", dev_name(device));
|
||||
f_dev->parent = device;
|
||||
f_dev->class = &firmware_class;
|
||||
dev_set_drvdata(f_dev, fw_priv);
|
||||
@@ -400,14 +407,17 @@ static int fw_register_device(struct device **dev_p, const char *fw_name,
|
||||
retval = device_register(f_dev);
|
||||
if (retval) {
|
||||
dev_err(device, "%s: device_register failed\n", __func__);
|
||||
goto error_kfree;
|
||||
put_device(f_dev);
|
||||
goto error_kfree_fw_id;
|
||||
}
|
||||
*dev_p = f_dev;
|
||||
return 0;
|
||||
|
||||
error_kfree_fw_id:
|
||||
kfree(fw_priv->fw_id);
|
||||
error_kfree:
|
||||
kfree(fw_priv);
|
||||
kfree(f_dev);
|
||||
kfree(fw_priv);
|
||||
return retval;
|
||||
}
|
||||
|
||||
@@ -615,8 +625,9 @@ request_firmware_work_func(void *arg)
|
||||
* @cont: function will be called asynchronously when the firmware
|
||||
* request is over.
|
||||
*
|
||||
* Asynchronous variant of request_firmware() for contexts where
|
||||
* it is not possible to sleep.
|
||||
* Asynchronous variant of request_firmware() for user contexts where
|
||||
* it is not possible to sleep for long time. It can't be called
|
||||
* in atomic contexts.
|
||||
**/
|
||||
int
|
||||
request_firmware_nowait(
|
||||
|
||||
@@ -69,7 +69,8 @@ EXPORT_SYMBOL_GPL(platform_get_irq);
|
||||
* @name: resource name
|
||||
*/
|
||||
struct resource *platform_get_resource_byname(struct platform_device *dev,
|
||||
unsigned int type, char *name)
|
||||
unsigned int type,
|
||||
const char *name)
|
||||
{
|
||||
int i;
|
||||
|
||||
@@ -88,7 +89,7 @@ EXPORT_SYMBOL_GPL(platform_get_resource_byname);
|
||||
* @dev: platform device
|
||||
* @name: IRQ name
|
||||
*/
|
||||
int platform_get_irq_byname(struct platform_device *dev, char *name)
|
||||
int platform_get_irq_byname(struct platform_device *dev, const char *name)
|
||||
{
|
||||
struct resource *r = platform_get_resource_byname(dev, IORESOURCE_IRQ,
|
||||
name);
|
||||
@@ -244,7 +245,7 @@ int platform_device_add(struct platform_device *pdev)
|
||||
if (pdev->id != -1)
|
||||
dev_set_name(&pdev->dev, "%s.%d", pdev->name, pdev->id);
|
||||
else
|
||||
dev_set_name(&pdev->dev, pdev->name);
|
||||
dev_set_name(&pdev->dev, "%s", pdev->name);
|
||||
|
||||
for (i = 0; i < pdev->num_resources; i++) {
|
||||
struct resource *p, *r = &pdev->resource[i];
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user