mirror of
https://github.com/torvalds/linux.git
synced 2026-11-06 21:58:01 +01:00
Compare commits
No commits in common. "master" and "v7.4-rc1" have entirely different histories.
4
.mailmap
4
.mailmap
|
|
@ -233,10 +233,6 @@ Chuck Lever <cel@kernel.org> <chuck.lever@oracle.com>
|
|||
Chuck Lever <cel@kernel.org> <cel@netapp.com>
|
||||
Chuck Lever <cel@kernel.org> <cel@citi.umich.edu>
|
||||
Claudiu Beznea <claudiu.beznea@tuxon.dev> <claudiu.beznea@microchip.com>
|
||||
Clément Léger <clement.leger@linux.dev> <cleger@kalray.eu>
|
||||
Clément Léger <clement.leger@linux.dev> <clement.leger@bootlin.com>
|
||||
Clément Léger <clement.leger@linux.dev> <cleger@rivosinc.com>
|
||||
Clément Léger <clement.leger@linux.dev> <cleger@meta.com>
|
||||
Coiby Xu <coiby.xu@gmail.com> <coxu@redhat.com>
|
||||
Colin Ian King <colin.i.king@gmail.com> <colin.king@canonical.com>
|
||||
Corey Minyard <minyard@acm.org>
|
||||
|
|
|
|||
|
|
@ -407,13 +407,6 @@ referenced kptr (by invoking bpf_kptr_xchg). If not, the verifier fails the
|
|||
loading of the BPF program until no lingering references remain in all possible
|
||||
explored states of the program.
|
||||
|
||||
A pointer to a struct in the arguments of a KF_ACQUIRE kfunc accepts only an
|
||||
object of that type. The same applies to the argument that a KF_RELEASE kfunc
|
||||
releases. For other arguments a kfunc also accepts memory of the program, if the
|
||||
struct has only scalar members. A struct without members, struct __sk_buff and
|
||||
struct xdp_md never accept memory. A KF_ACQUIRE kfunc which wants such memory
|
||||
has to pair the pointer with a __sz argument.
|
||||
|
||||
2.5.2 KF_RET_NULL flag
|
||||
----------------------
|
||||
|
||||
|
|
|
|||
|
|
@ -50,14 +50,6 @@ mount points. Each 9P export is seen by the client as a virtio device with an
|
|||
associated "mount_tag" property. Available mount tags can be
|
||||
seen by reading /sys/bus/virtio/drivers/9pnet_virtio/virtio<n>/mount_tag files.
|
||||
|
||||
For server accessible over vsock (VM sockets)::
|
||||
|
||||
mount -t 9p -o trans=vsock[,port=<port>] <CID> /mnt/9
|
||||
|
||||
where CID is the vsock Context ID of the remote endpoint (2 for host from
|
||||
a guest VM, 3+ for guest VMs from the host). The port to connect to can be
|
||||
specified with the port option (default: 564).
|
||||
|
||||
USBG Usage
|
||||
==========
|
||||
|
||||
|
|
@ -125,8 +117,6 @@ Options
|
|||
tcp specifying a normal TCP/IP connection
|
||||
fd used passed file descriptors for connection
|
||||
(see rfdno and wfdno)
|
||||
vsock connect over VM sockets (vsock) using
|
||||
CID as the mount source
|
||||
virtio connect to the next virtio channel available
|
||||
(from QEMU with trans_virtio module)
|
||||
rdma connect to a specified RDMA channel
|
||||
|
|
@ -238,7 +228,7 @@ Options
|
|||
any
|
||||
v9fs does single attach and performs all
|
||||
operations as one user
|
||||
client
|
||||
clien
|
||||
ACL based access check on the 9p client
|
||||
side for access validation
|
||||
|
||||
|
|
|
|||
|
|
@ -731,8 +731,7 @@ When decoding an overlay file handle, the following steps are followed:
|
|||
|
||||
1. Find underlying layer by UUID and path type information.
|
||||
2. Decode the underlying filesystem file handle to underlying dentry.
|
||||
3. For a lower file handle, encode the decoded underlying inode again and
|
||||
lookup that handle in index directory by name.
|
||||
3. For a lower file handle, lookup the handle in index directory by name.
|
||||
4. If a whiteout is found in index, return ESTALE. This represents an
|
||||
overlay object that was deleted after its file handle was encoded.
|
||||
5. For a non-directory, instantiate a disconnected overlay dentry from the
|
||||
|
|
|
|||
|
|
@ -34,12 +34,6 @@ Usage notes
|
|||
As these are USB HIDs, the driver can be loaded automatically by the kernel and
|
||||
supports hot swapping.
|
||||
|
||||
The pump of the RYUJIN III also has a 4-pin cable for a motherboard fan header.
|
||||
The cooler either hands the pump to its internal controller, which follows the
|
||||
PWM of the header its 4-pin cable is plugged into, or runs it at the pump duty
|
||||
set over USB. Writing pwm1 selects the duty set over USB. Writing pwm2 sets
|
||||
only the internal fan duty and leaves the pump control as it is.
|
||||
|
||||
Sysfs entries
|
||||
-------------
|
||||
|
||||
|
|
|
|||
|
|
@ -130,19 +130,8 @@ pages of ``struct page`` (page 1 to page 7) are tail pages.
|
|||
The optimization is only applied when the size of the struct page is a power
|
||||
of 2. In this case, all tail pages of the same order are identical. See
|
||||
compound_head(). This allows us to remap the tail pages of the vmemmap to a
|
||||
shared page. The head page is also remapped to a new page. This allows the
|
||||
original vmemmap pages to be freed.
|
||||
|
||||
The shared page is mapped writable. A lockless get of a page reference can
|
||||
read a non-zero refcount before the remap and attempt its atomic update
|
||||
after it. The refcount of a tail page is zero, so the update fails without
|
||||
changing the page. Nothing else may write to the shared page: it is shared
|
||||
by all HugeTLB pages of the same size in the zone, and a stray write would
|
||||
corrupt all of them.
|
||||
|
||||
HugeTLB pages whose vmemmap is optimized when the memmap is first set up at
|
||||
boot keep a read-only mapping of the shared page. Nothing can do a lockless
|
||||
get on them before they are handed to HugeTLB.
|
||||
shared, read-only page. The head page is also remapped to a new page. This
|
||||
allows the original vmemmap pages to be freed.
|
||||
|
||||
Here is how things look after remapping::
|
||||
|
||||
|
|
|
|||
|
|
@ -1040,21 +1040,17 @@ As described in :ref:`socketcan-receive-lists` the SocketCAN core uses several f
|
|||
lists to deliver received CAN frames to CAN protocol modules. These
|
||||
receive lists, their filters and the count of filter matches can be
|
||||
checked in the appropriate receive list. All entries contain the
|
||||
CAN network device, the filter (can_id/can_mask), the number of filter
|
||||
matches, the inode number of the subscribing socket and the name of the
|
||||
receive function. A sock_inode of 0 denotes a kernel internal subscriber
|
||||
without a socket (e.g. CAN gateway or J1939). When the function name can
|
||||
not be resolved (e.g. with CONFIG_KALLSYMS=n) "(unknown)" is printed::
|
||||
device and a protocol module identifier::
|
||||
|
||||
foo@bar:~$ cat /proc/net/can/rcvlist_all
|
||||
|
||||
receive list 'rx_all':
|
||||
(any: no entry)
|
||||
device can_id can_mask matches sock_inode function
|
||||
vcan0 000 00000000 0 63586 raw_rcv [can_raw]
|
||||
(vcan1: no entry)
|
||||
(vcan2: no entry)
|
||||
(vcan3: no entry)
|
||||
(vcan2: no entry)
|
||||
(vcan1: no entry)
|
||||
device can_id can_mask function userdata matches ident
|
||||
vcan0 000 00000000 f88e6370 f6c6f400 0 raw
|
||||
(any: no entry)
|
||||
|
||||
In this example an application requests any CAN traffic from vcan0::
|
||||
|
||||
|
|
|
|||
|
|
@ -27,20 +27,15 @@ SA Identification
|
|||
=================
|
||||
|
||||
The struct is defined in ``include/uapi/linux/xfrm.h``. The SA is looked
|
||||
up using ``xfrm_state_lookup_exact()`` with ``id.spi``, ``id.daddr``,
|
||||
``id.proto``, ``id.family``, and an exact match against ``old_mark.v``
|
||||
and ``old_mark.m``. Unlike the data path, which uses a masked
|
||||
comparison, this requires the SA's mark and mask to equal ``old_mark``
|
||||
exactly, so a broad-mask SA is never matched when a more specific one
|
||||
was intended. If no such SA exists, ``-ESRCH`` is returned.
|
||||
|
||||
The layout is::
|
||||
up using ``xfrm_state_lookup()`` with ``id.spi``,
|
||||
``id.daddr``, ``id.proto``, ``id.family``, and
|
||||
``old_mark.v & old_mark.m`` as the mark key::
|
||||
|
||||
struct xfrm_user_migrate_state {
|
||||
struct xfrm_usersa_id id; /* spi, daddr, proto, family */
|
||||
xfrm_address_t new_daddr;
|
||||
xfrm_address_t new_saddr;
|
||||
struct xfrm_mark old_mark; /* SA lookup key (exact v/m match) */
|
||||
struct xfrm_mark old_mark; /* SA lookup: key = v & m */
|
||||
struct xfrm_selector new_sel; /* new selector (see Flags) */
|
||||
__u32 new_reqid;
|
||||
__u32 flags; /* XFRM_MIGRATE_STATE_* */
|
||||
|
|
@ -77,8 +72,8 @@ inherits the value from the existing SA (omit-to-inherit).
|
|||
- Description
|
||||
* - ``XFRMA_MARK``
|
||||
- Mark on the migrated SA (``struct xfrm_mark``). Absent inherits
|
||||
the mark of the existing SA. To use no mark on the new SA, send
|
||||
``XFRMA_MARK`` with ``{0, 0}``.
|
||||
``old_mark``. To use no mark on the new SA, send ``XFRMA_MARK``
|
||||
with ``{0, 0}``.
|
||||
* - ``XFRMA_ENCAP``
|
||||
- UDP encapsulation template; only ``UDP_ENCAP_ESPINUDP`` is supported.
|
||||
Set ``encap_type=0`` to remove encap.
|
||||
|
|
@ -264,12 +259,8 @@ Attributes in the notification
|
|||
Error Handling
|
||||
==============
|
||||
|
||||
If the target SA tuple (new daddr, SPI, proto, new family, mark) is
|
||||
already occupied, the operation returns ``-EEXIST`` before the migration
|
||||
begins. "Occupied" includes wildcard shadowing: an existing SA with a
|
||||
broader mask (e.g. mark 0/0) claims every mark value, so it blocks
|
||||
migrating to any more specific mark at the same tuple, not just an
|
||||
exact mark/mask duplicate.
|
||||
If the target SA tuple (new daddr, SPI, proto, new family) is already
|
||||
occupied, the operation returns ``-EEXIST`` before the migration begins.
|
||||
The old SA remains intact and the operation is safe to retry after
|
||||
resolving the conflict.
|
||||
|
||||
|
|
|
|||
|
|
@ -315,10 +315,6 @@ reproducer and against kernel selftests. If the bug is in a hardware driver,
|
|||
the testing statement must include information about the HW on which the
|
||||
fix was tested.
|
||||
|
||||
Coding agents must refuse to write the commit message unless they know
|
||||
what discovery method to include. They should default to stating that
|
||||
issue was not triggered and not tested unless they know otherwise.
|
||||
|
||||
Stable tree
|
||||
~~~~~~~~~~~
|
||||
|
||||
|
|
|
|||
250
MAINTAINERS
250
MAINTAINERS
|
|
@ -6868,13 +6868,11 @@ R: Muchun Song <muchun.song@linux.dev>
|
|||
L: cgroups@vger.kernel.org
|
||||
L: linux-mm@kvack.org
|
||||
S: Maintained
|
||||
F: Documentation/admin-guide/cgroup-v1/memory.rst
|
||||
F: include/linux/memcontrol.h
|
||||
F: include/linux/page_counter.h
|
||||
F: include/trace/events/memcg.h
|
||||
F: mm/memcontrol.c
|
||||
F: mm/memcontrol-v1.c
|
||||
F: mm/memcontrol-v1.h
|
||||
F: mm/memcontrol.c
|
||||
F: mm/page_counter.c
|
||||
F: samples/cgroup/*
|
||||
F: tools/testing/selftests/cgroup/memcg_protection.m
|
||||
|
|
@ -7838,7 +7836,7 @@ W: http://www.win.tue.nl/~aeb/linux/zip/zip-1.html
|
|||
W: http://www.win.tue.nl/~aeb/partitions/partition_types-1.html
|
||||
|
||||
DISKQUOTA
|
||||
M: Jan Kara <jack@suse.cz>
|
||||
M: Jan Kara <jack@suse.com>
|
||||
S: Maintained
|
||||
F: Documentation/filesystems/quota.rst
|
||||
F: fs/quota/
|
||||
|
|
@ -10109,7 +10107,7 @@ F: drivers/leds/leds-expresswire.c
|
|||
F: include/linux/leds-expresswire.h
|
||||
|
||||
EXT2 FILE SYSTEM
|
||||
M: Jan Kara <jack@suse.cz>
|
||||
M: Jan Kara <jack@suse.com>
|
||||
L: linux-ext4@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/filesystems/ext2.rst
|
||||
|
|
@ -12378,7 +12376,6 @@ R: David Hildenbrand <david@kernel.org>
|
|||
L: linux-mm@kvack.org
|
||||
S: Maintained
|
||||
F: Documentation/ABI/testing/sysfs-kernel-mm-hugepages
|
||||
F: Documentation/admin-guide/cgroup-v1/hugetlb.rst
|
||||
F: Documentation/admin-guide/mm/hugetlbpage.rst
|
||||
F: Documentation/mm/hugetlbfs_reserv.rst
|
||||
F: Documentation/mm/vmemmap_dedup.rst
|
||||
|
|
@ -12390,7 +12387,6 @@ F: mm/hugetlb.c
|
|||
F: mm/hugetlb_cgroup.c
|
||||
F: mm/hugetlb_cma.c
|
||||
F: mm/hugetlb_cma.h
|
||||
F: mm/hugetlb_internal.h
|
||||
F: mm/hugetlb_sysctl.c
|
||||
F: mm/hugetlb_sysfs.c
|
||||
F: mm/hugetlb_vmemmap.c
|
||||
|
|
@ -12410,7 +12406,6 @@ M: Miaohe Lin <linmiaohe@huawei.com>
|
|||
R: Naoya Horiguchi <nao.horiguchi@gmail.com>
|
||||
L: linux-mm@kvack.org
|
||||
S: Maintained
|
||||
F: Documentation/ABI/testing/sysfs-memory-page-offline
|
||||
F: include/linux/memory-failure.h
|
||||
F: include/trace/events/memory-failure.h
|
||||
F: mm/hwpoison-inject.c
|
||||
|
|
@ -14075,16 +14070,6 @@ S: Maintained
|
|||
F: io_uring/bpf-ops.*
|
||||
F: io_uring/loop.*
|
||||
|
||||
IPC
|
||||
M: Andrew Morton <akpm@linux-foundation.org>
|
||||
R: Manfred Spraul <manfred@colorfullife.com>
|
||||
R: Davidlohr Bueso <dave@stgolabs.net>
|
||||
L: linux-kernel@vger.kernel.org
|
||||
S: Maintained
|
||||
F: ipc/
|
||||
F: tools/testing/selftests/ipc/
|
||||
F: tools/testing/selftests/mqueue/
|
||||
|
||||
IPMI SUBSYSTEM
|
||||
M: Corey Minyard <corey@minyard.net>
|
||||
L: openipmi-developer@lists.sourceforge.net (moderated for non-subscribers)
|
||||
|
|
@ -14324,7 +14309,7 @@ F: include/uapi/linux/jffs2.h
|
|||
|
||||
JOURNALLING LAYER FOR BLOCK DEVICES (JBD2)
|
||||
M: "Theodore Ts'o" <tytso@mit.edu>
|
||||
M: Jan Kara <jack@suse.cz>
|
||||
M: Jan Kara <jack@suse.com>
|
||||
L: linux-ext4@vger.kernel.org
|
||||
S: Maintained
|
||||
F: fs/jbd2/
|
||||
|
|
@ -17471,6 +17456,21 @@ S: Maintained
|
|||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/chanwoo/linux.git
|
||||
F: drivers/devfreq/tegra30-devfreq.c
|
||||
|
||||
MEMORY HOT(UN)PLUG
|
||||
M: David Hildenbrand <david@kernel.org>
|
||||
M: Oscar Salvador <osalvador@suse.de>
|
||||
L: linux-mm@kvack.org
|
||||
L: linux-cxl@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/admin-guide/mm/memory-hotplug.rst
|
||||
F: Documentation/core-api/memory-hotplug.rst
|
||||
F: drivers/base/memory.c
|
||||
F: include/linux/memory_hotplug.h
|
||||
F: include/linux/memremap.h
|
||||
F: mm/memremap.c
|
||||
F: mm/memory_hotplug.c
|
||||
F: tools/testing/selftests/memory-hotplug/
|
||||
|
||||
MEMORY MANAGEMENT
|
||||
M: Andrew Morton <akpm@linux-foundation.org>
|
||||
L: linux-mm@kvack.org
|
||||
|
|
@ -17494,15 +17494,18 @@ F: mm/alloc_tag.c
|
|||
F: tools/testing/selftests/alloc_tag/
|
||||
|
||||
MEMORY MANAGEMENT - BALLOON
|
||||
M: Andrew Morton <akpm@linux-foundation.org>
|
||||
M: David Hildenbrand <david@kernel.org>
|
||||
L: linux-mm@kvack.org
|
||||
L: virtualization@lists.linux.dev
|
||||
S: Maintained
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/mm/core.git for-next
|
||||
W: http://www.linux-mm.org
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm
|
||||
F: include/linux/balloon.h
|
||||
F: mm/balloon.c
|
||||
|
||||
MEMORY MANAGEMENT - CORE
|
||||
M: Andrew Morton <akpm@linux-foundation.org>
|
||||
M: David Hildenbrand <david@kernel.org>
|
||||
R: Lorenzo Stoakes <ljs@kernel.org>
|
||||
R: Liam R. Howlett <liam@infradead.org>
|
||||
|
|
@ -17512,34 +17515,27 @@ R: Suren Baghdasaryan <surenb@google.com>
|
|||
R: Michal Hocko <mhocko@suse.com>
|
||||
L: linux-mm@kvack.org
|
||||
S: Maintained
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/mm/core.git for-next
|
||||
W: http://www.linux-mm.org
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm
|
||||
F: Documentation/admin-guide/sysctl/vm.rst
|
||||
F: Documentation/core-api/gfp_mask-from-fs-io.rst
|
||||
F: fs/proc/meminfo.c
|
||||
F: include/linux/cacheflush.h
|
||||
F: include/linux/folio_batch.h
|
||||
F: include/linux/gfp.h
|
||||
F: include/linux/gfp_types.h
|
||||
F: include/linux/highmem-internal.h
|
||||
F: include/linux/highmem.h
|
||||
F: include/linux/leafops.h
|
||||
F: include/linux/memory.h
|
||||
F: include/linux/mm.h
|
||||
F: include/linux/mm_*.h
|
||||
F: include/linux/mmzone.h
|
||||
F: include/linux/mmdebug.h
|
||||
F: include/linux/mmu_notifier.h
|
||||
F: include/linux/mmzone.h
|
||||
F: include/linux/pagewalk.h
|
||||
F: include/linux/pfn.h
|
||||
F: include/linux/pgalloc.h
|
||||
F: include/linux/pgtable.h
|
||||
F: include/linux/ptdump.h
|
||||
F: include/linux/sched/mm.h
|
||||
F: include/linux/vm_event_item.h
|
||||
F: include/linux/vmpressure.h
|
||||
F: include/linux/vmstat.h
|
||||
F: include/trace/events/mmflags.h
|
||||
F: include/trace/events/pagemap.h
|
||||
F: fs/proc/meminfo.c
|
||||
F: kernel/fork.c
|
||||
F: mm/Kconfig
|
||||
F: mm/debug.c
|
||||
|
|
@ -17558,7 +17554,6 @@ F: mm/ptdump.c
|
|||
F: mm/util.c
|
||||
F: mm/vmpressure.c
|
||||
F: mm/vmstat.c
|
||||
F: scripts/gdb/linux/mm.py
|
||||
N: include\/linux\/page[-_][a-zA-Z]*
|
||||
|
||||
MEMORY MANAGEMENT - EXECMEM
|
||||
|
|
@ -17570,14 +17565,15 @@ F: include/linux/execmem.h
|
|||
F: mm/execmem.c
|
||||
|
||||
MEMORY MANAGEMENT - GUP (GET USER PAGES)
|
||||
M: Andrew Morton <akpm@linux-foundation.org>
|
||||
M: David Hildenbrand <david@kernel.org>
|
||||
R: Jason Gunthorpe <jgg@nvidia.com>
|
||||
R: John Hubbard <jhubbard@nvidia.com>
|
||||
R: Peter Xu <peterx@redhat.com>
|
||||
L: linux-mm@kvack.org
|
||||
S: Maintained
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/mm/core.git for-next
|
||||
F: Documentation/core-api/pin_user_pages.rst
|
||||
W: http://www.linux-mm.org
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm
|
||||
F: mm/gup.c
|
||||
F: mm/gup_test.c
|
||||
F: mm/gup_test.h
|
||||
|
|
@ -17586,12 +17582,14 @@ F: tools/testing/selftests/mm/gup.c
|
|||
F: tools/testing/selftests/mm/gup_longterm.c
|
||||
|
||||
MEMORY MANAGEMENT - KSM (Kernel Samepage Merging)
|
||||
M: Andrew Morton <akpm@linux-foundation.org>
|
||||
M: David Hildenbrand <david@kernel.org>
|
||||
R: Xu Xin <xu.xin@linux.dev>
|
||||
R: Chengming Zhou <chengming.zhou@linux.dev>
|
||||
L: linux-mm@kvack.org
|
||||
S: Maintained
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/mm/core.git for-next
|
||||
W: http://www.linux-mm.org
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm
|
||||
F: Documentation/ABI/testing/sysfs-kernel-mm-ksm
|
||||
F: Documentation/admin-guide/mm/ksm.rst
|
||||
F: Documentation/mm/ksm.rst
|
||||
|
|
@ -17600,30 +17598,13 @@ F: include/trace/events/ksm.h
|
|||
F: mm/ksm.c
|
||||
F: mm/mm_slot.h
|
||||
|
||||
MEMORY MANAGEMENT - MEMORY HOT(UN)PLUG
|
||||
M: David Hildenbrand <david@kernel.org>
|
||||
M: Oscar Salvador <osalvador@suse.de>
|
||||
L: linux-mm@kvack.org
|
||||
L: linux-cxl@vger.kernel.org
|
||||
S: Maintained
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/mm/core.git for-next
|
||||
F: Documentation/ABI/testing/sysfs-devices-memory
|
||||
F: Documentation/admin-guide/mm/memory-hotplug.rst
|
||||
F: Documentation/core-api/memory-hotplug.rst
|
||||
F: drivers/base/memory.c
|
||||
F: include/linux/memory_hotplug.h
|
||||
F: include/linux/memremap.h
|
||||
F: mm/memory_hotplug.c
|
||||
F: mm/memremap.c
|
||||
F: tools/testing/selftests/memory-hotplug/
|
||||
|
||||
MEMORY MANAGEMENT - MEMORY MAP
|
||||
M: Muchun Song <muchun.song@linux.dev>
|
||||
M: Mike Rapoport <rppt@kernel.org>
|
||||
M: David Hildenbrand <david@kernel.org>
|
||||
L: linux-mm@kvack.org
|
||||
S: Maintained
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/mm/core.git for-next
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/mm/core.git memmap
|
||||
F: Documentation/mm/memory-model.rst
|
||||
F: arch/*/include/asm/sparsemem.h
|
||||
F: include/asm-generic/memory_model.h
|
||||
|
|
@ -17655,6 +17636,7 @@ F: mm/vmscan.c
|
|||
F: mm/workingset.c
|
||||
|
||||
MEMORY MANAGEMENT - MIGRATION
|
||||
M: Andrew Morton <akpm@linux-foundation.org>
|
||||
M: David Hildenbrand <david@kernel.org>
|
||||
R: Zi Yan <ziy@nvidia.com>
|
||||
R: Matthew Brost <matthew.brost@intel.com>
|
||||
|
|
@ -17665,10 +17647,10 @@ R: Ying Huang <ying.huang@linux.alibaba.com>
|
|||
R: Alistair Popple <apopple@nvidia.com>
|
||||
L: linux-mm@kvack.org
|
||||
S: Maintained
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/mm/core.git for-next
|
||||
W: http://www.linux-mm.org
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm
|
||||
F: include/linux/migrate.h
|
||||
F: include/linux/migrate_mode.h
|
||||
F: include/trace/events/migrate.h
|
||||
F: mm/migrate.c
|
||||
F: mm/migrate_device.c
|
||||
|
||||
|
|
@ -17692,20 +17674,15 @@ F: Documentation/admin-guide/mm/
|
|||
F: Documentation/core-api/memory-allocation.rst
|
||||
F: Documentation/core-api/mm-api.rst
|
||||
F: Documentation/mm/
|
||||
F: fs/proc/page.c
|
||||
F: include/linux/backing-dev-defs.h
|
||||
F: include/linux/backing-dev.h
|
||||
X: Documentation/admin-guide/mm/damon/
|
||||
X: Documentation/mm/damon/
|
||||
F: mm/char-mem.c
|
||||
F: include/linux/cma.h
|
||||
F: include/linux/dmapool.h
|
||||
F: include/linux/ioremap.h
|
||||
F: include/linux/kernel-page-flags.h
|
||||
F: include/linux/page_idle.h
|
||||
F: include/trace/events/cma.h
|
||||
F: include/uapi/linux/kernel-page-flags.h
|
||||
F: mm/backing-dev.c
|
||||
F: mm/char-mem.c
|
||||
F: mm/cma.c
|
||||
F: mm/cma.h
|
||||
F: mm/cma_debug.c
|
||||
F: mm/cma_sysfs.c
|
||||
F: mm/dmapool.c
|
||||
|
|
@ -17718,11 +17695,7 @@ F: mm/page_idle.c
|
|||
F: mm/pgalloc-track.h
|
||||
F: mm/process_vm_access.c
|
||||
F: tools/lib/mm/
|
||||
F: tools/mm/
|
||||
F: tools/testing/selftests/mm/
|
||||
X: Documentation/ABI/testing/sysfs-kernel-mm-damon
|
||||
X: Documentation/admin-guide/mm/damon/
|
||||
X: Documentation/mm/damon/
|
||||
|
||||
MEMORY MANAGEMENT - NUMA MEMBLOCKS AND NUMA EMULATION
|
||||
M: Andrew Morton <akpm@linux-foundation.org>
|
||||
|
|
@ -17730,13 +17703,13 @@ M: Mike Rapoport <rppt@kernel.org>
|
|||
L: linux-mm@kvack.org
|
||||
S: Maintained
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/rppt/memblock.git
|
||||
F: include/linux/numa.h
|
||||
F: include/linux/numa_memblks.h
|
||||
F: mm/numa.c
|
||||
F: mm/numa_emulation.c
|
||||
F: mm/numa_memblks.c
|
||||
|
||||
MEMORY MANAGEMENT - NUMA PLACEMENT
|
||||
M: Andrew Morton <akpm@linux-foundation.org>
|
||||
M: David Hildenbrand <david@kernel.org>
|
||||
M: Gregory Price <gourry@gourry.net>
|
||||
R: Zi Yan <ziy@nvidia.com>
|
||||
|
|
@ -17745,11 +17718,11 @@ R: Rakie Kim <rakie.kim@sk.com>
|
|||
R: Ying Huang <ying.huang@linux.alibaba.com>
|
||||
L: linux-mm@kvack.org
|
||||
S: Maintained
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/mm/core.git for-next
|
||||
W: http://www.linux-mm.org
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm
|
||||
F: Documentation/ABI/testing/sysfs-kernel-mm-memory-tiers
|
||||
F: Documentation/ABI/testing/sysfs-kernel-mm-mempolicy
|
||||
F: Documentation/ABI/testing/sysfs-kernel-mm-mempolicy-weighted-interleave
|
||||
F: Documentation/admin-guide/numastat.rst
|
||||
F: include/linux/memory-tiers.h
|
||||
F: include/linux/mempolicy.h
|
||||
F: include/uapi/linux/mempolicy.h
|
||||
|
|
@ -17768,22 +17741,19 @@ F: include/uapi/linux/oom.h
|
|||
F: mm/oom_kill.c
|
||||
|
||||
MEMORY MANAGEMENT - PAGE ALLOCATOR
|
||||
M: Andrew Morton <akpm@linux-foundation.org>
|
||||
M: Vlastimil Babka <vbabka@kernel.org>
|
||||
M: Johannes Weiner <hannes@cmpxchg.org>
|
||||
R: Suren Baghdasaryan <surenb@google.com>
|
||||
R: Michal Hocko <mhocko@suse.com>
|
||||
R: Brendan Jackman <brendan.jackman@linux.dev>
|
||||
R: Johannes Weiner <hannes@cmpxchg.org>
|
||||
R: Zi Yan <ziy@nvidia.com>
|
||||
L: linux-mm@kvack.org
|
||||
S: Maintained
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/mm/page_alloc.git page_alloc/for-next
|
||||
F: include/linux/compaction.h
|
||||
F: include/linux/gfp.h
|
||||
F: include/linux/page-isolation.h
|
||||
F: include/linux/pageblock-flags.h
|
||||
F: include/trace/events/compaction.h
|
||||
F: include/trace/events/page_isolation.h
|
||||
F: include/trace/events/page_ref.h
|
||||
F: mm/compaction.c
|
||||
F: mm/debug_page_alloc.c
|
||||
F: mm/debug_page_ref.c
|
||||
|
|
@ -17800,9 +17770,6 @@ F: mm/page_reporting.h
|
|||
F: mm/show_mem.c
|
||||
F: mm/shuffle.c
|
||||
F: mm/shuffle.h
|
||||
F: scripts/gdb/linux/page_owner.py
|
||||
F: tools/mm/page_owner_filter.c
|
||||
F: tools/mm/page_owner_sort.c
|
||||
|
||||
MEMORY MANAGEMENT - RECLAIM
|
||||
M: Andrew Morton <akpm@linux-foundation.org>
|
||||
|
|
@ -17814,11 +17781,11 @@ R: Shakeel Butt <shakeel.butt@linux.dev>
|
|||
R: Lorenzo Stoakes <ljs@kernel.org>
|
||||
L: linux-mm@kvack.org
|
||||
S: Maintained
|
||||
F: include/trace/events/vmscan.h
|
||||
F: mm/vmscan.c
|
||||
F: mm/workingset.c
|
||||
|
||||
MEMORY MANAGEMENT - RMAP (REVERSE MAPPING)
|
||||
M: Andrew Morton <akpm@linux-foundation.org>
|
||||
M: David Hildenbrand <david@kernel.org>
|
||||
M: Lorenzo Stoakes <ljs@kernel.org>
|
||||
R: Rik van Riel <riel@surriel.com>
|
||||
|
|
@ -17829,7 +17796,6 @@ R: Jann Horn <jannh@google.com>
|
|||
R: Lance Yang <lance.yang@linux.dev>
|
||||
L: linux-mm@kvack.org
|
||||
S: Maintained
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/mm/core.git for-next
|
||||
F: include/linux/rmap.h
|
||||
F: mm/interval_tree.c
|
||||
F: mm/page_vma_mapped.c
|
||||
|
|
@ -17844,54 +17810,6 @@ S: Maintained
|
|||
F: include/linux/secretmem.h
|
||||
F: mm/secretmem.c
|
||||
|
||||
MEMORY MANAGEMENT - SHARED MEMORY (SHMEM/TMPFS/MEMFD)
|
||||
M: Hugh Dickins <hughd@google.com>
|
||||
M: David Hildenbrand <david@kernel.org>
|
||||
R: Baolin Wang <baolin.wang@linux.alibaba.com>
|
||||
L: linux-mm@kvack.org
|
||||
S: Maintained
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/mm/core.git for-next
|
||||
F: Documentation/filesystems/tmpfs.rst
|
||||
F: Documentation/mm/shmfs.rst
|
||||
F: Documentation/userspace-api/mfd_noexec.rst
|
||||
F: include/linux/memfd.h
|
||||
F: include/linux/shmem_fs.h
|
||||
F: include/uapi/linux/memfd.h
|
||||
F: mm/memfd.c
|
||||
F: mm/shmem.c
|
||||
F: mm/shmem_quota.c
|
||||
F: tools/testing/selftests/memfd/
|
||||
F: tools/testing/selftests/tmpfs/
|
||||
|
||||
MEMORY MANAGEMENT - SLAB ALLOCATOR
|
||||
M: Vlastimil Babka <vbabka@kernel.org>
|
||||
M: Harry Yoo <harry@kernel.org>
|
||||
R: Hao Li <hao.li@linux.dev>
|
||||
R: Christoph Lameter <cl@gentwo.org>
|
||||
R: David Rientjes <rientjes@google.com>
|
||||
R: Roman Gushchin <roman.gushchin@linux.dev>
|
||||
L: linux-mm@kvack.org
|
||||
S: Maintained
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/mm/slab.git slab/for-next
|
||||
F: Documentation/ABI/testing/sysfs-kernel-slab
|
||||
F: Documentation/admin-guide/mm/slab.rst
|
||||
F: Documentation/mm/slab.rst
|
||||
F: include/linux/mempool.h
|
||||
F: include/linux/slab.h
|
||||
F: include/trace/events/kmem.h
|
||||
F: lib/tests/slub_kunit.c
|
||||
F: mm/failslab.c
|
||||
F: mm/mempool.c
|
||||
F: mm/slab.h
|
||||
F: mm/slab_common.c
|
||||
F: mm/slub.c
|
||||
F: scripts/gdb/linux/slab.py
|
||||
F: tools/cgroup/memcg_slabinfo.py
|
||||
F: tools/include/linux/slab.h
|
||||
F: tools/lib/slab.c
|
||||
F: tools/mm/slabinfo-gnuplot.sh
|
||||
F: tools/mm/slabinfo.c
|
||||
|
||||
MEMORY MANAGEMENT - SWAP
|
||||
M: Andrew Morton <akpm@linux-foundation.org>
|
||||
M: Chris Li <chrisl@kernel.org>
|
||||
|
|
@ -17911,13 +17829,14 @@ F: include/linux/swapfile.h
|
|||
F: include/linux/swapops.h
|
||||
F: mm/page_io.c
|
||||
F: mm/swap.h
|
||||
F: mm/swap_state.c
|
||||
F: mm/swap_table.h
|
||||
F: mm/swap_state.c
|
||||
F: mm/swapfile.c
|
||||
|
||||
MEMORY MANAGEMENT - THP (TRANSPARENT HUGE PAGE)
|
||||
M: Andrew Morton <akpm@linux-foundation.org>
|
||||
M: David Hildenbrand <david@kernel.org>
|
||||
M: Zi Yan <ziy@nvidia.com>
|
||||
R: Zi Yan <ziy@nvidia.com>
|
||||
R: Baolin Wang <baolin.wang@linux.alibaba.com>
|
||||
R: Liam R. Howlett <liam@infradead.org>
|
||||
R: Nico Pache <nico.pache@linux.dev>
|
||||
|
|
@ -17929,18 +17848,17 @@ R: Usama Arif <usama.arif@linux.dev>
|
|||
R: Kiryl Shutsemau <kas@kernel.org>
|
||||
L: linux-mm@kvack.org
|
||||
S: Maintained
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/mm/core.git for-next
|
||||
W: http://www.linux-mm.org
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm
|
||||
F: Documentation/ABI/testing/sysfs-kernel-mm-transparent-hugepage
|
||||
F: Documentation/admin-guide/mm/transhuge.rst
|
||||
F: include/linux/huge_mm.h
|
||||
F: include/linux/khugepaged.h
|
||||
F: include/trace/events/huge_memory.h
|
||||
F: include/trace/events/thp.h
|
||||
F: mm/collapse.h
|
||||
F: mm/huge_memory.c
|
||||
F: mm/khugepaged.c
|
||||
F: mm/mm_slot.h
|
||||
F: tools/mm/thpmaps
|
||||
F: tools/testing/selftests/mm/khugepaged.c
|
||||
F: tools/testing/selftests/mm/split_huge_page_test.c
|
||||
F: tools/testing/selftests/mm/transhuge-stress.c
|
||||
|
|
@ -17984,16 +17902,10 @@ L: linux-mm@kvack.org
|
|||
S: Maintained
|
||||
W: http://www.linux-mm.org
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm
|
||||
F: Documentation/core-api/protection-keys.rst
|
||||
F: Documentation/filesystems/mmap_prepare.rst
|
||||
F: Documentation/userspace-api/mseal.rst
|
||||
F: mm/char-mem.c
|
||||
F: include/trace/events/mmap.h
|
||||
F: fs/proc/task_mmu.c
|
||||
F: fs/proc/task_nommu.c
|
||||
F: include/linux/mman.h
|
||||
F: include/linux/pkeys.h
|
||||
F: include/trace/events/mmap.h
|
||||
F: include/uapi/linux/mman.h
|
||||
F: mm/char-mem.c
|
||||
F: mm/mincore.c
|
||||
F: mm/mlock.c
|
||||
F: mm/mmap.c
|
||||
|
|
@ -18831,7 +18743,6 @@ M: Peter Zijlstra <peterz@infradead.org>
|
|||
L: linux-arch@vger.kernel.org
|
||||
L: linux-mm@kvack.org
|
||||
S: Maintained
|
||||
F: Documentation/core-api/cachetlb.rst
|
||||
F: arch/*/include/asm/tlb.h
|
||||
F: include/asm-generic/tlb.h
|
||||
F: include/trace/events/tlb.h
|
||||
|
|
@ -21013,7 +20924,7 @@ S: Maintained
|
|||
F: drivers/char/hw_random/optee-rng.c
|
||||
|
||||
OP-TEE RTC DRIVER
|
||||
M: Clément Léger <clement.leger@linux.dev>
|
||||
M: Clément Léger <clement.leger@bootlin.com>
|
||||
L: linux-rtc@vger.kernel.org
|
||||
S: Maintained
|
||||
F: drivers/rtc/rtc-optee.c
|
||||
|
|
@ -21942,7 +21853,6 @@ S: Maintained
|
|||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/dennis/percpu.git
|
||||
F: arch/*/include/asm/percpu.h
|
||||
F: include/linux/percpu*.h
|
||||
F: include/trace/events/percpu.h
|
||||
F: lib/percpu*.c
|
||||
F: mm/percpu*.c
|
||||
F: mm/percpu-internal.h
|
||||
|
|
@ -23913,7 +23823,7 @@ F: Documentation/devicetree/bindings/rtc/renesas,rz-rtca3.yaml
|
|||
F: drivers/rtc/rtc-renesas-rtca3.c
|
||||
|
||||
RENESAS RZ/N1 A5PSW SWITCH DRIVER
|
||||
M: Clément Léger <clement.leger@linux.dev>
|
||||
M: Clément Léger <clement.leger@bootlin.com>
|
||||
L: linux-renesas-soc@vger.kernel.org
|
||||
L: netdev@vger.kernel.org
|
||||
S: Maintained
|
||||
|
|
@ -25669,7 +25579,6 @@ F: include/linux/shrinker.h
|
|||
F: mm/list_lru.c
|
||||
F: mm/shrinker.c
|
||||
F: mm/shrinker_debug.c
|
||||
F: tools/cgroup/memcg_shrinker.py
|
||||
|
||||
SH_VOU V4L2 OUTPUT DRIVER
|
||||
L: linux-media@vger.kernel.org
|
||||
|
|
@ -25891,6 +25800,34 @@ S: Maintained
|
|||
F: Documentation/devicetree/bindings/nvmem/layouts/kontron,sl28-vpd.yaml
|
||||
F: drivers/nvmem/layouts/sl28vpd.c
|
||||
|
||||
SLAB ALLOCATOR
|
||||
M: Vlastimil Babka <vbabka@kernel.org>
|
||||
M: Harry Yoo <harry@kernel.org>
|
||||
M: Andrew Morton <akpm@linux-foundation.org>
|
||||
R: Hao Li <hao.li@linux.dev>
|
||||
R: Christoph Lameter <cl@gentwo.org>
|
||||
R: David Rientjes <rientjes@google.com>
|
||||
R: Roman Gushchin <roman.gushchin@linux.dev>
|
||||
L: linux-mm@kvack.org
|
||||
S: Maintained
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/mm/slab.git
|
||||
F: Documentation/admin-guide/mm/slab.rst
|
||||
F: Documentation/mm/slab.rst
|
||||
F: include/linux/mempool.h
|
||||
F: include/linux/slab.h
|
||||
F: lib/tests/slub_kunit.c
|
||||
F: mm/failslab.c
|
||||
F: mm/mempool.c
|
||||
F: mm/slab.h
|
||||
F: mm/slab_common.c
|
||||
F: mm/slub.c
|
||||
F: scripts/gdb/linux/slab.py
|
||||
F: tools/cgroup/memcg_slabinfo.py
|
||||
F: tools/include/linux/slab.h
|
||||
F: tools/lib/slab.c
|
||||
F: tools/mm/slabinfo-gnuplot.sh
|
||||
F: tools/mm/slabinfo.c
|
||||
|
||||
SLCAN CAN NETWORK DRIVER
|
||||
M: Dario Binacchi <dario.binacchi@amarulasolutions.com>
|
||||
L: linux-can@vger.kernel.org
|
||||
|
|
@ -28308,6 +28245,17 @@ S: Maintained
|
|||
F: Documentation/hwmon/tmp513.rst
|
||||
F: drivers/hwmon/tmp513.c
|
||||
|
||||
TMPFS (SHMEM FILESYSTEM)
|
||||
M: Hugh Dickins <hughd@google.com>
|
||||
R: Baolin Wang <baolin.wang@linux.alibaba.com>
|
||||
L: linux-mm@kvack.org
|
||||
S: Maintained
|
||||
F: include/linux/memfd.h
|
||||
F: include/linux/shmem_fs.h
|
||||
F: mm/memfd.c
|
||||
F: mm/shmem.c
|
||||
F: mm/shmem_quota.c
|
||||
|
||||
TOMOYO SECURITY MODULE
|
||||
M: Kentaro Takeda <takedakn@nttdata.co.jp>
|
||||
M: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
|
||||
|
|
@ -28714,7 +28662,7 @@ F: arch/m68k/coldfire/
|
|||
F: arch/m68k/include/asm/*_no.*
|
||||
|
||||
UDF FILESYSTEM
|
||||
M: Jan Kara <jack@suse.cz>
|
||||
M: Jan Kara <jack@suse.com>
|
||||
S: Maintained
|
||||
F: Documentation/filesystems/udf.rst
|
||||
F: fs/udf/
|
||||
|
|
@ -29662,12 +29610,9 @@ F: drivers/block/virtio_blk.c
|
|||
F: drivers/crypto/virtio/
|
||||
F: drivers/vdpa/
|
||||
F: drivers/virtio/
|
||||
F: include/linux/device-id/virtio.h
|
||||
F: include/linux/vdpa.h
|
||||
F: include/linux/virtio*.h
|
||||
F: include/linux/vringh.h
|
||||
F: include/uapi/linux/vdpa.h
|
||||
F: include/uapi/linux/vduse.h
|
||||
F: include/uapi/linux/virtio_*.h
|
||||
F: net/vmw_vsock/virtio*
|
||||
F: tools/virtio/
|
||||
|
|
@ -29741,7 +29686,6 @@ F: drivers/vhost/
|
|||
F: include/linux/sched/vhost_task.h
|
||||
F: include/linux/vhost_iotlb.h
|
||||
F: include/uapi/linux/vhost.h
|
||||
F: include/uapi/linux/vhost_types.h
|
||||
F: kernel/vhost_task.c
|
||||
|
||||
VIRTIO HOST (VHOST-SCSI)
|
||||
|
|
@ -29935,11 +29879,9 @@ S: Maintained
|
|||
W: http://www.linux-mm.org
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm
|
||||
F: include/linux/vmalloc.h
|
||||
F: include/trace/events/vmalloc.h
|
||||
F: lib/test_vmalloc.c
|
||||
F: mm/vmalloc.c
|
||||
F: mm/vmalloc.h
|
||||
F: scripts/gdb/linux/vmalloc.py
|
||||
F: lib/test_vmalloc.c
|
||||
|
||||
VME SUBSYSTEM
|
||||
L: linux-kernel@vger.kernel.org
|
||||
|
|
|
|||
|
|
@ -17,10 +17,16 @@ SYM_FUNC_START(arch_bpf_timed_may_goto)
|
|||
str x7, [sp, #80]
|
||||
|
||||
/*
|
||||
* The pointer to count and timestamp was passed in BPF_REG_AX (x9),
|
||||
* pass it as the first argument in x0.
|
||||
* Stack depth was passed in BPF_REG_AX (x9), add it to the BPF_FP
|
||||
* (x25) to get the pointer to count and timestamp and pass it as the
|
||||
* first argument in x0.
|
||||
*
|
||||
* Before generating the call to arch_bpf_timed_may_goto, the verifier
|
||||
* generates a load instruction using FP, i.e. REG_AX = *(u64 *)(FP -
|
||||
* stack_off_cnt), so BPF_REG_FP (x25) is always set up by the arm64
|
||||
* jit in this case.
|
||||
*/
|
||||
mov x0, x9
|
||||
add x0, x9, x25
|
||||
bl bpf_check_timed_may_goto
|
||||
/* BPF_REG_AX(x9) will be stored into count, so move return value to it. */
|
||||
mov x9, x0
|
||||
|
|
|
|||
|
|
@ -22,10 +22,14 @@ SYM_FUNC_START(arch_bpf_timed_may_goto)
|
|||
st.d a4, sp, 48
|
||||
|
||||
/*
|
||||
* BPF_REG_AX (t0) holds the pointer to the count and timestamp;
|
||||
* pass it as the first argument in a0.
|
||||
* BPF_REG_AX (t0) holds the offset passed in by the verifier;
|
||||
* add it to BPF_REG_FP (s4) to get the pointer to the count and
|
||||
* timestamp, then pass it as the first argument in a0.
|
||||
*
|
||||
* The verifier emits a load using FP right before this call,
|
||||
* so BPF_REG_FP (s4) is always set up by the JIT in this case.
|
||||
*/
|
||||
move a0, t0
|
||||
add.d a0, t0, s4
|
||||
bl bpf_check_timed_may_goto
|
||||
/* BPF_REG_AX (t0) will be stored into count, so move the return value to it. */
|
||||
move t0, a0
|
||||
|
|
|
|||
|
|
@ -35,7 +35,6 @@ DECLARE_EXPORT(__divsi3);
|
|||
DECLARE_EXPORT(__umodsi3);
|
||||
DECLARE_EXPORT(__modsi3);
|
||||
DECLARE_EXPORT(__muldi3);
|
||||
DECLARE_EXPORT(__mulsi3);
|
||||
DECLARE_EXPORT(__ashrdi3);
|
||||
DECLARE_EXPORT(__ashldi3);
|
||||
DECLARE_EXPORT(__lshrdi3);
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@
|
|||
* arch_bpf_timed_may_goto() trampoline for powerpc64
|
||||
*
|
||||
* Custom BPF convention (verifier/JIT):
|
||||
* - input: pointer to count and timestamp in BPF_REG_AX (r12)
|
||||
* - input: stack offset in BPF_REG_AX (r12)
|
||||
* - output: updated count in BPF_REG_AX (r12)
|
||||
*
|
||||
* Call bpf_check_timed_may_goto(ptr) with normal powerpc64 ABI:
|
||||
|
|
@ -31,8 +31,11 @@ SYM_FUNC_START(arch_bpf_timed_may_goto)
|
|||
std r7, 64(r1)
|
||||
std r8, 72(r1)
|
||||
|
||||
/* r3 = BPF_REG_AX (r12) */
|
||||
mr r3, r12
|
||||
/*
|
||||
* r3 = BPF_REG_FP + BPF_REG_AX
|
||||
* BPF_REG_FP is r31; BPF_REG_AX is r12 (stack offset in bytes).
|
||||
*/
|
||||
add r3, r31, r12
|
||||
bl CFUNC(bpf_check_timed_may_goto)
|
||||
|
||||
/* Put return value back into AX */
|
||||
|
|
|
|||
|
|
@ -6,11 +6,13 @@
|
|||
|
||||
/*
|
||||
* Trampoline for the BPF timed may_goto loop bound. Custom calling convention:
|
||||
* - input: pointer to count and timestamp in BPF_REG_AX (t0)
|
||||
* - input: stack offset in BPF_REG_AX (t0)
|
||||
* - output: updated count in BPF_REG_AX (t0)
|
||||
*
|
||||
* Calls bpf_check_timed_may_goto(ptr) with the standard RISC-V ABI. BPF R0-R5
|
||||
* (t6, a0-a4) and stack arguments 6-8 (a5-a7) are saved across the call.
|
||||
* Calls bpf_check_timed_may_goto(ptr) with the standard RISC-V ABI, where
|
||||
* ptr = BPF_REG_FP (s5) + BPF_REG_AX (t0). BPF R0-R5 (t6, a0-a4) and stack
|
||||
* arguments 6-8 (a5-a7) are saved across the call; BPF_REG_FP (s5) is
|
||||
* callee-saved and needs no saving.
|
||||
*/
|
||||
|
||||
SYM_FUNC_START(arch_bpf_timed_may_goto)
|
||||
|
|
@ -31,7 +33,7 @@ SYM_FUNC_START(arch_bpf_timed_may_goto)
|
|||
REG_S a6, 7*SZREG(sp)
|
||||
REG_S a7, 8*SZREG(sp)
|
||||
|
||||
mv a0, t0
|
||||
add a0, t0, s5
|
||||
call bpf_check_timed_may_goto
|
||||
mv t0, a0
|
||||
|
||||
|
|
|
|||
|
|
@ -1005,17 +1005,6 @@ static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp,
|
|||
(jit->prg - patch_brc) >> 1;
|
||||
break;
|
||||
}
|
||||
if (insn_is_mov_percpu_addr(insn)) {
|
||||
const u64 *percpu_offset = &get_lowcore()->percpu_offset;
|
||||
|
||||
if (dst_reg != src_reg)
|
||||
/* lgr %dst,%src */
|
||||
EMIT4(0xb9040000, dst_reg, src_reg);
|
||||
/* ag %dst,percpu_offset */
|
||||
EMIT6_DISP_LH(0xe3000000, 0x0008, dst_reg, REG_0, REG_0,
|
||||
(unsigned long)percpu_offset);
|
||||
break;
|
||||
}
|
||||
switch (insn->off) {
|
||||
case 0: /* DST = SRC */
|
||||
/* lgr %dst,%src */
|
||||
|
|
@ -1877,9 +1866,9 @@ static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp,
|
|||
if ((void *)func == arch_bpf_timed_may_goto) {
|
||||
/*
|
||||
* arch_bpf_timed_may_goto() has a special ABI: the
|
||||
* parameter is in BPF_REG_AX; the return value is in
|
||||
* BPF_REG_AX; and all GPRs except REG_W0, REG_W1, and
|
||||
* BPF_REG_AX are callee-saved.
|
||||
* parameters are in BPF_REG_AX and BPF_REG_10; the
|
||||
* return value is in BPF_REG_AX; and all GPRs except
|
||||
* REG_W0, REG_W1, and BPF_REG_AX are callee-saved.
|
||||
*/
|
||||
|
||||
/* brasl %r0,func */
|
||||
|
|
@ -2439,6 +2428,8 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_verifier_env *env, struct bpf_pr
|
|||
fp->jited_len = jit.size - cfi_get_offset();
|
||||
|
||||
if (!fp->is_func || extra_pass) {
|
||||
for (int i = 0; i < fp->len; i++)
|
||||
jit.addrs[i] -= cfi_get_offset();
|
||||
bpf_prog_fill_jited_linfo(fp, jit.addrs + 1);
|
||||
free_addrs:
|
||||
kvfree(jit.addrs);
|
||||
|
|
@ -3125,11 +3116,6 @@ bool bpf_jit_supports_timed_may_goto(void)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool bpf_jit_supports_percpu_insn(void)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool bpf_jit_inlines_helper_call(s32 imm)
|
||||
{
|
||||
switch (imm) {
|
||||
|
|
|
|||
|
|
@ -21,9 +21,9 @@
|
|||
|
||||
SYM_FUNC_START(arch_bpf_timed_may_goto)
|
||||
/*
|
||||
* This function has a special ABI: the parameter is in %r12; the
|
||||
* return value is in %r12; all GPRs except %r0, %r1, and %r12 are
|
||||
* callee-saved; and the return address is in %r0.
|
||||
* This function has a special ABI: the parameters are in %r12 and
|
||||
* %r13; the return value is in %r12; all GPRs except %r0, %r1, and
|
||||
* %r12 are callee-saved; and the return address is in %r0.
|
||||
*/
|
||||
stmg %r2,%r5,FRAME_OFF+R2_OFF(%r15)
|
||||
stg %r14,FRAME_OFF+R14_OFF(%r15)
|
||||
|
|
@ -33,7 +33,7 @@ SYM_FUNC_START(arch_bpf_timed_may_goto)
|
|||
lay %r15,-FRAME_SIZE(%r15)
|
||||
stg %r1,__SF_BACKCHAIN(%r15)
|
||||
|
||||
lgr %r2,%r12
|
||||
lay %r2,0(%r12,%r13)
|
||||
brasl %r14,bpf_check_timed_may_goto
|
||||
lgr %r12,%r2
|
||||
|
||||
|
|
|
|||
|
|
@ -286,9 +286,9 @@ SYM_INNER_LABEL(ftrace_regs_caller_end, SYM_L_GLOBAL)
|
|||
RET
|
||||
|
||||
1:
|
||||
/* See ftrace_jmp_set(), jmp to the trampoline */
|
||||
btsq $63, %rax
|
||||
jc 2f
|
||||
testb $1, %al
|
||||
jz 2f
|
||||
andq $0xfffffffffffffffe, %rax
|
||||
movq %rax, MCOUNT_REG_SIZE+8(%rsp)
|
||||
restore_mcount_regs
|
||||
/* Restore flags */
|
||||
|
|
|
|||
|
|
@ -2359,16 +2359,6 @@ static struct kvm_mmu_page *kvm_mmu_find_shadow_page(struct kvm *kvm,
|
|||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* Note! Unlike fully direct MMUs, direct SPs in indirect MMUs
|
||||
* can have an arbitrary number of parents, e.g if the guest is
|
||||
* mapping a huge PTE at many points in its page tables.
|
||||
*/
|
||||
if (pte_list_count(&sp->parent_ptes) >= RMAP_RECYCLE_THRESHOLD) {
|
||||
kvm_mmu_prepare_zap_page(kvm, sp, &invalid_list);
|
||||
break;
|
||||
}
|
||||
|
||||
/* unsync and write-flooding only apply to indirect SPs. */
|
||||
if (sp->role.direct)
|
||||
goto out;
|
||||
|
|
|
|||
|
|
@ -339,13 +339,6 @@ static int FNAME(walk_addr_generic)(struct guest_walker *walker,
|
|||
gpa_t real_gpa;
|
||||
gfn_t gfn;
|
||||
|
||||
/*
|
||||
* KVM might sleep/resched when retrying the walk if the updating A/D
|
||||
* fails because the gPTE changed between reading the gPTE and trying
|
||||
* the CMPXHG to set A/D bits.
|
||||
*/
|
||||
might_sleep();
|
||||
|
||||
trace_kvm_mmu_pagetable_walk(addr, access);
|
||||
retry_walk:
|
||||
walker->level = w->cpu_role.base.level;
|
||||
|
|
@ -488,10 +481,8 @@ static int FNAME(walk_addr_generic)(struct guest_walker *walker,
|
|||
addr, write_fault);
|
||||
if (unlikely(ret < 0))
|
||||
goto error;
|
||||
else if (ret) {
|
||||
cond_resched();
|
||||
else if (ret)
|
||||
goto retry_walk;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
|
|
|||
|
|
@ -1889,21 +1889,6 @@ static void nested_copy_vmcb_cache_to_control(struct vmcb_control_area *dst,
|
|||
/* 'clean' and 'hv_enlightenments' are not changed by KVM */
|
||||
}
|
||||
|
||||
bool nested_svm_check_vmcb01_save(struct kvm_vcpu *vcpu,
|
||||
struct vmcb_save_area *save)
|
||||
{
|
||||
struct vmcb_save_area_cached save_cached;
|
||||
|
||||
if (!(save->cr0 & X86_CR0_PG) ||
|
||||
!(save->cr0 & X86_CR0_PE) ||
|
||||
(save->rflags & X86_EFLAGS_VM) ||
|
||||
((save->efer & EFER_LMA) && !(save->efer & EFER_LME)))
|
||||
return false;
|
||||
|
||||
__nested_copy_vmcb_save_to_cache(&save_cached, save);
|
||||
return nested_vmcb_check_save(vcpu, &save_cached, false);
|
||||
}
|
||||
|
||||
static int svm_get_nested_state(struct kvm_vcpu *vcpu,
|
||||
struct kvm_nested_state __user *user_kvm_nested_state,
|
||||
u32 user_data_size)
|
||||
|
|
@ -1983,6 +1968,7 @@ static int svm_set_nested_state(struct kvm_vcpu *vcpu,
|
|||
&user_kvm_nested_state->data.svm[0];
|
||||
struct vmcb_control_area *ctl;
|
||||
struct vmcb_save_area *save;
|
||||
struct vmcb_save_area_cached save_cached;
|
||||
struct vmcb_ctrl_area_cached ctl_cached;
|
||||
bool use_separate_l2_pat;
|
||||
unsigned long cr0;
|
||||
|
|
@ -2054,7 +2040,12 @@ static int svm_set_nested_state(struct kvm_vcpu *vcpu,
|
|||
* KVM_GET_NESTED_STATE, and (b) it is not loaded at emulated
|
||||
* #VMEXIT.
|
||||
*/
|
||||
if (!nested_svm_check_vmcb01_save(vcpu, save))
|
||||
__nested_copy_vmcb_save_to_cache(&save_cached, save);
|
||||
if (!(save->cr0 & X86_CR0_PG) ||
|
||||
!(save->cr0 & X86_CR0_PE) ||
|
||||
(save->rflags & X86_EFLAGS_VM) ||
|
||||
((save->efer & EFER_LMA) && !(save->efer & EFER_LME)) ||
|
||||
!nested_vmcb_check_save(vcpu, &save_cached, false))
|
||||
goto out_free;
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -5223,8 +5223,6 @@ static int svm_leave_smm(struct kvm_vcpu *vcpu, const union kvm_smram *smram)
|
|||
*/
|
||||
|
||||
svm_copy_vmrun_state(vcpu, &svm->vmcb01.ptr->save, m_save.map.hva + 0x400);
|
||||
if (!nested_svm_check_vmcb01_save(vcpu, &svm->vmcb01.ptr->save))
|
||||
return 1;
|
||||
|
||||
/*
|
||||
* Enter the nested guest now
|
||||
|
|
|
|||
|
|
@ -911,8 +911,6 @@ void nested_copy_vmcb_control_to_cache(struct vcpu_svm *svm,
|
|||
void nested_copy_vmcb_save_to_cache(struct vcpu_svm *svm,
|
||||
struct vmcb_save_area *save);
|
||||
void nested_sync_control_from_vmcb02(struct vcpu_svm *svm);
|
||||
bool nested_svm_check_vmcb01_save(struct kvm_vcpu *vcpu,
|
||||
struct vmcb_save_area *save);
|
||||
void svm_switch_vmcb(struct vcpu_svm *svm, struct kvm_vmcb_info *target_vmcb);
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -136,8 +136,6 @@ static __always_inline int evmcs_field_offset(unsigned long field,
|
|||
if (unlikely(index >= nr_evmcs_1_fields))
|
||||
return -ENOENT;
|
||||
|
||||
index = array_index_nospec(index, nr_evmcs_1_fields);
|
||||
|
||||
evmcs_field = &vmcs_field_to_evmcs_1[index];
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -5059,7 +5059,6 @@ static void nested_vmx_restore_host_state(struct kvm_vcpu *vcpu)
|
|||
__func__, j, h.index, h.value);
|
||||
goto vmabort;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6558,12 +6558,10 @@ int x86_emulate_instruction(struct kvm_vcpu *vcpu, gpa_t cr2_or_gpa,
|
|||
} else if (vcpu->arch.complete_userspace_io) {
|
||||
writeback = false;
|
||||
r = 0;
|
||||
} else if (r == EMULATION_RESTART) {
|
||||
cond_resched();
|
||||
} else if (r == EMULATION_RESTART)
|
||||
goto restart;
|
||||
} else {
|
||||
else
|
||||
r = 1;
|
||||
}
|
||||
|
||||
writeback:
|
||||
if (writeback) {
|
||||
|
|
@ -9732,31 +9730,29 @@ void kvm_vcpu_reset(struct kvm_vcpu *vcpu, bool init_event)
|
|||
kvm_x86_call(update_exception_bitmap)(vcpu);
|
||||
|
||||
/*
|
||||
* Unconditionally reset the MMU, even though super strictly speaking,
|
||||
* a MMU reset is only necessary if and only one of the page role bits
|
||||
* is changing. All of the CR0/CR4/EFER bits effectively get covered
|
||||
* by checking CR0.PG=1, as CR0.WP and the paging-related bits in CR4
|
||||
* and EFER are irrelevant if CR0.PG was '0'. Subtly, if the vCPU was
|
||||
* in guest mode (L2) or SMM (although emulating INIT in SMM _should_
|
||||
* be impossible), an MMU reset is also necessary as "guest mode" and
|
||||
* "smm" are both encoded in the shadow page role. As a result, the
|
||||
* only scenarios where an MMU reset is *not* needed is if the vCPU is
|
||||
* in Real Mode or Unpaged Protected Mode, and micro-optimizing those
|
||||
* paths are not worth the risk of running with a stale MMU context.
|
||||
* On the standard CR0/CR4/EFER modification paths, there are several
|
||||
* complex conditions determining whether the MMU has to be reset and/or
|
||||
* which PCIDs have to be flushed. However, CR0.WP and the paging-related
|
||||
* bits in CR4 and EFER are irrelevant if CR0.PG was '0'; and a reset+flush
|
||||
* is needed anyway if CR0.PG was '1' (which can only happen for INIT, as
|
||||
* CR0 will be '0' prior to RESET). So we only need to check CR0.PG here.
|
||||
*/
|
||||
kvm_mmu_reset_context(vcpu);
|
||||
if (old_cr0 & X86_CR0_PG) {
|
||||
kvm_make_request(KVM_REQ_TLB_FLUSH_GUEST, vcpu);
|
||||
kvm_mmu_reset_context(vcpu);
|
||||
}
|
||||
|
||||
/*
|
||||
* Intel's SDM states that all TLB entries are flushed on INIT "as with
|
||||
* a hardware reset", and AMD's APM states the TLBs are flushed on
|
||||
* "External initialization of the processor". Flush the guest TLB for
|
||||
* both RESET and INIT, regardless of vendor, even though both the SDM
|
||||
* and APM contradict the above statements in other tables. There is
|
||||
* no meaningful benefit in relying on the guest to flush the TLB, and
|
||||
* a spurious TLB flush is benign and likely negligible from a
|
||||
* performance perspective (especially for RESET).
|
||||
* Intel's SDM states that all TLB entries are flushed on INIT. AMD's
|
||||
* APM states the TLBs are untouched by INIT, but it also states that
|
||||
* the TLBs are flushed on "External initialization of the processor."
|
||||
* Flush the guest TLB regardless of vendor, there is no meaningful
|
||||
* benefit in relying on the guest to flush the TLB immediately after
|
||||
* INIT. A spurious TLB flush is benign and likely negligible from a
|
||||
* performance perspective.
|
||||
*/
|
||||
kvm_make_request(KVM_REQ_TLB_FLUSH_GUEST, vcpu);
|
||||
if (init_event)
|
||||
kvm_make_request(KVM_REQ_TLB_FLUSH_GUEST, vcpu);
|
||||
}
|
||||
EXPORT_SYMBOL_FOR_KVM_INTERNAL(kvm_vcpu_reset);
|
||||
|
||||
|
|
|
|||
|
|
@ -2626,13 +2626,8 @@ static int do_jit(struct bpf_verifier_env *env, struct bpf_prog *bpf_prog, int *
|
|||
* Arg 6 goes into r9 register, not on stack.
|
||||
*/
|
||||
outgoing_rsp = out_stack_arg_cnt > 1 ? (out_stack_arg_cnt - 1) * 8 : 0;
|
||||
/*
|
||||
* bpf_throw() sees rsp of this frame as it is at a call. The callee-saved
|
||||
* regs are above the outgoing args, or above r9, which is pushed around
|
||||
* every call when the stack is private.
|
||||
*/
|
||||
if (bpf_prog->aux->exception_boundary)
|
||||
bpf_prog->aux->stack_arg_sp_adjust = outgoing_rsp + (priv_frame_ptr ? 8 : 0);
|
||||
bpf_prog->aux->stack_arg_sp_adjust = outgoing_rsp;
|
||||
emit_sub_rsp(&prog, outgoing_rsp);
|
||||
|
||||
if (arena_vm_start)
|
||||
|
|
@ -3441,6 +3436,18 @@ static int do_jit(struct bpf_verifier_env *env, struct bpf_prog *bpf_prog, int *
|
|||
ip += emit_kfunc_arg_moves(fm, outgoing_arg_base -
|
||||
outgoing_rsp, &prog);
|
||||
}
|
||||
if (func == (u8 *)arch_bpf_timed_may_goto) {
|
||||
u32 fp = priv_frame_ptr ? X86_REG_R9 : BPF_REG_FP;
|
||||
|
||||
/*
|
||||
* AX has the offset of count and timestamp
|
||||
* in the stack. Turn it into a pointer.
|
||||
* add r10, rbp or add r10, r9
|
||||
*/
|
||||
maybe_emit_mod(&prog, BPF_REG_AX, fp, true);
|
||||
EMIT2(0x01, add_2reg(0xC0, BPF_REG_AX, fp));
|
||||
ip += 3;
|
||||
}
|
||||
if (priv_frame_ptr) {
|
||||
push_r9(&prog);
|
||||
ip += 2;
|
||||
|
|
|
|||
|
|
@ -25,7 +25,10 @@ SYM_FUNC_START(arch_bpf_timed_may_goto)
|
|||
/* Save stack argument 6. */
|
||||
pushq %r9
|
||||
|
||||
/* r10 has the pointer to count and timestamp. Pass it as first argument. */
|
||||
/*
|
||||
* r10 has the pointer to count and timestamp. JIT added the frame
|
||||
* pointer to the offset. Pass it as first argument.
|
||||
*/
|
||||
movq %r10, %rdi
|
||||
|
||||
/* Emit call depth accounting for call below. */
|
||||
|
|
|
|||
|
|
@ -1022,30 +1022,6 @@ static int init_vq(struct virtio_blk *vblk)
|
|||
goto out;
|
||||
|
||||
for (i = 0; i < num_vqs; i++) {
|
||||
unsigned int ring_size = virtqueue_get_vring_size(vqs[i]);
|
||||
/*
|
||||
* Each request consumes 2 extra descriptors (out_hdr and
|
||||
* in_hdr) in addition to the data segments.
|
||||
*
|
||||
* At initial probe (!vblk->disk), each virtqueue must fit at
|
||||
* least 1 data segment + 2 header descriptors (3).
|
||||
* On resume/recovery (vblk->disk), each virtqueue must fit the
|
||||
* existing queue_max_segments() + 2 header descriptors.
|
||||
*/
|
||||
unsigned int min_ring_size = 3;
|
||||
|
||||
if (vblk->disk)
|
||||
min_ring_size = queue_max_segments(vblk->disk->queue) + 2;
|
||||
|
||||
if (ring_size < min_ring_size) {
|
||||
dev_err(&vdev->dev,
|
||||
"virtqueue %u ring size %u is smaller than minimum %u\n",
|
||||
i, ring_size, min_ring_size);
|
||||
vdev->config->del_vqs(vdev);
|
||||
err = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
spin_lock_init(&vblk->vqs[i].lock);
|
||||
vblk->vqs[i].vq = vqs[i];
|
||||
}
|
||||
|
|
@ -1278,7 +1254,7 @@ static int virtblk_read_limits(struct virtio_blk *vblk,
|
|||
u16 min_io_size;
|
||||
u8 physical_block_exp, alignment_offset;
|
||||
size_t max_dma_size;
|
||||
int err, i;
|
||||
int err;
|
||||
|
||||
/* We need to know how many segments before we allocate. */
|
||||
err = virtio_cread_feature(vdev, VIRTIO_BLK_F_SEG_MAX,
|
||||
|
|
@ -1292,23 +1268,6 @@ static int virtblk_read_limits(struct virtio_blk *vblk,
|
|||
/* Prevent integer overflows and honor max vq size */
|
||||
sg_elems = min_t(u32, sg_elems, VIRTIO_BLK_MAX_SG_ELEMS - 2);
|
||||
|
||||
/*
|
||||
* virtblk_add_req() uses separate outgoing and incoming header
|
||||
* descriptors (out_hdr and in_hdr), consuming 2 extra descriptors
|
||||
* per request in addition to the data segments.
|
||||
*
|
||||
* Per virtio specification (2.7.5.3.1), a driver MUST NOT create a
|
||||
* descriptor chain longer than the Queue Size of the device.
|
||||
*
|
||||
* Clamp max_segments to (ring_size - 2) across all virtqueues so
|
||||
* that a request never exceeds the ring size of any queue.
|
||||
*/
|
||||
for (i = 0; i < vblk->num_vqs; i++) {
|
||||
u32 ring_size = virtqueue_get_vring_size(vblk->vqs[i].vq);
|
||||
|
||||
sg_elems = min_t(u32, sg_elems, ring_size - 2);
|
||||
}
|
||||
|
||||
/* We can handle whatever the host told us to handle. */
|
||||
lim->max_segments = sg_elems;
|
||||
|
||||
|
|
@ -1508,7 +1467,6 @@ static int virtblk_probe(struct virtio_device *vdev)
|
|||
mutex_init(&vblk->vdev_mutex);
|
||||
|
||||
vblk->vdev = vdev;
|
||||
vblk->disk = NULL;
|
||||
|
||||
INIT_WORK(&vblk->config_work, virtblk_config_changed_work);
|
||||
|
||||
|
|
@ -1590,7 +1548,6 @@ static int virtblk_probe(struct virtio_device *vdev)
|
|||
return 0;
|
||||
|
||||
out_cleanup_disk:
|
||||
virtio_reset_device(vdev);
|
||||
put_disk(vblk->disk);
|
||||
out_free_tags:
|
||||
blk_mq_free_tag_set(&vblk->tag_set);
|
||||
|
|
|
|||
|
|
@ -318,10 +318,8 @@ struct xen_blkif {
|
|||
unsigned int nr_ring_pages;
|
||||
bool multi_ref;
|
||||
/* All rings for this device. */
|
||||
rwlock_t rings_lock;
|
||||
struct xen_blkif_ring *rings;
|
||||
unsigned int nr_rings;
|
||||
|
||||
unsigned long buffer_squeeze_end;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -127,23 +127,14 @@ static void xen_update_blkif_status(struct xen_blkif *blkif)
|
|||
return;
|
||||
}
|
||||
|
||||
static int xen_blkif_alloc_rings(struct xen_blkif *blkif,
|
||||
unsigned int nr_rings)
|
||||
static int xen_blkif_alloc_rings(struct xen_blkif *blkif)
|
||||
{
|
||||
unsigned int r;
|
||||
struct xen_blkif_ring *rings;
|
||||
|
||||
rings = kzalloc_objs(struct xen_blkif_ring, nr_rings);
|
||||
if (!rings)
|
||||
blkif->rings = kzalloc_objs(struct xen_blkif_ring, blkif->nr_rings);
|
||||
if (!blkif->rings)
|
||||
return -ENOMEM;
|
||||
|
||||
write_lock(&blkif->rings_lock);
|
||||
|
||||
blkif->rings = rings;
|
||||
blkif->nr_rings = nr_rings;
|
||||
|
||||
write_unlock(&blkif->rings_lock);
|
||||
|
||||
for (r = 0; r < blkif->nr_rings; r++) {
|
||||
struct xen_blkif_ring *ring = &blkif->rings[r];
|
||||
|
||||
|
|
@ -183,7 +174,6 @@ static struct xen_blkif *xen_blkif_alloc(domid_t domid)
|
|||
blkif->domid = domid;
|
||||
atomic_set(&blkif->refcnt, 1);
|
||||
init_completion(&blkif->drain_complete);
|
||||
rwlock_init(&blkif->rings_lock);
|
||||
|
||||
/*
|
||||
* Because freeing back to the cache may be deferred, it is not
|
||||
|
|
@ -278,7 +268,6 @@ static int xen_blkif_disconnect(struct xen_blkif *blkif)
|
|||
struct pending_req *req, *n;
|
||||
unsigned int j, r;
|
||||
bool busy = false;
|
||||
struct xen_blkif_ring *rings;
|
||||
|
||||
for (r = 0; r < blkif->nr_rings; r++) {
|
||||
struct xen_blkif_ring *ring = &blkif->rings[r];
|
||||
|
|
@ -345,16 +334,10 @@ static int xen_blkif_disconnect(struct xen_blkif *blkif)
|
|||
* blkif->rings was allocated in connect_ring, so we should free it in
|
||||
* here.
|
||||
*/
|
||||
write_lock(&blkif->rings_lock);
|
||||
|
||||
rings = blkif->rings;
|
||||
kfree(blkif->rings);
|
||||
blkif->rings = NULL;
|
||||
blkif->nr_rings = 0;
|
||||
|
||||
write_unlock(&blkif->rings_lock);
|
||||
|
||||
kfree(rings);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -402,7 +385,6 @@ void xen_blkif_interface_fini(void)
|
|||
unsigned int i; \
|
||||
unsigned long long result = 0; \
|
||||
\
|
||||
read_lock(&blkif->rings_lock); \
|
||||
if (!blkif->rings) \
|
||||
goto out; \
|
||||
\
|
||||
|
|
@ -413,7 +395,6 @@ void xen_blkif_interface_fini(void)
|
|||
} \
|
||||
\
|
||||
out: \
|
||||
read_unlock(&blkif->rings_lock); \
|
||||
return sprintf(buf, format, result); \
|
||||
} \
|
||||
static DEVICE_ATTR(name, 0444, show_##name, NULL)
|
||||
|
|
@ -1121,7 +1102,8 @@ static int connect_ring(struct backend_info *be)
|
|||
requested_num_queues, xenblk_max_queues);
|
||||
return -ENOSYS;
|
||||
}
|
||||
if (xen_blkif_alloc_rings(blkif, requested_num_queues))
|
||||
blkif->nr_rings = requested_num_queues;
|
||||
if (xen_blkif_alloc_rings(blkif))
|
||||
return -ENOMEM;
|
||||
|
||||
pr_info("%s: using %d queues, protocol %d (%s) %s\n", dev->nodename,
|
||||
|
|
|
|||
|
|
@ -1201,29 +1201,7 @@ static int btintel_download_firmware_payload(struct hci_dev *hdev,
|
|||
err = -EINVAL;
|
||||
|
||||
while (fw_ptr - fw->data < fw->size) {
|
||||
struct hci_command_hdr *cmd;
|
||||
size_t remain = fw->size - (fw_ptr - fw->data);
|
||||
|
||||
/* Ensure the header fits before dereferencing */
|
||||
if (frag_len + sizeof(*cmd) > remain) {
|
||||
bt_dev_err(hdev,
|
||||
"Firmware buffer overrun at header (frag_len %u, need %zu, remain %zu)",
|
||||
frag_len, frag_len + sizeof(*cmd), remain);
|
||||
err = -EINVAL;
|
||||
goto done;
|
||||
}
|
||||
|
||||
cmd = (void *)(fw_ptr + frag_len);
|
||||
|
||||
/* Ensure the full command (header + payload) fits before use */
|
||||
if (frag_len + sizeof(*cmd) + cmd->plen > remain) {
|
||||
bt_dev_err(hdev,
|
||||
"Firmware buffer overrun at payload (frag_len %u, plen %u, need %zu, remain %zu)",
|
||||
frag_len, cmd->plen,
|
||||
frag_len + sizeof(*cmd) + cmd->plen, remain);
|
||||
err = -EINVAL;
|
||||
goto done;
|
||||
}
|
||||
struct hci_command_hdr *cmd = (void *)(fw_ptr + frag_len);
|
||||
|
||||
frag_len += sizeof(*cmd) + cmd->plen;
|
||||
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@
|
|||
#include <linux/usb.h>
|
||||
#include <linux/iopoll.h>
|
||||
#include <linux/overflow.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/unaligned.h>
|
||||
|
||||
#include <net/bluetooth/bluetooth.h>
|
||||
|
|
@ -31,7 +30,7 @@
|
|||
#define BTMTK_CBMCU_FLAG_ENABLE_PATCH 0xF1
|
||||
|
||||
/* It is for mt79xx iso data transmission setting */
|
||||
#define MTK_ISO_THRESHOLD 342
|
||||
#define MTK_ISO_THRESHOLD 264
|
||||
|
||||
struct btmtk_patch_header {
|
||||
u8 datetime[16];
|
||||
|
|
@ -1557,15 +1556,8 @@ static int btmtk_recv_isopkt(struct hci_dev *hdev, void *buffer, int count)
|
|||
struct btmtk_data *btmtk_data = hci_get_priv(hdev);
|
||||
struct sk_buff *skb;
|
||||
unsigned long flags;
|
||||
unsigned int iso_mtu;
|
||||
int err = 0;
|
||||
|
||||
/* The controller reports the largest Data_Total_Length it will send in
|
||||
* LE Read Buffer Size [v2]. Fall back to HCI_MAX_ISO_SIZE while that
|
||||
* command has not completed yet.
|
||||
*/
|
||||
iso_mtu = hdev->iso_mtu ? hdev->iso_mtu : HCI_MAX_ISO_SIZE;
|
||||
|
||||
spin_lock_irqsave(&btmtk_data->isorxlock, flags);
|
||||
skb = btmtk_data->isopkt_skb;
|
||||
|
||||
|
|
@ -1573,16 +1565,7 @@ static int btmtk_recv_isopkt(struct hci_dev *hdev, void *buffer, int count)
|
|||
int len;
|
||||
|
||||
if (!skb) {
|
||||
/* Drop the endpoint's zero-filled padding before
|
||||
* allocating an skb for it; a zero Data_Total_Length
|
||||
* check below would miss a padding remainder
|
||||
* shorter than an ISO header.
|
||||
*/
|
||||
if (mem_is_zero(buffer, count))
|
||||
break;
|
||||
|
||||
skb = bt_skb_alloc(HCI_ISO_HDR_SIZE + iso_mtu,
|
||||
GFP_ATOMIC);
|
||||
skb = bt_skb_alloc(HCI_MAX_ISO_SIZE, GFP_ATOMIC);
|
||||
if (!skb) {
|
||||
err = -ENOMEM;
|
||||
break;
|
||||
|
|
@ -1605,24 +1588,7 @@ static int btmtk_recv_isopkt(struct hci_dev *hdev, void *buffer, int count)
|
|||
/* Complete ISO header */
|
||||
hci_skb_expect(skb) = __le16_to_cpu(dlen);
|
||||
|
||||
if (!hci_skb_expect(skb)) {
|
||||
/* Zero padding was ruled out above, so a
|
||||
* zero Data_Total_Length here is invalid.
|
||||
*/
|
||||
kfree_skb(skb);
|
||||
skb = NULL;
|
||||
|
||||
err = -EILSEQ;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Reject a length the controller said it would never
|
||||
* send. The skb_tailroom() test is kept because a
|
||||
* fragment started before hdev->iso_mtu was populated
|
||||
* sits in a smaller skb than iso_mtu now allows.
|
||||
*/
|
||||
if (hci_skb_expect(skb) > iso_mtu ||
|
||||
skb_tailroom(skb) < hci_skb_expect(skb)) {
|
||||
if (skb_tailroom(skb) < hci_skb_expect(skb)) {
|
||||
kfree_skb(skb);
|
||||
skb = NULL;
|
||||
|
||||
|
|
@ -1741,15 +1707,13 @@ static int btmtk_submit_intr_urb(struct hci_dev *hdev, gfp_t mem_flags)
|
|||
static int btmtk_usb_isointf_init(struct hci_dev *hdev)
|
||||
{
|
||||
struct btmtk_data *btmtk_data = hci_get_priv(hdev);
|
||||
__le16 iso_param = cpu_to_le16(MTK_ISO_THRESHOLD);
|
||||
u8 iso_param[2] = { 0x08, 0x01 };
|
||||
struct sk_buff *skb;
|
||||
int err;
|
||||
|
||||
spin_lock_init(&btmtk_data->isorxlock);
|
||||
|
||||
err = __set_mtk_intr_interface(hdev);
|
||||
if (err < 0)
|
||||
return err;
|
||||
__set_mtk_intr_interface(hdev);
|
||||
|
||||
err = btmtk_submit_intr_urb(hdev, GFP_KERNEL);
|
||||
if (err < 0) {
|
||||
|
|
@ -1758,10 +1722,9 @@ static int btmtk_usb_isointf_init(struct hci_dev *hdev)
|
|||
return err;
|
||||
}
|
||||
|
||||
skb = __hci_cmd_sync(hdev, 0xfd98, sizeof(iso_param), &iso_param,
|
||||
skb = __hci_cmd_sync(hdev, 0xfd98, sizeof(iso_param), iso_param,
|
||||
HCI_INIT_TIMEOUT);
|
||||
if (IS_ERR(skb)) {
|
||||
usb_kill_anchored_urbs(&btmtk_data->isopkt_anchor);
|
||||
bt_dev_err(hdev, "Failed to apply iso setting (%ld)", PTR_ERR(skb));
|
||||
return PTR_ERR(skb);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -426,8 +426,7 @@ static int qca_tlv_check_data(struct hci_dev *hdev,
|
|||
tlv_nvm->data[0] |= 0x80;
|
||||
|
||||
/* UART Baud Rate */
|
||||
if (soc_type == QCA_WCN3950 ||
|
||||
soc_type >= QCA_WCN3991)
|
||||
if (soc_type >= QCA_WCN3991)
|
||||
tlv_nvm->data[1] = nvm_baud_rate;
|
||||
else
|
||||
tlv_nvm->data[2] = nvm_baud_rate;
|
||||
|
|
|
|||
|
|
@ -190,7 +190,6 @@ static int probe_common(struct virtio_device *vdev)
|
|||
err_find:
|
||||
ida_free(&rng_index_ida, index);
|
||||
err_ida:
|
||||
vdev->priv = NULL;
|
||||
kfree(vi);
|
||||
return err;
|
||||
}
|
||||
|
|
@ -199,11 +198,6 @@ static void remove_common(struct virtio_device *vdev)
|
|||
{
|
||||
struct virtrng_info *vi = vdev->priv;
|
||||
|
||||
if (!vi) {
|
||||
virtio_reset_device(vdev);
|
||||
return;
|
||||
}
|
||||
|
||||
vi->hwrng_removed = true;
|
||||
vi->data_avail = 0;
|
||||
vi->data_idx = 0;
|
||||
|
|
@ -213,7 +207,6 @@ static void remove_common(struct virtio_device *vdev)
|
|||
virtio_reset_device(vdev);
|
||||
vdev->config->del_vqs(vdev);
|
||||
ida_free(&rng_index_ida, vi->index);
|
||||
vdev->priv = NULL;
|
||||
kfree(vi);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -341,7 +341,7 @@ static int coreboot_cfr_read_value(const struct coreboot_cfr_setting *setting,
|
|||
int ret;
|
||||
|
||||
if (IS_ERR(efi_name))
|
||||
return PTR_ERR(efi_name);
|
||||
return PTR_ERR(no_free_ptr(efi_name));
|
||||
|
||||
ret = efivar_lock();
|
||||
if (ret)
|
||||
|
|
|
|||
|
|
@ -114,30 +114,6 @@ void coreboot_driver_unregister(struct coreboot_driver *driver)
|
|||
}
|
||||
EXPORT_SYMBOL(coreboot_driver_unregister);
|
||||
|
||||
/*
|
||||
* Whether the memory of a CBMEM entry may be mapped: it must be exclusively
|
||||
* System RAM, or exclusively Reserved memory, as CBMEM often is on x86, or
|
||||
* memory that the kernel doesn't know about at all. coreboot leaves CBMEM out
|
||||
* of the /memory node of the device tree that it passes to FIT payloads, e.g.
|
||||
* on arm64, and only lists it in the memory reservation block.
|
||||
*
|
||||
* Anything else, such as no-map regions on arm64, which are IORESOURCE_MEM
|
||||
* (see request_standard_resources() in arch/arm64/kernel/setup.c), must not
|
||||
* be mapped.
|
||||
*/
|
||||
static bool cbmem_entry_is_mappable(const struct lb_cbmem_entry *entry)
|
||||
{
|
||||
resource_size_t start = entry->address;
|
||||
size_t size = entry->entry_size;
|
||||
|
||||
return region_intersects(start, size, IORESOURCE_SYSTEM_RAM,
|
||||
IORES_DESC_NONE) == REGION_INTERSECTS ||
|
||||
region_intersects(start, size, IORESOURCE_MEM,
|
||||
IORES_DESC_RESERVED) == REGION_INTERSECTS ||
|
||||
region_intersects(start, size, IORESOURCE_MEM,
|
||||
IORES_DESC_NONE) == REGION_DISJOINT;
|
||||
}
|
||||
|
||||
static int coreboot_table_populate(struct device *dev, void *ptr, resource_size_t len)
|
||||
{
|
||||
int i, ret;
|
||||
|
|
@ -173,7 +149,23 @@ static int coreboot_table_populate(struct device *dev, void *ptr, resource_size_
|
|||
|
||||
switch (device->entry.tag) {
|
||||
case LB_TAG_CBMEM_ENTRY:
|
||||
if (!cbmem_entry_is_mappable(&device->cbmem_entry)) {
|
||||
/*
|
||||
* Skip entries that are not exclusively System RAM or
|
||||
* Reserved memory.
|
||||
* On ARM64, no-map regions are filtered out as they are
|
||||
* IORESOURCE_MEM (see request_standard_resources() in
|
||||
* arch/arm64/kernel/setup.c).
|
||||
* On x86, CBMEM often resides in standard reserved regions
|
||||
* (IORES_DESC_RESERVED).
|
||||
*/
|
||||
if (region_intersects(device->cbmem_entry.address,
|
||||
device->cbmem_entry.entry_size,
|
||||
IORESOURCE_SYSTEM_RAM,
|
||||
IORES_DESC_NONE) != REGION_INTERSECTS &&
|
||||
region_intersects(device->cbmem_entry.address,
|
||||
device->cbmem_entry.entry_size,
|
||||
IORESOURCE_MEM,
|
||||
IORES_DESC_RESERVED) != REGION_INTERSECTS) {
|
||||
kfree(device);
|
||||
continue;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,6 +30,13 @@
|
|||
#define POWER_METER_CAN_CAP (1 << 2)
|
||||
#define POWER_METER_CAN_NOTIFY (1 << 3)
|
||||
#define POWER_METER_IS_BATTERY (1 << 8)
|
||||
#define UNKNOWN_HYSTERESIS 0xFFFFFFFF
|
||||
/*
|
||||
* ACPI integers can either be 32-bit or 64-bit wide, so
|
||||
* we have to check for both values.
|
||||
*/
|
||||
#define UNKNOWN_POWER_32 U32_MAX
|
||||
#define UNKNOWN_POWER_64 U64_MAX
|
||||
|
||||
#define METER_NOTIFY_CONFIG 0x80
|
||||
#define METER_NOTIFY_TRIP 0x81
|
||||
|
|
@ -47,15 +54,6 @@ static bool force_cap_on;
|
|||
|
||||
static DEFINE_MUTEX(acpi_notify_lock);
|
||||
|
||||
/*
|
||||
* ACPI integers can either be 32-bit or 64-bit wide, so
|
||||
* we have to check for both values.
|
||||
*/
|
||||
static bool acpi_power_meter_is_unknown(u64 val)
|
||||
{
|
||||
return val == U32_MAX || val == U64_MAX;
|
||||
}
|
||||
|
||||
static int can_cap_in_hardware(void)
|
||||
{
|
||||
return force_cap_on || cap_in_hardware;
|
||||
|
|
@ -181,10 +179,9 @@ static int update_meter(struct acpi_power_meter_resource *resource)
|
|||
acpi_status status;
|
||||
unsigned long local_jiffies = jiffies;
|
||||
|
||||
if (!acpi_power_meter_is_unknown(resource->caps.sampling_time) &&
|
||||
time_before(local_jiffies, resource->sensors_last_updated +
|
||||
if (time_before(local_jiffies, resource->sensors_last_updated +
|
||||
msecs_to_jiffies(resource->caps.sampling_time)) &&
|
||||
resource->sensors_valid)
|
||||
resource->sensors_valid)
|
||||
return 0;
|
||||
|
||||
status = acpi_evaluate_integer(resource->acpi_dev->handle, "_PMM",
|
||||
|
|
@ -380,30 +377,28 @@ static int set_avg_interval(struct acpi_power_meter_resource *resource,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static bool get_power_alarm_state(struct acpi_power_meter_resource *resource)
|
||||
static int get_power_alarm_state(struct acpi_power_meter_resource *resource,
|
||||
long *val)
|
||||
{
|
||||
bool alarm = false;
|
||||
int ret;
|
||||
|
||||
if (resource->caps.flags & POWER_METER_CAN_NOTIFY)
|
||||
alarm = resource->power_alarm;
|
||||
resource->power_alarm = false;
|
||||
|
||||
ret = update_meter(resource);
|
||||
if (ret || acpi_power_meter_is_unknown(resource->power))
|
||||
return alarm;
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* need to update cap if not to support the notification. */
|
||||
if (!(resource->caps.flags & POWER_METER_CAN_NOTIFY)) {
|
||||
ret = update_cap(resource);
|
||||
if (ret)
|
||||
return false;
|
||||
return ret;
|
||||
resource->power_alarm = resource->power > resource->cap;
|
||||
*val = resource->power_alarm;
|
||||
} else {
|
||||
*val = resource->power_alarm || resource->power > resource->cap;
|
||||
resource->power_alarm = resource->power > resource->cap;
|
||||
}
|
||||
|
||||
if (acpi_power_meter_is_unknown(resource->cap))
|
||||
return alarm;
|
||||
|
||||
return alarm || resource->power > resource->cap;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static umode_t power_meter_is_visible(const void *data,
|
||||
|
|
@ -463,47 +458,37 @@ static int power_meter_read(struct device *dev, enum hwmon_sensor_types type,
|
|||
ret = update_meter(res);
|
||||
if (ret)
|
||||
return ret;
|
||||
if (acpi_power_meter_is_unknown(res->power))
|
||||
if (res->power == UNKNOWN_POWER_32 || res->power == UNKNOWN_POWER_64)
|
||||
return -ENODATA;
|
||||
*val = res->power * 1000;
|
||||
break;
|
||||
case hwmon_power_average_interval_min:
|
||||
if (acpi_power_meter_is_unknown(res->caps.min_avg_interval))
|
||||
return -ENODATA;
|
||||
*val = res->caps.min_avg_interval;
|
||||
break;
|
||||
case hwmon_power_average_interval_max:
|
||||
if (acpi_power_meter_is_unknown(res->caps.max_avg_interval))
|
||||
return -ENODATA;
|
||||
*val = res->caps.max_avg_interval;
|
||||
break;
|
||||
case hwmon_power_average_interval:
|
||||
ret = update_avg_interval(res);
|
||||
if (ret)
|
||||
return ret;
|
||||
if (acpi_power_meter_is_unknown(res->avg_interval))
|
||||
return -ENODATA;
|
||||
*val = res->avg_interval;
|
||||
*val = (res)->avg_interval;
|
||||
break;
|
||||
case hwmon_power_cap_min:
|
||||
if (acpi_power_meter_is_unknown(res->caps.min_cap))
|
||||
return -ENODATA;
|
||||
*val = res->caps.min_cap * 1000;
|
||||
break;
|
||||
case hwmon_power_cap_max:
|
||||
if (acpi_power_meter_is_unknown(res->caps.max_cap))
|
||||
return -ENODATA;
|
||||
*val = res->caps.max_cap * 1000;
|
||||
break;
|
||||
case hwmon_power_alarm:
|
||||
*val = get_power_alarm_state(res);
|
||||
ret = get_power_alarm_state(res, val);
|
||||
if (ret)
|
||||
return ret;
|
||||
break;
|
||||
case hwmon_power_cap:
|
||||
ret = update_cap(res);
|
||||
if (ret)
|
||||
return ret;
|
||||
if (acpi_power_meter_is_unknown(res->cap))
|
||||
return -ENODATA;
|
||||
*val = res->cap * 1000;
|
||||
break;
|
||||
default:
|
||||
|
|
@ -599,8 +584,6 @@ static ssize_t power1_average_min_show(struct device *dev,
|
|||
{
|
||||
struct acpi_power_meter_resource *res = dev_get_drvdata(dev);
|
||||
|
||||
guard(mutex)(&res->lock);
|
||||
|
||||
if (res->trip[POWER_METER_TRIP_AVERAGE_MIN_IDX] < 0)
|
||||
return sysfs_emit(buf, "unknown\n");
|
||||
|
||||
|
|
@ -613,8 +596,6 @@ static ssize_t power1_average_max_show(struct device *dev,
|
|||
{
|
||||
struct acpi_power_meter_resource *res = dev_get_drvdata(dev);
|
||||
|
||||
guard(mutex)(&res->lock);
|
||||
|
||||
if (res->trip[POWER_METER_TRIP_AVERAGE_MAX_IDX] < 0)
|
||||
return sysfs_emit(buf, "unknown\n");
|
||||
|
||||
|
|
@ -627,9 +608,7 @@ static ssize_t power1_cap_hyst_show(struct device *dev,
|
|||
{
|
||||
struct acpi_power_meter_resource *res = dev_get_drvdata(dev);
|
||||
|
||||
guard(mutex)(&res->lock);
|
||||
|
||||
if (acpi_power_meter_is_unknown(res->caps.hysteresis))
|
||||
if (res->caps.hysteresis == UNKNOWN_HYSTERESIS)
|
||||
return sysfs_emit(buf, "unknown\n");
|
||||
|
||||
return sysfs_emit(buf, "%llu\n", res->caps.hysteresis * 1000);
|
||||
|
|
@ -640,14 +619,8 @@ static ssize_t power1_accuracy_show(struct device *dev,
|
|||
char *buf)
|
||||
{
|
||||
struct acpi_power_meter_resource *res = dev_get_drvdata(dev);
|
||||
unsigned int acc;
|
||||
unsigned int acc = res->caps.accuracy;
|
||||
|
||||
guard(mutex)(&res->lock);
|
||||
|
||||
if (acpi_power_meter_is_unknown(res->caps.accuracy))
|
||||
return sysfs_emit(buf, "unknown\n");
|
||||
|
||||
acc = res->caps.accuracy;
|
||||
return sysfs_emit(buf, "%u.%u%%\n", acc / 1000, acc % 1000);
|
||||
}
|
||||
|
||||
|
|
@ -657,8 +630,6 @@ static ssize_t power1_is_battery_show(struct device *dev,
|
|||
{
|
||||
struct acpi_power_meter_resource *res = dev_get_drvdata(dev);
|
||||
|
||||
guard(mutex)(&res->lock);
|
||||
|
||||
return sysfs_emit(buf, "%u\n",
|
||||
res->caps.flags & POWER_METER_IS_BATTERY ? 1 : 0);
|
||||
}
|
||||
|
|
@ -669,11 +640,6 @@ static ssize_t power1_model_number_show(struct device *dev,
|
|||
{
|
||||
struct acpi_power_meter_resource *res = dev_get_drvdata(dev);
|
||||
|
||||
guard(mutex)(&res->lock);
|
||||
|
||||
if (!res->model_number)
|
||||
return -ENODATA;
|
||||
|
||||
return sysfs_emit(buf, "%s\n", res->model_number);
|
||||
}
|
||||
|
||||
|
|
@ -683,11 +649,6 @@ static ssize_t power1_oem_info_show(struct device *dev,
|
|||
{
|
||||
struct acpi_power_meter_resource *res = dev_get_drvdata(dev);
|
||||
|
||||
guard(mutex)(&res->lock);
|
||||
|
||||
if (!res->oem_info)
|
||||
return -ENODATA;
|
||||
|
||||
return sysfs_emit(buf, "%s\n", res->oem_info);
|
||||
}
|
||||
|
||||
|
|
@ -697,11 +658,6 @@ static ssize_t power1_serial_number_show(struct device *dev,
|
|||
{
|
||||
struct acpi_power_meter_resource *res = dev_get_drvdata(dev);
|
||||
|
||||
guard(mutex)(&res->lock);
|
||||
|
||||
if (!res->serial_number)
|
||||
return -ENODATA;
|
||||
|
||||
return sysfs_emit(buf, "%s\n", res->serial_number);
|
||||
}
|
||||
|
||||
|
|
@ -1028,8 +984,6 @@ static int acpi_power_meter_resume(struct device *dev)
|
|||
{
|
||||
struct acpi_power_meter_resource *resource = dev_get_drvdata(dev);
|
||||
|
||||
guard(mutex)(&resource->lock);
|
||||
|
||||
free_capabilities(resource);
|
||||
read_capabilities(resource);
|
||||
|
||||
|
|
|
|||
|
|
@ -19,7 +19,6 @@
|
|||
#include <linux/hwmon.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/ktime.h>
|
||||
#include <linux/limits.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/unaligned.h>
|
||||
|
|
@ -133,7 +132,6 @@ static u8 aquaero_secondary_ctrl_report[] = {
|
|||
#define AQUAERO_FAN_CURRENT_OFFSET 0x06
|
||||
#define AQUAERO_FAN_POWER_OFFSET 0x08
|
||||
#define AQUAERO_FAN_SPEED_OFFSET 0x00
|
||||
#define AQUAERO_MIN_STATUS_REPORT_SIZE (0x18B + AQUAERO_FAN_POWER_OFFSET + sizeof(u16))
|
||||
static u16 aquaero_sensor_fan_offsets[] = { 0x167, 0x173, 0x17f, 0x18B };
|
||||
|
||||
/* Control report offsets for the Aquaero fan controllers */
|
||||
|
|
@ -157,8 +155,6 @@ static u16 aquaero_ctrl_fan_offsets[] = { 0x20c, 0x220, 0x234, 0x248 };
|
|||
#define D5NEXT_5V_VOLTAGE 0x39
|
||||
#define D5NEXT_12V_VOLTAGE 0x37
|
||||
#define D5NEXT_VIRTUAL_SENSORS_START 0x3f
|
||||
#define D5NEXT_MIN_STATUS_REPORT_SIZE (D5NEXT_PUMP_OFFSET + AQC_FAN_SPEED_OFFSET + \
|
||||
sizeof(u16))
|
||||
static u16 d5next_sensor_fan_offsets[] = { D5NEXT_PUMP_OFFSET, D5NEXT_FAN_OFFSET };
|
||||
|
||||
/* Control report offsets for the D5 Next pump */
|
||||
|
|
@ -183,14 +179,11 @@ static u16 d5next_ctrl_fan_offsets[] = { 0x97, 0x42 }; /* Pump and fan speed (fr
|
|||
#define AQUASTREAMULT_FAN_CURRENT_OFFSET 0x00
|
||||
#define AQUASTREAMULT_FAN_POWER_OFFSET 0x04
|
||||
#define AQUASTREAMULT_FAN_SPEED_OFFSET 0x06
|
||||
#define AQUASTREAMULT_MIN_STATUS_REPORT_SIZE (AQUASTREAMULT_PRESSURE_OFFSET + sizeof(u16))
|
||||
static u16 aquastreamult_sensor_fan_offsets[] = { AQUASTREAMULT_FAN_OFFSET };
|
||||
|
||||
/* Spec and sensor report offset for the Farbwerk RGB controller */
|
||||
#define FARBWERK_NUM_SENSORS 4
|
||||
#define FARBWERK_SENSOR_START 0x2f
|
||||
#define FARBWERK_MIN_STATUS_REPORT_SIZE (FARBWERK_SENSOR_START + \
|
||||
FARBWERK_NUM_SENSORS * AQC_SENSOR_SIZE)
|
||||
|
||||
/* Specs of the Farbwerk 360 RGB controller */
|
||||
#define FARBWERK360_NUM_SENSORS 4
|
||||
|
|
@ -200,8 +193,6 @@ static u16 aquastreamult_sensor_fan_offsets[] = { AQUASTREAMULT_FAN_OFFSET };
|
|||
/* Sensor report offsets for the Farbwerk 360 */
|
||||
#define FARBWERK360_SENSOR_START 0x32
|
||||
#define FARBWERK360_VIRTUAL_SENSORS_START 0x3a
|
||||
#define FARBWERK360_MIN_STATUS_REPORT_SIZE (FARBWERK360_VIRTUAL_SENSORS_START + \
|
||||
FARBWERK360_NUM_VIRTUAL_SENSORS * AQC_SENSOR_SIZE)
|
||||
|
||||
/* Control report offsets for the Farbwerk 360 */
|
||||
#define FARBWERK360_TEMP_CTRL_OFFSET 0x8
|
||||
|
|
@ -218,7 +209,6 @@ static u16 aquastreamult_sensor_fan_offsets[] = { AQUASTREAMULT_FAN_OFFSET };
|
|||
#define OCTO_SENSOR_START 0x3D
|
||||
#define OCTO_VIRTUAL_SENSORS_START 0x45
|
||||
#define OCTO_FLOW_SENSOR_OFFSET 0x7B
|
||||
#define OCTO_MIN_STATUS_REPORT_SIZE (0xD8 + AQC_FAN_SPEED_OFFSET + sizeof(u16))
|
||||
static u16 octo_sensor_fan_offsets[] = { 0x7D, 0x8A, 0x97, 0xA4, 0xB1, 0xBE, 0xCB, 0xD8 };
|
||||
|
||||
/* Control report offsets for the Octo */
|
||||
|
|
@ -239,7 +229,6 @@ static u16 octo_ctrl_fan_offsets[] = { 0x5B, 0xB0, 0x105, 0x15A, 0x1AF, 0x204, 0
|
|||
#define QUADRO_SENSOR_START 0x34
|
||||
#define QUADRO_VIRTUAL_SENSORS_START 0x3c
|
||||
#define QUADRO_FLOW_SENSOR_OFFSET 0x6e
|
||||
#define QUADRO_MIN_STATUS_REPORT_SIZE (0x97 + AQC_FAN_SPEED_OFFSET + sizeof(u16))
|
||||
static u16 quadro_sensor_fan_offsets[] = { 0x70, 0x7D, 0x8A, 0x97 };
|
||||
|
||||
/* Control report offsets for the Quadro */
|
||||
|
|
@ -259,7 +248,6 @@ static u16 quadro_ctrl_fan_offsets[] = { 0x37, 0x8c, 0xe1, 0x136 }; /* Fan speed
|
|||
#define HIGHFLOWNEXT_CONDUCTIVITY 95
|
||||
#define HIGHFLOWNEXT_5V_VOLTAGE 97
|
||||
#define HIGHFLOWNEXT_5V_VOLTAGE_USB 99
|
||||
#define HIGHFLOWNEXT_MIN_STATUS_REPORT_SIZE (HIGHFLOWNEXT_5V_VOLTAGE_USB + sizeof(u16))
|
||||
|
||||
/* Specs of the Leakshield */
|
||||
#define LEAKSHIELD_NUM_SENSORS 2
|
||||
|
|
@ -275,7 +263,6 @@ static u16 quadro_ctrl_fan_offsets[] = { 0x37, 0x8c, 0xe1, 0x136 }; /* Fan speed
|
|||
#define LEAKSHIELD_FLOW_IN 111
|
||||
#define LEAKSHIELD_RESERVOIR_VOLUME 313
|
||||
#define LEAKSHIELD_RESERVOIR_FILLED 311
|
||||
#define LEAKSHIELD_MIN_STATUS_REPORT_SIZE (LEAKSHIELD_RESERVOIR_VOLUME + sizeof(u16))
|
||||
|
||||
/* Specs of the Aquastream XT pump */
|
||||
#define AQUASTREAMXT_SERIAL_START 0x3a
|
||||
|
|
@ -567,7 +554,6 @@ struct aqc_data {
|
|||
const char *name;
|
||||
|
||||
int status_report_id; /* Used for legacy devices, report is stored in buffer */
|
||||
u16 min_report_size;
|
||||
int ctrl_report_id;
|
||||
int secondary_ctrl_report_id;
|
||||
int secondary_ctrl_report_size;
|
||||
|
|
@ -613,9 +599,9 @@ struct aqc_data {
|
|||
u32 speed_input_min[1];
|
||||
u32 speed_input_target[1];
|
||||
u32 speed_input_max[1];
|
||||
long power_input[8];
|
||||
u32 power_input[8];
|
||||
u16 voltage_input[8];
|
||||
u32 current_input[8];
|
||||
u16 current_input[8];
|
||||
|
||||
/* Label values */
|
||||
const char *const *temp_label;
|
||||
|
|
@ -990,7 +976,7 @@ static int aqc_legacy_read(struct aqc_data *priv)
|
|||
|
||||
/* Calculation derived from linear regression */
|
||||
sensor_value = get_unaligned_le16(priv->buffer + AQUASTREAMXT_PUMP_CURR_OFFSET);
|
||||
priv->current_input[0] = max(DIV_ROUND_CLOSEST(sensor_value * 176, 100) - 52, 0);
|
||||
priv->current_input[0] = DIV_ROUND_CLOSEST(sensor_value * 176, 100) - 52;
|
||||
|
||||
sensor_value = get_unaligned_le16(priv->buffer + AQUASTREAMXT_PUMP_VOLTAGE_OFFSET);
|
||||
priv->voltage_input[0] = DIV_ROUND_CLOSEST(sensor_value * 1000, 61);
|
||||
|
|
@ -1020,7 +1006,6 @@ static int aqc_legacy_read(struct aqc_data *priv)
|
|||
static int aqc_read(struct device *dev, enum hwmon_sensor_types type, u32 attr,
|
||||
int channel, long *val)
|
||||
{
|
||||
long power;
|
||||
int ret;
|
||||
struct aqc_data *priv = dev_get_drvdata(dev);
|
||||
|
||||
|
|
@ -1085,10 +1070,7 @@ static int aqc_read(struct device *dev, enum hwmon_sensor_types type, u32 attr,
|
|||
}
|
||||
break;
|
||||
case hwmon_power:
|
||||
power = READ_ONCE(priv->power_input[channel]);
|
||||
if (power == -ENODATA)
|
||||
return -ENODATA;
|
||||
*val = power;
|
||||
*val = priv->power_input[channel];
|
||||
break;
|
||||
case hwmon_pwm:
|
||||
switch (priv->kind) {
|
||||
|
|
@ -1351,8 +1333,6 @@ static int aqc_raw_event(struct hid_device *hdev, struct hid_report *report, u8
|
|||
return 0;
|
||||
|
||||
priv = hid_get_drvdata(hdev);
|
||||
if (!priv->min_report_size || size < priv->min_report_size)
|
||||
return 0;
|
||||
|
||||
/* Info provided with every report */
|
||||
priv->serial_number[0] = get_unaligned_be16(data + priv->serial_number_start_offset);
|
||||
|
|
@ -1388,9 +1368,9 @@ static int aqc_raw_event(struct hid_device *hdev, struct hid_report *report, u8
|
|||
priv->speed_input[i] =
|
||||
get_unaligned_be16(data + priv->fan_sensor_offsets[i] +
|
||||
priv->fan_structure->speed);
|
||||
WRITE_ONCE(priv->power_input[i],
|
||||
get_unaligned_be16(data + priv->fan_sensor_offsets[i] +
|
||||
priv->fan_structure->power) * 10000);
|
||||
priv->power_input[i] =
|
||||
get_unaligned_be16(data + priv->fan_sensor_offsets[i] +
|
||||
priv->fan_structure->power) * 10000;
|
||||
priv->voltage_input[i] =
|
||||
get_unaligned_be16(data + priv->fan_sensor_offsets[i] +
|
||||
priv->fan_structure->voltage) * 10;
|
||||
|
|
@ -1430,8 +1410,7 @@ static int aqc_raw_event(struct hid_device *hdev, struct hid_report *report, u8
|
|||
priv->speed_input[2] = get_unaligned_be16(data + AQUASTREAMULT_PRESSURE_OFFSET);
|
||||
priv->speed_input[3] = get_unaligned_be16(data + AQUASTREAMULT_FLOW_SENSOR_OFFSET);
|
||||
|
||||
WRITE_ONCE(priv->power_input[1],
|
||||
get_unaligned_be16(data + AQUASTREAMULT_PUMP_POWER) * 10000);
|
||||
priv->power_input[1] = get_unaligned_be16(data + AQUASTREAMULT_PUMP_POWER) * 10000;
|
||||
|
||||
priv->voltage_input[1] = get_unaligned_be16(data + AQUASTREAMULT_PUMP_VOLTAGE) * 10;
|
||||
|
||||
|
|
@ -1444,11 +1423,10 @@ static int aqc_raw_event(struct hid_device *hdev, struct hid_report *report, u8
|
|||
case highflownext:
|
||||
/* If external temp sensor is not connected, its power reading is also N/A */
|
||||
if (priv->temp_input[1] == -ENODATA)
|
||||
WRITE_ONCE(priv->power_input[0], -ENODATA);
|
||||
priv->power_input[0] = -ENODATA;
|
||||
else
|
||||
WRITE_ONCE(priv->power_input[0],
|
||||
min_t(u64, get_unaligned_be16(data + HIGHFLOWNEXT_POWER) *
|
||||
1000000ULL, LONG_MAX));
|
||||
priv->power_input[0] =
|
||||
get_unaligned_be16(data + HIGHFLOWNEXT_POWER) * 1000000;
|
||||
|
||||
priv->voltage_input[0] = get_unaligned_be16(data + HIGHFLOWNEXT_5V_VOLTAGE) * 10;
|
||||
priv->voltage_input[1] =
|
||||
|
|
@ -1540,7 +1518,6 @@ static void aqc_debugfs_init(struct aqc_data *priv)
|
|||
static int aqc_probe(struct hid_device *hdev, const struct hid_device_id *id)
|
||||
{
|
||||
struct aqc_data *priv;
|
||||
u16 min_report_size = 0;
|
||||
int ret;
|
||||
|
||||
priv = devm_kzalloc(&hdev->dev, sizeof(*priv), GFP_KERNEL);
|
||||
|
|
@ -1577,7 +1554,7 @@ static int aqc_probe(struct hid_device *hdev, const struct hid_device_id *id)
|
|||
* they present. The two other devices have the type of the second element in
|
||||
* their respective collections set to 1, while the real device has it set to 0.
|
||||
*/
|
||||
if (hdev->maxcollection < 2 || hdev->collection[1].type != 0) {
|
||||
if (hdev->collection[1].type != 0) {
|
||||
ret = -ENODEV;
|
||||
goto fail_and_close;
|
||||
}
|
||||
|
|
@ -1608,7 +1585,6 @@ static int aqc_probe(struct hid_device *hdev, const struct hid_device_id *id)
|
|||
priv->power_label = label_fan_power;
|
||||
priv->voltage_label = label_fan_voltage;
|
||||
priv->current_label = label_fan_current;
|
||||
min_report_size = AQUAERO_MIN_STATUS_REPORT_SIZE;
|
||||
break;
|
||||
case USB_PRODUCT_ID_D5NEXT:
|
||||
priv->kind = d5next;
|
||||
|
|
@ -1634,7 +1610,6 @@ static int aqc_probe(struct hid_device *hdev, const struct hid_device_id *id)
|
|||
priv->power_label = label_d5next_power;
|
||||
priv->voltage_label = label_d5next_voltages;
|
||||
priv->current_label = label_d5next_current;
|
||||
min_report_size = D5NEXT_MIN_STATUS_REPORT_SIZE;
|
||||
break;
|
||||
case USB_PRODUCT_ID_FARBWERK:
|
||||
priv->kind = farbwerk;
|
||||
|
|
@ -1645,7 +1620,6 @@ static int aqc_probe(struct hid_device *hdev, const struct hid_device_id *id)
|
|||
priv->temp_sensor_start_offset = FARBWERK_SENSOR_START;
|
||||
|
||||
priv->temp_label = label_temp_sensors;
|
||||
min_report_size = FARBWERK_MIN_STATUS_REPORT_SIZE;
|
||||
break;
|
||||
case USB_PRODUCT_ID_FARBWERK360:
|
||||
priv->kind = farbwerk360;
|
||||
|
|
@ -1662,7 +1636,6 @@ static int aqc_probe(struct hid_device *hdev, const struct hid_device_id *id)
|
|||
|
||||
priv->temp_label = label_temp_sensors;
|
||||
priv->virtual_temp_label = label_virtual_temp_sensors;
|
||||
min_report_size = FARBWERK360_MIN_STATUS_REPORT_SIZE;
|
||||
break;
|
||||
case USB_PRODUCT_ID_OCTO:
|
||||
priv->kind = octo;
|
||||
|
|
@ -1692,7 +1665,6 @@ static int aqc_probe(struct hid_device *hdev, const struct hid_device_id *id)
|
|||
priv->power_label = label_fan_power;
|
||||
priv->voltage_label = label_fan_voltage;
|
||||
priv->current_label = label_fan_current;
|
||||
min_report_size = OCTO_MIN_STATUS_REPORT_SIZE;
|
||||
break;
|
||||
case USB_PRODUCT_ID_QUADRO:
|
||||
priv->kind = quadro;
|
||||
|
|
@ -1722,7 +1694,6 @@ static int aqc_probe(struct hid_device *hdev, const struct hid_device_id *id)
|
|||
priv->power_label = label_fan_power;
|
||||
priv->voltage_label = label_fan_voltage;
|
||||
priv->current_label = label_fan_current;
|
||||
min_report_size = QUADRO_MIN_STATUS_REPORT_SIZE;
|
||||
break;
|
||||
case USB_PRODUCT_ID_HIGHFLOWNEXT:
|
||||
priv->kind = highflownext;
|
||||
|
|
@ -1740,7 +1711,6 @@ static int aqc_probe(struct hid_device *hdev, const struct hid_device_id *id)
|
|||
priv->speed_label = label_highflownext_fan_speed;
|
||||
priv->power_label = label_highflownext_power;
|
||||
priv->voltage_label = label_highflownext_voltage;
|
||||
min_report_size = HIGHFLOWNEXT_MIN_STATUS_REPORT_SIZE;
|
||||
break;
|
||||
case USB_PRODUCT_ID_LEAKSHIELD:
|
||||
/*
|
||||
|
|
@ -1760,7 +1730,6 @@ static int aqc_probe(struct hid_device *hdev, const struct hid_device_id *id)
|
|||
|
||||
priv->temp_label = label_leakshield_temp_sensors;
|
||||
priv->speed_label = label_leakshield_fan_speed;
|
||||
min_report_size = LEAKSHIELD_MIN_STATUS_REPORT_SIZE;
|
||||
break;
|
||||
case USB_PRODUCT_ID_AQUASTREAMXT:
|
||||
priv->kind = aquastreamxt;
|
||||
|
|
@ -1791,7 +1760,6 @@ static int aqc_probe(struct hid_device *hdev, const struct hid_device_id *id)
|
|||
priv->power_label = label_aquastreamult_power;
|
||||
priv->voltage_label = label_aquastreamult_voltages;
|
||||
priv->current_label = label_aquastreamult_current;
|
||||
min_report_size = AQUASTREAMULT_MIN_STATUS_REPORT_SIZE;
|
||||
break;
|
||||
case USB_PRODUCT_ID_POWERADJUST3:
|
||||
priv->kind = poweradjust3;
|
||||
|
|
@ -1865,8 +1833,6 @@ static int aqc_probe(struct hid_device *hdev, const struct hid_device_id *id)
|
|||
break;
|
||||
}
|
||||
|
||||
priv->min_report_size = min_report_size;
|
||||
|
||||
if (priv->buffer_size != 0) {
|
||||
priv->checksum_start = 0x01;
|
||||
priv->checksum_length = priv->buffer_size - 3;
|
||||
|
|
|
|||
|
|
@ -50,7 +50,6 @@ static const struct rog_ryujin_device_info rog_ryujin_iii_info = {
|
|||
#define MAX_REPORT_LENGTH 65
|
||||
|
||||
/* Cooler duty report offsets */
|
||||
#define RYUJIN_PUMP_SOURCE 3
|
||||
#define RYUJIN_PUMP_DUTY 4
|
||||
#define RYUJIN_INTERNAL_FAN_DUTY 5
|
||||
|
||||
|
|
@ -71,15 +70,10 @@ static const u8 get_cooler_duty_cmd[] = { RYUJIN_CMD_PREFIX, 0x9A };
|
|||
static const u8 get_controller_speed_cmd[] = { RYUJIN_CMD_PREFIX, 0xA0 };
|
||||
static const u8 get_controller_duty_cmd[] = { RYUJIN_CMD_PREFIX, 0xA1 };
|
||||
|
||||
#define RYUJIN_SET_COOLER_CHANNEL_OFFSET 2
|
||||
#define RYUJIN_SET_COOLER_PUMP_DUTY_OFFSET 3
|
||||
#define RYUJIN_SET_COOLER_FAN_DUTY_OFFSET 4
|
||||
static const u8 set_cooler_duty_cmd[] = { RYUJIN_CMD_PREFIX, 0x1A, 0x00, 0x00, 0x00 };
|
||||
|
||||
/* Pump control sources in the set cooler duty command and the cooler duty report */
|
||||
#define RYUJIN_SOURCE_HEADER 0
|
||||
#define RYUJIN_SOURCE_USB 1
|
||||
|
||||
#define RYUJIN_SET_CONTROLLER_FAN_DUTY_OFFSET 4
|
||||
static const u8 set_controller_duty_cmd[] = { RYUJIN_CMD_PREFIX, 0x21, 0x00, 0x00, 0x00 };
|
||||
|
||||
|
|
@ -123,7 +117,6 @@ struct rog_ryujin_data {
|
|||
s32 temp_input[1];
|
||||
u16 speed_input[6]; /* Pump, internal fan and four controller fan speeds in RPM */
|
||||
u8 duty_input[3]; /* Pump, internal fan and controller fan duty in PWM */
|
||||
u8 pump_source; /* Pump control source from the cooler duty report */
|
||||
|
||||
u8 *buffer;
|
||||
unsigned long updated; /* jiffies */
|
||||
|
|
@ -207,23 +200,16 @@ static int rog_ryujin_execute_cmd(struct rog_ryujin_data *priv, const u8 *cmd, i
|
|||
/* Send command for getting data */
|
||||
ret = rog_ryujin_write_expanded(priv, cmd, cmd_length);
|
||||
if (ret < 0)
|
||||
goto out_complete;
|
||||
return ret;
|
||||
|
||||
ret = wait_for_completion_interruptible_timeout(status_completion,
|
||||
msecs_to_jiffies(STATUS_VALIDITY));
|
||||
if (ret == 0)
|
||||
ret = -ETIMEDOUT;
|
||||
if (ret < 0)
|
||||
goto out_complete;
|
||||
return -ETIMEDOUT;
|
||||
else if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
|
||||
out_complete:
|
||||
spin_lock_irqsave(&priv->status_report_request_lock, flags);
|
||||
if (!completion_done(status_completion))
|
||||
complete_all(status_completion);
|
||||
spin_unlock_irqrestore(&priv->status_report_request_lock, flags);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int rog_ryujin_get_status(struct rog_ryujin_data *priv)
|
||||
|
|
@ -320,44 +306,6 @@ static int rog_ryujin_read_string(struct device *dev, enum hwmon_sensor_types ty
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* On devices with a non-zero duty_channel (the RYUJIN III), the channel byte of
|
||||
* the set cooler duty command selects the pump control source.
|
||||
* RYUJIN_SOURCE_HEADER hands the pump to its internal controller, which follows
|
||||
* the PWM of the header its 4-pin cable is plugged into. RYUJIN_SOURCE_USB
|
||||
* makes the pump follow the pump duty in the command. The cooler duty report
|
||||
* returns the current source.
|
||||
*
|
||||
* A fan duty write sends the reported source back, so that it leaves the pump
|
||||
* control source as it is. A pump duty write selects USB. The cooler does not
|
||||
* pass on a pump duty equal to the one it reports, and after power-on it
|
||||
* reports 40% while a pump handed over at that duty runs at full speed. So
|
||||
* when a pump duty write asks for the reported duty, write a duty 1% away
|
||||
* first.
|
||||
*/
|
||||
static int rog_ryujin_select_pump_source(struct rog_ryujin_data *priv, u8 *set_cmd,
|
||||
int channel)
|
||||
{
|
||||
u8 duty = set_cmd[RYUJIN_SET_COOLER_PUMP_DUTY_OFFSET];
|
||||
int ret;
|
||||
|
||||
if (channel == 1) {
|
||||
set_cmd[RYUJIN_SET_COOLER_CHANNEL_OFFSET] = priv->pump_source;
|
||||
return 0;
|
||||
}
|
||||
|
||||
set_cmd[RYUJIN_SET_COOLER_CHANNEL_OFFSET] = RYUJIN_SOURCE_USB;
|
||||
|
||||
if (duty != rog_ryujin_pwm_to_percent(priv->duty_input[0]))
|
||||
return 0;
|
||||
|
||||
set_cmd[RYUJIN_SET_COOLER_PUMP_DUTY_OFFSET] = duty < 100 ? duty + 1 : duty - 1;
|
||||
ret = rog_ryujin_execute_cmd(priv, set_cmd, SET_CMD_LENGTH, &priv->cooler_duty_set);
|
||||
set_cmd[RYUJIN_SET_COOLER_PUMP_DUTY_OFFSET] = duty;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int rog_ryujin_write_fixed_duty(struct rog_ryujin_data *priv, int channel, int val)
|
||||
{
|
||||
u8 set_cmd[SET_CMD_LENGTH];
|
||||
|
|
@ -375,7 +323,7 @@ static int rog_ryujin_write_fixed_duty(struct rog_ryujin_data *priv, int channel
|
|||
return ret;
|
||||
|
||||
memcpy(set_cmd, set_cooler_duty_cmd, SET_CMD_LENGTH);
|
||||
set_cmd[RYUJIN_SET_COOLER_CHANNEL_OFFSET] = priv->info->duty_channel;
|
||||
set_cmd[2] = priv->info->duty_channel;
|
||||
|
||||
/* Cooler duties are set as 0-100% */
|
||||
val = rog_ryujin_pwm_to_percent(val);
|
||||
|
|
@ -392,12 +340,6 @@ static int rog_ryujin_write_fixed_duty(struct rog_ryujin_data *priv, int channel
|
|||
set_cmd[RYUJIN_SET_COOLER_FAN_DUTY_OFFSET] = val;
|
||||
}
|
||||
|
||||
if (priv->info->duty_channel) {
|
||||
ret = rog_ryujin_select_pump_source(priv, set_cmd, channel);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return rog_ryujin_execute_cmd(priv, set_cmd, SET_CMD_LENGTH, &priv->cooler_duty_set);
|
||||
} else {
|
||||
/*
|
||||
|
|
@ -540,7 +482,6 @@ static int rog_ryujin_raw_event(struct hid_device *hdev, struct hid_report *repo
|
|||
goto unlock;
|
||||
}
|
||||
read_cooler_duty:
|
||||
priv->pump_source = data[RYUJIN_PUMP_SOURCE];
|
||||
priv->duty_input[0] = rog_ryujin_percent_to_pwm(data[RYUJIN_PUMP_DUTY]);
|
||||
priv->duty_input[1] = rog_ryujin_percent_to_pwm(data[RYUJIN_INTERNAL_FAN_DUTY]);
|
||||
|
||||
|
|
@ -637,18 +578,6 @@ static int rog_ryujin_probe(struct hid_device *hdev, const struct hid_device_id
|
|||
init_completion(&priv->cooler_duty_set);
|
||||
init_completion(&priv->controller_duty_set);
|
||||
|
||||
/*
|
||||
* Start completions in the completed state so rog_ryujin_raw_event()
|
||||
* only sees !completion_done() while rog_ryujin_execute_cmd() is
|
||||
* awaiting a response.
|
||||
*/
|
||||
complete_all(&priv->cooler_status_received);
|
||||
complete_all(&priv->controller_status_received);
|
||||
complete_all(&priv->cooler_duty_received);
|
||||
complete_all(&priv->controller_duty_received);
|
||||
complete_all(&priv->cooler_duty_set);
|
||||
complete_all(&priv->controller_duty_set);
|
||||
|
||||
priv->hwmon_dev = hwmon_device_register_with_info(&hdev->dev, "rog_ryujin",
|
||||
priv, &rog_ryujin_chip_info, NULL);
|
||||
if (IS_ERR(priv->hwmon_dev)) {
|
||||
|
|
|
|||
|
|
@ -164,7 +164,6 @@ struct asus_wmi_wmi_info {
|
|||
|
||||
struct asus_wmi_sensors {
|
||||
struct asus_wmi_wmi_info wmi;
|
||||
struct hwmon_chip_info chip_info;
|
||||
/* lock access to internal cache */
|
||||
struct mutex lock;
|
||||
};
|
||||
|
|
@ -497,6 +496,11 @@ static const struct hwmon_ops asus_wmi_hwmon_ops = {
|
|||
.read_string = asus_wmi_hwmon_read_string,
|
||||
};
|
||||
|
||||
static struct hwmon_chip_info asus_wmi_chip_info = {
|
||||
.ops = &asus_wmi_hwmon_ops,
|
||||
.info = NULL,
|
||||
};
|
||||
|
||||
static int asus_wmi_configure_sensor_setup(struct device *dev,
|
||||
struct asus_wmi_sensors *sensor_data)
|
||||
{
|
||||
|
|
@ -504,7 +508,7 @@ static int asus_wmi_configure_sensor_setup(struct device *dev,
|
|||
struct hwmon_channel_info *asus_wmi_hwmon_chan;
|
||||
int nr_count[hwmon_max] = {}, nr_types = 0;
|
||||
struct asus_wmi_sensor_info *temp_sensor;
|
||||
struct hwmon_chip_info *chip_info;
|
||||
const struct hwmon_chip_info *chip_info;
|
||||
enum hwmon_sensor_types type;
|
||||
struct device *hwdev;
|
||||
int i, idx;
|
||||
|
|
@ -545,9 +549,8 @@ static int asus_wmi_configure_sensor_setup(struct device *dev,
|
|||
if (!ptr_asus_wmi_ci)
|
||||
return -ENOMEM;
|
||||
|
||||
chip_info = &sensor_data->chip_info;
|
||||
chip_info->ops = &asus_wmi_hwmon_ops;
|
||||
chip_info->info = ptr_asus_wmi_ci;
|
||||
asus_wmi_chip_info.info = ptr_asus_wmi_ci;
|
||||
chip_info = &asus_wmi_chip_info;
|
||||
|
||||
sensor_data->wmi.info_by_id = devm_kcalloc(dev, sensor_data->wmi.sensor_count,
|
||||
sizeof(*sensor_data->wmi.info_by_id),
|
||||
|
|
|
|||
|
|
@ -20,9 +20,7 @@
|
|||
#include <linux/i2c.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/unaligned.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <linux/mod_devicetable.h>
|
||||
#include <linux/property.h>
|
||||
|
|
@ -92,9 +90,6 @@ struct cc2_data {
|
|||
int irq_low;
|
||||
int irq_high;
|
||||
bool process_irqs;
|
||||
/* protects process_irqs and the alarm indicators */
|
||||
struct mutex irq_lock;
|
||||
bool regulator_enabled;
|
||||
};
|
||||
|
||||
/* %RH as a per cent mille from a register value */
|
||||
|
|
@ -123,33 +118,20 @@ static int cc2_enable(struct cc2_data *data)
|
|||
{
|
||||
int ret;
|
||||
|
||||
if (data->irq_ready > 0) {
|
||||
scoped_guard(mutex, &data->irq_lock)
|
||||
data->process_irqs = false;
|
||||
|
||||
synchronize_irq(data->irq_ready);
|
||||
|
||||
scoped_guard(mutex, &data->irq_lock)
|
||||
reinit_completion(&data->complete);
|
||||
}
|
||||
|
||||
/* exclusive regulator, check in case a disable failed */
|
||||
if (data->regulator_enabled) {
|
||||
scoped_guard(mutex, &data->irq_lock)
|
||||
data->process_irqs = true;
|
||||
if (regulator_is_enabled(data->regulator))
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* clear any pending completion */
|
||||
try_wait_for_completion(&data->complete);
|
||||
|
||||
ret = regulator_enable(data->regulator);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
data->regulator_enabled = true;
|
||||
|
||||
usleep_range(CC2_STARTUP_TIME_US, CC2_STARTUP_TIME_US + 125);
|
||||
|
||||
scoped_guard(mutex, &data->irq_lock)
|
||||
data->process_irqs = true;
|
||||
data->process_irqs = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -158,36 +140,15 @@ static void cc2_disable(struct cc2_data *data)
|
|||
{
|
||||
int err;
|
||||
|
||||
/* let the alarms already raised by the last measurement be processed */
|
||||
if (data->irq_low > 0)
|
||||
synchronize_irq(data->irq_low);
|
||||
|
||||
if (data->irq_high > 0)
|
||||
synchronize_irq(data->irq_high);
|
||||
|
||||
/* ignore alarms triggered by voltage toggling when powering up */
|
||||
scoped_guard(mutex, &data->irq_lock)
|
||||
data->process_irqs = false;
|
||||
|
||||
if (data->irq_ready > 0)
|
||||
synchronize_irq(data->irq_ready);
|
||||
data->process_irqs = false;
|
||||
|
||||
/* exclusive regulator, check in case an enable failed */
|
||||
if (!data->regulator_enabled)
|
||||
return;
|
||||
|
||||
err = regulator_disable(data->regulator);
|
||||
if (err) {
|
||||
dev_dbg(&data->client->dev, "Failed to disable device");
|
||||
return;
|
||||
if (regulator_is_enabled(data->regulator)) {
|
||||
err = regulator_disable(data->regulator);
|
||||
if (err)
|
||||
dev_dbg(&data->client->dev, "Failed to disable device");
|
||||
}
|
||||
|
||||
data->regulator_enabled = false;
|
||||
}
|
||||
|
||||
static void cc2_disable_action(void *data)
|
||||
{
|
||||
cc2_disable(data);
|
||||
}
|
||||
|
||||
static int cc2_cmd_response_diagnostic(struct device *dev, u8 status)
|
||||
|
|
@ -206,13 +167,13 @@ static int cc2_cmd_response_diagnostic(struct device *dev, u8 status)
|
|||
case CC2_RESPONSE_BUSY:
|
||||
return -EBUSY;
|
||||
case CC2_RESPONSE_NACK:
|
||||
if (status & CC2_ERR_CORR_EEPROM)
|
||||
if (resp & CC2_ERR_CORR_EEPROM)
|
||||
dev_dbg(dev, "Command failed: corrected EEPROM\n");
|
||||
if (status & CC2_ERR_UNCORR_EEPROM)
|
||||
if (resp & CC2_ERR_UNCORR_EEPROM)
|
||||
dev_dbg(dev, "Command failed: uncorrected EEPROM\n");
|
||||
if (status & CC2_ERR_RAM_PARITY)
|
||||
if (resp & CC2_ERR_RAM_PARITY)
|
||||
dev_dbg(dev, "Command failed: RAM parity\n");
|
||||
if (status & CC2_ERR_CONFIG_LOAD)
|
||||
if (resp & CC2_ERR_RAM_PARITY)
|
||||
dev_dbg(dev, "Command failed: configuration error\n");
|
||||
return -ENODATA;
|
||||
default:
|
||||
|
|
@ -265,7 +226,7 @@ static int cc2_command_mode_start(struct cc2_data *data)
|
|||
2 * CC2_RESP_START_CM_US);
|
||||
}
|
||||
ret = cc2_read_command_status(data->client);
|
||||
if (ret != -ETIMEDOUT || i == CC2_CM_RETRIES - 1)
|
||||
if (ret != -ETIMEDOUT || i == CC2_CM_RETRIES)
|
||||
break;
|
||||
|
||||
/* command window missed, prepare for a retry */
|
||||
|
|
@ -299,7 +260,8 @@ static int cc2_write_reg(struct cc2_data *data, u8 reg, u16 val)
|
|||
if (ret < 0)
|
||||
goto disable;
|
||||
|
||||
ret = i2c_smbus_write_word_swapped(data->client, reg, val);
|
||||
cpu_to_be16s(&val);
|
||||
ret = i2c_smbus_write_word_data(data->client, reg, val);
|
||||
if (ret < 0)
|
||||
goto disable;
|
||||
|
||||
|
|
@ -349,7 +311,7 @@ static int cc2_read_reg(struct cc2_data *data, u8 reg, u16 *val)
|
|||
if (ret != CC2_EEPROM_DATA_LEN)
|
||||
return ret < 0 ? ret : -EIO;
|
||||
|
||||
*val = get_unaligned_be16(&buf[1]);
|
||||
*val = be16_to_cpup((__be16 *)&buf[1]);
|
||||
|
||||
return cc2_read_command_status(data->client);
|
||||
}
|
||||
|
|
@ -389,10 +351,10 @@ static int cc2_data_fetch(struct i2c_client *client,
|
|||
|
||||
switch (type) {
|
||||
case hwmon_humidity:
|
||||
*val = cc2_rh_convert(get_unaligned_be16(&data[0]));
|
||||
*val = cc2_rh_convert(be16_to_cpup((__be16 *)&data[0]));
|
||||
break;
|
||||
case hwmon_temp:
|
||||
*val = cc2_temp_convert(get_unaligned_be16(&data[2]));
|
||||
*val = cc2_temp_convert(be16_to_cpup((__be16 *)&data[2]));
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
|
|
@ -520,10 +482,8 @@ static irqreturn_t cc2_ready_interrupt(int irq, void *data)
|
|||
{
|
||||
struct cc2_data *cc2 = data;
|
||||
|
||||
scoped_guard(mutex, &cc2->irq_lock) {
|
||||
if (cc2->process_irqs)
|
||||
complete(&cc2->complete);
|
||||
}
|
||||
if (cc2->process_irqs)
|
||||
complete(&cc2->complete);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
|
@ -532,12 +492,10 @@ static irqreturn_t cc2_low_interrupt(int irq, void *data)
|
|||
{
|
||||
struct cc2_data *cc2 = data;
|
||||
|
||||
scoped_guard(mutex, &cc2->irq_lock) {
|
||||
if (cc2->process_irqs) {
|
||||
hwmon_notify_event(cc2->hwmon, hwmon_humidity,
|
||||
hwmon_humidity_min_alarm, 0);
|
||||
cc2->rh_alarm.low_alarm = true;
|
||||
}
|
||||
if (cc2->process_irqs) {
|
||||
hwmon_notify_event(cc2->hwmon, hwmon_humidity,
|
||||
hwmon_humidity_min_alarm, 0);
|
||||
cc2->rh_alarm.low_alarm = true;
|
||||
}
|
||||
|
||||
return IRQ_HANDLED;
|
||||
|
|
@ -547,12 +505,10 @@ static irqreturn_t cc2_high_interrupt(int irq, void *data)
|
|||
{
|
||||
struct cc2_data *cc2 = data;
|
||||
|
||||
scoped_guard(mutex, &cc2->irq_lock) {
|
||||
if (cc2->process_irqs) {
|
||||
hwmon_notify_event(cc2->hwmon, hwmon_humidity,
|
||||
hwmon_humidity_max_alarm, 0);
|
||||
cc2->rh_alarm.high_alarm = true;
|
||||
}
|
||||
if (cc2->process_irqs) {
|
||||
hwmon_notify_event(cc2->hwmon, hwmon_humidity,
|
||||
hwmon_humidity_max_alarm, 0);
|
||||
cc2->rh_alarm.high_alarm = true;
|
||||
}
|
||||
|
||||
return IRQ_HANDLED;
|
||||
|
|
@ -568,13 +524,11 @@ static int cc2_humidity_min_alarm_status(struct cc2_data *data, long *val)
|
|||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
scoped_guard(mutex, &data->irq_lock) {
|
||||
if (data->rh_alarm.low_alarm) {
|
||||
*val = (measurement < min_hyst) ? 1 : 0;
|
||||
data->rh_alarm.low_alarm = *val;
|
||||
} else {
|
||||
*val = 0;
|
||||
}
|
||||
if (data->rh_alarm.low_alarm) {
|
||||
*val = (measurement < min_hyst) ? 1 : 0;
|
||||
data->rh_alarm.low_alarm = *val;
|
||||
} else {
|
||||
*val = 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
@ -590,13 +544,11 @@ static int cc2_humidity_max_alarm_status(struct cc2_data *data, long *val)
|
|||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
scoped_guard(mutex, &data->irq_lock) {
|
||||
if (data->rh_alarm.high_alarm) {
|
||||
*val = (measurement > max_hyst) ? 1 : 0;
|
||||
data->rh_alarm.high_alarm = *val;
|
||||
} else {
|
||||
*val = 0;
|
||||
}
|
||||
if (data->rh_alarm.high_alarm) {
|
||||
*val = (measurement > max_hyst) ? 1 : 0;
|
||||
data->rh_alarm.high_alarm = *val;
|
||||
} else {
|
||||
*val = 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
@ -679,47 +631,28 @@ static int cc2_write(struct device *dev, enum hwmon_sensor_types type, u32 attr,
|
|||
}
|
||||
}
|
||||
|
||||
static int cc2_get_irqs(struct cc2_data *data, struct device *dev)
|
||||
{
|
||||
data->irq_ready = fwnode_irq_get_byname(dev_fwnode(dev), "ready");
|
||||
if (data->irq_ready == -EPROBE_DEFER)
|
||||
return data->irq_ready;
|
||||
if (data->irq_ready > 0)
|
||||
init_completion(&data->complete);
|
||||
|
||||
data->irq_low = fwnode_irq_get_byname(dev_fwnode(dev), "low");
|
||||
if (data->irq_low == -EPROBE_DEFER)
|
||||
return data->irq_low;
|
||||
if (data->irq_low > 0)
|
||||
data->rh_alarm.low_alarm_visible = true;
|
||||
|
||||
data->irq_high = fwnode_irq_get_byname(dev_fwnode(dev), "high");
|
||||
if (data->irq_high == -EPROBE_DEFER)
|
||||
return data->irq_high;
|
||||
if (data->irq_high > 0)
|
||||
data->rh_alarm.high_alarm_visible = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cc2_request_data_ready(struct cc2_data *data, struct device *dev)
|
||||
static int cc2_request_ready_irq(struct cc2_data *data, struct device *dev)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (data->irq_ready > 0)
|
||||
data->irq_ready = fwnode_irq_get_byname(dev_fwnode(dev), "ready");
|
||||
if (data->irq_ready > 0) {
|
||||
init_completion(&data->complete);
|
||||
ret = devm_request_threaded_irq(dev, data->irq_ready, NULL,
|
||||
cc2_ready_interrupt,
|
||||
IRQF_ONESHOT |
|
||||
IRQF_TRIGGER_RISING,
|
||||
dev_name(dev), data);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int cc2_request_alarms(struct cc2_data *data, struct device *dev)
|
||||
static int cc2_request_alarm_irqs(struct cc2_data *data, struct device *dev)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
data->irq_low = fwnode_irq_get_byname(dev_fwnode(dev), "low");
|
||||
if (data->irq_low > 0) {
|
||||
ret = devm_request_threaded_irq(dev, data->irq_low, NULL,
|
||||
cc2_low_interrupt,
|
||||
|
|
@ -728,8 +661,11 @@ static int cc2_request_alarms(struct cc2_data *data, struct device *dev)
|
|||
dev_name(dev), data);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
data->rh_alarm.low_alarm_visible = true;
|
||||
}
|
||||
|
||||
data->irq_high = fwnode_irq_get_byname(dev_fwnode(dev), "high");
|
||||
if (data->irq_high > 0) {
|
||||
ret = devm_request_threaded_irq(dev, data->irq_high, NULL,
|
||||
cc2_high_interrupt,
|
||||
|
|
@ -738,6 +674,8 @@ static int cc2_request_alarms(struct cc2_data *data, struct device *dev)
|
|||
dev_name(dev), data);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
data->rh_alarm.high_alarm_visible = true;
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
|
@ -779,8 +717,6 @@ static int cc2_probe(struct i2c_client *client)
|
|||
|
||||
i2c_set_clientdata(client, data);
|
||||
|
||||
mutex_init(&data->irq_lock);
|
||||
|
||||
data->client = client;
|
||||
|
||||
data->regulator = devm_regulator_get_exclusive(dev, "vdd");
|
||||
|
|
@ -790,18 +726,14 @@ static int cc2_probe(struct i2c_client *client)
|
|||
|
||||
device_property_read_string(dev, "label", &data->label);
|
||||
|
||||
ret = cc2_get_irqs(data, dev);
|
||||
if (ret)
|
||||
return dev_err_probe(dev, ret, "Failed to get IRQs\n");
|
||||
|
||||
ret = devm_add_action_or_reset(dev, cc2_disable_action, data);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = cc2_request_data_ready(data, dev);
|
||||
ret = cc2_request_ready_irq(data, dev);
|
||||
if (ret)
|
||||
return dev_err_probe(dev, ret, "Failed to request ready irq\n");
|
||||
|
||||
ret = cc2_request_alarm_irqs(data, dev);
|
||||
if (ret)
|
||||
return dev_err_probe(dev, ret, "Failed to request alarm irqs\n");
|
||||
|
||||
data->hwmon = devm_hwmon_device_register_with_info(dev, client->name,
|
||||
data, &cc2_chip_info,
|
||||
NULL);
|
||||
|
|
@ -809,13 +741,16 @@ static int cc2_probe(struct i2c_client *client)
|
|||
return dev_err_probe(dev, PTR_ERR(data->hwmon),
|
||||
"Failed to register hwmon device\n");
|
||||
|
||||
ret = cc2_request_alarms(data, dev);
|
||||
if (ret)
|
||||
return dev_err_probe(dev, ret, "Failed to request alarm irqs\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void cc2_remove(struct i2c_client *client)
|
||||
{
|
||||
struct cc2_data *data = i2c_get_clientdata(client);
|
||||
|
||||
cc2_disable(data);
|
||||
}
|
||||
|
||||
static const struct i2c_device_id cc2_id[] = {
|
||||
{ .name = "cc2d23" },
|
||||
{ .name = "cc2d23s" },
|
||||
|
|
@ -848,6 +783,7 @@ static struct i2c_driver cc2_driver = {
|
|||
.of_match_table = cc2_of_match,
|
||||
},
|
||||
.probe = cc2_probe,
|
||||
.remove = cc2_remove,
|
||||
.id_table = cc2_id,
|
||||
};
|
||||
module_i2c_driver(cc2_driver);
|
||||
|
|
|
|||
|
|
@ -76,7 +76,7 @@ struct temp_data {
|
|||
int temp;
|
||||
bool temp_valid;
|
||||
int tjmax;
|
||||
u64 last_updated;
|
||||
unsigned long last_updated;
|
||||
unsigned int cpu;
|
||||
int index;
|
||||
u32 cpu_core_id;
|
||||
|
|
@ -407,7 +407,7 @@ static ssize_t show_temp(struct device *dev,
|
|||
mutex_lock(&tdata->update_lock);
|
||||
|
||||
/* Check whether the time interval has elapsed */
|
||||
if (time_after64(get_jiffies_64(), tdata->last_updated + HZ)) {
|
||||
if (time_after(jiffies, tdata->last_updated + HZ)) {
|
||||
tjmax = get_tjmax(tdata, dev);
|
||||
rdmsrq_on_cpu(tdata->cpu, tdata->status_reg, &val.q);
|
||||
/*
|
||||
|
|
@ -417,7 +417,7 @@ static ssize_t show_temp(struct device *dev,
|
|||
*/
|
||||
tdata->temp_valid = (val.l >> 31) & 1;
|
||||
tdata->temp = tjmax - ((val.l >> 16) & 0xff) * 1000;
|
||||
tdata->last_updated = get_jiffies_64();
|
||||
tdata->last_updated = jiffies;
|
||||
}
|
||||
|
||||
valid = tdata->temp_valid;
|
||||
|
|
@ -491,12 +491,11 @@ init_temp_data(struct platform_data *pdata, unsigned int cpu, int pkg_flag)
|
|||
struct temp_data *tdata;
|
||||
|
||||
if (!pdata->core_data) {
|
||||
int nr_cores = topology_num_cores_per_package();
|
||||
|
||||
pdata->core_data = kzalloc_objs(struct temp_data *, nr_cores);
|
||||
pdata->nr_cores = topology_num_cores_per_package();
|
||||
pdata->core_data = kzalloc_objs(struct temp_data *,
|
||||
pdata->nr_cores);
|
||||
if (!pdata->core_data)
|
||||
return NULL;
|
||||
pdata->nr_cores = nr_cores;
|
||||
}
|
||||
|
||||
tdata = kzalloc_obj(struct temp_data);
|
||||
|
|
@ -521,8 +520,11 @@ init_temp_data(struct platform_data *pdata, unsigned int cpu, int pkg_flag)
|
|||
tdata->cpu = cpu;
|
||||
tdata->cpu_core_id = topology_core_id(cpu);
|
||||
tdata->attr_size = MAX_CORE_ATTRS;
|
||||
/* Backdate to force a refresh on the first read */
|
||||
tdata->last_updated = get_jiffies_64() - HZ - 1;
|
||||
/*
|
||||
* A zero timestamp does not look stale on 32-bit, where jiffies
|
||||
* starts just short of wrapping. Backdate it instead.
|
||||
*/
|
||||
tdata->last_updated = jiffies - HZ - 1;
|
||||
mutex_init(&tdata->update_lock);
|
||||
return tdata;
|
||||
}
|
||||
|
|
@ -693,9 +695,6 @@ static int coretemp_cpu_online(unsigned int cpu)
|
|||
if (!housekeeping_cpu(cpu, HK_TYPE_MISC))
|
||||
return 0;
|
||||
|
||||
if (!pdev)
|
||||
return 0;
|
||||
|
||||
pdata = platform_get_drvdata(pdev);
|
||||
if (!pdata->hwmon_dev) {
|
||||
struct device *hwmon;
|
||||
|
|
@ -747,9 +746,6 @@ static int coretemp_cpu_offline(unsigned int cpu)
|
|||
return 0;
|
||||
|
||||
/* If the physical CPU device does not exist, just return */
|
||||
if (!pdev)
|
||||
return 0;
|
||||
|
||||
pd = platform_get_drvdata(pdev);
|
||||
if (!pd->hwmon_dev)
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -215,11 +215,10 @@ static int set_target(struct ccp_device *ccp, int channel, long val)
|
|||
int ret;
|
||||
|
||||
val = clamp_val(val, 0, 0xFFFF);
|
||||
ccp->target[channel] = val;
|
||||
|
||||
mutex_lock(&ccp->mutex);
|
||||
ret = send_usb_cmd(ccp, CTL_SET_FAN_TARGET, channel, val >> 8, val);
|
||||
if (!ret)
|
||||
ccp->target[channel] = val;
|
||||
|
||||
mutex_unlock(&ccp->mutex);
|
||||
return ret;
|
||||
|
|
|
|||
|
|
@ -444,7 +444,6 @@ static void gpd_duo_set_pwm_enable(struct gpd_fan_data *data, enum FAN_PWM_ENABL
|
|||
break;
|
||||
case AUTOMATIC:
|
||||
gpd_ecram_write(data->drvdata, data->drvdata->pwm_write, 0);
|
||||
gpd_ecram_write(data->drvdata, data->drvdata->pwm_write + 1, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -150,10 +150,7 @@ static int set_fan_speed(struct gpio_fan_data *fan_data, int speed_index)
|
|||
|
||||
__set_fan_ctrl(fan_data, fan_data->speed[speed_index].ctrl_val);
|
||||
|
||||
/* The GPIOs have changed, and a PM put drops the reference on error. */
|
||||
fan_data->speed_index = speed_index;
|
||||
|
||||
if (speed_index == 0) {
|
||||
if (fan_data->speed_index > 0 && speed_index == 0) {
|
||||
int ret;
|
||||
|
||||
ret = pm_runtime_put_sync(fan_data->dev);
|
||||
|
|
@ -161,6 +158,8 @@ static int set_fan_speed(struct gpio_fan_data *fan_data, int speed_index)
|
|||
return ret;
|
||||
}
|
||||
|
||||
fan_data->speed_index = speed_index;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -390,7 +390,6 @@ struct hp_wmi_info {
|
|||
*/
|
||||
struct hp_wmi_sensors {
|
||||
struct wmi_device *wdev;
|
||||
struct hwmon_chip_info chip_info;
|
||||
struct hp_wmi_info **info_map[hwmon_max];
|
||||
u8 channel_count[hwmon_max];
|
||||
bool has_intrusion;
|
||||
|
|
@ -739,21 +738,15 @@ static long scale_numeric_sensor(const struct hp_wmi_numeric_sensor *nsensor)
|
|||
|
||||
val = current_reading;
|
||||
|
||||
for (; val && unit_modifier < target_modifier; unit_modifier++)
|
||||
for (; unit_modifier < target_modifier; unit_modifier++)
|
||||
val = DIV_ROUND_CLOSEST(val, 10);
|
||||
|
||||
if (val) {
|
||||
for (; unit_modifier > target_modifier; unit_modifier--) {
|
||||
if (val > LONG_MAX / 10) {
|
||||
val = LONG_MAX;
|
||||
break;
|
||||
}
|
||||
if (val < LONG_MIN / 10) {
|
||||
val = LONG_MIN;
|
||||
break;
|
||||
}
|
||||
val *= 10;
|
||||
for (; unit_modifier > target_modifier; unit_modifier--) {
|
||||
if (val > LONG_MAX / 10) {
|
||||
val = LONG_MAX;
|
||||
break;
|
||||
}
|
||||
val *= 10;
|
||||
}
|
||||
|
||||
if (sensor_type == HP_WMI_TYPE_TEMPERATURE) {
|
||||
|
|
@ -1480,10 +1473,8 @@ static int hp_wmi_hwmon_read(struct device *dev, enum hwmon_sensor_types type,
|
|||
|
||||
if ((type == hwmon_temp && attr == hwmon_temp_alarm) ||
|
||||
(type == hwmon_fan && attr == hwmon_fan_alarm)) {
|
||||
mutex_lock(&state->lock);
|
||||
*out_val = info->alarm ? 1 : 0;
|
||||
info->alarm = false;
|
||||
mutex_unlock(&state->lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1540,6 +1531,11 @@ static const struct hwmon_ops hp_wmi_hwmon_ops = {
|
|||
.write = hp_wmi_hwmon_write,
|
||||
};
|
||||
|
||||
static struct hwmon_chip_info hp_wmi_chip_info = {
|
||||
.ops = &hp_wmi_hwmon_ops,
|
||||
.info = NULL,
|
||||
};
|
||||
|
||||
static struct hp_wmi_info *match_fan_event(struct hp_wmi_sensors *state,
|
||||
const char *event_description)
|
||||
{
|
||||
|
|
@ -1966,8 +1962,7 @@ static int make_chip_info(struct hp_wmi_sensors *state, bool has_events)
|
|||
if (!ptr_channel_info)
|
||||
return -ENOMEM;
|
||||
|
||||
state->chip_info.ops = &hp_wmi_hwmon_ops;
|
||||
state->chip_info.info = ptr_channel_info;
|
||||
hp_wmi_chip_info.info = ptr_channel_info;
|
||||
|
||||
for (type = hwmon_chip; type < hwmon_max; type++) {
|
||||
count = channel_count[type];
|
||||
|
|
@ -2058,7 +2053,7 @@ static int hp_wmi_sensors_init(struct hp_wmi_sensors *state)
|
|||
return err;
|
||||
|
||||
hwdev = devm_hwmon_device_register_with_info(dev, "hp_wmi_sensors",
|
||||
state, &state->chip_info,
|
||||
state, &hp_wmi_chip_info,
|
||||
NULL);
|
||||
return PTR_ERR_OR_ZERO(hwdev);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -123,7 +123,8 @@ struct lm75_data {
|
|||
|
||||
static const u8 lm75_sample_set_masks[] = { 0 << 5, 1 << 5, 2 << 5, 3 << 5 };
|
||||
|
||||
#define LM75_ALERT_POLARITY_HIGH_BIT BIT(2)
|
||||
#define LM75_ALERT_POLARITY_HIGH_8_BIT (BIT(2))
|
||||
#define LM75_ALERT_POLARITY_HIGH_16_BIT (BIT(2) << 8)
|
||||
#define LM75_SAMPLE_CLEAR_MASK (3 << 5)
|
||||
|
||||
/* The structure below stores the configuration values of the supported devices.
|
||||
|
|
@ -769,7 +770,11 @@ static int lm75_generic_probe(struct device *dev, const char *name,
|
|||
data->orig_conf = status;
|
||||
|
||||
/* Enforce polarity active-low (default) or active-high (devicetree) */
|
||||
pol_mask = LM75_ALERT_POLARITY_HIGH_BIT;
|
||||
if (!data->params->config_reg_16bits)
|
||||
pol_mask = LM75_ALERT_POLARITY_HIGH_8_BIT;
|
||||
else
|
||||
pol_mask = LM75_ALERT_POLARITY_HIGH_16_BIT;
|
||||
|
||||
clr_mask = data->params->clr_mask | pol_mask;
|
||||
set_mask = data->params->set_mask & ~pol_mask;
|
||||
if (device_property_read_bool(dev, "ti,alert-polarity-active-high"))
|
||||
|
|
|
|||
|
|
@ -606,16 +606,13 @@ static DEVICE_ATTR_RO(cpu0_vid);
|
|||
static ssize_t vrm_show(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct i2c_client *client = dev_get_drvdata(dev);
|
||||
struct lm87_data *data = i2c_get_clientdata(client);
|
||||
|
||||
struct lm87_data *data = dev_get_drvdata(dev);
|
||||
return sprintf(buf, "%d\n", data->vrm);
|
||||
}
|
||||
static ssize_t vrm_store(struct device *dev, struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct i2c_client *client = dev_get_drvdata(dev);
|
||||
struct lm87_data *data = i2c_get_clientdata(client);
|
||||
struct lm87_data *data = dev_get_drvdata(dev);
|
||||
unsigned long val;
|
||||
int err;
|
||||
|
||||
|
|
|
|||
|
|
@ -920,7 +920,7 @@ static ssize_t
|
|||
show_pwm(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct nct6683_data *data = nct6683_update_device(dev);
|
||||
struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
|
||||
struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
|
||||
int index = sattr->index;
|
||||
|
||||
return sprintf(buf, "%d\n", data->pwm[index]);
|
||||
|
|
@ -930,7 +930,7 @@ static ssize_t
|
|||
store_pwm(struct device *dev, struct device_attribute *attr, const char *buf,
|
||||
size_t count)
|
||||
{
|
||||
struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
|
||||
struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
|
||||
struct nct6683_data *data = dev_get_drvdata(dev);
|
||||
int index = sattr->index;
|
||||
unsigned long val;
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
#include <linux/auxiliary_bus.h>
|
||||
#include <linux/bitfield.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/devm-helpers.h>
|
||||
#include <linux/hwmon.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/module.h>
|
||||
|
|
@ -325,13 +326,11 @@ static int create_dimm_temp_info(struct peci_dimmtemp *priv)
|
|||
if (ret == -ENODEV) {
|
||||
dev_dbg(priv->dev, "No DIMMs found\n");
|
||||
return 0;
|
||||
}
|
||||
if (ret == -EAGAIN) {
|
||||
} else if (ret) {
|
||||
schedule_delayed_work(&priv->detect_work, DIMM_MASK_CHECK_DELAY_JIFFIES);
|
||||
dev_dbg(priv->dev, "Deferred populating DIMM temp info\n");
|
||||
}
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
channels = priv->gen_info->chan_rank_max * priv->gen_info->dimm_idx_max;
|
||||
|
||||
|
|
@ -399,8 +398,10 @@ static int peci_dimmtemp_probe(struct auxiliary_device *adev, const struct auxil
|
|||
"Unexpected PECI revision %#x, some features may be unavailable\n",
|
||||
peci_dev->info.peci_revision);
|
||||
|
||||
auxiliary_set_drvdata(adev, priv);
|
||||
INIT_DELAYED_WORK(&priv->detect_work, create_dimm_temp_info_delayed);
|
||||
ret = devm_delayed_work_autocancel(priv->dev, &priv->detect_work,
|
||||
create_dimm_temp_info_delayed);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = create_dimm_temp_info(priv);
|
||||
if (ret && ret != -EAGAIN) {
|
||||
|
|
@ -411,13 +412,6 @@ static int peci_dimmtemp_probe(struct auxiliary_device *adev, const struct auxil
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void peci_dimmtemp_remove(struct auxiliary_device *adev)
|
||||
{
|
||||
struct peci_dimmtemp *priv = auxiliary_get_drvdata(adev);
|
||||
|
||||
cancel_delayed_work_sync(&priv->detect_work);
|
||||
}
|
||||
|
||||
static int
|
||||
read_thresholds_hsx(struct peci_dimmtemp *priv, int dimm_order, int chan_rank, u32 *data)
|
||||
{
|
||||
|
|
@ -671,7 +665,6 @@ MODULE_DEVICE_TABLE(auxiliary, peci_dimmtemp_ids);
|
|||
|
||||
static struct auxiliary_driver peci_dimmtemp_driver = {
|
||||
.probe = peci_dimmtemp_probe,
|
||||
.remove = peci_dimmtemp_remove,
|
||||
.id_table = peci_dimmtemp_ids,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1524,22 +1524,14 @@ static int pmbus_thermal_add_sensor(struct pmbus_data *pmbus_data,
|
|||
tdata->sensor = sensor;
|
||||
tdata->pmbus_data = pmbus_data;
|
||||
|
||||
/*
|
||||
* The PMBus core numbers its temperature sensors from 1, as the
|
||||
* hwmon tempN attributes, while the thermal core expects a 0-based
|
||||
* sensor index.
|
||||
*/
|
||||
tzd = devm_thermal_of_zone_register(dev, index - 1, tdata,
|
||||
tzd = devm_thermal_of_zone_register(dev, index, tdata,
|
||||
&pmbus_thermal_ops);
|
||||
/*
|
||||
* If CONFIG_THERMAL_OF is disabled, devm_thermal_of_zone_register()
|
||||
* returns -ENOTSUPP. If no thermal zone is configured for the sensor,
|
||||
* it returns -ENODEV. Ignore those errors but forward any other error.
|
||||
* If CONFIG_THERMAL_OF is disabled, this returns -ENODEV,
|
||||
* so ignore that error but forward any other error.
|
||||
*/
|
||||
if (IS_ERR(tzd) && PTR_ERR(tzd) != -ENODEV && PTR_ERR(tzd) != -ENOTSUPP) {
|
||||
devm_kfree(dev, tdata);
|
||||
if (IS_ERR(tzd) && (PTR_ERR(tzd) != -ENODEV))
|
||||
return PTR_ERR(tzd);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1554,11 +1546,10 @@ static struct pmbus_sensor *pmbus_add_sensor(struct pmbus_data *data,
|
|||
{
|
||||
struct sensor_device_attribute *a;
|
||||
struct pmbus_sensor *sensor;
|
||||
int err;
|
||||
|
||||
sensor = devm_kzalloc(data->dev, sizeof(*sensor), GFP_KERNEL);
|
||||
if (!sensor)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
return NULL;
|
||||
a = &sensor->attribute;
|
||||
|
||||
if (type)
|
||||
|
|
@ -1583,17 +1574,14 @@ static struct pmbus_sensor *pmbus_add_sensor(struct pmbus_data *data,
|
|||
pmbus_set_sensor, -1);
|
||||
|
||||
if (pmbus_add_attribute(data, &a->dev_attr.attr))
|
||||
return ERR_PTR(-ENOMEM);
|
||||
return NULL;
|
||||
|
||||
sensor->next = data->sensors;
|
||||
data->sensors = sensor;
|
||||
|
||||
/* temperature sensors with _input values are registered with thermal */
|
||||
if (class == PSC_TEMPERATURE && strcmp(type, "input") == 0) {
|
||||
err = pmbus_thermal_add_sensor(data, sensor, seq);
|
||||
if (err)
|
||||
return ERR_PTR(err);
|
||||
}
|
||||
if (class == PSC_TEMPERATURE && strcmp(type, "input") == 0)
|
||||
pmbus_thermal_add_sensor(data, sensor, seq);
|
||||
|
||||
return sensor;
|
||||
}
|
||||
|
|
@ -1694,8 +1682,8 @@ static int pmbus_add_limit_attrs(struct i2c_client *client,
|
|||
page, 0xff, l->reg, attr->class,
|
||||
attr->update || l->update,
|
||||
l->readonly, l->writeonly, true);
|
||||
if (IS_ERR(curr))
|
||||
return PTR_ERR(curr);
|
||||
if (!curr)
|
||||
return -ENOMEM;
|
||||
if (l->sbit && (info->func[page] & attr->sfunc)) {
|
||||
ret = pmbus_add_boolean(data, name,
|
||||
l->alarm, index,
|
||||
|
|
@ -1734,8 +1722,8 @@ static int pmbus_add_sensor_attrs_one(struct i2c_client *client,
|
|||
}
|
||||
base = pmbus_add_sensor(data, name, "input", index, page, phase,
|
||||
attr->reg, attr->class, true, true, false, true);
|
||||
if (IS_ERR(base))
|
||||
return PTR_ERR(base);
|
||||
if (!base)
|
||||
return -ENOMEM;
|
||||
/* No limit and alarm attributes for phase specific sensors */
|
||||
if (attr->sfunc && phase == 0xff) {
|
||||
ret = pmbus_add_limit_attrs(client, data, info, name,
|
||||
|
|
@ -2408,8 +2396,8 @@ static int pmbus_add_fan_ctrl(struct i2c_client *client,
|
|||
0xff, PMBUS_VIRT_FAN_TARGET_1 + id, PSC_FAN,
|
||||
false, false, false, true);
|
||||
|
||||
if (IS_ERR(sensor))
|
||||
return PTR_ERR(sensor);
|
||||
if (!sensor)
|
||||
return -ENOMEM;
|
||||
|
||||
if (!((data->info->func[page] & PMBUS_HAVE_PWM12) ||
|
||||
(data->info->func[page] & PMBUS_HAVE_PWM34)))
|
||||
|
|
@ -2419,15 +2407,15 @@ static int pmbus_add_fan_ctrl(struct i2c_client *client,
|
|||
0xff, PMBUS_VIRT_PWM_1 + id, PSC_PWM,
|
||||
false, false, false, true);
|
||||
|
||||
if (IS_ERR(sensor))
|
||||
return PTR_ERR(sensor);
|
||||
if (!sensor)
|
||||
return -ENOMEM;
|
||||
|
||||
sensor = pmbus_add_sensor(data, "pwm", "enable", index, page,
|
||||
0xff, PMBUS_VIRT_PWM_ENABLE_1 + id, PSC_PWM,
|
||||
true, false, false, false);
|
||||
|
||||
if (IS_ERR(sensor))
|
||||
return PTR_ERR(sensor);
|
||||
if (!sensor)
|
||||
return -ENOMEM;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -2444,7 +2432,6 @@ static int pmbus_add_fan_attributes(struct i2c_client *client,
|
|||
int f;
|
||||
|
||||
for (f = 0; f < ARRAY_SIZE(pmbus_fan_registers); f++) {
|
||||
struct pmbus_sensor *sensor;
|
||||
int regval;
|
||||
|
||||
if (!(info->func[page] & pmbus_fan_flags[f]))
|
||||
|
|
@ -2465,11 +2452,10 @@ static int pmbus_add_fan_attributes(struct i2c_client *client,
|
|||
(!(regval & (PB_FAN_1_INSTALLED >> ((f & 1) * 4)))))
|
||||
continue;
|
||||
|
||||
sensor = pmbus_add_sensor(data, "fan", "input", index,
|
||||
page, 0xff, pmbus_fan_registers[f],
|
||||
PSC_FAN, true, true, false, true);
|
||||
if (IS_ERR(sensor))
|
||||
return PTR_ERR(sensor);
|
||||
if (pmbus_add_sensor(data, "fan", "input", index,
|
||||
page, 0xff, pmbus_fan_registers[f],
|
||||
PSC_FAN, true, true, false, true) == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
/* Fan control */
|
||||
if (pmbus_check_word_register(client, page,
|
||||
|
|
|
|||
|
|
@ -351,8 +351,6 @@ static int q54sj108a2_probe(struct i2c_client *client)
|
|||
psu->client = client;
|
||||
|
||||
debugfs = pmbus_get_debugfs_dir(client);
|
||||
if (!debugfs)
|
||||
return 0;
|
||||
|
||||
q54sj108a2_dir = debugfs_create_dir(client->name, debugfs);
|
||||
|
||||
|
|
|
|||
|
|
@ -31,7 +31,6 @@
|
|||
#include <linux/bitrev.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/workqueue.h>
|
||||
|
||||
/* Commands */
|
||||
#define SHT15_MEASURE_TEMP 0x03
|
||||
|
|
@ -977,22 +976,25 @@ static int sht15_probe(struct platform_device *pdev)
|
|||
goto err_release_reg;
|
||||
}
|
||||
|
||||
ret = request_irq(gpiod_to_irq(data->data), sht15_interrupt_fired,
|
||||
IRQF_TRIGGER_FALLING, "sht15 data", data);
|
||||
ret = devm_request_irq(&pdev->dev, gpiod_to_irq(data->data),
|
||||
sht15_interrupt_fired,
|
||||
IRQF_TRIGGER_FALLING,
|
||||
"sht15 data",
|
||||
data);
|
||||
if (ret)
|
||||
goto err_release_reg;
|
||||
disable_irq_nosync(gpiod_to_irq(data->data));
|
||||
ret = sht15_connection_reset(data);
|
||||
if (ret)
|
||||
goto err_free_irq;
|
||||
goto err_release_reg;
|
||||
ret = sht15_soft_reset(data);
|
||||
if (ret)
|
||||
goto err_free_irq;
|
||||
goto err_release_reg;
|
||||
|
||||
ret = sysfs_create_group(&pdev->dev.kobj, &sht15_attr_group);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "sysfs create failed\n");
|
||||
goto err_free_irq;
|
||||
goto err_release_reg;
|
||||
}
|
||||
|
||||
data->hwmon_dev = hwmon_device_register(data->dev);
|
||||
|
|
@ -1005,13 +1007,9 @@ static int sht15_probe(struct platform_device *pdev)
|
|||
|
||||
err_release_sysfs_group:
|
||||
sysfs_remove_group(&pdev->dev.kobj, &sht15_attr_group);
|
||||
err_free_irq:
|
||||
disable_work_sync(&data->read_work);
|
||||
free_irq(gpiod_to_irq(data->data), data);
|
||||
err_release_reg:
|
||||
if (!IS_ERR(data->reg)) {
|
||||
regulator_unregister_notifier(data->reg, &data->nb);
|
||||
cancel_work_sync(&data->update_supply_work);
|
||||
regulator_disable(data->reg);
|
||||
}
|
||||
return ret;
|
||||
|
|
@ -1025,16 +1023,12 @@ static void sht15_remove(struct platform_device *pdev)
|
|||
hwmon_device_unregister(data->hwmon_dev);
|
||||
sysfs_remove_group(&pdev->dev.kobj, &sht15_attr_group);
|
||||
|
||||
disable_work_sync(&data->read_work);
|
||||
free_irq(gpiod_to_irq(data->data), data);
|
||||
|
||||
ret = sht15_soft_reset(data);
|
||||
if (ret)
|
||||
dev_err(&pdev->dev, "Failed to reset device (%pe)\n", ERR_PTR(ret));
|
||||
|
||||
if (!IS_ERR(data->reg)) {
|
||||
regulator_unregister_notifier(data->reg, &data->nb);
|
||||
cancel_work_sync(&data->update_supply_work);
|
||||
regulator_disable(data->reg);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -111,9 +111,7 @@ static int sht4x_read_values(struct sht4x_data *data)
|
|||
}
|
||||
|
||||
if (data->data_pending &&
|
||||
time_before64(get_jiffies_64(),
|
||||
data->heating_complete +
|
||||
msecs_to_jiffies(data->update_interval))) {
|
||||
time_before64(get_jiffies_64(), data->heating_complete + data->update_interval)) {
|
||||
data->data_pending = false;
|
||||
} else {
|
||||
next_update = data->last_updated +
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@
|
|||
#include <linux/i2c.h>
|
||||
#include <linux/i3c/device.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/ktime.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <linux/slab.h>
|
||||
|
|
@ -78,7 +78,7 @@
|
|||
struct tmp108 {
|
||||
struct regmap *regmap;
|
||||
u16 orig_config;
|
||||
ktime_t ready_time;
|
||||
u64 ready_time;
|
||||
const struct tmp108_params *params;
|
||||
};
|
||||
|
||||
|
|
@ -121,7 +121,6 @@ static int tmp108_read(struct device *dev, enum hwmon_sensor_types type,
|
|||
struct tmp108 *tmp108 = dev_get_drvdata(dev);
|
||||
unsigned int regval;
|
||||
int err, hyst;
|
||||
s64 delay;
|
||||
|
||||
if (type == hwmon_chip) {
|
||||
if (attr == hwmon_chip_update_interval) {
|
||||
|
|
@ -138,10 +137,12 @@ static int tmp108_read(struct device *dev, enum hwmon_sensor_types type,
|
|||
|
||||
switch (attr) {
|
||||
case hwmon_temp_input:
|
||||
/* Wait if it is too early to return a conversion */
|
||||
delay = ktime_us_delta(tmp108->ready_time, ktime_get());
|
||||
if (delay > 0)
|
||||
usleep_range(delay, delay + 1000);
|
||||
/* Is it too early to return a conversion ? */
|
||||
if (time_before64(get_jiffies_64(), tmp108->ready_time)) {
|
||||
dev_dbg(dev, "%s: Conversion not ready yet..\n",
|
||||
__func__);
|
||||
return -EAGAIN;
|
||||
}
|
||||
err = regmap_read(tmp108->regmap, TMP108_REG_TEMP, ®val);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
|
@ -476,8 +477,11 @@ static int tmp108_common_probe(struct device *dev, struct regmap *regmap, char *
|
|||
return err;
|
||||
}
|
||||
|
||||
tmp108->ready_time = ktime_add_ms(ktime_get(),
|
||||
TMP108_CONVERSION_TIME_MS);
|
||||
tmp108->ready_time = get_jiffies_64();
|
||||
if ((tmp108->orig_config & TMP108_CONF_MODE_MASK) ==
|
||||
TMP108_MODE_SHUTDOWN)
|
||||
tmp108->ready_time +=
|
||||
msecs_to_jiffies(TMP108_CONVERSION_TIME_MS);
|
||||
|
||||
err = devm_add_action_or_reset(dev, tmp108_restore_config, tmp108);
|
||||
if (err) {
|
||||
|
|
@ -524,8 +528,8 @@ static int tmp108_resume(struct device *dev)
|
|||
|
||||
err = regmap_update_bits(tmp108->regmap, TMP108_REG_CONF,
|
||||
TMP108_CONF_MODE_MASK, TMP108_MODE_CONTINUOUS);
|
||||
tmp108->ready_time = ktime_add_ms(ktime_get(),
|
||||
TMP108_CONVERSION_TIME_MS);
|
||||
tmp108->ready_time = get_jiffies_64() +
|
||||
msecs_to_jiffies(TMP108_CONVERSION_TIME_MS);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1227,12 +1227,12 @@ static int viommu_probe(struct virtio_device *vdev)
|
|||
/* Populate the event queue with buffers */
|
||||
ret = viommu_fill_evtq(viommu);
|
||||
if (ret)
|
||||
goto err_reset_vdev;
|
||||
goto err_free_vqs;
|
||||
|
||||
ret = iommu_device_sysfs_add(&viommu->iommu, dev, NULL, "%s",
|
||||
virtio_bus_name(vdev));
|
||||
if (ret)
|
||||
goto err_reset_vdev;
|
||||
goto err_free_vqs;
|
||||
|
||||
vdev->priv = viommu;
|
||||
|
||||
|
|
@ -1244,8 +1244,6 @@ static int viommu_probe(struct virtio_device *vdev)
|
|||
|
||||
return 0;
|
||||
|
||||
err_reset_vdev:
|
||||
virtio_reset_device(vdev);
|
||||
err_free_vqs:
|
||||
vdev->config->del_vqs(vdev);
|
||||
|
||||
|
|
|
|||
|
|
@ -2779,27 +2779,6 @@ static void bond_miimon_link_change(struct bonding *bond,
|
|||
}
|
||||
}
|
||||
|
||||
static bool bond_miimon_slave_down(struct bonding *bond,
|
||||
struct slave *slave)
|
||||
{
|
||||
if (slave->link_failure_count < UINT_MAX)
|
||||
slave->link_failure_count++;
|
||||
|
||||
bond_set_slave_link_state(slave, BOND_LINK_DOWN,
|
||||
BOND_SLAVE_NOTIFY_NOW);
|
||||
|
||||
if (BOND_MODE(bond) == BOND_MODE_ACTIVEBACKUP ||
|
||||
BOND_MODE(bond) == BOND_MODE_8023AD)
|
||||
bond_set_slave_inactive_flags(slave,
|
||||
BOND_SLAVE_NOTIFY_NOW);
|
||||
|
||||
slave_info(bond->dev, slave->dev, "link status definitely down, disabling slave\n");
|
||||
|
||||
bond_miimon_link_change(bond, slave, BOND_LINK_DOWN);
|
||||
|
||||
return slave == rcu_access_pointer(bond->curr_active_slave);
|
||||
}
|
||||
|
||||
static void bond_miimon_commit(struct bonding *bond)
|
||||
{
|
||||
struct slave *slave, *primary, *active;
|
||||
|
|
@ -2828,22 +2807,10 @@ static void bond_miimon_commit(struct bonding *bond)
|
|||
err = bond_update_speed_duplex(slave);
|
||||
netdev_unlock_ops(slave->dev);
|
||||
if (err && bond_needs_speed_duplex(bond)) {
|
||||
slave->link = BOND_LINK_DOWN;
|
||||
if (net_ratelimit())
|
||||
slave_warn(bond->dev, slave->dev,
|
||||
"failed to get link speed/duplex\n");
|
||||
/* Coming from FAIL/UP, the slave may still be
|
||||
* in use and may be curr_active_slave, so take
|
||||
* it through the full down path. Coming from
|
||||
* DOWN/BACK, it was never brought up, so just
|
||||
* revert it to DOWN.
|
||||
*/
|
||||
if (slave->link == BOND_LINK_FAIL ||
|
||||
slave->link == BOND_LINK_UP) {
|
||||
if (bond_miimon_slave_down(bond, slave))
|
||||
do_failover = true;
|
||||
continue;
|
||||
}
|
||||
slave->link = BOND_LINK_DOWN;
|
||||
continue;
|
||||
}
|
||||
bond_set_slave_link_state(slave, BOND_LINK_UP,
|
||||
|
|
@ -2872,13 +2839,28 @@ static void bond_miimon_commit(struct bonding *bond)
|
|||
continue;
|
||||
|
||||
case BOND_LINK_DOWN:
|
||||
if (bond_miimon_slave_down(bond, slave))
|
||||
if (slave->link_failure_count < UINT_MAX)
|
||||
slave->link_failure_count++;
|
||||
|
||||
bond_set_slave_link_state(slave, BOND_LINK_DOWN,
|
||||
BOND_SLAVE_NOTIFY_NOW);
|
||||
|
||||
if (BOND_MODE(bond) == BOND_MODE_ACTIVEBACKUP ||
|
||||
BOND_MODE(bond) == BOND_MODE_8023AD)
|
||||
bond_set_slave_inactive_flags(slave,
|
||||
BOND_SLAVE_NOTIFY_NOW);
|
||||
|
||||
slave_info(bond->dev, slave->dev, "link status definitely down, disabling slave\n");
|
||||
|
||||
bond_miimon_link_change(bond, slave, BOND_LINK_DOWN);
|
||||
|
||||
if (slave == rcu_access_pointer(bond->curr_active_slave))
|
||||
do_failover = true;
|
||||
|
||||
continue;
|
||||
|
||||
case BOND_LINK_FAIL:
|
||||
case BOND_LINK_BACK:
|
||||
bond_commit_link_state(slave, BOND_SLAVE_NOTIFY_LATER);
|
||||
slave_dbg(bond->dev, slave->dev, "link_new_state %d on slave\n",
|
||||
slave->link_new_state);
|
||||
continue;
|
||||
|
|
@ -2912,6 +2894,8 @@ static void bond_mii_monitor(struct work_struct *work)
|
|||
{
|
||||
struct bonding *bond = container_of(work, struct bonding,
|
||||
mii_work.work);
|
||||
struct list_head *iter;
|
||||
struct slave *slave;
|
||||
unsigned long delay;
|
||||
bool commit;
|
||||
|
||||
|
|
@ -2933,8 +2917,13 @@ static void bond_mii_monitor(struct work_struct *work)
|
|||
goto re_arm;
|
||||
}
|
||||
|
||||
if (commit)
|
||||
if (commit) {
|
||||
bond_for_each_slave(bond, slave, iter) {
|
||||
bond_commit_link_state(slave,
|
||||
BOND_SLAVE_NOTIFY_LATER);
|
||||
}
|
||||
bond_miimon_commit(bond);
|
||||
}
|
||||
|
||||
if (bond->send_peer_notif)
|
||||
bond_peer_notify_may_events(bond, true);
|
||||
|
|
@ -3984,13 +3973,18 @@ static int bond_slave_netdev_event(unsigned long event,
|
|||
case NETDEV_CHANGE:
|
||||
/* For 802.3ad mode only:
|
||||
* Getting invalid Speed/Duplex values here will put slave
|
||||
* in weird state. Mark an up slave as link-fail and let
|
||||
* miimon set it right when correct speed/duplex are available.
|
||||
* in weird state. Mark it as link-fail if the link was
|
||||
* previously up or link-down if it hasn't yet come up, and
|
||||
* let link-monitoring (miimon) set it right when correct
|
||||
* speeds/duplex are available.
|
||||
*/
|
||||
if (bond_update_speed_duplex(slave) &&
|
||||
BOND_MODE(bond) == BOND_MODE_8023AD &&
|
||||
slave->link == BOND_LINK_UP)
|
||||
slave->link = BOND_LINK_FAIL;
|
||||
BOND_MODE(bond) == BOND_MODE_8023AD) {
|
||||
if (slave->last_link_up)
|
||||
slave->link = BOND_LINK_FAIL;
|
||||
else
|
||||
slave->link = BOND_LINK_DOWN;
|
||||
}
|
||||
|
||||
if (BOND_MODE(bond) == BOND_MODE_8023AD)
|
||||
bond_3ad_adapter_speed_duplex_changed(slave);
|
||||
|
|
|
|||
|
|
@ -720,8 +720,7 @@ static int can_changelink(struct net_device *dev, struct nlattr *tb[],
|
|||
return 0;
|
||||
}
|
||||
|
||||
static size_t can_tdc_get_size(const struct net_device *dev,
|
||||
struct data_bittiming_params *dbt_params,
|
||||
static size_t can_tdc_get_size(struct data_bittiming_params *dbt_params,
|
||||
u32 tdc_flags)
|
||||
{
|
||||
bool tdc_manual = tdc_flags & CAN_CTRLMODE_TDC_MANUAL_MASK;
|
||||
|
|
@ -743,8 +742,7 @@ static size_t can_tdc_get_size(const struct net_device *dev,
|
|||
}
|
||||
|
||||
if (tdc_flags) {
|
||||
if (tdc_manual ||
|
||||
(dbt_params->do_get_auto_tdcv && netif_running(dev)))
|
||||
if (tdc_manual || dbt_params->do_get_auto_tdcv)
|
||||
size += nla_total_size(sizeof(u32)); /* IFLA_CAN_TDCV */
|
||||
size += nla_total_size(sizeof(u32)); /* IFLA_CAN_TDCO */
|
||||
if (dbt_params->tdc_const->tdcf_max)
|
||||
|
|
@ -754,8 +752,7 @@ static size_t can_tdc_get_size(const struct net_device *dev,
|
|||
return size;
|
||||
}
|
||||
|
||||
static size_t can_data_bittiming_get_size(const struct net_device *dev,
|
||||
struct data_bittiming_params *dbt_params,
|
||||
static size_t can_data_bittiming_get_size(struct data_bittiming_params *dbt_params,
|
||||
u32 tdc_flags)
|
||||
{
|
||||
size_t size = 0;
|
||||
|
|
@ -767,7 +764,7 @@ static size_t can_data_bittiming_get_size(const struct net_device *dev,
|
|||
if (dbt_params->data_bitrate_const) /* IFLA_CAN_{,XL}_DATA_BITRATE_CONST */
|
||||
size += nla_total_size(sizeof(*dbt_params->data_bitrate_const) *
|
||||
dbt_params->data_bitrate_const_cnt);
|
||||
size += can_tdc_get_size(dev, dbt_params, tdc_flags);/* IFLA_CAN_{,XL}_TDC */
|
||||
size += can_tdc_get_size(dbt_params, tdc_flags);/* IFLA_CAN_{,XL}_TDC */
|
||||
|
||||
return size;
|
||||
}
|
||||
|
|
@ -815,7 +812,7 @@ static size_t can_get_size(const struct net_device *dev)
|
|||
size += nla_total_size(sizeof(u32)); /* IFLA_CAN_STATE */
|
||||
size += nla_total_size(sizeof(struct can_ctrlmode)); /* IFLA_CAN_CTRLMODE */
|
||||
size += nla_total_size(sizeof(u32)); /* IFLA_CAN_RESTART_MS */
|
||||
if (priv->do_get_berr_counter && netif_running(dev)) /* IFLA_CAN_BERR_COUNTER */
|
||||
if (priv->do_get_berr_counter) /* IFLA_CAN_BERR_COUNTER */
|
||||
size += nla_total_size(sizeof(struct can_berr_counter));
|
||||
if (priv->termination_const) {
|
||||
size += nla_total_size(sizeof(priv->termination)); /* IFLA_CAN_TERMINATION */
|
||||
|
|
@ -828,10 +825,10 @@ static size_t can_get_size(const struct net_device *dev)
|
|||
size += sizeof(priv->bitrate_max); /* IFLA_CAN_BITRATE_MAX */
|
||||
size += can_ctrlmode_ext_get_size(); /* IFLA_CAN_CTRLMODE_EXT */
|
||||
|
||||
size += can_data_bittiming_get_size(dev, &priv->fd,
|
||||
size += can_data_bittiming_get_size(&priv->fd,
|
||||
priv->ctrlmode & CAN_CTRLMODE_FD_TDC_MASK);
|
||||
|
||||
size += can_data_bittiming_get_size(dev, &priv->xl,
|
||||
size += can_data_bittiming_get_size(&priv->xl,
|
||||
priv->ctrlmode & CAN_CTRLMODE_XL_TDC_MASK);
|
||||
size += can_pwm_get_size(priv->xl.pwm_const, /* IFLA_CAN_XL_PWM */
|
||||
priv->ctrlmode & CAN_CTRLMODE_XL_TMS);
|
||||
|
|
@ -913,7 +910,7 @@ static int can_tdc_fill_info(struct sk_buff *skb, const struct net_device *dev,
|
|||
if (tdc_manual) {
|
||||
tdcv = tdc->tdcv;
|
||||
err = 0;
|
||||
} else if (dbt_params->do_get_auto_tdcv && netif_running(dev)) {
|
||||
} else if (dbt_params->do_get_auto_tdcv) {
|
||||
err = dbt_params->do_get_auto_tdcv(dev, &tdcv);
|
||||
}
|
||||
if (!err && nla_put_u32(skb, IFLA_CAN_TDC_TDCV, tdcv))
|
||||
|
|
@ -1009,7 +1006,7 @@ static int can_fill_info(struct sk_buff *skb, const struct net_device *dev)
|
|||
nla_put(skb, IFLA_CAN_CTRLMODE, sizeof(cm), &cm) ||
|
||||
nla_put_u32(skb, IFLA_CAN_RESTART_MS, priv->restart_ms) ||
|
||||
|
||||
(priv->do_get_berr_counter && netif_running(dev) &&
|
||||
(priv->do_get_berr_counter &&
|
||||
!priv->do_get_berr_counter(dev, &bec) &&
|
||||
nla_put(skb, IFLA_CAN_BERR_COUNTER, sizeof(bec), &bec)) ||
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@
|
|||
* Copyright (C) 2008-2009 Wolfgang Grandegger <wg@grandegger.com>
|
||||
*/
|
||||
|
||||
#include <linux/can/can-ml.h>
|
||||
#include <linux/can/dev.h>
|
||||
#include <linux/module.h>
|
||||
#include <net/can.h>
|
||||
|
|
@ -55,7 +54,6 @@ int can_put_echo_skb(struct sk_buff *skb, struct net_device *dev,
|
|||
if (idx >= priv->echo_skb_max) {
|
||||
netdev_err(dev, "%s: BUG! Trying to access can_priv::echo_skb out of bounds (%u/max %u)\n",
|
||||
__func__, idx, priv->echo_skb_max);
|
||||
dev_kfree_skb_any(skb);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
|
@ -64,7 +62,7 @@ int can_put_echo_skb(struct sk_buff *skb, struct net_device *dev,
|
|||
(skb->protocol != htons(ETH_P_CAN) &&
|
||||
skb->protocol != htons(ETH_P_CANFD) &&
|
||||
skb->protocol != htons(ETH_P_CANXL))) {
|
||||
dev_kfree_skb_any(skb);
|
||||
kfree_skb(skb);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -92,7 +90,7 @@ int can_put_echo_skb(struct sk_buff *skb, struct net_device *dev,
|
|||
} else {
|
||||
/* locking problem with netif_stop_queue() ?? */
|
||||
netdev_err(dev, "%s: BUG! echo_skb %d is occupied!\n", __func__, idx);
|
||||
dev_kfree_skb_any(skb);
|
||||
kfree_skb(skb);
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
|
|
@ -229,7 +227,7 @@ struct sk_buff *alloc_can_skb(struct net_device *dev, struct can_frame **cf)
|
|||
|
||||
csx = can_skb_ext_add(skb);
|
||||
if (!csx) {
|
||||
dev_kfree_skb_any(skb);
|
||||
kfree_skb(skb);
|
||||
goto out_error_cc;
|
||||
}
|
||||
|
||||
|
|
@ -260,7 +258,7 @@ struct sk_buff *alloc_canfd_skb(struct net_device *dev,
|
|||
|
||||
csx = can_skb_ext_add(skb);
|
||||
if (!csx) {
|
||||
dev_kfree_skb_any(skb);
|
||||
kfree_skb(skb);
|
||||
goto out_error_fd;
|
||||
}
|
||||
|
||||
|
|
@ -298,7 +296,7 @@ struct sk_buff *alloc_canxl_skb(struct net_device *dev,
|
|||
|
||||
csx = can_skb_ext_add(skb);
|
||||
if (!csx) {
|
||||
dev_kfree_skb_any(skb);
|
||||
kfree_skb(skb);
|
||||
goto out_error_xl;
|
||||
}
|
||||
|
||||
|
|
@ -390,7 +388,7 @@ bool can_dropped_invalid_skb(struct net_device *dev, struct sk_buff *skb)
|
|||
break;
|
||||
|
||||
case ETH_P_CANXL:
|
||||
if (!can_cap_enabled(dev, CAN_CAP_XL) || !can_is_canxl_skb(skb))
|
||||
if (!can_is_canxl_skb(skb))
|
||||
goto inval_skb;
|
||||
break;
|
||||
|
||||
|
|
@ -404,7 +402,7 @@ bool can_dropped_invalid_skb(struct net_device *dev, struct sk_buff *skb)
|
|||
return false;
|
||||
|
||||
inval_skb:
|
||||
dev_kfree_skb_any(skb);
|
||||
kfree_skb(skb);
|
||||
dev->stats.tx_dropped++;
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -755,7 +755,7 @@ static int pcan_usb_fd_decode_buf(struct peak_usb_device *dev, struct urb *urb)
|
|||
u16 rx_msg_type, rx_msg_size;
|
||||
size_t rx_msg_min_size;
|
||||
|
||||
if (msg_end - msg_ptr < sizeof(rx_msg->size)) {
|
||||
if (msg_end - msg_ptr < sizeof(*rx_msg)) {
|
||||
err = -EBADMSG;
|
||||
break;
|
||||
}
|
||||
|
|
@ -766,11 +766,6 @@ static int pcan_usb_fd_decode_buf(struct peak_usb_device *dev, struct urb *urb)
|
|||
break;
|
||||
}
|
||||
|
||||
if (msg_end - msg_ptr < sizeof(*rx_msg)) {
|
||||
err = -EBADMSG;
|
||||
break;
|
||||
}
|
||||
|
||||
rx_msg_size = le16_to_cpu(rx_msg->size);
|
||||
rx_msg_type = le16_to_cpu(rx_msg->type);
|
||||
|
||||
|
|
|
|||
|
|
@ -836,59 +836,6 @@ void b53_brcm_hdr_setup(struct dsa_switch *ds, int port)
|
|||
}
|
||||
EXPORT_SYMBOL(b53_brcm_hdr_setup);
|
||||
|
||||
int b53_enable_mcast_snooping(struct b53_device *dev)
|
||||
{
|
||||
u16 val16;
|
||||
u32 val;
|
||||
int ret;
|
||||
|
||||
/* Older switches use different IGMP controls, not HL_PRTC_CTRL. */
|
||||
if (is5325(dev) || is5365(dev) || dev->chip_id == BCM5389_DEVICE_ID ||
|
||||
is5397_98(dev) || is63xx(dev))
|
||||
return 0;
|
||||
|
||||
/* IGMPv2 and MLDv1 reports use the group's destination MAC. Once
|
||||
* the first listener is offloaded, ordinary multicast forwarding
|
||||
* can keep subsequent reports from reaching the bridge CPU.
|
||||
*/
|
||||
|
||||
/* BCM5395 has a narrower register and a single IGMP classifier.
|
||||
* Its ICMPv6 classifier also covers MLD.
|
||||
*/
|
||||
if (dev->chip_id == BCM5395_DEVICE_ID) {
|
||||
ret = b53_read16(dev, B53_MGMT_PAGE, B53_HL_PRTC_CTRL, &val16);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
val16 |= HL_PRTC_IGMP_IP_EN_5395 | HL_PRTC_ICMPV6_EN;
|
||||
/* Zero forwarding modes copy control traffic to the CPU
|
||||
* independently of the ARL lookup, retaining L2 forwarding.
|
||||
*/
|
||||
val16 &= ~(HL_PRTC_IGMP_FWD_MODE_5395 |
|
||||
HL_PRTC_ICMPV6_FWD_MODE);
|
||||
|
||||
return b53_write16(dev, B53_MGMT_PAGE, B53_HL_PRTC_CTRL,
|
||||
val16);
|
||||
}
|
||||
|
||||
ret = b53_read32(dev, B53_MGMT_PAGE, B53_HL_PRTC_CTRL, &val);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
val |= HL_PRTC_IGMP_RPTLVE_EN | HL_PRTC_IGMP_QRY_EN |
|
||||
HL_PRTC_IGMP_UKN_EN | HL_PRTC_MLD_RPTDONE_EN |
|
||||
HL_PRTC_MLD_QRY_EN;
|
||||
/* Zero forwarding modes copy control traffic to the CPU
|
||||
* independently of the ARL lookup, retaining L2 forwarding.
|
||||
*/
|
||||
val &= ~(HL_PRTC_IGMP_RPTLVE_FWD_MODE | HL_PRTC_IGMP_QRY_FWD_MODE |
|
||||
HL_PRTC_IGMP_UKN_FWD_MODE | HL_PRTC_MLD_RPTDONE_FWD_MODE |
|
||||
HL_PRTC_MLD_QRY_FWD_MODE);
|
||||
|
||||
return b53_write32(dev, B53_MGMT_PAGE, B53_HL_PRTC_CTRL, val);
|
||||
}
|
||||
EXPORT_SYMBOL(b53_enable_mcast_snooping);
|
||||
|
||||
static void b53_enable_cpu_port(struct b53_device *dev, int port)
|
||||
{
|
||||
u8 port_ctrl;
|
||||
|
|
@ -1387,10 +1334,6 @@ static int b53_setup(struct dsa_switch *ds)
|
|||
b53_disable_port(ds, port);
|
||||
}
|
||||
|
||||
ret = b53_enable_mcast_snooping(dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return b53_setup_devlink_resources(ds);
|
||||
}
|
||||
|
||||
|
|
@ -1720,15 +1663,9 @@ static void b53_phylink_mac_link_up(struct phylink_config *config,
|
|||
}
|
||||
|
||||
if (mode == MLO_AN_FIXED) {
|
||||
/* Force flow control and 2Gbits/sec on BCM5301x and NSP CPU
|
||||
* ports
|
||||
*/
|
||||
if ((is5301x(dev) || dev->chip_id == BCM58XX_DEVICE_ID) &&
|
||||
dsa_is_cpu_port(ds, port)) {
|
||||
tx_pause = true;
|
||||
rx_pause = true;
|
||||
speed = 2000;
|
||||
}
|
||||
/* Force flow control on BCM5301x's CPU port */
|
||||
if (is5301x(dev) && dsa_is_cpu_port(ds, port))
|
||||
tx_pause = rx_pause = true;
|
||||
|
||||
b53_force_port_config(dev, port, speed, duplex,
|
||||
tx_pause, rx_pause);
|
||||
|
|
|
|||
|
|
@ -504,7 +504,6 @@ static inline struct gpio_desc *b53_switch_get_reset_gpio(struct b53_device *dev
|
|||
/* Exported functions towards other drivers */
|
||||
void b53_imp_vlan_setup(struct dsa_switch *ds, int cpu_port);
|
||||
int b53_configure_vlan(struct dsa_switch *ds);
|
||||
int b53_enable_mcast_snooping(struct b53_device *dev);
|
||||
void b53_get_strings(struct dsa_switch *ds, int port, u32 stringset,
|
||||
uint8_t *data);
|
||||
void b53_get_ethtool_stats(struct dsa_switch *ds, int port, uint64_t *data);
|
||||
|
|
|
|||
|
|
@ -274,23 +274,6 @@
|
|||
/* Revision ID register (8 bit) */
|
||||
#define B53_REV_ID 0x40
|
||||
|
||||
/* High-level protocol control (16 bit on BCM5395, otherwise 32 bit) */
|
||||
#define B53_HL_PRTC_CTRL 0x50
|
||||
#define HL_PRTC_ICMPV6_EN BIT(4)
|
||||
#define HL_PRTC_ICMPV6_FWD_MODE BIT(5)
|
||||
#define HL_PRTC_IGMP_IP_EN_5395 BIT(6)
|
||||
#define HL_PRTC_IGMP_FWD_MODE_5395 BIT(8)
|
||||
#define HL_PRTC_IGMP_RPTLVE_EN BIT(9)
|
||||
#define HL_PRTC_IGMP_RPTLVE_FWD_MODE BIT(10)
|
||||
#define HL_PRTC_IGMP_QRY_EN BIT(11)
|
||||
#define HL_PRTC_IGMP_QRY_FWD_MODE BIT(12)
|
||||
#define HL_PRTC_IGMP_UKN_EN BIT(13)
|
||||
#define HL_PRTC_IGMP_UKN_FWD_MODE BIT(14)
|
||||
#define HL_PRTC_MLD_RPTDONE_EN BIT(15)
|
||||
#define HL_PRTC_MLD_RPTDONE_FWD_MODE BIT(16)
|
||||
#define HL_PRTC_MLD_QRY_EN BIT(17)
|
||||
#define HL_PRTC_MLD_QRY_FWD_MODE BIT(18)
|
||||
|
||||
/* Broadcom header RX control (16 bit) */
|
||||
#define B53_BRCM_HDR_RX_DIS 0x60
|
||||
|
||||
|
|
|
|||
|
|
@ -1059,7 +1059,6 @@ static int bcm_sf2_sw_setup(struct dsa_switch *ds)
|
|||
{
|
||||
struct bcm_sf2_priv *priv = bcm_sf2_to_priv(ds);
|
||||
unsigned int port;
|
||||
int ret;
|
||||
|
||||
/* Enable all valid ports and disable those unused */
|
||||
for (port = 0; port < priv->hw_params.num_ports; port++) {
|
||||
|
|
@ -1075,10 +1074,6 @@ static int bcm_sf2_sw_setup(struct dsa_switch *ds)
|
|||
b53_configure_vlan(ds);
|
||||
bcm_sf2_enable_acb(ds);
|
||||
|
||||
ret = b53_enable_mcast_snooping(priv->dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return b53_setup_devlink_resources(ds);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1934,39 +1934,6 @@ static int atl1c_clean_rx(struct napi_struct *napi, int budget)
|
|||
break;
|
||||
}
|
||||
atl1c_clean_rfd(rfd_ring, rrs, rfd_num);
|
||||
|
||||
/* A link partner whose l2mtu is larger than ours can hand us a
|
||||
* frame that does not fit the buffer the hardware was given:
|
||||
* the descriptor reports the untruncated length while at most
|
||||
* buffer_info->length bytes were written. skb_put() of such a
|
||||
* length would pull in whatever the tail of the buffer holds
|
||||
* and, past the end of the skb, trips skb_over_panic and takes
|
||||
* the host down. Bound it by what the device actually wrote
|
||||
* rather than by skb_tailroom(): the skb carries 64 bytes of
|
||||
* slack for the DMA erratum, so the two are not the same.
|
||||
*
|
||||
* Frames shorter than an Ethernet header plus its FCS are
|
||||
* rejected by the same test; before this, a length below
|
||||
* ETH_FCS_LEN underflowed in skb_put().
|
||||
*/
|
||||
if (unlikely(length < ETH_HLEN + ETH_FCS_LEN ||
|
||||
length > buffer_info->length)) {
|
||||
dev_core_stats_rx_dropped_inc(netdev);
|
||||
if (netif_msg_rx_err(adapter))
|
||||
dev_warn_ratelimited(&pdev->dev,
|
||||
"dropped rx frame: %u bytes, buffer %u\n",
|
||||
length, buffer_info->length);
|
||||
kfree_skb_reason(skb, SKB_DROP_REASON_PKT_TOO_BIG);
|
||||
/* atl1c_clean_rfd() has already recycled the RFD, so
|
||||
* count the drop as work: the refill at the end of the
|
||||
* poll only runs when work_done is non-zero, and
|
||||
* sustained oversized traffic would otherwise drain the
|
||||
* ring and stop RX for good.
|
||||
*/
|
||||
work_done++;
|
||||
continue;
|
||||
}
|
||||
|
||||
skb_put(skb, length - ETH_FCS_LEN);
|
||||
skb->protocol = eth_type_trans(skb, netdev);
|
||||
atl1c_rx_checksum(adapter, skb, rrs);
|
||||
|
|
|
|||
|
|
@ -243,8 +243,7 @@ static int bgmac_probe(struct platform_device *pdev)
|
|||
bgmac->phy_connect = platform_phy_connect;
|
||||
} else {
|
||||
bgmac->phy_connect = bgmac_phy_connect_direct;
|
||||
if (of_machine_is_compatible("brcm,nsp"))
|
||||
bgmac->feature_flags |= BGMAC_FEAT_FORCE_SPEED_2500;
|
||||
bgmac->feature_flags |= BGMAC_FEAT_FORCE_SPEED_2500;
|
||||
}
|
||||
|
||||
return bgmac_enet_probe(bgmac);
|
||||
|
|
|
|||
|
|
@ -1430,15 +1430,11 @@ void bgmac_adjust_link(struct net_device *net_dev)
|
|||
{
|
||||
struct bgmac *bgmac = netdev_priv(net_dev);
|
||||
struct phy_device *phy_dev = net_dev->phydev;
|
||||
int speed = phy_dev->speed;
|
||||
bool update = false;
|
||||
|
||||
if (bgmac->feature_flags & BGMAC_FEAT_FORCE_SPEED_2500)
|
||||
speed = SPEED_2500;
|
||||
|
||||
if (phy_dev->link) {
|
||||
if (speed != bgmac->mac_speed) {
|
||||
bgmac->mac_speed = speed;
|
||||
if (phy_dev->speed != bgmac->mac_speed) {
|
||||
bgmac->mac_speed = phy_dev->speed;
|
||||
update = true;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -11544,7 +11544,6 @@ static int bnxt_change_msix(struct bnxt *bp, int total)
|
|||
map.index = i - 1;
|
||||
map.virq = bp->irq_tbl[i - 1].vector;
|
||||
pci_msix_free_irq(bp->pdev, map);
|
||||
bp->irq_tbl[i - 1].vector = 0;
|
||||
bp->total_irqs--;
|
||||
}
|
||||
return bp->total_irqs;
|
||||
|
|
@ -11722,23 +11721,8 @@ int bnxt_reserve_rings(struct bnxt *bp, bool irq_re_init)
|
|||
int irqs_required;
|
||||
int rc;
|
||||
|
||||
if (!bnxt_need_reserve_rings(bp)) {
|
||||
/* FW may already hold the reservation from an earlier
|
||||
* reservation that was not followed by growing the dynamic
|
||||
* MSI-X vectors, e.g. because the allocation failed.
|
||||
*/
|
||||
if (irq_re_init && BNXT_NEW_RM(bp) && bp->irq_tbl &&
|
||||
pci_msix_can_alloc_dyn(bp->pdev)) {
|
||||
irqs_required = bnxt_get_num_msix(bp);
|
||||
if (irqs_required > bp->total_irqs &&
|
||||
bnxt_change_msix(bp, irqs_required) != irqs_required) {
|
||||
netdev_err(bp->dev, "Unable to allocate %d MSIX vectors, maximum available %d\n",
|
||||
irqs_required, bp->total_irqs);
|
||||
return -ENOSPC;
|
||||
}
|
||||
}
|
||||
if (!bnxt_need_reserve_rings(bp))
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (BNXT_NEW_RM(bp) && !bnxt_ulp_registered(edev)) {
|
||||
int ulp_msix = bnxt_get_avail_msix(bp, bp->ulp_num_msix_want);
|
||||
|
|
@ -11764,10 +11748,6 @@ int bnxt_reserve_rings(struct bnxt *bp, bool irq_re_init)
|
|||
rc = bnxt_init_int_mode(bp);
|
||||
bnxt_ulp_irq_restart(bp, rc);
|
||||
} else if (irq_change && !rc) {
|
||||
/* Size the vectors from what FW actually reserved, which
|
||||
* can be less than what was requested.
|
||||
*/
|
||||
irqs_required = bnxt_get_num_msix(bp);
|
||||
if (bnxt_change_msix(bp, irqs_required) != irqs_required)
|
||||
rc = -ENOSPC;
|
||||
}
|
||||
|
|
@ -15133,7 +15113,6 @@ int bnxt_check_rings(struct bnxt *bp, int tx, int rx, bool sh, int tcs,
|
|||
hwr.cp = min_t(int, hwr.cp, bnxt_get_max_func_irqs(bp));
|
||||
}
|
||||
if (hwr.cp > bp->total_irqs) {
|
||||
int old_total = bp->total_irqs;
|
||||
int total_msix = bnxt_change_msix(bp, hwr.cp);
|
||||
|
||||
if (total_msix < hwr.cp) {
|
||||
|
|
@ -15141,17 +15120,6 @@ int bnxt_check_rings(struct bnxt *bp, int tx, int rx, bool sh, int tcs,
|
|||
hwr.cp, total_msix);
|
||||
rc = -ENOSPC;
|
||||
}
|
||||
/* FW has not reserved the new vectors yet, and writes to
|
||||
* MSI-X table entries beyond the reserved IRQs don't
|
||||
* stick (seen on BCM57508). Free them again;
|
||||
* bnxt_reserve_rings() allocates them after
|
||||
* __bnxt_reserve_rings(). Without the new resource
|
||||
* manager there is no IRQ reservation and
|
||||
* bnxt_reserve_rings() does not grow the vectors, so
|
||||
* keep them.
|
||||
*/
|
||||
if (BNXT_NEW_RM(bp))
|
||||
bnxt_change_msix(bp, old_total);
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
|
|
|
|||
|
|
@ -1502,8 +1502,7 @@ jme_intr_msi(struct jme_adapter *jme, u32 intrstat)
|
|||
* all other events are ignored
|
||||
*/
|
||||
jwrite32(jme, JME_IEVE, intrstat);
|
||||
if (!test_bit(JME_FLAG_WOL_QUIESCE, &jme->flags))
|
||||
schedule_work(&jme->linkch_task);
|
||||
schedule_work(&jme->linkch_task);
|
||||
goto out_reenable;
|
||||
}
|
||||
|
||||
|
|
@ -1547,8 +1546,7 @@ jme_intr_msi(struct jme_adapter *jme, u32 intrstat)
|
|||
/*
|
||||
* Re-enable interrupt
|
||||
*/
|
||||
if (!test_bit(JME_FLAG_WOL_QUIESCE, &jme->flags))
|
||||
jwrite32f(jme, JME_IENS, INTR_ENABLE);
|
||||
jwrite32f(jme, JME_IENS, INTR_ENABLE);
|
||||
}
|
||||
|
||||
static irqreturn_t
|
||||
|
|
@ -1894,7 +1892,6 @@ jme_powersave_phy(struct jme_adapter *jme)
|
|||
jme_set_100m_half(jme);
|
||||
if (jme->reg_pmcs & (PMCS_LFEN | PMCS_LREN))
|
||||
jme_wait_link(jme);
|
||||
jme_mac_rxclk_on(jme);
|
||||
jme_clear_pm_enable_wol(jme);
|
||||
} else {
|
||||
jme_phy_off(jme);
|
||||
|
|
@ -3161,21 +3158,6 @@ jme_shutdown(struct pci_dev *pdev)
|
|||
struct net_device *netdev = pci_get_drvdata(pdev);
|
||||
struct jme_adapter *jme = netdev_priv(netdev);
|
||||
|
||||
if (netif_running(netdev)) {
|
||||
set_bit(JME_FLAG_WOL_QUIESCE, &jme->flags);
|
||||
netif_device_detach(netdev);
|
||||
netif_stop_queue(netdev);
|
||||
jme_stop_irq(jme);
|
||||
synchronize_irq(pdev->irq);
|
||||
jme_stop_irq(jme);
|
||||
cancel_work_sync(&jme->linkch_task);
|
||||
tasklet_disable(&jme->pcc_task);
|
||||
napi_disable(&jme->napi);
|
||||
tasklet_disable(&jme->txclean_task);
|
||||
tasklet_disable(&jme->rxclean_task);
|
||||
tasklet_disable(&jme->rxempty_task);
|
||||
}
|
||||
|
||||
jme_powersave_phy(jme);
|
||||
pci_pme_active(pdev, true);
|
||||
}
|
||||
|
|
@ -3190,16 +3172,11 @@ jme_suspend(struct device *dev)
|
|||
if (!netif_running(netdev))
|
||||
return 0;
|
||||
|
||||
set_bit(JME_FLAG_WOL_QUIESCE, &jme->flags);
|
||||
atomic_dec(&jme->link_changing);
|
||||
|
||||
netif_device_detach(netdev);
|
||||
netif_stop_queue(netdev);
|
||||
jme_stop_irq(jme);
|
||||
synchronize_irq(jme->pdev->irq);
|
||||
jme_stop_irq(jme);
|
||||
cancel_work_sync(&jme->linkch_task);
|
||||
tasklet_disable(&jme->pcc_task);
|
||||
napi_disable(&jme->napi);
|
||||
atomic_dec(&jme->link_changing);
|
||||
|
||||
tasklet_disable(&jme->txclean_task);
|
||||
tasklet_disable(&jme->rxclean_task);
|
||||
|
|
@ -3238,7 +3215,6 @@ jme_resume(struct device *dev)
|
|||
return 0;
|
||||
|
||||
jme_clear_pm_disable_wol(jme);
|
||||
jme_mac_rxclk_off(jme);
|
||||
jme_phy_on(jme);
|
||||
if (test_bit(JME_FLAG_SSET, &jme->flags))
|
||||
jme_set_link_ksettings(netdev, &jme->old_cmd);
|
||||
|
|
@ -3250,11 +3226,8 @@ jme_resume(struct device *dev)
|
|||
|
||||
atomic_inc(&jme->link_changing);
|
||||
|
||||
napi_enable(&jme->napi);
|
||||
tasklet_enable(&jme->pcc_task);
|
||||
clear_bit(JME_FLAG_WOL_QUIESCE, &jme->flags);
|
||||
|
||||
jme_reset_link(jme);
|
||||
|
||||
jme_start_irq(jme);
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -450,7 +450,6 @@ enum jme_flags_bits {
|
|||
JME_FLAG_SSET = 2,
|
||||
JME_FLAG_POLL = 5,
|
||||
JME_FLAG_SHUTDOWN = 6,
|
||||
JME_FLAG_WOL_QUIESCE = 7,
|
||||
};
|
||||
|
||||
#define TX_TIMEOUT (5 * HZ)
|
||||
|
|
|
|||
|
|
@ -754,7 +754,8 @@ void __mtk_ppe_check_skb(struct mtk_ppe *ppe, struct sk_buff *skb, u16 hash)
|
|||
|
||||
hlist_for_each_entry_safe(entry, n, head, list) {
|
||||
if (entry->type == MTK_FLOW_TYPE_L2_SUBFLOW) {
|
||||
if (entry->hash != hash)
|
||||
if (unlikely(FIELD_GET(MTK_FOE_IB1_STATE, hwe->ib1) ==
|
||||
MTK_FOE_STATE_BIND))
|
||||
continue;
|
||||
|
||||
entry->hash = 0xffff;
|
||||
|
|
@ -763,7 +764,7 @@ void __mtk_ppe_check_skb(struct mtk_ppe *ppe, struct sk_buff *skb, u16 hash)
|
|||
}
|
||||
|
||||
if (found || !mtk_flow_entry_match(ppe->eth, entry, hwe)) {
|
||||
if (entry->hash == hash)
|
||||
if (entry->hash != 0xffff)
|
||||
entry->hash = 0xffff;
|
||||
continue;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -257,7 +257,7 @@ mtk_wdma_rx_reset(struct mtk_wed_device *dev)
|
|||
wdma_w32(dev, MTK_WDMA_RESET_IDX, 0);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(dev->rx_wdma); i++) {
|
||||
if (!dev->rx_wdma[i].desc)
|
||||
if (dev->rx_wdma[i].desc)
|
||||
continue;
|
||||
|
||||
wdma_w32(dev,
|
||||
|
|
@ -949,14 +949,6 @@ mtk_wed_free_ring(struct mtk_wed_device *dev, struct mtk_wed_ring *ring)
|
|||
static void
|
||||
mtk_wed_free_rx_rings(struct mtk_wed_device *dev)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(dev->rx_ring); i++)
|
||||
mtk_wed_free_ring(dev, &dev->rx_ring[i]);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(dev->tx_wdma); i++)
|
||||
mtk_wed_free_ring(dev, &dev->tx_wdma[i]);
|
||||
|
||||
mtk_wed_free_rx_buffer(dev);
|
||||
mtk_wed_free_ring(dev, &dev->rro.ring);
|
||||
}
|
||||
|
|
@ -1946,7 +1938,7 @@ mtk_wed_wdma_tx_ring_setup(struct mtk_wed_device *dev, int idx, int size,
|
|||
wdma_w32(dev, MTK_WDMA_RING_TX(idx) + MTK_WED_RING_OFS_CPU_IDX, 0);
|
||||
wdma_w32(dev, MTK_WDMA_RING_TX(idx) + MTK_WED_RING_OFS_DMA_IDX, 0);
|
||||
|
||||
if (!mtk_wed_is_v3_or_greater(dev->hw) && reset)
|
||||
if (reset)
|
||||
mtk_wed_ring_reset(wdma, MTK_WED_WDMA_RING_SIZE, true);
|
||||
|
||||
if (!idx) {
|
||||
|
|
@ -2345,20 +2337,7 @@ mtk_wed_start(struct mtk_wed_device *dev, u32 irq_mask)
|
|||
|
||||
for (i = 0; i < ARRAY_SIZE(dev->rx_wdma); i++)
|
||||
if (!dev->rx_wdma[i].desc)
|
||||
if (mtk_wed_wdma_rx_ring_setup(dev, i, 16, false)) {
|
||||
dev_err(dev->hw->dev, "wdma rx ring %d setup failed\n", i);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* non-DBDC MT7986 allocates only rx_ring[1] and tx_wdma[1] during setup
|
||||
* but tx_wdma[0] is also needed for WED to function.
|
||||
*/
|
||||
if (mtk_wed_is_v2(dev->hw) && !dev->rx_ring[0].desc)
|
||||
if (mtk_wed_wdma_tx_ring_setup(dev, 0, MTK_WED_WDMA_RING_SIZE, !!dev->tx_wdma[0].desc)) {
|
||||
dev_err(dev->hw->dev, "wdma tx ring 0 setup failed\n");
|
||||
return;
|
||||
}
|
||||
mtk_wed_wdma_rx_ring_setup(dev, i, 16, false);
|
||||
|
||||
if (dev->wlan.hw_rro) {
|
||||
for (i = 0; i < MTK_WED_RX_PAGE_QUEUES; i++) {
|
||||
|
|
|
|||
|
|
@ -94,7 +94,6 @@ struct mlx5_fs_id {
|
|||
refcount_t refcnt;
|
||||
sci_t sci;
|
||||
struct rhash_head hash;
|
||||
struct rcu_head rcu;
|
||||
};
|
||||
|
||||
struct mlx5_macsec_device {
|
||||
|
|
@ -685,7 +684,7 @@ static void macsec_fs_id_del(struct list_head *macsec_devices_list, u32 fs_id,
|
|||
|
||||
xa_erase(fs_id_xa, fs_id);
|
||||
|
||||
kfree_rcu(fs_id_found, rcu);
|
||||
kfree(fs_id_found);
|
||||
|
||||
if (macsec_fs_is_macsec_device_empty(macsec_device)) {
|
||||
list_del(&macsec_device->macsec_devices_list_entry);
|
||||
|
|
|
|||
|
|
@ -2072,7 +2072,7 @@ static int fbnic_alloc_rx_qt_resources(struct fbnic_net *fbn,
|
|||
|
||||
fbnic_bdq_set_page_size(&qt->sub1, rx_page_size);
|
||||
|
||||
err = xdp_rxq_info_reg(&qt->xdp_rxq, fbn->netdev, qt->cmpl.q_idx,
|
||||
err = xdp_rxq_info_reg(&qt->xdp_rxq, fbn->netdev, qt->sub0.q_idx,
|
||||
nv->napi.napi_id);
|
||||
if (err)
|
||||
goto free_page_pools;
|
||||
|
|
|
|||
|
|
@ -353,12 +353,6 @@ static void lan966x_fdma_tx_clear_buf(struct lan966x *lan966x, int weight)
|
|||
if (!fdma_db_is_done(db))
|
||||
continue;
|
||||
|
||||
/* XDP and page pool APIs can't be used with a budget of 0.
|
||||
* Leave these buffers for the next NAPI poll.
|
||||
*/
|
||||
if (!weight && !dcb_buf->use_skb)
|
||||
continue;
|
||||
|
||||
dcb_buf->dev->stats.tx_packets++;
|
||||
dcb_buf->dev->stats.tx_bytes += dcb_buf->len;
|
||||
|
||||
|
|
|
|||
|
|
@ -204,10 +204,9 @@ static void sparx5_ptp_classify(struct sparx5_port *port, struct sk_buff *skb,
|
|||
*rew_op = IFH_REW_OP_TWO_STEP_PTP;
|
||||
}
|
||||
|
||||
static unsigned int sparx5_ptp_txtstamp_old_release(struct sparx5_port *port)
|
||||
static void sparx5_ptp_txtstamp_old_release(struct sparx5_port *port)
|
||||
{
|
||||
struct sk_buff *skb, *skb_tmp;
|
||||
unsigned int purged = 0;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&port->tx_skbs.lock, flags);
|
||||
|
|
@ -218,11 +217,8 @@ static unsigned int sparx5_ptp_txtstamp_old_release(struct sparx5_port *port)
|
|||
|
||||
__skb_unlink(skb, &port->tx_skbs);
|
||||
dev_kfree_skb_any(skb);
|
||||
purged++;
|
||||
}
|
||||
spin_unlock_irqrestore(&port->tx_skbs.lock, flags);
|
||||
|
||||
return purged;
|
||||
}
|
||||
|
||||
int sparx5_ptp_txtstamp_request(struct sparx5_port *port,
|
||||
|
|
@ -230,7 +226,6 @@ int sparx5_ptp_txtstamp_request(struct sparx5_port *port,
|
|||
{
|
||||
struct sparx5 *sparx5 = port->sparx5;
|
||||
u8 rew_op, pdu_type, pdu_w16_offset;
|
||||
unsigned int purged;
|
||||
unsigned long flags;
|
||||
|
||||
sparx5_ptp_classify(port, skb, &rew_op, &pdu_type, &pdu_w16_offset);
|
||||
|
|
@ -241,10 +236,9 @@ int sparx5_ptp_txtstamp_request(struct sparx5_port *port,
|
|||
if (rew_op != IFH_REW_OP_TWO_STEP_PTP)
|
||||
return 0;
|
||||
|
||||
purged = sparx5_ptp_txtstamp_old_release(port);
|
||||
sparx5_ptp_txtstamp_old_release(port);
|
||||
|
||||
spin_lock_irqsave(&sparx5->ptp_ts_id_lock, flags);
|
||||
sparx5->ptp_skbs -= purged;
|
||||
if (sparx5->ptp_skbs == SPARX5_MAX_PTP_ID) {
|
||||
spin_unlock_irqrestore(&sparx5->ptp_ts_id_lock, flags);
|
||||
return -EBUSY;
|
||||
|
|
|
|||
|
|
@ -757,27 +757,6 @@ void mana_gd_free_service_wq(struct gdma_context *gc)
|
|||
gc->service_wq = NULL;
|
||||
}
|
||||
|
||||
static void mana_gd_schedule_eq_cqs(struct gdma_queue *eq)
|
||||
{
|
||||
struct gdma_context *gc = eq->gdma_dev->gdma_context;
|
||||
struct gdma_queue *cq;
|
||||
u8 i;
|
||||
|
||||
for (i = 0; i < GDMA_EQ_MAX_CHILD_CQ; i++) {
|
||||
cq = rcu_dereference(eq->eq.child_cq[i]);
|
||||
|
||||
if (!cq)
|
||||
continue;
|
||||
|
||||
if (cq->id >= READ_ONCE(gc->max_num_cqs) ||
|
||||
!gc->cq_table || gc->cq_table[cq->id] != cq)
|
||||
continue;
|
||||
|
||||
if (cq->cq.callback)
|
||||
cq->cq.callback(cq->cq.context, cq);
|
||||
}
|
||||
}
|
||||
|
||||
static void mana_gd_process_eqe(struct gdma_queue *eq)
|
||||
{
|
||||
u32 head = eq->head % (eq->queue_size / GDMA_EQE_SIZE);
|
||||
|
|
@ -808,14 +787,6 @@ static void mana_gd_process_eqe(struct gdma_queue *eq)
|
|||
|
||||
break;
|
||||
|
||||
case GDMA_EQE_THROTTLE:
|
||||
u64_stats_update_begin(&eq->eq.stats.syncp);
|
||||
u64_stats_inc(&eq->eq.stats.throttle_count);
|
||||
u64_stats_update_end(&eq->eq.stats.syncp);
|
||||
|
||||
mana_gd_schedule_eq_cqs(eq);
|
||||
break;
|
||||
|
||||
case GDMA_EQE_TEST_EVENT:
|
||||
gc->test_event_eq_id = eq->id;
|
||||
complete(&gc->eq_test_event);
|
||||
|
|
@ -1061,8 +1032,6 @@ static int mana_gd_create_eq(struct gdma_dev *gd,
|
|||
queue->eq.msix_index = INVALID_PCI_MSIX_INDEX;
|
||||
queue->id = INVALID_QUEUE_ID;
|
||||
|
||||
u64_stats_init(&queue->eq.stats.syncp);
|
||||
|
||||
log2_num_entries = ilog2(queue->queue_size / GDMA_EQE_SIZE);
|
||||
|
||||
if (spec->eq.log2_throttle_limit > log2_num_entries) {
|
||||
|
|
@ -1104,66 +1073,25 @@ static void mana_gd_create_cq(const struct gdma_queue_spec *spec,
|
|||
struct gdma_queue *queue)
|
||||
{
|
||||
u32 log2_num_entries = ilog2(spec->queue_size / GDMA_CQE_SIZE);
|
||||
struct gdma_queue *parent;
|
||||
u8 i;
|
||||
|
||||
queue->head |= INITIALIZED_OWNER_BIT(log2_num_entries);
|
||||
parent = spec->cq.parent_eq;
|
||||
queue->cq.parent = parent;
|
||||
queue->cq.parent = spec->cq.parent_eq;
|
||||
queue->cq.context = spec->cq.context;
|
||||
queue->cq.callback = spec->cq.callback;
|
||||
|
||||
if (!parent)
|
||||
return;
|
||||
|
||||
/* For throttled EQE store the child CQ */
|
||||
for (i = 0; i < GDMA_EQ_MAX_CHILD_CQ; i++) {
|
||||
if (!rcu_access_pointer(parent->eq.child_cq[i])) {
|
||||
rcu_assign_pointer(parent->eq.child_cq[i], queue);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
WARN_ONCE(1, "mana: EQ %u has no free child CQ slot\n", parent->id);
|
||||
}
|
||||
|
||||
/* Unlink queue from its parent EQ's child_cq[] and from gc->cq_table[].
|
||||
*
|
||||
* Return: true if queue was in the parent EQ's child_cq[]. In that case the
|
||||
* caller must wait for an RCU grace period before freeing queue, because
|
||||
* mana_gd_intr() may still be handling a throttle EQE for it.
|
||||
*/
|
||||
bool mana_gd_detach_cq(struct gdma_context *gc, struct gdma_queue *queue)
|
||||
{
|
||||
struct gdma_queue *eq = queue->cq.parent;
|
||||
bool attached = false;
|
||||
u32 id = queue->id;
|
||||
u8 i;
|
||||
|
||||
if (eq) {
|
||||
for (i = 0; i < GDMA_EQ_MAX_CHILD_CQ; i++) {
|
||||
if (rcu_access_pointer(eq->eq.child_cq[i]) == queue) {
|
||||
RCU_INIT_POINTER(eq->eq.child_cq[i], NULL);
|
||||
attached = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if CQ might have been detached already, only clear if
|
||||
* it still points to same queue .
|
||||
*/
|
||||
if (id < gc->max_num_cqs && READ_ONCE(gc->cq_table[id]) == queue)
|
||||
WRITE_ONCE(gc->cq_table[id], NULL);
|
||||
|
||||
return attached;
|
||||
}
|
||||
|
||||
static void mana_gd_destroy_cq(struct gdma_context *gc,
|
||||
struct gdma_queue *queue)
|
||||
{
|
||||
/* Wait for irq reader holding the cq */
|
||||
if (mana_gd_detach_cq(gc, queue))
|
||||
synchronize_net();
|
||||
u32 id = queue->id;
|
||||
|
||||
if (id >= gc->max_num_cqs)
|
||||
return;
|
||||
|
||||
if (!gc->cq_table[id])
|
||||
return;
|
||||
|
||||
gc->cq_table[id] = NULL;
|
||||
}
|
||||
|
||||
int mana_gd_create_hwc_queue(struct gdma_dev *gd,
|
||||
|
|
|
|||
|
|
@ -364,7 +364,7 @@ static void mana_hwc_comp_event(void *ctx, struct gdma_queue *q_self)
|
|||
|
||||
completions = hwc_cq->comp_buf;
|
||||
comp_read = mana_gd_poll_cq(q_self, completions, hwc_cq->queue_depth);
|
||||
WARN_ON_ONCE(comp_read < 0 || comp_read > hwc_cq->queue_depth);
|
||||
WARN_ON_ONCE(comp_read <= 0 || comp_read > hwc_cq->queue_depth);
|
||||
|
||||
for (i = 0; i < comp_read; ++i) {
|
||||
comp_data = *(struct hwc_rx_oob *)completions[i].cqe_data;
|
||||
|
|
@ -820,14 +820,9 @@ void mana_hwc_destroy_channel(struct gdma_context *gc)
|
|||
*/
|
||||
if (gc->max_num_cqs > 0) {
|
||||
mana_smc_teardown_hwc(&gc->shm_channel, false);
|
||||
WRITE_ONCE(gc->max_num_cqs, 0);
|
||||
gc->max_num_cqs = 0;
|
||||
}
|
||||
|
||||
if (hwc->cq)
|
||||
mana_gd_detach_cq(gc, hwc->cq->gdma_cq);
|
||||
|
||||
synchronize_rcu();
|
||||
|
||||
if (hwc->txq)
|
||||
mana_hwc_destroy_wq(hwc, hwc->txq);
|
||||
|
||||
|
|
|
|||
|
|
@ -2703,7 +2703,6 @@ static void mana_deinit_txq(struct mana_port_context *apc, struct mana_txq *txq)
|
|||
|
||||
static void mana_destroy_txq(struct mana_port_context *apc)
|
||||
{
|
||||
struct gdma_context *gc = apc->ac->gdma_dev->gdma_context;
|
||||
struct napi_struct *napi;
|
||||
int i;
|
||||
|
||||
|
|
@ -2722,6 +2721,8 @@ static void mana_destroy_txq(struct mana_port_context *apc)
|
|||
napi_synchronize(napi);
|
||||
napi_disable_locked(napi);
|
||||
cancel_work_sync(&apc->tx_qp[i]->tx_cq.dim.work);
|
||||
netif_napi_del_locked(napi);
|
||||
apc->tx_qp[i]->txq.napi_initialized = false;
|
||||
}
|
||||
|
||||
/* Forget the SKBs freed without being completed after a drain
|
||||
|
|
@ -2734,18 +2735,6 @@ static void mana_destroy_txq(struct mana_port_context *apc)
|
|||
if (apc->tx_qp[i]->tx_object != INVALID_MANA_HANDLE)
|
||||
mana_destroy_wq_obj(apc, GDMA_SQ, apc->tx_qp[i]->tx_object);
|
||||
|
||||
if (apc->tx_qp[i]->txq.napi_initialized) {
|
||||
/* Detach the CQ only after the WQ object is destroyed,
|
||||
* so a completion EQE that arrives before then still
|
||||
* finds the CQ in cq_table[] rather than hitting the
|
||||
* WARN in mana_gd_process_eqe(). One grace period then
|
||||
* covers both mana_gd_intr() and NAPI users.
|
||||
*/
|
||||
mana_gd_detach_cq(gc, apc->tx_qp[i]->tx_cq.gdma_cq);
|
||||
netif_napi_del_locked(napi);
|
||||
apc->tx_qp[i]->txq.napi_initialized = false;
|
||||
}
|
||||
|
||||
mana_deinit_cq(apc, &apc->tx_qp[i]->tx_cq);
|
||||
|
||||
mana_deinit_txq(apc, &apc->tx_qp[i]->txq);
|
||||
|
|
@ -2952,6 +2941,7 @@ static void mana_destroy_rxq(struct mana_port_context *apc,
|
|||
|
||||
napi_disable_locked(napi);
|
||||
cancel_work_sync(&rxq->rx_cq.dim.work);
|
||||
netif_napi_del_locked(napi);
|
||||
}
|
||||
|
||||
if (xdp_rxq_info_is_reg(&rxq->xdp_rxq))
|
||||
|
|
@ -2960,12 +2950,6 @@ static void mana_destroy_rxq(struct mana_port_context *apc,
|
|||
if (rxq->rxobj != INVALID_MANA_HANDLE)
|
||||
mana_destroy_wq_obj(apc, GDMA_RQ, rxq->rxobj);
|
||||
|
||||
if (napi_initialized) {
|
||||
/* See the comment in mana_destroy_txq() */
|
||||
mana_gd_detach_cq(gc, rxq->rx_cq.gdma_cq);
|
||||
netif_napi_del_locked(napi);
|
||||
}
|
||||
|
||||
mana_deinit_cq(apc, &rxq->rx_cq);
|
||||
|
||||
if (rxq->xdp_save_va)
|
||||
|
|
|
|||
|
|
@ -147,8 +147,7 @@ static int mana_get_sset_count(struct net_device *ndev, int stringset)
|
|||
return ARRAY_SIZE(mana_eth_stats) +
|
||||
ARRAY_SIZE(mana_phy_stats) +
|
||||
ARRAY_SIZE(mana_hc_stats) +
|
||||
num_queues * (MANA_STATS_RX_COUNT + MANA_STATS_TX_COUNT +
|
||||
MANA_STATS_EQ_COUNT);
|
||||
num_queues * (MANA_STATS_RX_COUNT + MANA_STATS_TX_COUNT);
|
||||
|
||||
case ETH_SS_PRIV_FLAGS:
|
||||
return MANA_PRIV_FLAG_MAX;
|
||||
|
|
@ -199,9 +198,6 @@ static void mana_get_strings_stats(struct mana_port_context *apc, u8 **data)
|
|||
ethtool_sprintf(data, "tx_%d_csum_partial", i);
|
||||
ethtool_sprintf(data, "tx_%d_mana_map_err", i);
|
||||
}
|
||||
|
||||
for (i = 0; i < num_queues; i++)
|
||||
ethtool_sprintf(data, "eq_%d_throttle_events", i);
|
||||
}
|
||||
|
||||
static void mana_get_strings_priv_flags(u8 **data)
|
||||
|
|
@ -238,7 +234,6 @@ static void mana_get_ethtool_stats(struct net_device *ndev,
|
|||
void *phy_stats = &apc->phy_stats;
|
||||
struct mana_stats_rx *rx_stats;
|
||||
struct mana_stats_tx *tx_stats;
|
||||
struct gdma_eq_stats *eq_stats;
|
||||
unsigned int start;
|
||||
u64 packets, bytes;
|
||||
u64 xdp_redirect;
|
||||
|
|
@ -256,7 +251,6 @@ static void mana_get_ethtool_stats(struct net_device *ndev,
|
|||
u64 csum_partial;
|
||||
u64 mana_map_err;
|
||||
int q, i = 0, j;
|
||||
u64 throttled;
|
||||
|
||||
if (!apc->port_is_up)
|
||||
return;
|
||||
|
|
@ -331,17 +325,6 @@ static void mana_get_ethtool_stats(struct net_device *ndev,
|
|||
data[i++] = csum_partial;
|
||||
data[i++] = mana_map_err;
|
||||
}
|
||||
|
||||
for (q = 0; q < num_queues; q++) {
|
||||
eq_stats = &apc->eqs[q].eq->eq.stats;
|
||||
|
||||
do {
|
||||
start = u64_stats_fetch_begin(&eq_stats->syncp);
|
||||
throttled = u64_stats_read(&eq_stats->throttle_count);
|
||||
} while (u64_stats_fetch_retry(&eq_stats->syncp, start));
|
||||
|
||||
data[i++] = throttled;
|
||||
}
|
||||
}
|
||||
|
||||
static u32 mana_get_rx_ring_count(struct net_device *ndev)
|
||||
|
|
|
|||
|
|
@ -600,11 +600,11 @@ static irqreturn_t cp_interrupt (int irq, void *dev_instance)
|
|||
goto out_unlock;
|
||||
}
|
||||
|
||||
if (status & (RxOK | RxErr | RxEmpty | RxFIFOOvr)) {
|
||||
cpw16_f(IntrMask, cp_norx_intr_mask);
|
||||
if (napi_schedule_prep(&cp->napi))
|
||||
if (status & (RxOK | RxErr | RxEmpty | RxFIFOOvr))
|
||||
if (napi_schedule_prep(&cp->napi)) {
|
||||
cpw16_f(IntrMask, cp_norx_intr_mask);
|
||||
__napi_schedule(&cp->napi);
|
||||
}
|
||||
}
|
||||
|
||||
if (status & (TxOK | TxErr | TxEmpty | SWInt))
|
||||
cp_tx(cp);
|
||||
|
|
|
|||
|
|
@ -36,7 +36,6 @@
|
|||
#include <linux/errno.h>
|
||||
#include <linux/ktime.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/pps_kernel.h>
|
||||
#include <linux/ptp_clock_kernel.h>
|
||||
#include "net_driver.h"
|
||||
|
|
@ -267,12 +266,11 @@ struct efx_ptp_rxfilter {
|
|||
* @evt_frag_idx: Current fragment number
|
||||
* @evt_code: Last event code
|
||||
* @start: Address at which MC indicates ready for synchronisation
|
||||
* @host_time_pps: Host time at last PPS
|
||||
* @adjfreq_ppb_shift: Shift required to convert scaled parts-per-billion
|
||||
* frequency adjustment into a fixed point fractional nanosecond format.
|
||||
* @current_adjfreq: Current ppb adjustment.
|
||||
* @phc_clock: Pointer to registered phc device (if primary function)
|
||||
* @phc_lock: Serializes PHC commands and synchronization, and protects
|
||||
* @current_adjfreq
|
||||
* @phc_clock_info: Registration structure for phc device
|
||||
* @pps_work: pps work task for handling pps events
|
||||
* @pps_workwq: pps work queue
|
||||
|
|
@ -328,10 +326,10 @@ struct efx_ptp_data {
|
|||
int evt_frag_idx;
|
||||
int evt_code;
|
||||
struct efx_buffer start;
|
||||
struct pps_event_time host_time_pps;
|
||||
unsigned int adjfreq_ppb_shift;
|
||||
s64 current_adjfreq;
|
||||
struct ptp_clock *phc_clock;
|
||||
struct mutex phc_lock;
|
||||
struct ptp_clock_info phc_clock_info;
|
||||
struct work_struct pps_work;
|
||||
struct workqueue_struct *pps_workwq;
|
||||
|
|
@ -909,8 +907,7 @@ static void efx_ptp_read_timeset(MCDI_DECLARE_STRUCT_PTR(data),
|
|||
static int
|
||||
efx_ptp_process_times(struct efx_nic *efx, MCDI_DECLARE_STRUCT_PTR(synch_buf),
|
||||
size_t response_length,
|
||||
const struct pps_event_time *last_time,
|
||||
struct pps_event_time *host_time_pps)
|
||||
const struct pps_event_time *last_time)
|
||||
{
|
||||
unsigned number_readings =
|
||||
MCDI_VAR_ARRAY_LEN(response_length,
|
||||
|
|
@ -988,10 +985,6 @@ efx_ptp_process_times(struct efx_nic *efx, MCDI_DECLARE_STRUCT_PTR(synch_buf),
|
|||
"PTP bad synchronisation seconds\n");
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
if (!host_time_pps)
|
||||
return 0;
|
||||
|
||||
delta.tv_sec = (last_sec - start_sec) & 1;
|
||||
delta.tv_nsec =
|
||||
last_time->ts_real.tv_nsec -
|
||||
|
|
@ -1008,22 +1001,14 @@ efx_ptp_process_times(struct efx_nic *efx, MCDI_DECLARE_STRUCT_PTR(synch_buf),
|
|||
delta.tv_nsec += ktime_to_timespec64(mc_time).tv_nsec;
|
||||
|
||||
/* Set PPS timestamp to match NIC top of second */
|
||||
*host_time_pps = *last_time;
|
||||
pps_sub_ts(host_time_pps, delta);
|
||||
ptp->host_time_pps = *last_time;
|
||||
pps_sub_ts(&ptp->host_time_pps, delta);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Synchronize times between the host and the MC.
|
||||
*
|
||||
* The MC serializes PTP requests, so MC_CMD_PTP_OP_ADJUST cannot be applied
|
||||
* while MC_CMD_PTP_OP_SYNCHRONIZE is collecting timesets. This holds across
|
||||
* functions of a controller, which share the clock but adjust it only through
|
||||
* the function that registered it, so a secondary function can capture here
|
||||
* without serializing against the primary.
|
||||
*/
|
||||
static int efx_ptp_synchronize(struct efx_nic *efx, unsigned int num_readings,
|
||||
struct pps_event_time *host_time_pps)
|
||||
/* Synchronize times between the host and the MC */
|
||||
static int efx_ptp_synchronize(struct efx_nic *efx, unsigned int num_readings)
|
||||
{
|
||||
struct efx_ptp_data *ptp = efx->ptp_data;
|
||||
MCDI_DECLARE_BUF(synch_buf, MC_CMD_PTP_OUT_SYNCHRONIZE_LENMAX);
|
||||
|
|
@ -1041,14 +1026,11 @@ static int efx_ptp_synchronize(struct efx_nic *efx, unsigned int num_readings,
|
|||
MCDI_SET_QWORD(synch_buf, PTP_IN_SYNCHRONIZE_START_ADDR,
|
||||
ptp->start.dma_addr);
|
||||
|
||||
mutex_lock(&ptp->phc_lock);
|
||||
|
||||
/* Clear flag that signals MC ready */
|
||||
WRITE_ONCE(*start, 0);
|
||||
rc = efx_mcdi_rpc_start(efx, MC_CMD_PTP, synch_buf,
|
||||
MC_CMD_PTP_IN_SYNCHRONIZE_LEN);
|
||||
if (rc)
|
||||
goto out;
|
||||
EFX_WARN_ON_ONCE_PARANOID(rc);
|
||||
|
||||
/* Wait for start from MCDI (or timeout) */
|
||||
timeout = jiffies + msecs_to_jiffies(MAX_SYNCHRONISE_WAIT_MS);
|
||||
|
|
@ -1072,20 +1054,18 @@ static int efx_ptp_synchronize(struct efx_nic *efx, unsigned int num_readings,
|
|||
&response_length);
|
||||
if (rc == 0) {
|
||||
rc = efx_ptp_process_times(efx, synch_buf, response_length,
|
||||
&last_time, host_time_pps);
|
||||
&last_time);
|
||||
if (rc == 0)
|
||||
++ptp->good_syncs;
|
||||
else
|
||||
++ptp->no_time_syncs;
|
||||
}
|
||||
|
||||
out:
|
||||
/* Increment the bad syncs counter if the synchronize fails, whatever
|
||||
* the reason.
|
||||
*/
|
||||
if (rc != 0)
|
||||
++ptp->bad_syncs;
|
||||
mutex_unlock(&ptp->phc_lock);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
|
@ -1465,6 +1445,7 @@ static int efx_ptp_start(struct efx_nic *efx)
|
|||
goto fail;
|
||||
|
||||
ptp->evt_frag_idx = 0;
|
||||
ptp->current_adjfreq = 0;
|
||||
|
||||
return 0;
|
||||
|
||||
|
|
@ -1504,15 +1485,14 @@ static void efx_ptp_pps_worker(struct work_struct *work)
|
|||
{
|
||||
struct efx_ptp_data *ptp =
|
||||
container_of(work, struct efx_ptp_data, pps_work);
|
||||
struct pps_event_time host_time_pps = {};
|
||||
struct efx_nic *efx = ptp->efx;
|
||||
struct ptp_clock_event ptp_evt;
|
||||
|
||||
if (efx_ptp_synchronize(efx, PTP_SYNC_ATTEMPTS, &host_time_pps))
|
||||
if (efx_ptp_synchronize(efx, PTP_SYNC_ATTEMPTS))
|
||||
return;
|
||||
|
||||
ptp_evt.type = PTP_CLOCK_PPSUSR;
|
||||
ptp_evt.pps_times = host_time_pps;
|
||||
ptp_evt.pps_times = ptp->host_time_pps;
|
||||
ptp_clock_event(ptp->phc_clock, &ptp_evt);
|
||||
}
|
||||
|
||||
|
|
@ -1589,7 +1569,6 @@ int efx_ptp_probe(struct efx_nic *efx, struct efx_channel *channel)
|
|||
if (!efx->ptp_data)
|
||||
return -ENOMEM;
|
||||
|
||||
mutex_init(&ptp->phc_lock);
|
||||
ptp->efx = efx;
|
||||
ptp->channel = channel;
|
||||
|
||||
|
|
@ -1661,7 +1640,6 @@ int efx_ptp_probe(struct efx_nic *efx, struct efx_channel *channel)
|
|||
efx_nic_free_buffer(efx, &ptp->start);
|
||||
|
||||
fail1:
|
||||
mutex_destroy(&ptp->phc_lock);
|
||||
kfree(efx->ptp_data);
|
||||
efx->ptp_data = NULL;
|
||||
|
||||
|
|
@ -1716,7 +1694,6 @@ void efx_ptp_remove(struct efx_nic *efx)
|
|||
destroy_workqueue(efx->ptp_data->workwq);
|
||||
|
||||
efx_nic_free_buffer(efx, &efx->ptp_data->start);
|
||||
mutex_destroy(&efx->ptp_data->phc_lock);
|
||||
kfree(efx->ptp_data);
|
||||
efx->ptp_data = NULL;
|
||||
}
|
||||
|
|
@ -1848,8 +1825,7 @@ int efx_ptp_change_mode(struct efx_nic *efx, bool enable_wanted,
|
|||
rc = efx_ptp_start(efx);
|
||||
if (rc == 0) {
|
||||
rc = efx_ptp_synchronize(efx,
|
||||
PTP_SYNC_ATTEMPTS * 2,
|
||||
NULL);
|
||||
PTP_SYNC_ATTEMPTS * 2);
|
||||
if (rc != 0)
|
||||
efx_ptp_stop(efx);
|
||||
}
|
||||
|
|
@ -2129,23 +2105,23 @@ static int efx_phc_adjfine(struct ptp_clock_info *ptp, long scaled_ppm)
|
|||
MCDI_SET_QWORD(inadj, PTP_IN_ADJUST_FREQ, adjustment_ns);
|
||||
MCDI_SET_DWORD(inadj, PTP_IN_ADJUST_SECONDS, 0);
|
||||
MCDI_SET_DWORD(inadj, PTP_IN_ADJUST_NANOSECONDS, 0);
|
||||
mutex_lock(&ptp_data->phc_lock);
|
||||
rc = efx_mcdi_rpc(efx, MC_CMD_PTP, inadj, sizeof(inadj),
|
||||
NULL, 0, NULL);
|
||||
if (!rc)
|
||||
ptp_data->current_adjfreq = adjustment_ns;
|
||||
mutex_unlock(&ptp_data->phc_lock);
|
||||
return rc;
|
||||
if (rc != 0)
|
||||
return rc;
|
||||
|
||||
ptp_data->current_adjfreq = adjustment_ns;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _efx_phc_adjtime(struct efx_ptp_data *ptp_data, s64 delta)
|
||||
__must_hold(&ptp_data->phc_lock)
|
||||
static int efx_phc_adjtime(struct ptp_clock_info *ptp, s64 delta)
|
||||
{
|
||||
MCDI_DECLARE_BUF(inbuf, MC_CMD_PTP_IN_ADJUST_LEN);
|
||||
struct efx_nic *efx = ptp_data->efx;
|
||||
u32 nic_major, nic_minor;
|
||||
|
||||
lockdep_assert_held(&ptp_data->phc_lock);
|
||||
struct efx_ptp_data *ptp_data = container_of(ptp,
|
||||
struct efx_ptp_data,
|
||||
phc_clock_info);
|
||||
struct efx_nic *efx = ptp_data->efx;
|
||||
MCDI_DECLARE_BUF(inbuf, MC_CMD_PTP_IN_ADJUST_LEN);
|
||||
|
||||
efx->ptp_data->ns_to_nic_time(delta, &nic_major, &nic_minor);
|
||||
|
||||
|
|
@ -2158,18 +2134,6 @@ static int _efx_phc_adjtime(struct efx_ptp_data *ptp_data, s64 delta)
|
|||
NULL, 0, NULL);
|
||||
}
|
||||
|
||||
static int efx_phc_adjtime(struct ptp_clock_info *ptp, s64 delta)
|
||||
{
|
||||
struct efx_ptp_data *ptp_data = container_of(ptp, struct efx_ptp_data,
|
||||
phc_clock_info);
|
||||
int rc;
|
||||
|
||||
mutex_lock(&ptp_data->phc_lock);
|
||||
rc = _efx_phc_adjtime(ptp_data, delta);
|
||||
mutex_unlock(&ptp_data->phc_lock);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int efx_phc_gettime(struct ptp_clock_info *ptp, struct timespec64 *ts)
|
||||
{
|
||||
struct efx_ptp_data *ptp_data = container_of(ptp,
|
||||
|
|
@ -2201,21 +2165,23 @@ static int efx_phc_settime(struct ptp_clock_info *ptp,
|
|||
{
|
||||
/* Get the current NIC time, efx_phc_gettime.
|
||||
* Subtract from the desired time to get the offset
|
||||
* call _efx_phc_adjtime with the offset
|
||||
* call efx_phc_adjtime with the offset
|
||||
*/
|
||||
struct efx_ptp_data *ptp_data = container_of(ptp, struct efx_ptp_data,
|
||||
phc_clock_info);
|
||||
struct timespec64 time_now, delta;
|
||||
int rc;
|
||||
struct timespec64 time_now;
|
||||
struct timespec64 delta;
|
||||
|
||||
mutex_lock(&ptp_data->phc_lock);
|
||||
rc = efx_phc_gettime(ptp, &time_now);
|
||||
if (!rc) {
|
||||
delta = timespec64_sub(*e_ts, time_now);
|
||||
rc = _efx_phc_adjtime(ptp_data, timespec64_to_ns(&delta));
|
||||
}
|
||||
mutex_unlock(&ptp_data->phc_lock);
|
||||
return rc;
|
||||
if (rc != 0)
|
||||
return rc;
|
||||
|
||||
delta = timespec64_sub(*e_ts, time_now);
|
||||
|
||||
rc = efx_phc_adjtime(ptp, timespec64_to_ns(&delta));
|
||||
if (rc != 0)
|
||||
return rc;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int efx_phc_enable(struct ptp_clock_info *ptp,
|
||||
|
|
|
|||
|
|
@ -205,7 +205,7 @@ static int enh_desc_get_rx_status(struct stmmac_extra_stats *x,
|
|||
|
||||
if (unlikely(!(rdes0 & RDES0_LAST_DESCRIPTOR))) {
|
||||
x->rx_length++;
|
||||
return discard_frame | rx_not_ls;
|
||||
return discard_frame;
|
||||
}
|
||||
|
||||
if (unlikely(rdes0 & RDES0_ERROR_SUMMARY)) {
|
||||
|
|
|
|||
|
|
@ -620,7 +620,7 @@ struct stmmac_mmc_ops {
|
|||
|
||||
struct stmmac_est_ops {
|
||||
int (*configure)(struct stmmac_priv *priv, struct stmmac_est *cfg,
|
||||
unsigned int ptp_rate, bool enable);
|
||||
unsigned int ptp_rate);
|
||||
void (*irq_status)(struct stmmac_priv *priv, struct net_device *dev,
|
||||
struct stmmac_extra_stats *x, u32 txqcnt);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -70,7 +70,7 @@ static int ndesc_get_rx_status(struct stmmac_extra_stats *x,
|
|||
|
||||
if (unlikely(!(rdes0 & RDES0_LAST_DESCRIPTOR))) {
|
||||
x->rx_length++;
|
||||
return discard_frame | rx_not_ls;
|
||||
return discard_frame;
|
||||
}
|
||||
|
||||
if (unlikely(rdes0 & RDES0_ERROR_SUMMARY)) {
|
||||
|
|
|
|||
|
|
@ -239,7 +239,6 @@ struct stmmac_est {
|
|||
u32 gcl[EST_GCL];
|
||||
u32 gcl_size;
|
||||
u32 max_sdu[MTL_MAX_TX_QUEUES];
|
||||
u32 pclass;
|
||||
};
|
||||
|
||||
struct stmmac_msi {
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ static int est_write(void __iomem *est_addr, u32 reg, u32 val, bool gcl)
|
|||
}
|
||||
|
||||
static int est_configure(struct stmmac_priv *priv, struct stmmac_est *cfg,
|
||||
unsigned int ptp_rate, bool enable)
|
||||
unsigned int ptp_rate)
|
||||
{
|
||||
void __iomem *est_addr = priv->estaddr;
|
||||
int i, ret = 0;
|
||||
|
|
@ -62,7 +62,7 @@ static int est_configure(struct stmmac_priv *priv, struct stmmac_est *cfg,
|
|||
ctrl |= ((NSEC_PER_SEC / ptp_rate) * EST_GMAC5_PTOV_MUL) <<
|
||||
EST_GMAC5_PTOV_SHIFT;
|
||||
}
|
||||
if (enable)
|
||||
if (cfg->enable)
|
||||
ctrl |= EST_EEST | EST_SSWL | EST_DFBS;
|
||||
else
|
||||
ctrl &= ~EST_EEST;
|
||||
|
|
@ -70,7 +70,7 @@ static int est_configure(struct stmmac_priv *priv, struct stmmac_est *cfg,
|
|||
writel(ctrl, est_addr + EST_CONTROL);
|
||||
|
||||
/* Configure EST interrupt */
|
||||
if (enable)
|
||||
if (cfg->enable)
|
||||
ctrl = EST_IECGCE | EST_IEHS | EST_IEHF | EST_IEBE | EST_IECC;
|
||||
else
|
||||
ctrl = 0;
|
||||
|
|
@ -80,61 +80,6 @@ static int est_configure(struct stmmac_priv *priv, struct stmmac_est *cfg,
|
|||
return 0;
|
||||
}
|
||||
|
||||
int __stmmac_setup_est(struct stmmac_priv *priv)
|
||||
{
|
||||
struct timespec64 current_time, time;
|
||||
ktime_t current_time_ns, basetime;
|
||||
u64 cycle_time;
|
||||
int err;
|
||||
|
||||
lockdep_assert_held(&priv->est_lock);
|
||||
|
||||
priv->ptp_clock_ops.gettimex64(&priv->ptp_clock_ops, ¤t_time,
|
||||
NULL);
|
||||
current_time_ns = timespec64_to_ktime(current_time);
|
||||
|
||||
time.tv_nsec = priv->est->btr_reserve[0];
|
||||
time.tv_sec = priv->est->btr_reserve[1];
|
||||
basetime = timespec64_to_ktime(time);
|
||||
|
||||
cycle_time = (u64)priv->est->ctr[1] * NSEC_PER_SEC + priv->est->ctr[0];
|
||||
|
||||
time = stmmac_calc_tas_basetime(basetime, current_time_ns, cycle_time);
|
||||
priv->est->btr[0] = (u32)time.tv_nsec;
|
||||
priv->est->btr[1] = (u32)time.tv_sec;
|
||||
|
||||
err = stmmac_est_configure(priv, priv, priv->est,
|
||||
priv->plat->clk_ptp_rate, true);
|
||||
if (err) {
|
||||
netdev_err(priv->dev, "failed to re-configure EST\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int stmmac_setup_est(struct stmmac_priv *priv)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (!priv->ptp_enabled)
|
||||
return 0;
|
||||
|
||||
mutex_lock(&priv->est_lock);
|
||||
if (priv->est && priv->est->enable) {
|
||||
ret = __stmmac_setup_est(priv);
|
||||
if (ret)
|
||||
goto unlock;
|
||||
|
||||
ret = stmmac_fpe_map_preemption_class(priv, priv->dev, NULL,
|
||||
priv->est->pclass);
|
||||
}
|
||||
unlock:
|
||||
mutex_unlock(&priv->est_lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void est_irq_status(struct stmmac_priv *priv, struct net_device *dev,
|
||||
struct stmmac_extra_stats *x, u32 txqcnt)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -4,9 +4,6 @@
|
|||
* stmmac EST(802.3 Qbv) handling
|
||||
*/
|
||||
|
||||
#ifndef __STMMAC_EST_H__
|
||||
#define __STMMAC_EST_H__
|
||||
|
||||
#define EST_GMAC4_OFFSET 0x00000c50
|
||||
#define EST_XGMAC_OFFSET 0x00001050
|
||||
|
||||
|
|
@ -68,8 +65,3 @@
|
|||
#define EST_GCL_DATA 0x00000034
|
||||
|
||||
extern const struct stmmac_est_ops dwmac510_est_ops;
|
||||
|
||||
int __stmmac_setup_est(struct stmmac_priv *priv);
|
||||
int stmmac_setup_est(struct stmmac_priv *priv);
|
||||
|
||||
#endif /* __STMMAC_EST_H__ */
|
||||
|
|
|
|||
|
|
@ -48,7 +48,6 @@
|
|||
#include "stmmac_ptp.h"
|
||||
#include "stmmac_fpe.h"
|
||||
#include "stmmac.h"
|
||||
#include "stmmac_est.h"
|
||||
#include "stmmac_pcs.h"
|
||||
#include "stmmac_xdp.h"
|
||||
#include <linux/reset.h>
|
||||
|
|
@ -2183,9 +2182,6 @@ static void __free_dma_rx_desc_resources(struct stmmac_priv *priv,
|
|||
else
|
||||
dma_free_rx_skbufs(priv, dma_conf, queue);
|
||||
|
||||
dev_kfree_skb_any(rx_q->state.skb);
|
||||
rx_q->state.skb = NULL;
|
||||
rx_q->state_saved = false;
|
||||
rx_q->buf_alloc_num = 0;
|
||||
rx_q->xsk_pool = NULL;
|
||||
|
||||
|
|
@ -4205,10 +4201,6 @@ static int __stmmac_open(struct net_device *dev,
|
|||
if (ret)
|
||||
goto ptp_error;
|
||||
|
||||
ret = stmmac_setup_est(priv);
|
||||
if (ret)
|
||||
goto est_error;
|
||||
|
||||
stmmac_init_coalesce(priv);
|
||||
|
||||
phylink_start(priv->phylink);
|
||||
|
|
@ -4232,7 +4224,7 @@ static int __stmmac_open(struct net_device *dev,
|
|||
|
||||
for (chan = 0; chan < priv->plat->tx_queues_to_use; chan++)
|
||||
hrtimer_cancel(&priv->dma_conf.tx_queue[chan].txtimer);
|
||||
est_error:
|
||||
|
||||
stmmac_release_ptp(priv);
|
||||
ptp_error:
|
||||
stmmac_stop_all_dma(priv);
|
||||
|
|
@ -5107,35 +5099,22 @@ static netdev_features_t stmmac_features_check(struct sk_buff *skb,
|
|||
return vlan_features_check(skb, features);
|
||||
}
|
||||
|
||||
static int stmmac_rx_vlan(struct net_device *dev, struct sk_buff *skb)
|
||||
static void stmmac_rx_vlan(struct net_device *dev, struct sk_buff *skb)
|
||||
{
|
||||
struct vlan_ethhdr *veth;
|
||||
struct vlan_ethhdr *veth = skb_vlan_eth_hdr(skb);
|
||||
__be16 vlan_proto = veth->h_vlan_proto;
|
||||
u16 vlanid;
|
||||
|
||||
if (!pskb_may_pull(skb, ETH_HLEN))
|
||||
return -EINVAL;
|
||||
|
||||
veth = skb_vlan_eth_hdr(skb);
|
||||
if ((veth->h_vlan_proto == htons(ETH_P_8021Q) &&
|
||||
if ((vlan_proto == htons(ETH_P_8021Q) &&
|
||||
dev->features & NETIF_F_HW_VLAN_CTAG_RX) ||
|
||||
(veth->h_vlan_proto == htons(ETH_P_8021AD) &&
|
||||
(vlan_proto == htons(ETH_P_8021AD) &&
|
||||
dev->features & NETIF_F_HW_VLAN_STAG_RX)) {
|
||||
__be16 vlan_proto = veth->h_vlan_proto;
|
||||
u8 meta_len = skb_metadata_len(skb);
|
||||
u16 vlanid;
|
||||
|
||||
/* pop the vlan tag */
|
||||
if (!pskb_may_pull(skb, VLAN_ETH_HLEN))
|
||||
return -EINVAL;
|
||||
|
||||
veth = skb_vlan_eth_hdr(skb);
|
||||
vlanid = ntohs(veth->h_vlan_TCI);
|
||||
memmove(skb->data - meta_len + VLAN_HLEN,
|
||||
skb->data - meta_len, meta_len + ETH_ALEN * 2);
|
||||
memmove(skb->data + VLAN_HLEN, veth, ETH_ALEN * 2);
|
||||
skb_pull(skb, VLAN_HLEN);
|
||||
__vlan_hwaccel_put_tag(skb, vlan_proto, vlanid);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool stmmac_rx_need_ic(struct stmmac_priv *priv,
|
||||
|
|
@ -5537,8 +5516,7 @@ static struct sk_buff *stmmac_construct_skb_zc(struct stmmac_channel *ch,
|
|||
return NULL;
|
||||
|
||||
skb_reserve(skb, xdp->data - xdp->data_hard_start);
|
||||
__skb_put(skb, datasize);
|
||||
memcpy(skb->data - metasize, xdp->data_meta, datasize + metasize);
|
||||
memcpy(__skb_put(skb, datasize), xdp->data, datasize);
|
||||
if (metasize)
|
||||
skb_metadata_set(skb, metasize);
|
||||
|
||||
|
|
@ -5564,15 +5542,12 @@ static void stmmac_dispatch_skb_zc(struct stmmac_priv *priv, u32 queue,
|
|||
}
|
||||
|
||||
stmmac_get_rx_hwtstamp(priv, p, np, skb);
|
||||
if (priv->hw->hw_vlan_en) {
|
||||
if (priv->hw->hw_vlan_en)
|
||||
/* MAC level stripping. */
|
||||
stmmac_rx_hw_vlan(priv, priv->hw, p, skb);
|
||||
} else if (stmmac_rx_vlan(priv->dev, skb)) {
|
||||
dev_kfree_skb_any(skb);
|
||||
priv->xstats.rx_dropped++;
|
||||
return;
|
||||
}
|
||||
|
||||
else
|
||||
/* Driver level stripping. */
|
||||
stmmac_rx_vlan(priv->dev, skb);
|
||||
skb->protocol = eth_type_trans(skb, priv->dev);
|
||||
|
||||
if (unlikely(!coe) || !stmmac_has_ip_ethertype(skb))
|
||||
|
|
@ -5654,12 +5629,12 @@ static int stmmac_rx_zc(struct stmmac_priv *priv, int limit, u32 queue)
|
|||
unsigned int count = 0, error = 0, len = 0;
|
||||
int dirty = stmmac_rx_dirty(priv, queue);
|
||||
unsigned int next_entry = rx_q->cur_rx;
|
||||
bool in_progress = rx_q->state_saved;
|
||||
u32 rx_errors = 0, rx_dropped = 0;
|
||||
unsigned int desc_size;
|
||||
struct bpf_prog *prog;
|
||||
bool failure = false;
|
||||
int xdp_status = 0;
|
||||
int status = 0;
|
||||
|
||||
if (netif_msg_rx_status(priv)) {
|
||||
void *rx_head = stmmac_get_rx_desc(priv, rx_q, 0);
|
||||
|
|
@ -5670,25 +5645,23 @@ static int stmmac_rx_zc(struct stmmac_priv *priv, int limit, u32 queue)
|
|||
stmmac_display_ring(priv, rx_head, priv->dma_conf.dma_rx_size, true,
|
||||
rx_q->dma_rx_phy, desc_size);
|
||||
}
|
||||
|
||||
if (rx_q->state_saved) {
|
||||
error = rx_q->state.error;
|
||||
len = rx_q->state.len;
|
||||
rx_q->state_saved = false;
|
||||
}
|
||||
|
||||
while (count < limit) {
|
||||
struct stmmac_rx_buffer *buf;
|
||||
struct stmmac_xdp_buff *ctx;
|
||||
unsigned int buf1_len = 0;
|
||||
struct dma_desc *np, *p;
|
||||
int entry, status;
|
||||
int entry;
|
||||
int res;
|
||||
|
||||
if (!in_progress) {
|
||||
if (!count && rx_q->state_saved) {
|
||||
error = rx_q->state.error;
|
||||
len = rx_q->state.len;
|
||||
} else {
|
||||
rx_q->state_saved = false;
|
||||
error = 0;
|
||||
len = 0;
|
||||
}
|
||||
|
||||
read_again:
|
||||
if (count >= limit)
|
||||
break;
|
||||
|
|
@ -5727,8 +5700,6 @@ static int stmmac_rx_zc(struct stmmac_priv *priv, int limit, u32 queue)
|
|||
if (!buf->xdp)
|
||||
break;
|
||||
|
||||
in_progress = status & rx_not_ls;
|
||||
|
||||
if (priv->extend_desc) {
|
||||
/* Read the extended status after the own bit */
|
||||
dma_rmb();
|
||||
|
|
@ -5736,21 +5707,18 @@ static int stmmac_rx_zc(struct stmmac_priv *priv, int limit, u32 queue)
|
|||
&rx_q->dma_erx[entry],
|
||||
status);
|
||||
}
|
||||
|
||||
if (unlikely(!error && (status & discard_frame))) {
|
||||
if (unlikely(status == discard_frame)) {
|
||||
xsk_buff_free(buf->xdp);
|
||||
buf->xdp = NULL;
|
||||
dirty++;
|
||||
error = 1;
|
||||
if (!priv->hwts_rx_en)
|
||||
rx_errors++;
|
||||
}
|
||||
|
||||
if (unlikely(error && (status & rx_not_ls)))
|
||||
goto read_again;
|
||||
if (unlikely(error)) {
|
||||
xsk_buff_free(buf->xdp);
|
||||
buf->xdp = NULL;
|
||||
dirty++;
|
||||
|
||||
if (status & rx_not_ls)
|
||||
goto read_again;
|
||||
|
||||
count++;
|
||||
continue;
|
||||
}
|
||||
|
|
@ -5759,9 +5727,8 @@ static int stmmac_rx_zc(struct stmmac_priv *priv, int limit, u32 queue)
|
|||
if (likely(status & rx_not_ls)) {
|
||||
xsk_buff_free(buf->xdp);
|
||||
buf->xdp = NULL;
|
||||
rx_dropped++;
|
||||
error = 1;
|
||||
dirty++;
|
||||
count++;
|
||||
goto read_again;
|
||||
}
|
||||
|
||||
|
|
@ -5809,7 +5776,7 @@ static int stmmac_rx_zc(struct stmmac_priv *priv, int limit, u32 queue)
|
|||
count++;
|
||||
}
|
||||
|
||||
if (in_progress) {
|
||||
if (status & rx_not_ls) {
|
||||
rx_q->state_saved = true;
|
||||
rx_q->state.error = error;
|
||||
rx_q->state.len = len;
|
||||
|
|
@ -5851,10 +5818,9 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit, u32 queue)
|
|||
struct stmmac_rx_queue *rx_q = &priv->dma_conf.rx_queue[queue];
|
||||
struct stmmac_channel *ch = &priv->channel[queue];
|
||||
unsigned int count = 0, error = 0, len = 0;
|
||||
int status = 0, coe = priv->hw->rx_csum;
|
||||
unsigned int next_entry = rx_q->cur_rx;
|
||||
bool in_progress = rx_q->state_saved;
|
||||
enum dma_data_direction dma_dir;
|
||||
int coe = priv->hw->rx_csum;
|
||||
unsigned int desc_size;
|
||||
struct sk_buff *skb = NULL;
|
||||
struct stmmac_xdp_buff ctx;
|
||||
|
|
@ -5874,28 +5840,25 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit, u32 queue)
|
|||
stmmac_display_ring(priv, rx_head, priv->dma_conf.dma_rx_size, true,
|
||||
rx_q->dma_rx_phy, desc_size);
|
||||
}
|
||||
|
||||
if (rx_q->state_saved) {
|
||||
skb = rx_q->state.skb;
|
||||
error = rx_q->state.error;
|
||||
len = rx_q->state.len;
|
||||
rx_q->state.skb = NULL;
|
||||
rx_q->state_saved = false;
|
||||
}
|
||||
|
||||
while (count < limit) {
|
||||
unsigned int buf1_len = 0, buf2_len = 0;
|
||||
enum pkt_hash_types hash_type;
|
||||
struct stmmac_rx_buffer *buf;
|
||||
struct dma_desc *np, *p;
|
||||
int entry, status;
|
||||
int entry;
|
||||
u32 hash;
|
||||
|
||||
if (!in_progress) {
|
||||
if (!count && rx_q->state_saved) {
|
||||
skb = rx_q->state.skb;
|
||||
error = rx_q->state.error;
|
||||
len = rx_q->state.len;
|
||||
} else {
|
||||
rx_q->state_saved = false;
|
||||
skb = NULL;
|
||||
error = 0;
|
||||
len = 0;
|
||||
}
|
||||
|
||||
read_again:
|
||||
if (count >= limit)
|
||||
break;
|
||||
|
|
@ -5924,8 +5887,6 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit, u32 queue)
|
|||
|
||||
prefetch(np);
|
||||
|
||||
in_progress = status & rx_not_ls;
|
||||
|
||||
if (priv->extend_desc) {
|
||||
/* Read the extended status after the own bit */
|
||||
dma_rmb();
|
||||
|
|
@ -5933,26 +5894,21 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit, u32 queue)
|
|||
&rx_q->dma_erx[entry],
|
||||
status);
|
||||
}
|
||||
|
||||
if (unlikely(!error && (status & discard_frame))) {
|
||||
if (unlikely(status == discard_frame)) {
|
||||
page_pool_put_page(rx_q->page_pool, buf->page, 0, true);
|
||||
buf->page = NULL;
|
||||
error = 1;
|
||||
if (!priv->hwts_rx_en)
|
||||
rx_errors++;
|
||||
}
|
||||
|
||||
/* We do not support SG in XDP mode */
|
||||
if (unlikely(!error && (status & rx_not_ls) &&
|
||||
stmmac_xdp_is_enabled(priv))) {
|
||||
rx_dropped++;
|
||||
error = 1;
|
||||
}
|
||||
|
||||
if (unlikely(error && (status & rx_not_ls)))
|
||||
goto read_again;
|
||||
if (unlikely(error)) {
|
||||
if (status & rx_not_ls)
|
||||
goto read_again;
|
||||
|
||||
dev_kfree_skb(skb);
|
||||
goto next;
|
||||
skb = NULL;
|
||||
count++;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Buffer is good. Go on. */
|
||||
|
|
@ -5962,19 +5918,13 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit, u32 queue)
|
|||
buf2_len = stmmac_rx_buf2_len(priv, p, status, len);
|
||||
len += buf2_len;
|
||||
|
||||
/* Drop the packet if it is split over buf1 and buf2 on a
|
||||
* single descriptor if the interface is running in XDP mode.
|
||||
*/
|
||||
if (unlikely(stmmac_xdp_is_enabled(priv) && buf2_len)) {
|
||||
rx_dropped++;
|
||||
goto next;
|
||||
}
|
||||
|
||||
/* ACS is disabled; strip manually. */
|
||||
if (likely(!(status & rx_not_ls)))
|
||||
len -= ETH_FCS_LEN;
|
||||
|
||||
if (!skb) {
|
||||
unsigned int pre_len, sync_len;
|
||||
|
||||
/* Each frame starts here: reset the FCS handling */
|
||||
fcs_stripped = false;
|
||||
|
||||
|
|
@ -5992,32 +5942,55 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit, u32 queue)
|
|||
xdp_prepare_buff(&ctx.xdp, page_address(buf->page),
|
||||
buf->page_offset, buf1_len, true);
|
||||
|
||||
pre_len = ctx.xdp.data_end - ctx.xdp.data_hard_start -
|
||||
buf->page_offset;
|
||||
|
||||
ctx.priv = priv;
|
||||
ctx.desc = p;
|
||||
ctx.ndesc = np;
|
||||
|
||||
skb = stmmac_xdp_run_prog(priv, &ctx.xdp);
|
||||
/* Due xdp_adjust_tail: DMA sync for_device
|
||||
* cover max len CPU touch
|
||||
*/
|
||||
sync_len = ctx.xdp.data_end - ctx.xdp.data_hard_start -
|
||||
buf->page_offset;
|
||||
sync_len = max(sync_len, pre_len);
|
||||
|
||||
/* For Not XDP_PASS verdict */
|
||||
if (IS_ERR(skb)) {
|
||||
unsigned int xdp_res = -PTR_ERR(skb);
|
||||
|
||||
if (xdp_res & STMMAC_XDP_CONSUMED) {
|
||||
page_pool_recycle_direct(rx_q->page_pool,
|
||||
virt_to_head_page(ctx.xdp.data));
|
||||
page_pool_put_page(rx_q->page_pool,
|
||||
virt_to_head_page(ctx.xdp.data),
|
||||
sync_len, true);
|
||||
buf->page = NULL;
|
||||
rx_dropped++;
|
||||
goto next;
|
||||
|
||||
/* Clear skb as it was set as
|
||||
* status by XDP program.
|
||||
*/
|
||||
skb = NULL;
|
||||
|
||||
if (unlikely((status & rx_not_ls)))
|
||||
goto read_again;
|
||||
|
||||
count++;
|
||||
continue;
|
||||
} else if (xdp_res & (STMMAC_XDP_TX |
|
||||
STMMAC_XDP_REDIRECT)) {
|
||||
xdp_status |= xdp_res;
|
||||
buf->page = NULL;
|
||||
goto next;
|
||||
skb = NULL;
|
||||
count++;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!skb) {
|
||||
unsigned int metasize;
|
||||
unsigned int head_pad_len;
|
||||
|
||||
/* XDP program may expand or reduce tail */
|
||||
buf1_len = ctx.xdp.data_end - ctx.xdp.data;
|
||||
|
|
@ -6034,14 +6007,10 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit, u32 queue)
|
|||
}
|
||||
|
||||
/* XDP program may adjust header */
|
||||
skb_reserve(skb,
|
||||
ctx.xdp.data - ctx.xdp.data_hard_start);
|
||||
head_pad_len = ctx.xdp.data - ctx.xdp.data_hard_start;
|
||||
skb_reserve(skb, head_pad_len);
|
||||
skb_put(skb, buf1_len);
|
||||
skb_mark_for_recycle(skb);
|
||||
|
||||
metasize = ctx.xdp.data - ctx.xdp.data_meta;
|
||||
if (metasize)
|
||||
skb_metadata_set(skb, metasize);
|
||||
buf->page = NULL;
|
||||
} else if (buf1_len) {
|
||||
dma_sync_single_for_cpu(priv->device, buf->addr,
|
||||
|
|
@ -6072,20 +6041,20 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit, u32 queue)
|
|||
/* Remove FCS if needed */
|
||||
if (!fcs_stripped && pskb_trim(skb, len)) {
|
||||
dev_kfree_skb_any(skb);
|
||||
skb = NULL;
|
||||
rx_dropped++;
|
||||
goto next;
|
||||
count++;
|
||||
continue;
|
||||
}
|
||||
|
||||
stmmac_get_rx_hwtstamp(priv, p, np, skb);
|
||||
|
||||
if (priv->hw->hw_vlan_en) {
|
||||
if (priv->hw->hw_vlan_en)
|
||||
/* MAC level stripping. */
|
||||
stmmac_rx_hw_vlan(priv, priv->hw, p, skb);
|
||||
} else if (stmmac_rx_vlan(priv->dev, skb)) {
|
||||
dev_kfree_skb_any(skb);
|
||||
rx_dropped++;
|
||||
goto next;
|
||||
}
|
||||
else
|
||||
/* Driver level stripping. */
|
||||
stmmac_rx_vlan(priv->dev, skb);
|
||||
|
||||
skb->protocol = eth_type_trans(skb, priv->dev);
|
||||
|
||||
|
|
@ -6100,15 +6069,14 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit, u32 queue)
|
|||
|
||||
skb_record_rx_queue(skb, queue);
|
||||
napi_gro_receive(&ch->rx_napi, skb);
|
||||
skb = NULL;
|
||||
|
||||
rx_packets++;
|
||||
rx_bytes += len;
|
||||
next:
|
||||
in_progress = false;
|
||||
skb = NULL;
|
||||
count++;
|
||||
}
|
||||
|
||||
if (in_progress || skb) {
|
||||
if (status & rx_not_ls || skb) {
|
||||
rx_q->state_saved = true;
|
||||
rx_q->state.skb = skb;
|
||||
rx_q->state.error = error;
|
||||
|
|
@ -8245,7 +8213,6 @@ static int __stmmac_dvr_probe(struct device *device,
|
|||
stmmac_napi_add(ndev);
|
||||
|
||||
mutex_init(&priv->lock);
|
||||
mutex_init(&priv->est_lock);
|
||||
rwlock_init(&priv->ptp_lock);
|
||||
|
||||
stmmac_fpe_init(priv);
|
||||
|
|
@ -8379,7 +8346,6 @@ void stmmac_dvr_remove(struct device *dev)
|
|||
|
||||
destroy_workqueue(priv->wq);
|
||||
mutex_destroy(&priv->lock);
|
||||
mutex_destroy(&priv->est_lock);
|
||||
bitmap_free(priv->af_xdp_zc_qps);
|
||||
|
||||
pm_runtime_disable(dev);
|
||||
|
|
@ -8455,9 +8421,6 @@ static void stmmac_reset_rx_queue(struct stmmac_priv *priv, u32 queue)
|
|||
{
|
||||
struct stmmac_rx_queue *rx_q = &priv->dma_conf.rx_queue[queue];
|
||||
|
||||
dev_kfree_skb_any(rx_q->state.skb);
|
||||
rx_q->state.skb = NULL;
|
||||
rx_q->state_saved = false;
|
||||
rx_q->cur_rx = 0;
|
||||
rx_q->dirty_rx = 0;
|
||||
}
|
||||
|
|
@ -8562,10 +8525,6 @@ int stmmac_resume(struct device *dev)
|
|||
ret = stmmac_init_timestamping(priv);
|
||||
if (ret)
|
||||
goto error_stop_dma;
|
||||
|
||||
ret = stmmac_setup_est(priv);
|
||||
if (ret)
|
||||
goto error_stop_dma;
|
||||
}
|
||||
|
||||
init_coalesce:
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@
|
|||
Author: Rayagond Kokatanur <rayagond@vayavyalabs.com>
|
||||
*******************************************************************************/
|
||||
#include "stmmac.h"
|
||||
#include "stmmac_est.h"
|
||||
#include "stmmac_ptp.h"
|
||||
|
||||
#define PTP_SAFE_TIME_OFFSET_NS 500000
|
||||
|
|
@ -55,7 +54,8 @@ static int stmmac_adjust_time(struct ptp_clock_info *ptp, s64 delta)
|
|||
u32 sec, nsec;
|
||||
u32 quotient, reminder;
|
||||
int neg_adj = 0;
|
||||
bool xmac;
|
||||
bool xmac, est_rst = false;
|
||||
int ret;
|
||||
|
||||
xmac = dwmac_is_xmac(priv->plat->core_type);
|
||||
|
||||
|
|
@ -69,21 +69,47 @@ static int stmmac_adjust_time(struct ptp_clock_info *ptp, s64 delta)
|
|||
nsec = reminder;
|
||||
|
||||
/* If EST is enabled, disabled it before adjust ptp time. */
|
||||
mutex_lock(&priv->est_lock);
|
||||
if (priv->est && priv->est->enable)
|
||||
if (priv->est && priv->est->enable) {
|
||||
est_rst = true;
|
||||
mutex_lock(&priv->est_lock);
|
||||
priv->est->enable = false;
|
||||
stmmac_est_configure(priv, priv, priv->est,
|
||||
priv->plat->clk_ptp_rate, false);
|
||||
mutex_unlock(&priv->est_lock);
|
||||
priv->plat->clk_ptp_rate);
|
||||
mutex_unlock(&priv->est_lock);
|
||||
}
|
||||
|
||||
write_lock_irqsave(&priv->ptp_lock, flags);
|
||||
stmmac_adjust_systime(priv, priv->ptpaddr, sec, nsec, neg_adj, xmac);
|
||||
write_unlock_irqrestore(&priv->ptp_lock, flags);
|
||||
|
||||
/* Calculate new basetime and re-configured EST after PTP time adjust. */
|
||||
mutex_lock(&priv->est_lock);
|
||||
if (priv->est && priv->est->enable)
|
||||
__stmmac_setup_est(priv);
|
||||
mutex_unlock(&priv->est_lock);
|
||||
if (est_rst) {
|
||||
struct timespec64 current_time, time;
|
||||
ktime_t current_time_ns, basetime;
|
||||
u64 cycle_time;
|
||||
|
||||
mutex_lock(&priv->est_lock);
|
||||
priv->ptp_clock_ops.gettimex64(&priv->ptp_clock_ops,
|
||||
¤t_time, NULL);
|
||||
current_time_ns = timespec64_to_ktime(current_time);
|
||||
time.tv_nsec = priv->est->btr_reserve[0];
|
||||
time.tv_sec = priv->est->btr_reserve[1];
|
||||
basetime = timespec64_to_ktime(time);
|
||||
cycle_time = (u64)priv->est->ctr[1] * NSEC_PER_SEC +
|
||||
priv->est->ctr[0];
|
||||
time = stmmac_calc_tas_basetime(basetime,
|
||||
current_time_ns,
|
||||
cycle_time);
|
||||
|
||||
priv->est->btr[0] = (u32)time.tv_nsec;
|
||||
priv->est->btr[1] = (u32)time.tv_sec;
|
||||
priv->est->enable = true;
|
||||
ret = stmmac_est_configure(priv, priv, priv->est,
|
||||
priv->plat->clk_ptp_rate);
|
||||
mutex_unlock(&priv->est_lock);
|
||||
if (ret)
|
||||
netdev_err(priv->dev, "failed to configure EST\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -966,12 +966,11 @@ static void tc_taprio_map_maxsdu_txq(struct stmmac_priv *priv,
|
|||
static int tc_taprio_configure(struct stmmac_priv *priv,
|
||||
struct tc_taprio_qopt_offload *qopt)
|
||||
{
|
||||
u32 wid = priv->dma_cap.estwid, dep = priv->dma_cap.estdep;
|
||||
u32 size, wid = priv->dma_cap.estwid, dep = priv->dma_cap.estdep;
|
||||
struct netlink_ext_ack *extack = qopt->mqprio.extack;
|
||||
struct timespec64 time, current_time, qopt_time;
|
||||
ktime_t current_time_ns;
|
||||
int err, i, ret = 0;
|
||||
u32 *gcl = NULL;
|
||||
u64 ctr;
|
||||
|
||||
if (qopt->base_time < 0)
|
||||
|
|
@ -1014,46 +1013,44 @@ static int tc_taprio_configure(struct stmmac_priv *priv,
|
|||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
mutex_lock(&priv->est_lock);
|
||||
|
||||
if (qopt->cmd == TAPRIO_CMD_DESTROY)
|
||||
goto disable;
|
||||
|
||||
if (qopt->num_entries > dep) {
|
||||
ret = -EINVAL;
|
||||
goto error_unlock;
|
||||
if (qopt->num_entries > dep)
|
||||
return -EINVAL;
|
||||
if (!qopt->cycle_time)
|
||||
return -ERANGE;
|
||||
if (qopt->cycle_time_extension >= BIT(wid + 7))
|
||||
return -ERANGE;
|
||||
|
||||
if (!priv->est) {
|
||||
priv->est = devm_kzalloc(priv->device, sizeof(*priv->est),
|
||||
GFP_KERNEL);
|
||||
if (!priv->est)
|
||||
return -ENOMEM;
|
||||
|
||||
mutex_init(&priv->est_lock);
|
||||
} else {
|
||||
mutex_lock(&priv->est_lock);
|
||||
memset(priv->est, 0, sizeof(*priv->est));
|
||||
mutex_unlock(&priv->est_lock);
|
||||
}
|
||||
|
||||
if (!qopt->cycle_time ||
|
||||
qopt->cycle_time > (u64)U32_MAX * NSEC_PER_SEC) {
|
||||
ret = -ERANGE;
|
||||
goto error_unlock;
|
||||
}
|
||||
size = qopt->num_entries;
|
||||
|
||||
if (qopt->cycle_time_extension >= BIT(wid + 7)) {
|
||||
ret = -ERANGE;
|
||||
goto error_unlock;
|
||||
}
|
||||
mutex_lock(&priv->est_lock);
|
||||
priv->est->gcl_size = size;
|
||||
priv->est->enable = qopt->cmd == TAPRIO_CMD_REPLACE;
|
||||
mutex_unlock(&priv->est_lock);
|
||||
|
||||
gcl = kcalloc(qopt->num_entries, sizeof(*gcl), GFP_KERNEL);
|
||||
if (!gcl) {
|
||||
ret = -ENOMEM;
|
||||
goto error_unlock;
|
||||
}
|
||||
|
||||
for (i = 0; i < qopt->num_entries; i++) {
|
||||
for (i = 0; i < size; i++) {
|
||||
s64 delta_ns = qopt->entries[i].interval;
|
||||
u32 gates = qopt->entries[i].gate_mask;
|
||||
|
||||
if (delta_ns > GENMASK(wid - 1, 0)) {
|
||||
ret = -ERANGE;
|
||||
goto error_unlock;
|
||||
}
|
||||
|
||||
if (gates > GENMASK(31 - wid, 0)) {
|
||||
ret = -ERANGE;
|
||||
goto error_unlock;
|
||||
}
|
||||
if (delta_ns > GENMASK(wid - 1, 0))
|
||||
return -ERANGE;
|
||||
if (gates > GENMASK(31 - wid, 0))
|
||||
return -ERANGE;
|
||||
|
||||
switch (qopt->entries[i].command) {
|
||||
case TC_TAPRIO_CMD_SET_GATES:
|
||||
|
|
@ -1065,26 +1062,13 @@ static int tc_taprio_configure(struct stmmac_priv *priv,
|
|||
gates &= ~BIT(0);
|
||||
break;
|
||||
default:
|
||||
ret = -EOPNOTSUPP;
|
||||
goto error_unlock;
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
gcl[i] = delta_ns | (gates << wid);
|
||||
priv->est->gcl[i] = delta_ns | (gates << wid);
|
||||
}
|
||||
|
||||
if (!priv->est) {
|
||||
priv->est = devm_kzalloc(priv->device, sizeof(*priv->est),
|
||||
GFP_KERNEL);
|
||||
if (!priv->est) {
|
||||
ret = -ENOMEM;
|
||||
goto error_unlock;
|
||||
}
|
||||
} else {
|
||||
memset(priv->est, 0, sizeof(*priv->est));
|
||||
}
|
||||
memcpy(priv->est->gcl, gcl, sizeof(*gcl) * qopt->num_entries);
|
||||
priv->est->gcl_size = qopt->num_entries;
|
||||
|
||||
mutex_lock(&priv->est_lock);
|
||||
/* Adjust for real system time */
|
||||
priv->ptp_clock_ops.gettimex64(&priv->ptp_clock_ops, ¤t_time,
|
||||
NULL);
|
||||
|
|
@ -1108,7 +1092,8 @@ static int tc_taprio_configure(struct stmmac_priv *priv,
|
|||
tc_taprio_map_maxsdu_txq(priv, qopt);
|
||||
|
||||
ret = stmmac_est_configure(priv, priv, priv->est,
|
||||
priv->plat->clk_ptp_rate, true);
|
||||
priv->plat->clk_ptp_rate);
|
||||
mutex_unlock(&priv->est_lock);
|
||||
if (ret) {
|
||||
netdev_err(priv->dev, "failed to configure EST\n");
|
||||
goto disable;
|
||||
|
|
@ -1119,31 +1104,24 @@ static int tc_taprio_configure(struct stmmac_priv *priv,
|
|||
if (ret)
|
||||
goto disable;
|
||||
|
||||
priv->est->pclass = qopt->mqprio.preemptible_tcs;
|
||||
priv->est->enable = true;
|
||||
|
||||
mutex_unlock(&priv->est_lock);
|
||||
kfree(gcl);
|
||||
|
||||
return 0;
|
||||
|
||||
disable:
|
||||
if (priv->est) {
|
||||
mutex_lock(&priv->est_lock);
|
||||
priv->est->enable = false;
|
||||
stmmac_est_configure(priv, priv, priv->est,
|
||||
priv->plat->clk_ptp_rate, false);
|
||||
priv->plat->clk_ptp_rate);
|
||||
/* Reset taprio status */
|
||||
for (i = 0; i < priv->plat->tx_queues_to_use; i++) {
|
||||
priv->xstats.max_sdu_txq_drop[i] = 0;
|
||||
priv->xstats.mtl_est_txq_hlbf[i] = 0;
|
||||
priv->xstats.mtl_est_txq_hlbs[i] = 0;
|
||||
}
|
||||
mutex_unlock(&priv->est_lock);
|
||||
}
|
||||
|
||||
err = stmmac_fpe_map_preemption_class(priv, priv->dev, extack, 0);
|
||||
error_unlock:
|
||||
mutex_unlock(&priv->est_lock);
|
||||
kfree(gcl);
|
||||
|
||||
return qopt->cmd == TAPRIO_CMD_DESTROY ? err : ret;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -128,7 +128,6 @@
|
|||
#define AM65_CPSW_PN_TS_CTL_LTYPE2_TS_319 BIT(21)
|
||||
#define AM65_CPSW_PN_TS_CTL_LTYPE2_TS_320 BIT(22)
|
||||
#define AM65_CPSW_PN_TS_CTL_LTYPE2_TS_TTL_NONZERO BIT(23)
|
||||
#define AM65_CPSW_PN_TS_CTL_LTYPE2_TS_UNI_EN BIT(24)
|
||||
|
||||
/* The PTP event messages - Sync, Delay_Req, Pdelay_Req, and Pdelay_Resp. */
|
||||
#define AM65_CPSW_TS_EVENT_MSG_TYPE_BITS (BIT(0) | BIT(1) | BIT(2) | BIT(3))
|
||||
|
|
@ -1858,8 +1857,7 @@ static int am65_cpsw_nuss_hwtstamp_set(struct net_device *ndev,
|
|||
AM65_CPSW_PN_TS_CTL_LTYPE2_TS_132 |
|
||||
AM65_CPSW_PN_TS_CTL_LTYPE2_TS_319 |
|
||||
AM65_CPSW_PN_TS_CTL_LTYPE2_TS_320 |
|
||||
AM65_CPSW_PN_TS_CTL_LTYPE2_TS_TTL_NONZERO |
|
||||
AM65_CPSW_PN_TS_CTL_LTYPE2_TS_UNI_EN;
|
||||
AM65_CPSW_PN_TS_CTL_LTYPE2_TS_TTL_NONZERO;
|
||||
|
||||
ts_ctrl = AM65_CPSW_TS_EVENT_MSG_TYPE_BITS <<
|
||||
AM65_CPSW_PN_TS_CTL_MSG_TYPE_EN_SHIFT;
|
||||
|
|
|
|||
|
|
@ -176,9 +176,6 @@ struct am65_cpts {
|
|||
struct mutex ptp_clk_lock; /* PHC access sync */
|
||||
u64 timestamp;
|
||||
u32 genf_enable;
|
||||
bool genf_neg_adj;
|
||||
u32 genf_ppm_hi;
|
||||
u32 genf_ppm_low;
|
||||
u32 hw_ts_enable;
|
||||
u32 estf_enable;
|
||||
struct sk_buff_head txq;
|
||||
|
|
@ -439,11 +436,9 @@ static int am65_cpts_ptp_adjfine(struct ptp_clock_info *ptp, long scaled_ppm)
|
|||
{
|
||||
struct am65_cpts *cpts = container_of(ptp, struct am65_cpts, ptp_info);
|
||||
u32 estf_ctrl_val = 0, estf_ppm_hi = 0, estf_ppm_low = 0;
|
||||
u32 genf_ctrl_val[AM65_CPTS_GENF_MAX_NUM];
|
||||
u32 genf_ppm_hi, genf_ppm_low;
|
||||
s32 ppb = scaled_ppm_to_ppb(scaled_ppm);
|
||||
int pps_index = cpts->pps_genf_idx;
|
||||
u64 adj_period, genf_adj_period;
|
||||
u64 adj_period, pps_adj_period;
|
||||
u32 ctrl_val, ppm_hi, ppm_low;
|
||||
unsigned long flags;
|
||||
int neg_adj = 0, i;
|
||||
|
|
@ -475,33 +470,20 @@ static int am65_cpts_ptp_adjfine(struct ptp_clock_info *ptp, long scaled_ppm)
|
|||
ppm_hi = upper_32_bits(adj_period) & 0x3FF;
|
||||
ppm_low = lower_32_bits(adj_period);
|
||||
|
||||
/* GenF PPM will do correction using cpts refclk tick which is
|
||||
* (cpts->ts_add_val + 1) ns, so GenF length PPM adj period
|
||||
* need to be corrected.
|
||||
*/
|
||||
genf_adj_period = adj_period * (cpts->ts_add_val + 1);
|
||||
genf_ppm_hi = upper_32_bits(genf_adj_period) & 0x3FF;
|
||||
genf_ppm_low = lower_32_bits(genf_adj_period);
|
||||
cpts->genf_neg_adj = neg_adj;
|
||||
cpts->genf_ppm_hi = genf_ppm_hi;
|
||||
cpts->genf_ppm_low = genf_ppm_low;
|
||||
|
||||
for (i = 0; i < AM65_CPTS_GENF_MAX_NUM; i++) {
|
||||
if (cpts->genf_enable & BIT(i)) {
|
||||
genf_ctrl_val[i] = am65_cpts_read32(cpts,
|
||||
genf[i].control);
|
||||
if (neg_adj)
|
||||
genf_ctrl_val[i] &= ~BIT(1);
|
||||
else
|
||||
genf_ctrl_val[i] |= BIT(1);
|
||||
}
|
||||
}
|
||||
|
||||
if (cpts->pps_enabled) {
|
||||
/* am65_cpts_perout_enable_hw() sets pps_index in genf_enable */
|
||||
estf_ctrl_val = genf_ctrl_val[pps_index];
|
||||
estf_ppm_hi = genf_ppm_hi;
|
||||
estf_ppm_low = genf_ppm_low;
|
||||
estf_ctrl_val = am65_cpts_read32(cpts, genf[pps_index].control);
|
||||
if (neg_adj)
|
||||
estf_ctrl_val &= ~BIT(1);
|
||||
else
|
||||
estf_ctrl_val |= BIT(1);
|
||||
|
||||
/* GenF PPM will do correction using cpts refclk tick which is
|
||||
* (cpts->ts_add_val + 1) ns, so GenF length PPM adj period
|
||||
* need to be corrected.
|
||||
*/
|
||||
pps_adj_period = adj_period * (cpts->ts_add_val + 1);
|
||||
estf_ppm_hi = upper_32_bits(pps_adj_period) & 0x3FF;
|
||||
estf_ppm_low = lower_32_bits(pps_adj_period);
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&cpts->lock, flags);
|
||||
|
|
@ -518,13 +500,10 @@ static int am65_cpts_ptp_adjfine(struct ptp_clock_info *ptp, long scaled_ppm)
|
|||
am65_cpts_write32(cpts, ppm_hi, ts_ppm_hi);
|
||||
am65_cpts_write32(cpts, ppm_low, ts_ppm_low);
|
||||
|
||||
for (i = 0; i < AM65_CPTS_GENF_MAX_NUM; i++) {
|
||||
if (cpts->genf_enable & BIT(i)) {
|
||||
am65_cpts_write32(cpts, genf_ctrl_val[i],
|
||||
genf[i].control);
|
||||
am65_cpts_write32(cpts, genf_ppm_hi, genf[i].ppm_hi);
|
||||
am65_cpts_write32(cpts, genf_ppm_low, genf[i].ppm_low);
|
||||
}
|
||||
if (cpts->pps_enabled) {
|
||||
am65_cpts_write32(cpts, estf_ctrl_val, genf[pps_index].control);
|
||||
am65_cpts_write32(cpts, estf_ppm_hi, genf[pps_index].ppm_hi);
|
||||
am65_cpts_write32(cpts, estf_ppm_low, genf[pps_index].ppm_low);
|
||||
}
|
||||
|
||||
for (i = 0; i < AM65_CPTS_ESTF_MAX_NUM; i++) {
|
||||
|
|
@ -534,6 +513,7 @@ static int am65_cpts_ptp_adjfine(struct ptp_clock_info *ptp, long scaled_ppm)
|
|||
am65_cpts_write32(cpts, estf_ppm_low, estf[i].ppm_low);
|
||||
}
|
||||
}
|
||||
/* All GenF/EstF can be updated here the same way */
|
||||
spin_unlock_irqrestore(&cpts->lock, flags);
|
||||
|
||||
mutex_unlock(&cpts->ptp_clk_lock);
|
||||
|
|
@ -699,12 +679,9 @@ static void am65_cpts_perout_enable_hw(struct am65_cpts *cpts,
|
|||
val = lower_32_bits(cycles);
|
||||
am65_cpts_write32(cpts, val, genf[req->index].length);
|
||||
|
||||
am65_cpts_write32(cpts, cpts->genf_neg_adj ? 0 : BIT(1),
|
||||
genf[req->index].control);
|
||||
am65_cpts_write32(cpts, cpts->genf_ppm_hi,
|
||||
genf[req->index].ppm_hi);
|
||||
am65_cpts_write32(cpts, cpts->genf_ppm_low,
|
||||
genf[req->index].ppm_low);
|
||||
am65_cpts_write32(cpts, 0, genf[req->index].control);
|
||||
am65_cpts_write32(cpts, 0, genf[req->index].ppm_hi);
|
||||
am65_cpts_write32(cpts, 0, genf[req->index].ppm_low);
|
||||
|
||||
cpts->genf_enable |= BIT(req->index);
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -260,8 +260,10 @@ int ipa_interrupt_config(struct ipa *ipa)
|
|||
interrupt->enabled = 0;
|
||||
interrupt->suspend_enabled = bitmap_zalloc(ipa->endpoint_count,
|
||||
GFP_KERNEL);
|
||||
if (!interrupt->suspend_enabled)
|
||||
return -ENOMEM;
|
||||
if (!interrupt->suspend_enabled) {
|
||||
ret = -ENOMEM;
|
||||
goto err_kfree;
|
||||
}
|
||||
|
||||
/* Disable IPA interrupt types */
|
||||
reg = ipa_reg(ipa, IPA_IRQ_EN);
|
||||
|
|
@ -287,6 +289,8 @@ int ipa_interrupt_config(struct ipa *ipa)
|
|||
goto err_disable_wakeup;
|
||||
}
|
||||
|
||||
ipa->interrupt = interrupt;
|
||||
|
||||
return 0;
|
||||
|
||||
err_disable_wakeup:
|
||||
|
|
@ -295,6 +299,8 @@ int ipa_interrupt_config(struct ipa *ipa)
|
|||
free_irq(interrupt->irq, interrupt);
|
||||
err_free_bitmap:
|
||||
bitmap_free(interrupt->suspend_enabled);
|
||||
err_kfree:
|
||||
kfree(interrupt);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -305,6 +311,8 @@ void ipa_interrupt_deconfig(struct ipa *ipa)
|
|||
struct ipa_interrupt *interrupt = ipa->interrupt;
|
||||
struct device *dev = ipa->dev;
|
||||
|
||||
ipa->interrupt = NULL;
|
||||
|
||||
dev_pm_clear_wake_irq(dev);
|
||||
(void)device_init_wakeup(dev, false);
|
||||
free_irq(interrupt->irq, interrupt);
|
||||
|
|
|
|||
|
|
@ -643,14 +643,6 @@ static int macvlan_open(struct net_device *dev)
|
|||
if (err < 0)
|
||||
goto out;
|
||||
}
|
||||
if (dev->flags & IFF_ALLMULTI) {
|
||||
err = dev_set_allmulti(lowerdev, 1);
|
||||
if (err < 0) {
|
||||
if (!(vlan->flags & MACVLAN_FLAG_NOPROMISC))
|
||||
dev_set_promiscuity(lowerdev, -1);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
goto hash_add;
|
||||
}
|
||||
|
||||
|
|
@ -721,8 +713,6 @@ static int macvlan_stop(struct net_device *dev)
|
|||
dev_mc_unsync(lowerdev, dev);
|
||||
|
||||
if (macvlan_passthru(vlan->port)) {
|
||||
if (dev->flags & IFF_ALLMULTI)
|
||||
dev_set_allmulti(lowerdev, -1);
|
||||
if (!(vlan->flags & MACVLAN_FLAG_NOPROMISC))
|
||||
dev_set_promiscuity(lowerdev, -1);
|
||||
goto hash_del;
|
||||
|
|
|
|||
|
|
@ -111,7 +111,8 @@ static int mctp_i3c_read(struct mctp_i3c_device *mi)
|
|||
mi->mrl + sizeof(struct mctp_i3c_internal_hdr));
|
||||
if (!skb) {
|
||||
stats->rx_dropped++;
|
||||
return -ENOMEM;
|
||||
rc = -ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
|
||||
skb->protocol = htons(ETH_P_MCTP);
|
||||
|
|
|
|||
|
|
@ -1826,13 +1826,9 @@ static void phy_detach_internal(struct phy_device *phydev, bool notify_bus)
|
|||
struct hwtstamp_provider *hwprov;
|
||||
|
||||
/* hwprov may technically be protected by ops lock but
|
||||
* not for devices with a phydev, see phy_link_topo_add_phy().
|
||||
* Drivers may detach without RTNL while dev is unregistered,
|
||||
* but then nothing else can reach hwprov.
|
||||
* not for devices with a phydev, see phy_link_topo_add_phy()
|
||||
*/
|
||||
hwprov = rcu_dereference_protected(dev->hwprov,
|
||||
lockdep_rtnl_is_held() ||
|
||||
dev->reg_state != NETREG_REGISTERED);
|
||||
hwprov = rtnl_dereference(dev->hwprov);
|
||||
/* Disable timestamp if it is the one selected */
|
||||
if (hwprov && hwprov->phydev == phydev) {
|
||||
rcu_assign_pointer(dev->hwprov, NULL);
|
||||
|
|
|
|||
|
|
@ -1377,10 +1377,9 @@ static int veth_set_channels(struct net_device *dev,
|
|||
* to identify the range we have to disable
|
||||
*/
|
||||
veth_disable_range_safe(dev, new_rx_count, old_rx_count);
|
||||
if (peer && (peer->flags & IFF_UP)) {
|
||||
netif_carrier_on(dev);
|
||||
netif_carrier_on(dev);
|
||||
if (peer)
|
||||
netif_carrier_on(peer);
|
||||
}
|
||||
}
|
||||
|
||||
/* update XDP supported features */
|
||||
|
|
|
|||
|
|
@ -1005,6 +1005,12 @@ static int vxlan_fdb_update_existing(struct vxlan_dev *vxlan,
|
|||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
if (rcu_access_pointer(f->nh) &&
|
||||
!(state & (NUD_PERMANENT | NUD_NOARP))) {
|
||||
NL_SET_ERR_MSG(extack, "Cannot make a nexthop fdb dynamic");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
/* Do not allow an externally learned entry to take over an entry added
|
||||
* by the user.
|
||||
*/
|
||||
|
|
@ -1268,6 +1274,11 @@ static int vxlan_fdb_add(struct ndmsg *ndm, struct nlattr *tb[],
|
|||
if (err)
|
||||
return err;
|
||||
|
||||
if (nhid && !(ndm->ndm_state & (NUD_PERMANENT | NUD_NOARP))) {
|
||||
NL_SET_ERR_MSG(extack, "A nexthop fdb cannot be dynamic");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
cfg = rtnl_dereference(vxlan->cfg);
|
||||
if (cfg->remote_ip.sa.sa_family != ip.sa.sa_family)
|
||||
return -EAFNOSUPPORT;
|
||||
|
|
@ -2936,9 +2947,6 @@ static void vxlan_cleanup(struct timer_list *t)
|
|||
if (f->flags & NTF_EXT_LEARNED)
|
||||
continue;
|
||||
|
||||
if (rcu_access_pointer(f->nh))
|
||||
continue;
|
||||
|
||||
timeout = READ_ONCE(f->updated) + cfg->age_interval * HZ;
|
||||
if (time_before_eq(timeout, jiffies)) {
|
||||
spin_lock(&vxlan->hash_lock);
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user