mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-12-04 02:06:43 +07:00
A handful of obvious fixes that wandered in during the merge window.
-----BEGIN PGP SIGNATURE----- iQFDBAABCAAtFiEEIw+MvkEiF49krdp9F0NaE2wMflgFAl81p3sPHGNvcmJldEBs d24ubmV0AAoJEBdDWhNsDH5YTDAH/i+boeUlQsiobPcnfF7jxjQWd2wy9GVT6y7k RQsifOIIsJZB8DN/ChYbeFemtnn495HaIrwN4QvQss82A2NpaGYCRR8D4vncqLHL 1K36JLHE/5dOFvaKUvAVIquEcwuyvmRNU0Bbyz/3kzNUf8KkovDzoJ7xZ/2n/fev hksn3RChj1osJNViSGBkHEjF6NJ46gzNtbt4mW88/jDZNCENK7rZQWbwUvrvZ4ze B1LfMFYuZhm6s4sooBxO6y2njuzmKLoykM9MQFr5PXLuexHTcMlS5mpHVqvQsJ8l 70G2zXZiGUwxboC1YW7aRUEhkASVsXTb077zOVYXWY6duUqWVFs= =tuId -----END PGP SIGNATURE----- Merge tag 'docs-5.9-2' of git://git.lwn.net/linux Pull documentation fixes from Jonathan Corbet: "A handful of obvious fixes that wandered in during the merge window" * tag 'docs-5.9-2' of git://git.lwn.net/linux: Documentation/locking/locktypes: fix the typo doc/zh_CN: resolve undefined label warning in admin-guide index doc/zh_CN: fix title heading markup in admin-guide cpu-load docs: remove the 2.6 "Upgrading I2C Drivers" guide docs: Correct the release date of 5.2 stable mailmap: Update comments for with format and more detalis docs: cdrom: Fix a typo and rst markup Doc: admin-guide: use correct legends in kernel-parameters.txt Documentation/features: refresh RISC-V arch support files documentation: coccinelle: Improve command example for make C={1,2} Core-api: Documentation: Replace deprecated :c:func: Usage Dev-tools: Documentation: Replace deprecated :c:func: Usage Filesystems: Documentation: Replace deprecated :c:func: Usage docs: trace: fix a typo
This commit is contained in:
commit
dddcbc139e
9
.mailmap
9
.mailmap
@ -2,11 +2,16 @@
|
|||||||
# This list is used by git-shortlog to fix a few botched name translations
|
# This list is used by git-shortlog to fix a few botched name translations
|
||||||
# in the git archive, either because the author's full name was messed up
|
# in the git archive, either because the author's full name was messed up
|
||||||
# and/or not always written the same way, making contributions from the
|
# and/or not always written the same way, making contributions from the
|
||||||
# same person appearing not to be so or badly displayed.
|
# same person appearing not to be so or badly displayed. Also allows for
|
||||||
|
# old email addresses to map to new email addresses.
|
||||||
#
|
#
|
||||||
|
# For format details, see "MAPPING AUTHORS" in "man git-shortlog".
|
||||||
|
#
|
||||||
|
# Please keep this list dictionary sorted.
|
||||||
|
#
|
||||||
|
# This comment is parsed by git-shortlog:
|
||||||
# repo-abbrev: /pub/scm/linux/kernel/git/
|
# repo-abbrev: /pub/scm/linux/kernel/git/
|
||||||
#
|
#
|
||||||
|
|
||||||
Aaron Durbin <adurbin@google.com>
|
Aaron Durbin <adurbin@google.com>
|
||||||
Adam Oldham <oldhamca@gmail.com>
|
Adam Oldham <oldhamca@gmail.com>
|
||||||
Adam Radford <aradford@gmail.com>
|
Adam Radford <aradford@gmail.com>
|
||||||
|
@ -724,7 +724,7 @@
|
|||||||
memory region [offset, offset + size] for that kernel
|
memory region [offset, offset + size] for that kernel
|
||||||
image. If '@offset' is omitted, then a suitable offset
|
image. If '@offset' is omitted, then a suitable offset
|
||||||
is selected automatically.
|
is selected automatically.
|
||||||
[KNL, x86_64] select a region under 4G first, and
|
[KNL, X86-64] Select a region under 4G first, and
|
||||||
fall back to reserve region above 4G when '@offset'
|
fall back to reserve region above 4G when '@offset'
|
||||||
hasn't been specified.
|
hasn't been specified.
|
||||||
See Documentation/admin-guide/kdump/kdump.rst for further details.
|
See Documentation/admin-guide/kdump/kdump.rst for further details.
|
||||||
@ -737,14 +737,14 @@
|
|||||||
Documentation/admin-guide/kdump/kdump.rst for an example.
|
Documentation/admin-guide/kdump/kdump.rst for an example.
|
||||||
|
|
||||||
crashkernel=size[KMG],high
|
crashkernel=size[KMG],high
|
||||||
[KNL, x86_64] range could be above 4G. Allow kernel
|
[KNL, X86-64] range could be above 4G. Allow kernel
|
||||||
to allocate physical memory region from top, so could
|
to allocate physical memory region from top, so could
|
||||||
be above 4G if system have more than 4G ram installed.
|
be above 4G if system have more than 4G ram installed.
|
||||||
Otherwise memory region will be allocated below 4G, if
|
Otherwise memory region will be allocated below 4G, if
|
||||||
available.
|
available.
|
||||||
It will be ignored if crashkernel=X is specified.
|
It will be ignored if crashkernel=X is specified.
|
||||||
crashkernel=size[KMG],low
|
crashkernel=size[KMG],low
|
||||||
[KNL, x86_64] range under 4G. When crashkernel=X,high
|
[KNL, X86-64] range under 4G. When crashkernel=X,high
|
||||||
is passed, kernel could allocate physical memory region
|
is passed, kernel could allocate physical memory region
|
||||||
above 4G, that cause second kernel crash on system
|
above 4G, that cause second kernel crash on system
|
||||||
that require some amount of low memory, e.g. swiotlb
|
that require some amount of low memory, e.g. swiotlb
|
||||||
@ -1427,7 +1427,7 @@
|
|||||||
|
|
||||||
gamma= [HW,DRM]
|
gamma= [HW,DRM]
|
||||||
|
|
||||||
gart_fix_e820= [X86_64] disable the fix e820 for K8 GART
|
gart_fix_e820= [X86-64] disable the fix e820 for K8 GART
|
||||||
Format: off | on
|
Format: off | on
|
||||||
default: on
|
default: on
|
||||||
|
|
||||||
@ -1814,7 +1814,7 @@
|
|||||||
Format: 0 | 1
|
Format: 0 | 1
|
||||||
Default set by CONFIG_INIT_ON_FREE_DEFAULT_ON.
|
Default set by CONFIG_INIT_ON_FREE_DEFAULT_ON.
|
||||||
|
|
||||||
init_pkru= [x86] Specify the default memory protection keys rights
|
init_pkru= [X86] Specify the default memory protection keys rights
|
||||||
register contents for all processes. 0x55555554 by
|
register contents for all processes. 0x55555554 by
|
||||||
default (disallow access to all but pkey 0). Can
|
default (disallow access to all but pkey 0). Can
|
||||||
override in debugfs after boot.
|
override in debugfs after boot.
|
||||||
@ -1822,7 +1822,7 @@
|
|||||||
inport.irq= [HW] Inport (ATI XL and Microsoft) busmouse driver
|
inport.irq= [HW] Inport (ATI XL and Microsoft) busmouse driver
|
||||||
Format: <irq>
|
Format: <irq>
|
||||||
|
|
||||||
int_pln_enable [x86] Enable power limit notification interrupt
|
int_pln_enable [X86] Enable power limit notification interrupt
|
||||||
|
|
||||||
integrity_audit=[IMA]
|
integrity_audit=[IMA]
|
||||||
Format: { "0" | "1" }
|
Format: { "0" | "1" }
|
||||||
@ -1840,7 +1840,7 @@
|
|||||||
bypassed by not enabling DMAR with this option. In
|
bypassed by not enabling DMAR with this option. In
|
||||||
this case, gfx device will use physical address for
|
this case, gfx device will use physical address for
|
||||||
DMA.
|
DMA.
|
||||||
forcedac [x86_64]
|
forcedac [X86-64]
|
||||||
With this option iommu will not optimize to look
|
With this option iommu will not optimize to look
|
||||||
for io virtual address below 32-bit forcing dual
|
for io virtual address below 32-bit forcing dual
|
||||||
address cycle on pci bus for cards supporting greater
|
address cycle on pci bus for cards supporting greater
|
||||||
@ -1925,7 +1925,7 @@
|
|||||||
strict regions from userspace.
|
strict regions from userspace.
|
||||||
relaxed
|
relaxed
|
||||||
|
|
||||||
iommu= [x86]
|
iommu= [X86]
|
||||||
off
|
off
|
||||||
force
|
force
|
||||||
noforce
|
noforce
|
||||||
@ -1935,8 +1935,8 @@
|
|||||||
merge
|
merge
|
||||||
nomerge
|
nomerge
|
||||||
soft
|
soft
|
||||||
pt [x86]
|
pt [X86]
|
||||||
nopt [x86]
|
nopt [X86]
|
||||||
nobypass [PPC/POWERNV]
|
nobypass [PPC/POWERNV]
|
||||||
Disable IOMMU bypass, using IOMMU for PCI devices.
|
Disable IOMMU bypass, using IOMMU for PCI devices.
|
||||||
|
|
||||||
@ -2079,21 +2079,21 @@
|
|||||||
|
|
||||||
iucv= [HW,NET]
|
iucv= [HW,NET]
|
||||||
|
|
||||||
ivrs_ioapic [HW,X86_64]
|
ivrs_ioapic [HW,X86-64]
|
||||||
Provide an override to the IOAPIC-ID<->DEVICE-ID
|
Provide an override to the IOAPIC-ID<->DEVICE-ID
|
||||||
mapping provided in the IVRS ACPI table. For
|
mapping provided in the IVRS ACPI table. For
|
||||||
example, to map IOAPIC-ID decimal 10 to
|
example, to map IOAPIC-ID decimal 10 to
|
||||||
PCI device 00:14.0 write the parameter as:
|
PCI device 00:14.0 write the parameter as:
|
||||||
ivrs_ioapic[10]=00:14.0
|
ivrs_ioapic[10]=00:14.0
|
||||||
|
|
||||||
ivrs_hpet [HW,X86_64]
|
ivrs_hpet [HW,X86-64]
|
||||||
Provide an override to the HPET-ID<->DEVICE-ID
|
Provide an override to the HPET-ID<->DEVICE-ID
|
||||||
mapping provided in the IVRS ACPI table. For
|
mapping provided in the IVRS ACPI table. For
|
||||||
example, to map HPET-ID decimal 0 to
|
example, to map HPET-ID decimal 0 to
|
||||||
PCI device 00:14.0 write the parameter as:
|
PCI device 00:14.0 write the parameter as:
|
||||||
ivrs_hpet[0]=00:14.0
|
ivrs_hpet[0]=00:14.0
|
||||||
|
|
||||||
ivrs_acpihid [HW,X86_64]
|
ivrs_acpihid [HW,X86-64]
|
||||||
Provide an override to the ACPI-HID:UID<->DEVICE-ID
|
Provide an override to the ACPI-HID:UID<->DEVICE-ID
|
||||||
mapping provided in the IVRS ACPI table. For
|
mapping provided in the IVRS ACPI table. For
|
||||||
example, to map UART-HID:UID AMD0020:0 to
|
example, to map UART-HID:UID AMD0020:0 to
|
||||||
@ -2370,7 +2370,7 @@
|
|||||||
lapic [X86-32,APIC] Enable the local APIC even if BIOS
|
lapic [X86-32,APIC] Enable the local APIC even if BIOS
|
||||||
disabled it.
|
disabled it.
|
||||||
|
|
||||||
lapic= [x86,APIC] "notscdeadline" Do not use TSC deadline
|
lapic= [X86,APIC] "notscdeadline" Do not use TSC deadline
|
||||||
value for LAPIC timer one-shot implementation. Default
|
value for LAPIC timer one-shot implementation. Default
|
||||||
back to the programmable timer unit in the LAPIC.
|
back to the programmable timer unit in the LAPIC.
|
||||||
|
|
||||||
@ -3188,12 +3188,12 @@
|
|||||||
register save and restore. The kernel will only save
|
register save and restore. The kernel will only save
|
||||||
legacy floating-point registers on task switch.
|
legacy floating-point registers on task switch.
|
||||||
|
|
||||||
nohugeiomap [KNL,x86,PPC] Disable kernel huge I/O mappings.
|
nohugeiomap [KNL,X86,PPC] Disable kernel huge I/O mappings.
|
||||||
|
|
||||||
nosmt [KNL,S390] Disable symmetric multithreading (SMT).
|
nosmt [KNL,S390] Disable symmetric multithreading (SMT).
|
||||||
Equivalent to smt=1.
|
Equivalent to smt=1.
|
||||||
|
|
||||||
[KNL,x86] Disable symmetric multithreading (SMT).
|
[KNL,X86] Disable symmetric multithreading (SMT).
|
||||||
nosmt=force: Force disable SMT, cannot be undone
|
nosmt=force: Force disable SMT, cannot be undone
|
||||||
via the sysfs control file.
|
via the sysfs control file.
|
||||||
|
|
||||||
@ -3955,7 +3955,7 @@
|
|||||||
pt. [PARIDE]
|
pt. [PARIDE]
|
||||||
See Documentation/admin-guide/blockdev/paride.rst.
|
See Documentation/admin-guide/blockdev/paride.rst.
|
||||||
|
|
||||||
pti= [X86_64] Control Page Table Isolation of user and
|
pti= [X86-64] Control Page Table Isolation of user and
|
||||||
kernel address spaces. Disabling this feature
|
kernel address spaces. Disabling this feature
|
||||||
removes hardening, but improves performance of
|
removes hardening, but improves performance of
|
||||||
system calls and interrupts.
|
system calls and interrupts.
|
||||||
@ -3967,7 +3967,7 @@
|
|||||||
|
|
||||||
Not specifying this option is equivalent to pti=auto.
|
Not specifying this option is equivalent to pti=auto.
|
||||||
|
|
||||||
nopti [X86_64]
|
nopti [X86-64]
|
||||||
Equivalent to pti=off
|
Equivalent to pti=off
|
||||||
|
|
||||||
pty.legacy_count=
|
pty.legacy_count=
|
||||||
|
@ -557,7 +557,7 @@ phase. Currently, the capabilities are any of::
|
|||||||
CDC_DRIVE_STATUS /* driver implements drive status */
|
CDC_DRIVE_STATUS /* driver implements drive status */
|
||||||
|
|
||||||
The capability flag is declared *const*, to prevent drivers from
|
The capability flag is declared *const*, to prevent drivers from
|
||||||
accidentally tampering with the contents. The capability fags actually
|
accidentally tampering with the contents. The capability flags actually
|
||||||
inform `cdrom.c` of what the driver can do. If the drive found
|
inform `cdrom.c` of what the driver can do. If the drive found
|
||||||
by the driver does not have the capability, is can be masked out by
|
by the driver does not have the capability, is can be masked out by
|
||||||
the *cdrom_device_info* variable *mask*. For instance, the SCSI CD-ROM
|
the *cdrom_device_info* variable *mask*. For instance, the SCSI CD-ROM
|
||||||
@ -736,7 +736,7 @@ Description of routines in `cdrom.c`
|
|||||||
|
|
||||||
Only a few routines in `cdrom.c` are exported to the drivers. In this
|
Only a few routines in `cdrom.c` are exported to the drivers. In this
|
||||||
new section we will discuss these, as well as the functions that `take
|
new section we will discuss these, as well as the functions that `take
|
||||||
over' the CD-ROM interface to the kernel. The header file belonging
|
over` the CD-ROM interface to the kernel. The header file belonging
|
||||||
to `cdrom.c` is called `cdrom.h`. Formerly, some of the contents of this
|
to `cdrom.c` is called `cdrom.h`. Formerly, some of the contents of this
|
||||||
file were placed in the file `ucdrom.h`, but this file has now been
|
file were placed in the file `ucdrom.h`, but this file has now been
|
||||||
merged back into `cdrom.h`.
|
merged back into `cdrom.h`.
|
||||||
|
@ -20,48 +20,48 @@ only ID allocation, and as a result is much more memory-efficient.
|
|||||||
IDR usage
|
IDR usage
|
||||||
=========
|
=========
|
||||||
|
|
||||||
Start by initialising an IDR, either with :c:func:`DEFINE_IDR`
|
Start by initialising an IDR, either with DEFINE_IDR()
|
||||||
for statically allocated IDRs or :c:func:`idr_init` for dynamically
|
for statically allocated IDRs or idr_init() for dynamically
|
||||||
allocated IDRs.
|
allocated IDRs.
|
||||||
|
|
||||||
You can call :c:func:`idr_alloc` to allocate an unused ID. Look up
|
You can call idr_alloc() to allocate an unused ID. Look up
|
||||||
the pointer you associated with the ID by calling :c:func:`idr_find`
|
the pointer you associated with the ID by calling idr_find()
|
||||||
and free the ID by calling :c:func:`idr_remove`.
|
and free the ID by calling idr_remove().
|
||||||
|
|
||||||
If you need to change the pointer associated with an ID, you can call
|
If you need to change the pointer associated with an ID, you can call
|
||||||
:c:func:`idr_replace`. One common reason to do this is to reserve an
|
idr_replace(). One common reason to do this is to reserve an
|
||||||
ID by passing a ``NULL`` pointer to the allocation function; initialise the
|
ID by passing a ``NULL`` pointer to the allocation function; initialise the
|
||||||
object with the reserved ID and finally insert the initialised object
|
object with the reserved ID and finally insert the initialised object
|
||||||
into the IDR.
|
into the IDR.
|
||||||
|
|
||||||
Some users need to allocate IDs larger than ``INT_MAX``. So far all of
|
Some users need to allocate IDs larger than ``INT_MAX``. So far all of
|
||||||
these users have been content with a ``UINT_MAX`` limit, and they use
|
these users have been content with a ``UINT_MAX`` limit, and they use
|
||||||
:c:func:`idr_alloc_u32`. If you need IDs that will not fit in a u32,
|
idr_alloc_u32(). If you need IDs that will not fit in a u32,
|
||||||
we will work with you to address your needs.
|
we will work with you to address your needs.
|
||||||
|
|
||||||
If you need to allocate IDs sequentially, you can use
|
If you need to allocate IDs sequentially, you can use
|
||||||
:c:func:`idr_alloc_cyclic`. The IDR becomes less efficient when dealing
|
idr_alloc_cyclic(). The IDR becomes less efficient when dealing
|
||||||
with larger IDs, so using this function comes at a slight cost.
|
with larger IDs, so using this function comes at a slight cost.
|
||||||
|
|
||||||
To perform an action on all pointers used by the IDR, you can
|
To perform an action on all pointers used by the IDR, you can
|
||||||
either use the callback-based :c:func:`idr_for_each` or the
|
either use the callback-based idr_for_each() or the
|
||||||
iterator-style :c:func:`idr_for_each_entry`. You may need to use
|
iterator-style idr_for_each_entry(). You may need to use
|
||||||
:c:func:`idr_for_each_entry_continue` to continue an iteration. You can
|
idr_for_each_entry_continue() to continue an iteration. You can
|
||||||
also use :c:func:`idr_get_next` if the iterator doesn't fit your needs.
|
also use idr_get_next() if the iterator doesn't fit your needs.
|
||||||
|
|
||||||
When you have finished using an IDR, you can call :c:func:`idr_destroy`
|
When you have finished using an IDR, you can call idr_destroy()
|
||||||
to release the memory used by the IDR. This will not free the objects
|
to release the memory used by the IDR. This will not free the objects
|
||||||
pointed to from the IDR; if you want to do that, use one of the iterators
|
pointed to from the IDR; if you want to do that, use one of the iterators
|
||||||
to do it.
|
to do it.
|
||||||
|
|
||||||
You can use :c:func:`idr_is_empty` to find out whether there are any
|
You can use idr_is_empty() to find out whether there are any
|
||||||
IDs currently allocated.
|
IDs currently allocated.
|
||||||
|
|
||||||
If you need to take a lock while allocating a new ID from the IDR,
|
If you need to take a lock while allocating a new ID from the IDR,
|
||||||
you may need to pass a restrictive set of GFP flags, which can lead
|
you may need to pass a restrictive set of GFP flags, which can lead
|
||||||
to the IDR being unable to allocate memory. To work around this,
|
to the IDR being unable to allocate memory. To work around this,
|
||||||
you can call :c:func:`idr_preload` before taking the lock, and then
|
you can call idr_preload() before taking the lock, and then
|
||||||
:c:func:`idr_preload_end` after the allocation.
|
idr_preload_end() after the allocation.
|
||||||
|
|
||||||
.. kernel-doc:: include/linux/idr.h
|
.. kernel-doc:: include/linux/idr.h
|
||||||
:doc: idr sync
|
:doc: idr sync
|
||||||
|
@ -175,13 +175,20 @@ For example, to check drivers/net/wireless/ one may write::
|
|||||||
make coccicheck M=drivers/net/wireless/
|
make coccicheck M=drivers/net/wireless/
|
||||||
|
|
||||||
To apply Coccinelle on a file basis, instead of a directory basis, the
|
To apply Coccinelle on a file basis, instead of a directory basis, the
|
||||||
following command may be used::
|
C variable is used by the makefile to select which files to work with.
|
||||||
|
This variable can be used to run scripts for the entire kernel, a
|
||||||
|
specific directory, or for a single file.
|
||||||
|
|
||||||
make C=1 CHECK="scripts/coccicheck"
|
For example, to check drivers/bluetooth/bfusb.c, the value 1 is
|
||||||
|
passed to the C variable to check files that make considers
|
||||||
|
need to be compiled.::
|
||||||
|
|
||||||
To check only newly edited code, use the value 2 for the C flag, i.e.::
|
make C=1 CHECK=scripts/coccicheck drivers/bluetooth/bfusb.o
|
||||||
|
|
||||||
make C=2 CHECK="scripts/coccicheck"
|
The value 2 is passed to the C variable to check files regardless of
|
||||||
|
whether they need to be compiled or not.::
|
||||||
|
|
||||||
|
make C=2 CHECK=scripts/coccicheck drivers/bluetooth/bfusb.o
|
||||||
|
|
||||||
In these modes, which work on a file basis, there is no information
|
In these modes, which work on a file basis, there is no information
|
||||||
about semantic patches displayed, and no commit message proposed.
|
about semantic patches displayed, and no commit message proposed.
|
||||||
|
@ -316,7 +316,7 @@ driver as a loadable kernel module kgdbwait will not do anything.
|
|||||||
Kernel parameter: ``kgdbcon``
|
Kernel parameter: ``kgdbcon``
|
||||||
-----------------------------
|
-----------------------------
|
||||||
|
|
||||||
The ``kgdbcon`` feature allows you to see :c:func:`printk` messages inside gdb
|
The ``kgdbcon`` feature allows you to see printk() messages inside gdb
|
||||||
while gdb is connected to the kernel. Kdb does not make use of the kgdbcon
|
while gdb is connected to the kernel. Kdb does not make use of the kgdbcon
|
||||||
feature.
|
feature.
|
||||||
|
|
||||||
@ -432,7 +432,7 @@ This is a quick example of how to use kdb.
|
|||||||
``ps`` Displays only the active processes
|
``ps`` Displays only the active processes
|
||||||
``ps A`` Shows all the processes
|
``ps A`` Shows all the processes
|
||||||
``summary`` Shows kernel version info and memory usage
|
``summary`` Shows kernel version info and memory usage
|
||||||
``bt`` Get a backtrace of the current process using :c:func:`dump_stack`
|
``bt`` Get a backtrace of the current process using dump_stack()
|
||||||
``dmesg`` View the kernel syslog buffer
|
``dmesg`` View the kernel syslog buffer
|
||||||
``go`` Continue the system
|
``go`` Continue the system
|
||||||
=========== =================================================================
|
=========== =================================================================
|
||||||
@ -724,7 +724,7 @@ The kernel debugger is organized into a number of components:
|
|||||||
The arch-specific portion implements:
|
The arch-specific portion implements:
|
||||||
|
|
||||||
- contains an arch-specific trap catcher which invokes
|
- contains an arch-specific trap catcher which invokes
|
||||||
:c:func:`kgdb_handle_exception` to start kgdb about doing its work
|
kgdb_handle_exception() to start kgdb about doing its work
|
||||||
|
|
||||||
- translation to and from gdb specific packet format to :c:type:`pt_regs`
|
- translation to and from gdb specific packet format to :c:type:`pt_regs`
|
||||||
|
|
||||||
@ -769,7 +769,7 @@ The kernel debugger is organized into a number of components:
|
|||||||
config. Later run ``modprobe kdb_hello`` and the next time you
|
config. Later run ``modprobe kdb_hello`` and the next time you
|
||||||
enter the kdb shell, you can run the ``hello`` command.
|
enter the kdb shell, you can run the ``hello`` command.
|
||||||
|
|
||||||
- The implementation for :c:func:`kdb_printf` which emits messages directly
|
- The implementation for kdb_printf() which emits messages directly
|
||||||
to I/O drivers, bypassing the kernel log.
|
to I/O drivers, bypassing the kernel log.
|
||||||
|
|
||||||
- SW / HW breakpoint management for the kdb shell
|
- SW / HW breakpoint management for the kdb shell
|
||||||
@ -875,7 +875,7 @@ kernel when ``CONFIG_KDB_KEYBOARD=y`` is set in the kernel configuration.
|
|||||||
The core polled keyboard driver for PS/2 type keyboards is in
|
The core polled keyboard driver for PS/2 type keyboards is in
|
||||||
``drivers/char/kdb_keyboard.c``. This driver is hooked into the debug core
|
``drivers/char/kdb_keyboard.c``. This driver is hooked into the debug core
|
||||||
when kgdboc populates the callback in the array called
|
when kgdboc populates the callback in the array called
|
||||||
:c:type:`kdb_poll_funcs[]`. The :c:func:`kdb_get_kbd_char` is the top-level
|
:c:type:`kdb_poll_funcs[]`. The kdb_get_kbd_char() is the top-level
|
||||||
function which polls hardware for single character input.
|
function which polls hardware for single character input.
|
||||||
|
|
||||||
kgdboc and kms
|
kgdboc and kms
|
||||||
@ -887,10 +887,10 @@ that you have a video driver which has a frame buffer console and atomic
|
|||||||
kernel mode setting support.
|
kernel mode setting support.
|
||||||
|
|
||||||
Every time the kernel debugger is entered it calls
|
Every time the kernel debugger is entered it calls
|
||||||
:c:func:`kgdboc_pre_exp_handler` which in turn calls :c:func:`con_debug_enter`
|
kgdboc_pre_exp_handler() which in turn calls con_debug_enter()
|
||||||
in the virtual console layer. On resuming kernel execution, the kernel
|
in the virtual console layer. On resuming kernel execution, the kernel
|
||||||
debugger calls :c:func:`kgdboc_post_exp_handler` which in turn calls
|
debugger calls kgdboc_post_exp_handler() which in turn calls
|
||||||
:c:func:`con_debug_leave`.
|
con_debug_leave().
|
||||||
|
|
||||||
Any video driver that wants to be compatible with the kernel debugger
|
Any video driver that wants to be compatible with the kernel debugger
|
||||||
and the atomic kms callbacks must implement the ``mode_set_base_atomic``,
|
and the atomic kms callbacks must implement the ``mode_set_base_atomic``,
|
||||||
|
@ -23,7 +23,7 @@
|
|||||||
| openrisc: | TODO |
|
| openrisc: | TODO |
|
||||||
| parisc: | TODO |
|
| parisc: | TODO |
|
||||||
| powerpc: | ok |
|
| powerpc: | ok |
|
||||||
| riscv: | TODO |
|
| riscv: | ok |
|
||||||
| s390: | ok |
|
| s390: | ok |
|
||||||
| sh: | ok |
|
| sh: | ok |
|
||||||
| sparc: | ok |
|
| sparc: | ok |
|
||||||
|
@ -23,7 +23,7 @@
|
|||||||
| openrisc: | TODO |
|
| openrisc: | TODO |
|
||||||
| parisc: | TODO |
|
| parisc: | TODO |
|
||||||
| powerpc: | ok |
|
| powerpc: | ok |
|
||||||
| riscv: | TODO |
|
| riscv: | ok |
|
||||||
| s390: | TODO |
|
| s390: | TODO |
|
||||||
| sh: | ok |
|
| sh: | ok |
|
||||||
| sparc: | TODO |
|
| sparc: | TODO |
|
||||||
|
@ -23,7 +23,7 @@
|
|||||||
| openrisc: | ok |
|
| openrisc: | ok |
|
||||||
| parisc: | TODO |
|
| parisc: | TODO |
|
||||||
| powerpc: | ok |
|
| powerpc: | ok |
|
||||||
| riscv: | TODO |
|
| riscv: | ok |
|
||||||
| s390: | ok |
|
| s390: | ok |
|
||||||
| sh: | ok |
|
| sh: | ok |
|
||||||
| sparc: | ok |
|
| sparc: | ok |
|
||||||
|
@ -23,7 +23,7 @@
|
|||||||
| openrisc: | TODO |
|
| openrisc: | TODO |
|
||||||
| parisc: | TODO |
|
| parisc: | TODO |
|
||||||
| powerpc: | ok |
|
| powerpc: | ok |
|
||||||
| riscv: | TODO |
|
| riscv: | ok |
|
||||||
| s390: | TODO |
|
| s390: | TODO |
|
||||||
| sh: | TODO |
|
| sh: | TODO |
|
||||||
| sparc: | ok |
|
| sparc: | ok |
|
||||||
|
@ -10,27 +10,27 @@ Details
|
|||||||
The journalling layer is easy to use. You need to first of all create a
|
The journalling layer is easy to use. You need to first of all create a
|
||||||
journal_t data structure. There are two calls to do this dependent on
|
journal_t data structure. There are two calls to do this dependent on
|
||||||
how you decide to allocate the physical media on which the journal
|
how you decide to allocate the physical media on which the journal
|
||||||
resides. The :c:func:`jbd2_journal_init_inode` call is for journals stored in
|
resides. The jbd2_journal_init_inode() call is for journals stored in
|
||||||
filesystem inodes, or the :c:func:`jbd2_journal_init_dev` call can be used
|
filesystem inodes, or the jbd2_journal_init_dev() call can be used
|
||||||
for journal stored on a raw device (in a continuous range of blocks). A
|
for journal stored on a raw device (in a continuous range of blocks). A
|
||||||
journal_t is a typedef for a struct pointer, so when you are finally
|
journal_t is a typedef for a struct pointer, so when you are finally
|
||||||
finished make sure you call :c:func:`jbd2_journal_destroy` on it to free up
|
finished make sure you call jbd2_journal_destroy() on it to free up
|
||||||
any used kernel memory.
|
any used kernel memory.
|
||||||
|
|
||||||
Once you have got your journal_t object you need to 'mount' or load the
|
Once you have got your journal_t object you need to 'mount' or load the
|
||||||
journal file. The journalling layer expects the space for the journal
|
journal file. The journalling layer expects the space for the journal
|
||||||
was already allocated and initialized properly by the userspace tools.
|
was already allocated and initialized properly by the userspace tools.
|
||||||
When loading the journal you must call :c:func:`jbd2_journal_load` to process
|
When loading the journal you must call jbd2_journal_load() to process
|
||||||
journal contents. If the client file system detects the journal contents
|
journal contents. If the client file system detects the journal contents
|
||||||
does not need to be processed (or even need not have valid contents), it
|
does not need to be processed (or even need not have valid contents), it
|
||||||
may call :c:func:`jbd2_journal_wipe` to clear the journal contents before
|
may call jbd2_journal_wipe() to clear the journal contents before
|
||||||
calling :c:func:`jbd2_journal_load`.
|
calling jbd2_journal_load().
|
||||||
|
|
||||||
Note that jbd2_journal_wipe(..,0) calls
|
Note that jbd2_journal_wipe(..,0) calls
|
||||||
:c:func:`jbd2_journal_skip_recovery` for you if it detects any outstanding
|
jbd2_journal_skip_recovery() for you if it detects any outstanding
|
||||||
transactions in the journal and similarly :c:func:`jbd2_journal_load` will
|
transactions in the journal and similarly jbd2_journal_load() will
|
||||||
call :c:func:`jbd2_journal_recover` if necessary. I would advise reading
|
call jbd2_journal_recover() if necessary. I would advise reading
|
||||||
:c:func:`ext4_load_journal` in fs/ext4/super.c for examples on this stage.
|
ext4_load_journal() in fs/ext4/super.c for examples on this stage.
|
||||||
|
|
||||||
Now you can go ahead and start modifying the underlying filesystem.
|
Now you can go ahead and start modifying the underlying filesystem.
|
||||||
Almost.
|
Almost.
|
||||||
@ -39,57 +39,57 @@ You still need to actually journal your filesystem changes, this is done
|
|||||||
by wrapping them into transactions. Additionally you also need to wrap
|
by wrapping them into transactions. Additionally you also need to wrap
|
||||||
the modification of each of the buffers with calls to the journal layer,
|
the modification of each of the buffers with calls to the journal layer,
|
||||||
so it knows what the modifications you are actually making are. To do
|
so it knows what the modifications you are actually making are. To do
|
||||||
this use :c:func:`jbd2_journal_start` which returns a transaction handle.
|
this use jbd2_journal_start() which returns a transaction handle.
|
||||||
|
|
||||||
:c:func:`jbd2_journal_start` and its counterpart :c:func:`jbd2_journal_stop`,
|
jbd2_journal_start() and its counterpart jbd2_journal_stop(),
|
||||||
which indicates the end of a transaction are nestable calls, so you can
|
which indicates the end of a transaction are nestable calls, so you can
|
||||||
reenter a transaction if necessary, but remember you must call
|
reenter a transaction if necessary, but remember you must call
|
||||||
:c:func:`jbd2_journal_stop` the same number of times as
|
jbd2_journal_stop() the same number of times as
|
||||||
:c:func:`jbd2_journal_start` before the transaction is completed (or more
|
jbd2_journal_start() before the transaction is completed (or more
|
||||||
accurately leaves the update phase). Ext4/VFS makes use of this feature to
|
accurately leaves the update phase). Ext4/VFS makes use of this feature to
|
||||||
simplify handling of inode dirtying, quota support, etc.
|
simplify handling of inode dirtying, quota support, etc.
|
||||||
|
|
||||||
Inside each transaction you need to wrap the modifications to the
|
Inside each transaction you need to wrap the modifications to the
|
||||||
individual buffers (blocks). Before you start to modify a buffer you
|
individual buffers (blocks). Before you start to modify a buffer you
|
||||||
need to call :c:func:`jbd2_journal_get_create_access()` /
|
need to call jbd2_journal_get_create_access() /
|
||||||
:c:func:`jbd2_journal_get_write_access()` /
|
jbd2_journal_get_write_access() /
|
||||||
:c:func:`jbd2_journal_get_undo_access()` as appropriate, this allows the
|
jbd2_journal_get_undo_access() as appropriate, this allows the
|
||||||
journalling layer to copy the unmodified
|
journalling layer to copy the unmodified
|
||||||
data if it needs to. After all the buffer may be part of a previously
|
data if it needs to. After all the buffer may be part of a previously
|
||||||
uncommitted transaction. At this point you are at last ready to modify a
|
uncommitted transaction. At this point you are at last ready to modify a
|
||||||
buffer, and once you are have done so you need to call
|
buffer, and once you are have done so you need to call
|
||||||
:c:func:`jbd2_journal_dirty_metadata`. Or if you've asked for access to a
|
jbd2_journal_dirty_metadata(). Or if you've asked for access to a
|
||||||
buffer you now know is now longer required to be pushed back on the
|
buffer you now know is now longer required to be pushed back on the
|
||||||
device you can call :c:func:`jbd2_journal_forget` in much the same way as you
|
device you can call jbd2_journal_forget() in much the same way as you
|
||||||
might have used :c:func:`bforget` in the past.
|
might have used bforget() in the past.
|
||||||
|
|
||||||
A :c:func:`jbd2_journal_flush` may be called at any time to commit and
|
A jbd2_journal_flush() may be called at any time to commit and
|
||||||
checkpoint all your transactions.
|
checkpoint all your transactions.
|
||||||
|
|
||||||
Then at umount time , in your :c:func:`put_super` you can then call
|
Then at umount time , in your put_super() you can then call
|
||||||
:c:func:`jbd2_journal_destroy` to clean up your in-core journal object.
|
jbd2_journal_destroy() to clean up your in-core journal object.
|
||||||
|
|
||||||
Unfortunately there a couple of ways the journal layer can cause a
|
Unfortunately there a couple of ways the journal layer can cause a
|
||||||
deadlock. The first thing to note is that each task can only have a
|
deadlock. The first thing to note is that each task can only have a
|
||||||
single outstanding transaction at any one time, remember nothing commits
|
single outstanding transaction at any one time, remember nothing commits
|
||||||
until the outermost :c:func:`jbd2_journal_stop`. This means you must complete
|
until the outermost jbd2_journal_stop(). This means you must complete
|
||||||
the transaction at the end of each file/inode/address etc. operation you
|
the transaction at the end of each file/inode/address etc. operation you
|
||||||
perform, so that the journalling system isn't re-entered on another
|
perform, so that the journalling system isn't re-entered on another
|
||||||
journal. Since transactions can't be nested/batched across differing
|
journal. Since transactions can't be nested/batched across differing
|
||||||
journals, and another filesystem other than yours (say ext4) may be
|
journals, and another filesystem other than yours (say ext4) may be
|
||||||
modified in a later syscall.
|
modified in a later syscall.
|
||||||
|
|
||||||
The second case to bear in mind is that :c:func:`jbd2_journal_start` can block
|
The second case to bear in mind is that jbd2_journal_start() can block
|
||||||
if there isn't enough space in the journal for your transaction (based
|
if there isn't enough space in the journal for your transaction (based
|
||||||
on the passed nblocks param) - when it blocks it merely(!) needs to wait
|
on the passed nblocks param) - when it blocks it merely(!) needs to wait
|
||||||
for transactions to complete and be committed from other tasks, so
|
for transactions to complete and be committed from other tasks, so
|
||||||
essentially we are waiting for :c:func:`jbd2_journal_stop`. So to avoid
|
essentially we are waiting for jbd2_journal_stop(). So to avoid
|
||||||
deadlocks you must treat :c:func:`jbd2_journal_start` /
|
deadlocks you must treat jbd2_journal_start() /
|
||||||
:c:func:`jbd2_journal_stop` as if they were semaphores and include them in
|
jbd2_journal_stop() as if they were semaphores and include them in
|
||||||
your semaphore ordering rules to prevent
|
your semaphore ordering rules to prevent
|
||||||
deadlocks. Note that :c:func:`jbd2_journal_extend` has similar blocking
|
deadlocks. Note that jbd2_journal_extend() has similar blocking
|
||||||
behaviour to :c:func:`jbd2_journal_start` so you can deadlock here just as
|
behaviour to jbd2_journal_start() so you can deadlock here just as
|
||||||
easily as on :c:func:`jbd2_journal_start`.
|
easily as on jbd2_journal_start().
|
||||||
|
|
||||||
Try to reserve the right number of blocks the first time. ;-). This will
|
Try to reserve the right number of blocks the first time. ;-). This will
|
||||||
be the maximum number of blocks you are going to touch in this
|
be the maximum number of blocks you are going to touch in this
|
||||||
@ -116,8 +116,8 @@ called after each transaction commit. You can also use
|
|||||||
that need processing when the transaction commits.
|
that need processing when the transaction commits.
|
||||||
|
|
||||||
JBD2 also provides a way to block all transaction updates via
|
JBD2 also provides a way to block all transaction updates via
|
||||||
:c:func:`jbd2_journal_lock_updates()` /
|
jbd2_journal_lock_updates() /
|
||||||
:c:func:`jbd2_journal_unlock_updates()`. Ext4 uses this when it wants a
|
jbd2_journal_unlock_updates(). Ext4 uses this when it wants a
|
||||||
window with a clean and stable fs for a moment. E.g.
|
window with a clean and stable fs for a moment. E.g.
|
||||||
|
|
||||||
::
|
::
|
||||||
|
@ -62,7 +62,6 @@ Legacy documentation
|
|||||||
.. toctree::
|
.. toctree::
|
||||||
:maxdepth: 1
|
:maxdepth: 1
|
||||||
|
|
||||||
upgrading-clients
|
|
||||||
old-module-parameters
|
old-module-parameters
|
||||||
|
|
||||||
.. only:: subproject and html
|
.. only:: subproject and html
|
||||||
|
@ -1,285 +0,0 @@
|
|||||||
=================================================
|
|
||||||
Upgrading I2C Drivers to the new 2.6 Driver Model
|
|
||||||
=================================================
|
|
||||||
|
|
||||||
Ben Dooks <ben-linux@fluff.org>
|
|
||||||
|
|
||||||
Introduction
|
|
||||||
------------
|
|
||||||
|
|
||||||
This guide outlines how to alter existing Linux 2.6 client drivers from
|
|
||||||
the old to the new binding methods.
|
|
||||||
|
|
||||||
|
|
||||||
Example old-style driver
|
|
||||||
------------------------
|
|
||||||
|
|
||||||
::
|
|
||||||
|
|
||||||
struct example_state {
|
|
||||||
struct i2c_client client;
|
|
||||||
....
|
|
||||||
};
|
|
||||||
|
|
||||||
static struct i2c_driver example_driver;
|
|
||||||
|
|
||||||
static unsigned short ignore[] = { I2C_CLIENT_END };
|
|
||||||
static unsigned short normal_addr[] = { OUR_ADDR, I2C_CLIENT_END };
|
|
||||||
|
|
||||||
I2C_CLIENT_INSMOD;
|
|
||||||
|
|
||||||
static int example_attach(struct i2c_adapter *adap, int addr, int kind)
|
|
||||||
{
|
|
||||||
struct example_state *state;
|
|
||||||
struct device *dev = &adap->dev; /* to use for dev_ reports */
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
state = kzalloc(sizeof(struct example_state), GFP_KERNEL);
|
|
||||||
if (state == NULL) {
|
|
||||||
dev_err(dev, "failed to create our state\n");
|
|
||||||
return -ENOMEM;
|
|
||||||
}
|
|
||||||
|
|
||||||
example->client.addr = addr;
|
|
||||||
example->client.flags = 0;
|
|
||||||
example->client.adapter = adap;
|
|
||||||
|
|
||||||
i2c_set_clientdata(&state->i2c_client, state);
|
|
||||||
strscpy(client->i2c_client.name, "example", sizeof(client->i2c_client.name));
|
|
||||||
|
|
||||||
ret = i2c_attach_client(&state->i2c_client);
|
|
||||||
if (ret < 0) {
|
|
||||||
dev_err(dev, "failed to attach client\n");
|
|
||||||
kfree(state);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
dev = &state->i2c_client.dev;
|
|
||||||
|
|
||||||
/* rest of the initialisation goes here. */
|
|
||||||
|
|
||||||
dev_info(dev, "example client created\n");
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int example_detach(struct i2c_client *client)
|
|
||||||
{
|
|
||||||
struct example_state *state = i2c_get_clientdata(client);
|
|
||||||
|
|
||||||
i2c_detach_client(client);
|
|
||||||
kfree(state);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int example_attach_adapter(struct i2c_adapter *adap)
|
|
||||||
{
|
|
||||||
return i2c_probe(adap, &addr_data, example_attach);
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct i2c_driver example_driver = {
|
|
||||||
.driver = {
|
|
||||||
.owner = THIS_MODULE,
|
|
||||||
.name = "example",
|
|
||||||
.pm = &example_pm_ops,
|
|
||||||
},
|
|
||||||
.attach_adapter = example_attach_adapter,
|
|
||||||
.detach_client = example_detach,
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
Updating the client
|
|
||||||
-------------------
|
|
||||||
|
|
||||||
The new style binding model will check against a list of supported
|
|
||||||
devices and their associated address supplied by the code registering
|
|
||||||
the busses. This means that the driver .attach_adapter and
|
|
||||||
.detach_client methods can be removed, along with the addr_data,
|
|
||||||
as follows::
|
|
||||||
|
|
||||||
- static struct i2c_driver example_driver;
|
|
||||||
|
|
||||||
- static unsigned short ignore[] = { I2C_CLIENT_END };
|
|
||||||
- static unsigned short normal_addr[] = { OUR_ADDR, I2C_CLIENT_END };
|
|
||||||
|
|
||||||
- I2C_CLIENT_INSMOD;
|
|
||||||
|
|
||||||
- static int example_attach_adapter(struct i2c_adapter *adap)
|
|
||||||
- {
|
|
||||||
- return i2c_probe(adap, &addr_data, example_attach);
|
|
||||||
- }
|
|
||||||
|
|
||||||
static struct i2c_driver example_driver = {
|
|
||||||
- .attach_adapter = example_attach_adapter,
|
|
||||||
- .detach_client = example_detach,
|
|
||||||
}
|
|
||||||
|
|
||||||
Add the probe and remove methods to the i2c_driver, as so::
|
|
||||||
|
|
||||||
static struct i2c_driver example_driver = {
|
|
||||||
+ .probe = example_probe,
|
|
||||||
+ .remove = example_remove,
|
|
||||||
}
|
|
||||||
|
|
||||||
Change the example_attach method to accept the new parameters
|
|
||||||
which include the i2c_client that it will be working with::
|
|
||||||
|
|
||||||
- static int example_attach(struct i2c_adapter *adap, int addr, int kind)
|
|
||||||
+ static int example_probe(struct i2c_client *client,
|
|
||||||
+ const struct i2c_device_id *id)
|
|
||||||
|
|
||||||
Change the name of example_attach to example_probe to align it with the
|
|
||||||
i2c_driver entry names. The rest of the probe routine will now need to be
|
|
||||||
changed as the i2c_client has already been setup for use.
|
|
||||||
|
|
||||||
The necessary client fields have already been setup before
|
|
||||||
the probe function is called, so the following client setup
|
|
||||||
can be removed::
|
|
||||||
|
|
||||||
- example->client.addr = addr;
|
|
||||||
- example->client.flags = 0;
|
|
||||||
- example->client.adapter = adap;
|
|
||||||
-
|
|
||||||
- strscpy(client->i2c_client.name, "example", sizeof(client->i2c_client.name));
|
|
||||||
|
|
||||||
The i2c_set_clientdata is now::
|
|
||||||
|
|
||||||
- i2c_set_clientdata(&state->client, state);
|
|
||||||
+ i2c_set_clientdata(client, state);
|
|
||||||
|
|
||||||
The call to i2c_attach_client is no longer needed, if the probe
|
|
||||||
routine exits successfully, then the driver will be automatically
|
|
||||||
attached by the core. Change the probe routine as so::
|
|
||||||
|
|
||||||
- ret = i2c_attach_client(&state->i2c_client);
|
|
||||||
- if (ret < 0) {
|
|
||||||
- dev_err(dev, "failed to attach client\n");
|
|
||||||
- kfree(state);
|
|
||||||
- return ret;
|
|
||||||
- }
|
|
||||||
|
|
||||||
|
|
||||||
Remove the storage of 'struct i2c_client' from the 'struct example_state'
|
|
||||||
as we are provided with the i2c_client in our example_probe. Instead we
|
|
||||||
store a pointer to it for when it is needed.
|
|
||||||
|
|
||||||
::
|
|
||||||
|
|
||||||
struct example_state {
|
|
||||||
- struct i2c_client client;
|
|
||||||
+ struct i2c_client *client;
|
|
||||||
|
|
||||||
the new i2c client as so::
|
|
||||||
|
|
||||||
- struct device *dev = &adap->dev; /* to use for dev_ reports */
|
|
||||||
+ struct device *dev = &i2c_client->dev; /* to use for dev_ reports */
|
|
||||||
|
|
||||||
And remove the change after our client is attached, as the driver no
|
|
||||||
longer needs to register a new client structure with the core::
|
|
||||||
|
|
||||||
- dev = &state->i2c_client.dev;
|
|
||||||
|
|
||||||
In the probe routine, ensure that the new state has the client stored
|
|
||||||
in it::
|
|
||||||
|
|
||||||
static int example_probe(struct i2c_client *i2c_client,
|
|
||||||
const struct i2c_device_id *id)
|
|
||||||
{
|
|
||||||
struct example_state *state;
|
|
||||||
struct device *dev = &i2c_client->dev;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
state = kzalloc(sizeof(struct example_state), GFP_KERNEL);
|
|
||||||
if (state == NULL) {
|
|
||||||
dev_err(dev, "failed to create our state\n");
|
|
||||||
return -ENOMEM;
|
|
||||||
}
|
|
||||||
|
|
||||||
+ state->client = i2c_client;
|
|
||||||
|
|
||||||
Update the detach method, by changing the name to _remove and
|
|
||||||
to delete the i2c_detach_client call. It is possible that you
|
|
||||||
can also remove the ret variable as it is not needed for any
|
|
||||||
of the core functions.
|
|
||||||
|
|
||||||
::
|
|
||||||
|
|
||||||
- static int example_detach(struct i2c_client *client)
|
|
||||||
+ static int example_remove(struct i2c_client *client)
|
|
||||||
{
|
|
||||||
struct example_state *state = i2c_get_clientdata(client);
|
|
||||||
|
|
||||||
- i2c_detach_client(client);
|
|
||||||
|
|
||||||
And finally ensure that we have the correct ID table for the i2c-core
|
|
||||||
and other utilities::
|
|
||||||
|
|
||||||
+ struct i2c_device_id example_idtable[] = {
|
|
||||||
+ { "example", 0 },
|
|
||||||
+ { }
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
+MODULE_DEVICE_TABLE(i2c, example_idtable);
|
|
||||||
|
|
||||||
static struct i2c_driver example_driver = {
|
|
||||||
.driver = {
|
|
||||||
.owner = THIS_MODULE,
|
|
||||||
.name = "example",
|
|
||||||
},
|
|
||||||
+ .id_table = example_ids,
|
|
||||||
|
|
||||||
|
|
||||||
Our driver should now look like this::
|
|
||||||
|
|
||||||
struct example_state {
|
|
||||||
struct i2c_client *client;
|
|
||||||
....
|
|
||||||
};
|
|
||||||
|
|
||||||
static int example_probe(struct i2c_client *client,
|
|
||||||
const struct i2c_device_id *id)
|
|
||||||
{
|
|
||||||
struct example_state *state;
|
|
||||||
struct device *dev = &client->dev;
|
|
||||||
|
|
||||||
state = kzalloc(sizeof(struct example_state), GFP_KERNEL);
|
|
||||||
if (state == NULL) {
|
|
||||||
dev_err(dev, "failed to create our state\n");
|
|
||||||
return -ENOMEM;
|
|
||||||
}
|
|
||||||
|
|
||||||
state->client = client;
|
|
||||||
i2c_set_clientdata(client, state);
|
|
||||||
|
|
||||||
/* rest of the initialisation goes here. */
|
|
||||||
|
|
||||||
dev_info(dev, "example client created\n");
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int example_remove(struct i2c_client *client)
|
|
||||||
{
|
|
||||||
struct example_state *state = i2c_get_clientdata(client);
|
|
||||||
|
|
||||||
kfree(state);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct i2c_device_id example_idtable[] = {
|
|
||||||
{ "example", 0 },
|
|
||||||
{ }
|
|
||||||
};
|
|
||||||
|
|
||||||
MODULE_DEVICE_TABLE(i2c, example_idtable);
|
|
||||||
|
|
||||||
static struct i2c_driver example_driver = {
|
|
||||||
.driver = {
|
|
||||||
.owner = THIS_MODULE,
|
|
||||||
.name = "example",
|
|
||||||
.pm = &example_pm_ops,
|
|
||||||
},
|
|
||||||
.id_table = example_idtable,
|
|
||||||
.probe = example_probe,
|
|
||||||
.remove = example_remove,
|
|
||||||
};
|
|
@ -10,7 +10,7 @@ Introduction
|
|||||||
============
|
============
|
||||||
|
|
||||||
The kernel provides a variety of locking primitives which can be divided
|
The kernel provides a variety of locking primitives which can be divided
|
||||||
into two categories:
|
into three categories:
|
||||||
|
|
||||||
- Sleeping locks
|
- Sleeping locks
|
||||||
- CPU local locks
|
- CPU local locks
|
||||||
|
@ -113,7 +113,7 @@ than one development cycle past their initial release. So, for example, the
|
|||||||
5.2 kernel's history looked like this (all dates in 2019):
|
5.2 kernel's history looked like this (all dates in 2019):
|
||||||
|
|
||||||
============== ===============================
|
============== ===============================
|
||||||
September 15 5.2 stable release
|
July 7 5.2 stable release
|
||||||
July 14 5.2.1
|
July 14 5.2.1
|
||||||
July 21 5.2.2
|
July 21 5.2.2
|
||||||
July 26 5.2.3
|
July 26 5.2.3
|
||||||
|
@ -58,7 +58,7 @@ Bus and Subdevices
|
|||||||
|
|
||||||
For each Intel TH device in the system a bus of its own is
|
For each Intel TH device in the system a bus of its own is
|
||||||
created and assigned an id number that reflects the order in which TH
|
created and assigned an id number that reflects the order in which TH
|
||||||
devices were emumerated. All TH subdevices (devices on intel_th bus)
|
devices were enumerated. All TH subdevices (devices on intel_th bus)
|
||||||
begin with this id: 0-gth, 0-msc0, 0-msc1, 0-pti, 0-sth, which is
|
begin with this id: 0-gth, 0-msc0, 0-msc1, 0-pti, 0-sth, which is
|
||||||
followed by device's name and an optional index.
|
followed by device's name and an optional index.
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
=======
|
========
|
||||||
CPU 负载
|
CPU 负载
|
||||||
=======
|
========
|
||||||
|
|
||||||
Linux通过``/proc/stat``和``/proc/uptime``导出各种信息,用户空间工具
|
Linux通过``/proc/stat``和``/proc/uptime``导出各种信息,用户空间工具
|
||||||
如top(1)使用这些信息计算系统花费在某个特定状态的平均时间。
|
如top(1)使用这些信息计算系统花费在某个特定状态的平均时间。
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
.. include:: ../disclaimer-zh_CN.rst
|
.. include:: ../disclaimer-zh_CN.rst
|
||||||
|
|
||||||
:Original: :ref:`Documentation/admin-guide/index.rst`
|
:Original: :doc:`../../../admin-guide/index`
|
||||||
:Translator: Alex Shi <alex.shi@linux.alibaba.com>
|
:Translator: Alex Shi <alex.shi@linux.alibaba.com>
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user