mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-05 02:21:52 +09:00
Merge 6.1.107 into android14-6.1-lts
Changes in 6.1.107
tty: atmel_serial: use the correct RTS flag.
fuse: Initialize beyond-EOF page contents before setting uptodate
char: xillybus: Don't destroy workqueue from work item running on it
char: xillybus: Refine workqueue handling
char: xillybus: Check USB endpoints when probing device
ALSA: usb-audio: Add delay quirk for VIVO USB-C-XE710 HEADSET
ALSA: usb-audio: Support Yamaha P-125 quirk entry
xhci: Fix Panther point NULL pointer deref at full-speed re-enumeration
thunderbolt: Mark XDomain as unplugged when router is removed
s390/dasd: fix error recovery leading to data corruption on ESE devices
riscv: change XIP's kernel_map.size to be size of the entire kernel
arm64: ACPI: NUMA: initialize all values of acpi_early_node_map to NUMA_NO_NODE
dm resume: don't return EINVAL when signalled
dm persistent data: fix memory allocation failure
vfs: Don't evict inode under the inode lru traversing context
fs/ntfs3: add prefix to bitmap_size() and use BITS_TO_U64()
s390/cio: rename bitmap_size() -> idset_bitmap_size()
btrfs: rename bitmap_set_bits() -> btrfs_bitmap_set_bits()
bitmap: introduce generic optimized bitmap_size()
fix bitmap corruption on close_range() with CLOSE_RANGE_UNSHARE
i2c: qcom-geni: Add missing geni_icc_disable in geni_i2c_runtime_resume
rtla/osnoise: Prevent NULL dereference in error handling
fs/netfs/fscache_cookie: add missing "n_accesses" check
selinux: fix potential counting error in avc_add_xperms_decision()
mm/memory-failure: use raw_spinlock_t in struct memory_failure_cpu
btrfs: zoned: properly take lock to read/update block group's zoned variables
btrfs: tree-checker: add dev extent item checks
drm/amdgpu: Actually check flags for all context ops.
memcg_write_event_control(): fix a user-triggerable oops
drm/amdgpu/jpeg2: properly set atomics vmid field
s390/uv: Panic for set and remove shared access UVC errors
bpf: Fix updating attached freplace prog in prog_array map
nilfs2: prevent WARNING in nilfs_dat_commit_end()
ext4, jbd2: add an optimized bmap for the journal inode
9P FS: Fix wild-memory-access write in v9fs_get_acl
nilfs2: initialize "struct nilfs_binfo_dat"->bi_pad field
mm: khugepaged: fix kernel BUG in hpage_collapse_scan_file()
bpf: Split off basic BPF verifier log into separate file
bpf: drop unnecessary user-triggerable WARN_ONCE in verifierl log
posix-timers: Ensure timer ID search-loop limit is valid
pid: Replace struct pid 1-element array with flex-array
gfs2: Rename remaining "transaction" glock references
gfs2: Rename the {freeze,thaw}_super callbacks
gfs2: Rename gfs2_freeze_lock{ => _shared }
gfs2: Rename SDF_{FS_FROZEN => FREEZE_INITIATOR}
gfs2: Rework freeze / thaw logic
gfs2: Stop using gfs2_make_fs_ro for withdraw
Bluetooth: Fix hci_link_tx_to RCU lock usage
wifi: mac80211: take wiphy lock for MAC addr change
wifi: mac80211: fix change_address deadlock during unregister
net: sched: Print msecs when transmit queue time out
net: don't dump stack on queue timeout
jfs: fix shift-out-of-bounds in dbJoin
squashfs: squashfs_read_data need to check if the length is 0
Squashfs: fix variable overflow triggered by sysbot
reiserfs: fix uninit-value in comp_keys
erofs: avoid debugging output for (de)compressed data
quota: Detect loops in quota tree
net:rds: Fix possible deadlock in rds_message_put
net: sctp: fix skb leak in sctp_inq_free()
pppoe: Fix memory leak in pppoe_sendmsg()
wifi: mac80211: fix and simplify unencrypted drop check for mesh
wifi: cfg80211: move A-MSDU check in ieee80211_data_to_8023_exthdr
wifi: cfg80211: factor out bridge tunnel / RFC1042 header check
wifi: mac80211: remove mesh forwarding congestion check
wifi: mac80211: fix receiving A-MSDU frames on mesh interfaces
wifi: mac80211: add a workaround for receiving non-standard mesh A-MSDU
wifi: cfg80211: check A-MSDU format more carefully
docs/bpf: Document BPF_MAP_TYPE_LPM_TRIE map
bpf: Replace bpf_lpm_trie_key 0-length array with flexible array
bpf: Avoid kfree_rcu() under lock in bpf_lpm_trie.
Bluetooth: RFCOMM: Fix not validating setsockopt user input
ext4: check the return value of ext4_xattr_inode_dec_ref()
ext4: fold quota accounting into ext4_xattr_inode_lookup_create()
ext4: do not create EA inode under buffer lock
udf: Fix bogus checksum computation in udf_rename()
bpf, net: Use DEV_STAT_INC()
fou: remove warn in gue_gro_receive on unsupported protocol
jfs: fix null ptr deref in dtInsertEntry
jfs: Fix shift-out-of-bounds in dbDiscardAG
fs/ntfs3: Do copy_to_user out of run_lock
ALSA: usb: Fix UBSAN warning in parse_audio_unit()
igc: Correct the launchtime offset
igc: Fix packet still tx after gate close by reducing i226 MAC retry buffer
net/mlx5e: Take state lock during tx timeout reporter
net/mlx5e: Correctly report errors for ethtool rx flows
atm: idt77252: prevent use after free in dequeue_rx()
net: axienet: Fix register defines comment description
net: dsa: vsc73xx: pass value in phy_write operation
net: dsa: vsc73xx: use read_poll_timeout instead delay loop
net: dsa: vsc73xx: check busy flag in MDIO operations
mlxbf_gige: Remove two unused function declarations
mlxbf_gige: disable RX filters until RX path initialized
mptcp: correct MPTCP_SUBFLOW_ATTR_SSN_OFFSET reserved size
netfilter: allow ipv6 fragments to arrive on different devices
netfilter: flowtable: initialise extack before use
netfilter: nf_queue: drop packets with cloned unconfirmed conntracks
netfilter: nf_tables: Audit log dump reset after the fact
netfilter: nf_tables: Drop pointless memset in nf_tables_dump_obj
netfilter: nf_tables: Unconditionally allocate nft_obj_filter
netfilter: nf_tables: A better name for nft_obj_filter
netfilter: nf_tables: Carry s_idx in nft_obj_dump_ctx
netfilter: nf_tables: nft_obj_filter fits into cb->ctx
netfilter: nf_tables: Carry reset boolean in nft_obj_dump_ctx
netfilter: nf_tables: Introduce nf_tables_getobj_single
netfilter: nf_tables: Add locking for NFT_MSG_GETOBJ_RESET requests
net: hns3: fix wrong use of semaphore up
net: hns3: use the user's cfg after reset
net: hns3: fix a deadlock problem when config TC during resetting
ALSA: hda/realtek: Fix noise from speakers on Lenovo IdeaPad 3 15IAU7
drm/amd/amdgpu/imu_v11_0: Increase buffer size to ensure all possible values can be stored
ssb: Fix division by zero issue in ssb_calc_clock_rate
wifi: cfg80211: check wiphy mutex is held for wdev mutex
wifi: mac80211: fix BA session teardown race
mm: Remove kmem_valid_obj()
rcu: Dump memory object info if callback function is invalid
rcu: Eliminate rcu_gp_slow_unregister() false positive
wifi: cw1200: Avoid processing an invalid TIM IE
cgroup: Avoid extra dereference in css_populate_dir()
i2c: riic: avoid potential division by zero
RDMA/rtrs: Fix the problem of variable not initialized fully
s390/smp,mcck: fix early IPI handling
drm/bridge: tc358768: Attempt to fix DSI horizontal timings
i3c: mipi-i3c-hci: Remove BUG() when Ring Abort request times out
i3c: mipi-i3c-hci: Do not unmap region not mapped for transfer
drm/amdkfd: Move dma unmapping after TLB flush
media: radio-isa: use dev_name to fill in bus_info
staging: iio: resolver: ad2s1210: fix use before initialization
usb: gadget: uvc: cleanup request when not in correct state
drm/amd/display: Validate hw_points_num before using it
staging: ks7010: disable bh on tx_dev_lock
media: s5p-mfc: Fix potential deadlock on condlock
md/raid5-cache: use READ_ONCE/WRITE_ONCE for 'conf->log'
binfmt_misc: cleanup on filesystem umount
drm/tegra: Zero-initialize iosys_map
media: qcom: venus: fix incorrect return value
scsi: spi: Fix sshdr use
gfs2: setattr_chown: Add missing initialization
wifi: iwlwifi: abort scan when rfkill on but device enabled
wifi: iwlwifi: fw: Fix debugfs command sending
clk: visconti: Add bounds-checking coverage for struct visconti_pll_provider
IB/hfi1: Fix potential deadlock on &irq_src_lock and &dd->uctxt_lock
hwmon: (ltc2992) Avoid division by zero
kbuild: rust_is_available: normalize version matching
kbuild: rust_is_available: handle failures calling `$RUSTC`/`$BINDGEN`
rust: work around `bindgen` 0.69.0 issue
rust: suppress error messages from CONFIG_{RUSTC,BINDGEN}_VERSION_TEXT
rust: fix the default format for CONFIG_{RUSTC,BINDGEN}_VERSION_TEXT
arm64: Fix KASAN random tag seed initialization
block: Fix lockdep warning in blk_mq_mark_tag_wait
drm/msm: Reduce fallout of fence signaling vs reclaim hangs
memory: tegra: Skip SID programming if SID registers aren't set
powerpc/xics: Check return value of kasprintf in icp_native_map_one_cpu
ASoC: SOF: ipc4: check return value of snd_sof_ipc_msg_data
hwmon: (pc87360) Bounds check data->innr usage
drm/rockchip: vop2: clear afbc en and transform bit for cluster window at linear mode
Bluetooth: hci_conn: Check non NULL function before calling for HFP offload
gfs2: Refcounting fix in gfs2_thaw_super
nvmet-trace: avoid dereferencing pointer too early
ext4: do not trim the group with corrupted block bitmap
afs: fix __afs_break_callback() / afs_drop_open_mmap() race
fuse: fix UAF in rcu pathwalks
quota: Remove BUG_ON from dqget()
kernfs: fix false-positive WARN(nr_mmapped) in kernfs_drain_open_files
media: pci: cx23885: check cx23885_vdev_init() return
fs: binfmt_elf_efpic: don't use missing interpreter's properties
scsi: lpfc: Initialize status local variable in lpfc_sli4_repost_sgl_list()
media: drivers/media/dvb-core: copy user arrays safely
net/sun3_82586: Avoid reading past buffer in debug output
drm/lima: set gp bus_stop bit before hard reset
hrtimer: Select housekeeping CPU during migration
virtiofs: forbid newlines in tags
clocksource/drivers/arm_global_timer: Guard against division by zero
netlink: hold nlk->cb_mutex longer in __netlink_dump_start()
md: clean up invalid BUG_ON in md_ioctl
x86: Increase brk randomness entropy for 64-bit systems
memory: stm32-fmc2-ebi: check regmap_read return value
parisc: Use irq_enter_rcu() to fix warning at kernel/context_tracking.c:367
powerpc/boot: Handle allocation failure in simple_realloc()
powerpc/boot: Only free if realloc() succeeds
btrfs: delayed-inode: drop pointless BUG_ON in __btrfs_remove_delayed_item()
btrfs: change BUG_ON to assertion when checking for delayed_node root
btrfs: tests: allocate dummy fs_info and root in test_find_delalloc()
btrfs: handle invalid root reference found in may_destroy_subvol()
btrfs: send: handle unexpected data in header buffer in begin_cmd()
btrfs: change BUG_ON to assertion in tree_move_down()
btrfs: delete pointless BUG_ON check on quota root in btrfs_qgroup_account_extent()
f2fs: fix to do sanity check in update_sit_entry
usb: gadget: fsl: Increase size of name buffer for endpoints
nvme: clear caller pointer on identify failure
Bluetooth: bnep: Fix out-of-bound access
firmware: cirrus: cs_dsp: Initialize debugfs_root to invalid
rtc: nct3018y: fix possible NULL dereference
net: hns3: add checking for vf id of mailbox
nvmet-tcp: do not continue for invalid icreq
NFS: avoid infinite loop in pnfs_update_layout.
openrisc: Call setup_memory() earlier in the init sequence
s390/iucv: fix receive buffer virtual vs physical address confusion
irqchip/renesas-rzg2l: Do not set TIEN and TINT source at the same time
clocksource: Make watchdog and suspend-timing multiplication overflow safe
platform/x86: lg-laptop: fix %s null argument warning
usb: dwc3: core: Skip setting event buffers for host only controllers
fbdev: offb: replace of_node_put with __free(device_node)
irqchip/gic-v3-its: Remove BUG_ON in its_vpe_irq_domain_alloc
ext4: set the type of max_zeroout to unsigned int to avoid overflow
nvmet-rdma: fix possible bad dereference when freeing rsps
drm/amdgpu: fix dereference null return value for the function amdgpu_vm_pt_parent
hrtimer: Prevent queuing of hrtimer without a function callback
gtp: pull network headers in gtp_dev_xmit()
media: solo6x10: replace max(a, min(b, c)) by clamp(b, a, c)
i2c: tegra: allow DVC support to be compiled out
i2c: tegra: allow VI support to be compiled out
i2c: tegra: Do not mark ACPI devices as irq safe
dm suspend: return -ERESTARTSYS instead of -EINTR
net: mana: Fix doorbell out of order violation and avoid unnecessary doorbell rings
btrfs: replace sb::s_blocksize by fs_info::sectorsize
btrfs: send: allow cloning non-aligned extent if it ends at i_size
drm/amd/display: Adjust cursor position
platform/surface: aggregator: Fix warning when controller is destroyed in probe
drm/amdkfd: reserve the BO before validating it
Bluetooth: hci_core: Fix LE quote calculation
Bluetooth: SMP: Fix assumption of Central always being Initiator
net: dsa: tag_ocelot: do not rely on skb_mac_header() for VLAN xmit
net: dsa: tag_ocelot: call only the relevant portion of __skb_vlan_pop() on TX
net: mscc: ocelot: use ocelot_xmit_get_vlan_info() also for FDMA and register injection
net: mscc: ocelot: fix QoS class for injected packets with "ocelot-8021q"
net: mscc: ocelot: serialize access to the injection/extraction groups
tc-testing: don't access non-existent variable on exception
selftests/net: synchronize udpgro tests' tx and rx connection
selftests: udpgro: report error when receive failed
tcp/dccp: bypass empty buckets in inet_twsk_purge()
tcp/dccp: do not care about families in inet_twsk_purge()
tcp: prevent concurrent execution of tcp_sk_exit_batch
net: mctp: test: Use correct skb for route input check
kcm: Serialise kcm_sendmsg() for the same socket.
netfilter: nft_counter: Disable BH in nft_counter_offload_stats().
netfilter: nft_counter: Synchronize nft_counter_reset() against reader.
ip6_tunnel: Fix broken GRO
bonding: fix bond_ipsec_offload_ok return type
bonding: fix null pointer deref in bond_ipsec_offload_ok
bonding: fix xfrm real_dev null pointer dereference
bonding: fix xfrm state handling when clearing active slave
ice: Prepare legacy-rx for upcoming XDP multi-buffer support
ice: Add xdp_buff to ice_rx_ring struct
ice: Store page count inside ice_rx_buf
ice: Pull out next_to_clean bump out of ice_put_rx_buf()
ice: fix page reuse when PAGE_SIZE is over 8k
ice: fix ICE_LAST_OFFSET formula
dpaa2-switch: Fix error checking in dpaa2_switch_seed_bp()
net: dsa: mv88e6xxx: Fix out-of-bound access
netem: fix return value if duplicate enqueue fails
ipv6: prevent UAF in ip6_send_skb()
ipv6: fix possible UAF in ip6_finish_output2()
ipv6: prevent possible UAF in ip6_xmit()
netfilter: flowtable: validate vlan header
octeontx2-af: Fix CPT AF register offset calculation
net: xilinx: axienet: Always disable promiscuous mode
net: xilinx: axienet: Fix dangling multicast addresses
drm/msm/dpu: don't play tricks with debug macros
drm/msm/dp: fix the max supported bpp logic
drm/msm/dp: reset the link phy params before link training
drm/msm/dpu: cleanup FB if dpu_format_populate_layout fails
mmc: mmc_test: Fix NULL dereference on allocation failure
Bluetooth: MGMT: Add error handling to pair_device()
scsi: core: Fix the return value of scsi_logical_block_count()
ksmbd: the buffer of smb2 query dir response has at least 1 byte
drm/amdgpu: Validate TA binary size
MIPS: Loongson64: Set timer mode in cpu-probe
HID: wacom: Defer calculation of resolution until resolution_code is known
HID: microsoft: Add rumble support to latest xbox controllers
Input: i8042 - add forcenorestore quirk to leave controller untouched even on s3
Input: i8042 - use new forcenorestore quirk to replace old buggy quirk combination
cxgb4: add forgotten u64 ivlan cast before shift
KVM: arm64: Make ICC_*SGI*_EL1 undef in the absence of a vGICv3
mmc: dw_mmc: allow biu and ciu clocks to defer
pmdomain: imx: wait SSAR when i.MX93 power domain on
mptcp: pm: re-using ID of unused removed ADD_ADDR
mptcp: pm: re-using ID of unused removed subflows
mptcp: pm: re-using ID of unused flushed subflows
mptcp: pm: only decrement add_addr_accepted for MPJ req
Revert "usb: gadget: uvc: cleanup request when not in correct state"
Revert "drm/amd/display: Validate hw_points_num before using it"
tcp: do not export tcp_twsk_purge()
hwmon: (ltc2992) Fix memory leak in ltc2992_parse_dt()
ALSA: timer: Relax start tick time check for slave timer elements
mm/vmalloc: fix page mapping if vm_area_alloc_pages() with high order fallback to order 0
mm/numa: no task_numa_fault() call if PMD is changed
mm/numa: no task_numa_fault() call if PTE is changed
nfsd: Simplify code around svc_exit_thread() call in nfsd()
nfsd: separate nfsd_last_thread() from nfsd_put()
NFSD: simplify error paths in nfsd_svc()
nfsd: call nfsd_last_thread() before final nfsd_put()
nfsd: drop the nfsd_put helper
nfsd: don't call locks_release_private() twice concurrently
nfsd: Fix a regression in nfsd_setattr()
Bluetooth: hci_ldisc: check HCI_UART_PROTO_READY flag in HCIUARTGETPROTO
drm/amdgpu/vcn: identify unified queue in sw init
drm/amdgpu/vcn: not pause dpg for unified queue
KVM: x86: fire timer when it is migrated and expired, and in oneshot mode
Revert "s390/dasd: Establish DMA alignment"
udp: allow header check for dodgy GSO_UDP_L4 packets.
gso: fix dodgy bit handling for GSO_UDP_L4
net: more strict VIRTIO_NET_HDR_GSO_UDP_L4 validation
net: drop bad gso csum_start and offset in virtio_net_hdr
wifi: mac80211: add documentation for amsdu_mesh_control
wifi: mac80211: fix mesh path discovery based on unicast packets
wifi: mac80211: fix mesh forwarding
wifi: mac80211: fix flow dissection for forwarded packets
wifi: mac80211: fix receiving mesh packets in forwarding=0 networks
wifi: mac80211: drop bogus static keywords in A-MSDU rx
wifi: mac80211: fix potential null pointer dereference
wifi: cfg80211: fix receiving mesh packets without RFC1042 header
gfs2: Fix another freeze/thaw hang
gfs2: don't withdraw if init_threads() got interrupted
gfs2: Remove LM_FLAG_PRIORITY flag
gfs2: Remove freeze_go_demote_ok
udp: fix receiving fraglist GSO packets
ice: fix W=1 headers mismatch
Revert "jfs: fix shift-out-of-bounds in dbJoin"
net: change maximum number of UDP segments to 128
selftests: net: more strict check in net_helper
Input: MT - limit max slots
tools: move alignment-related macros to new <linux/align.h>
Linux 6.1.107
Change-Id: I11d18ae169b1e55f18f0dc2953df2dd3a1f25624
Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
This commit is contained in:
181
Documentation/bpf/map_lpm_trie.rst
Normal file
181
Documentation/bpf/map_lpm_trie.rst
Normal file
@@ -0,0 +1,181 @@
|
||||
.. SPDX-License-Identifier: GPL-2.0-only
|
||||
.. Copyright (C) 2022 Red Hat, Inc.
|
||||
|
||||
=====================
|
||||
BPF_MAP_TYPE_LPM_TRIE
|
||||
=====================
|
||||
|
||||
.. note::
|
||||
- ``BPF_MAP_TYPE_LPM_TRIE`` was introduced in kernel version 4.11
|
||||
|
||||
``BPF_MAP_TYPE_LPM_TRIE`` provides a longest prefix match algorithm that
|
||||
can be used to match IP addresses to a stored set of prefixes.
|
||||
Internally, data is stored in an unbalanced trie of nodes that uses
|
||||
``prefixlen,data`` pairs as its keys. The ``data`` is interpreted in
|
||||
network byte order, i.e. big endian, so ``data[0]`` stores the most
|
||||
significant byte.
|
||||
|
||||
LPM tries may be created with a maximum prefix length that is a multiple
|
||||
of 8, in the range from 8 to 2048. The key used for lookup and update
|
||||
operations is a ``struct bpf_lpm_trie_key_u8``, extended by
|
||||
``max_prefixlen/8`` bytes.
|
||||
|
||||
- For IPv4 addresses the data length is 4 bytes
|
||||
- For IPv6 addresses the data length is 16 bytes
|
||||
|
||||
The value type stored in the LPM trie can be any user defined type.
|
||||
|
||||
.. note::
|
||||
When creating a map of type ``BPF_MAP_TYPE_LPM_TRIE`` you must set the
|
||||
``BPF_F_NO_PREALLOC`` flag.
|
||||
|
||||
Usage
|
||||
=====
|
||||
|
||||
Kernel BPF
|
||||
----------
|
||||
|
||||
.. c:function::
|
||||
void *bpf_map_lookup_elem(struct bpf_map *map, const void *key)
|
||||
|
||||
The longest prefix entry for a given data value can be found using the
|
||||
``bpf_map_lookup_elem()`` helper. This helper returns a pointer to the
|
||||
value associated with the longest matching ``key``, or ``NULL`` if no
|
||||
entry was found.
|
||||
|
||||
The ``key`` should have ``prefixlen`` set to ``max_prefixlen`` when
|
||||
performing longest prefix lookups. For example, when searching for the
|
||||
longest prefix match for an IPv4 address, ``prefixlen`` should be set to
|
||||
``32``.
|
||||
|
||||
.. c:function::
|
||||
long bpf_map_update_elem(struct bpf_map *map, const void *key, const void *value, u64 flags)
|
||||
|
||||
Prefix entries can be added or updated using the ``bpf_map_update_elem()``
|
||||
helper. This helper replaces existing elements atomically.
|
||||
|
||||
``bpf_map_update_elem()`` returns ``0`` on success, or negative error in
|
||||
case of failure.
|
||||
|
||||
.. note::
|
||||
The flags parameter must be one of BPF_ANY, BPF_NOEXIST or BPF_EXIST,
|
||||
but the value is ignored, giving BPF_ANY semantics.
|
||||
|
||||
.. c:function::
|
||||
long bpf_map_delete_elem(struct bpf_map *map, const void *key)
|
||||
|
||||
Prefix entries can be deleted using the ``bpf_map_delete_elem()``
|
||||
helper. This helper will return 0 on success, or negative error in case
|
||||
of failure.
|
||||
|
||||
Userspace
|
||||
---------
|
||||
|
||||
Access from userspace uses libbpf APIs with the same names as above, with
|
||||
the map identified by ``fd``.
|
||||
|
||||
.. c:function::
|
||||
int bpf_map_get_next_key (int fd, const void *cur_key, void *next_key)
|
||||
|
||||
A userspace program can iterate through the entries in an LPM trie using
|
||||
libbpf's ``bpf_map_get_next_key()`` function. The first key can be
|
||||
fetched by calling ``bpf_map_get_next_key()`` with ``cur_key`` set to
|
||||
``NULL``. Subsequent calls will fetch the next key that follows the
|
||||
current key. ``bpf_map_get_next_key()`` returns ``0`` on success,
|
||||
``-ENOENT`` if ``cur_key`` is the last key in the trie, or negative
|
||||
error in case of failure.
|
||||
|
||||
``bpf_map_get_next_key()`` will iterate through the LPM trie elements
|
||||
from leftmost leaf first. This means that iteration will return more
|
||||
specific keys before less specific ones.
|
||||
|
||||
Examples
|
||||
========
|
||||
|
||||
Please see ``tools/testing/selftests/bpf/test_lpm_map.c`` for examples
|
||||
of LPM trie usage from userspace. The code snippets below demonstrate
|
||||
API usage.
|
||||
|
||||
Kernel BPF
|
||||
----------
|
||||
|
||||
The following BPF code snippet shows how to declare a new LPM trie for IPv4
|
||||
address prefixes:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
#include <linux/bpf.h>
|
||||
#include <bpf/bpf_helpers.h>
|
||||
|
||||
struct ipv4_lpm_key {
|
||||
__u32 prefixlen;
|
||||
__u32 data;
|
||||
};
|
||||
|
||||
struct {
|
||||
__uint(type, BPF_MAP_TYPE_LPM_TRIE);
|
||||
__type(key, struct ipv4_lpm_key);
|
||||
__type(value, __u32);
|
||||
__uint(map_flags, BPF_F_NO_PREALLOC);
|
||||
__uint(max_entries, 255);
|
||||
} ipv4_lpm_map SEC(".maps");
|
||||
|
||||
The following BPF code snippet shows how to lookup by IPv4 address:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
void *lookup(__u32 ipaddr)
|
||||
{
|
||||
struct ipv4_lpm_key key = {
|
||||
.prefixlen = 32,
|
||||
.data = ipaddr
|
||||
};
|
||||
|
||||
return bpf_map_lookup_elem(&ipv4_lpm_map, &key);
|
||||
}
|
||||
|
||||
Userspace
|
||||
---------
|
||||
|
||||
The following snippet shows how to insert an IPv4 prefix entry into an
|
||||
LPM trie:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
int add_prefix_entry(int lpm_fd, __u32 addr, __u32 prefixlen, struct value *value)
|
||||
{
|
||||
struct ipv4_lpm_key ipv4_key = {
|
||||
.prefixlen = prefixlen,
|
||||
.data = addr
|
||||
};
|
||||
return bpf_map_update_elem(lpm_fd, &ipv4_key, value, BPF_ANY);
|
||||
}
|
||||
|
||||
The following snippet shows a userspace program walking through the entries
|
||||
of an LPM trie:
|
||||
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
#include <bpf/libbpf.h>
|
||||
#include <bpf/bpf.h>
|
||||
|
||||
void iterate_lpm_trie(int map_fd)
|
||||
{
|
||||
struct ipv4_lpm_key *cur_key = NULL;
|
||||
struct ipv4_lpm_key next_key;
|
||||
struct value value;
|
||||
int err;
|
||||
|
||||
for (;;) {
|
||||
err = bpf_map_get_next_key(map_fd, cur_key, &next_key);
|
||||
if (err)
|
||||
break;
|
||||
|
||||
bpf_map_lookup_elem(map_fd, &next_key, &value);
|
||||
|
||||
/* Use key and value here */
|
||||
|
||||
cur_key = &next_key;
|
||||
}
|
||||
}
|
||||
@@ -20,8 +20,7 @@ The gl_holders list contains all the queued lock requests (not
|
||||
just the holders) associated with the glock. If there are any
|
||||
held locks, then they will be contiguous entries at the head
|
||||
of the list. Locks are granted in strictly the order that they
|
||||
are queued, except for those marked LM_FLAG_PRIORITY which are
|
||||
used only during recovery, and even then only for journal locks.
|
||||
are queued.
|
||||
|
||||
There are three lock states that users of the glock layer can request,
|
||||
namely shared (SH), deferred (DF) and exclusive (EX). Those translate
|
||||
|
||||
2
Makefile
2
Makefile
@@ -1,7 +1,7 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
VERSION = 6
|
||||
PATCHLEVEL = 1
|
||||
SUBLEVEL = 106
|
||||
SUBLEVEL = 107
|
||||
EXTRAVERSION =
|
||||
NAME = Curry Ramen
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
|
||||
#include <asm/numa.h>
|
||||
|
||||
static int acpi_early_node_map[NR_CPUS] __initdata = { NUMA_NO_NODE };
|
||||
static int acpi_early_node_map[NR_CPUS] __initdata = { [0 ... NR_CPUS - 1] = NUMA_NO_NODE };
|
||||
|
||||
int __init acpi_numa_get_nid(unsigned int cpu)
|
||||
{
|
||||
|
||||
@@ -367,9 +367,6 @@ void __init __no_sanitize_address setup_arch(char **cmdline_p)
|
||||
smp_init_cpus();
|
||||
smp_build_mpidr_hash();
|
||||
|
||||
/* Init percpu seeds for random tags after cpus are set up. */
|
||||
kasan_init_sw_tags();
|
||||
|
||||
#ifdef CONFIG_ARM64_SW_TTBR0_PAN
|
||||
/*
|
||||
* Make sure init_thread_info.ttbr0 always generates translation
|
||||
|
||||
@@ -469,6 +469,8 @@ void __init smp_prepare_boot_cpu(void)
|
||||
init_gic_priority_masking();
|
||||
|
||||
kasan_init_hw_tags();
|
||||
/* Init percpu seeds for random tags after cpus are set up. */
|
||||
kasan_init_sw_tags();
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
#include <trace/events/kvm.h>
|
||||
|
||||
#include "sys_regs.h"
|
||||
#include "vgic/vgic.h"
|
||||
|
||||
#include "trace.h"
|
||||
|
||||
@@ -180,6 +181,11 @@ static bool access_gic_sgi(struct kvm_vcpu *vcpu,
|
||||
{
|
||||
bool g1;
|
||||
|
||||
if (!kvm_has_gicv3(vcpu->kvm)) {
|
||||
kvm_inject_undefined(vcpu);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!p->is_write)
|
||||
return read_from_write_only(vcpu, p, r);
|
||||
|
||||
|
||||
@@ -343,4 +343,11 @@ void vgic_v4_configure_vsgis(struct kvm *kvm);
|
||||
void vgic_v4_get_vlpi_state(struct vgic_irq *irq, bool *val);
|
||||
int vgic_v4_request_vpe_irq(struct kvm_vcpu *vcpu, int irq);
|
||||
|
||||
static inline bool kvm_has_gicv3(struct kvm *kvm)
|
||||
{
|
||||
return (static_branch_unlikely(&kvm_vgic_global_state.gicv3_cpuif) &&
|
||||
irqchip_in_kernel(kvm) &&
|
||||
kvm->arch.vgic.vgic_model == KVM_DEV_TYPE_ARM_VGIC_V3);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1723,12 +1723,16 @@ static inline void cpu_probe_loongson(struct cpuinfo_mips *c, unsigned int cpu)
|
||||
c->ases |= (MIPS_ASE_LOONGSON_MMI | MIPS_ASE_LOONGSON_CAM |
|
||||
MIPS_ASE_LOONGSON_EXT | MIPS_ASE_LOONGSON_EXT2);
|
||||
c->ases &= ~MIPS_ASE_VZ; /* VZ of Loongson-3A2000/3000 is incomplete */
|
||||
change_c0_config6(LOONGSON_CONF6_EXTIMER | LOONGSON_CONF6_INTIMER,
|
||||
LOONGSON_CONF6_INTIMER);
|
||||
break;
|
||||
case PRID_IMP_LOONGSON_64G:
|
||||
__cpu_name[cpu] = "ICT Loongson-3";
|
||||
set_elf_platform(cpu, "loongson3a");
|
||||
set_isa(c, MIPS_CPU_ISA_M64R2);
|
||||
decode_cpucfg(c);
|
||||
change_c0_config6(LOONGSON_CONF6_EXTIMER | LOONGSON_CONF6_INTIMER,
|
||||
LOONGSON_CONF6_INTIMER);
|
||||
break;
|
||||
default:
|
||||
panic("Unknown Loongson Processor ID!");
|
||||
|
||||
@@ -270,6 +270,9 @@ void calibrate_delay(void)
|
||||
|
||||
void __init setup_arch(char **cmdline_p)
|
||||
{
|
||||
/* setup memblock allocator */
|
||||
setup_memory();
|
||||
|
||||
unflatten_and_copy_device_tree();
|
||||
|
||||
setup_cpuinfo();
|
||||
@@ -293,9 +296,6 @@ void __init setup_arch(char **cmdline_p)
|
||||
}
|
||||
#endif
|
||||
|
||||
/* setup memblock allocator */
|
||||
setup_memory();
|
||||
|
||||
/* paging_init() sets up the MMU and marks all pages as reserved */
|
||||
paging_init();
|
||||
|
||||
|
||||
@@ -501,7 +501,7 @@ void do_cpu_irq_mask(struct pt_regs *regs)
|
||||
|
||||
old_regs = set_irq_regs(regs);
|
||||
local_irq_disable();
|
||||
irq_enter();
|
||||
irq_enter_rcu();
|
||||
|
||||
eirr_val = mfctl(23) & cpu_eiem & per_cpu(local_ack_eiem, cpu);
|
||||
if (!eirr_val)
|
||||
@@ -536,7 +536,7 @@ void do_cpu_irq_mask(struct pt_regs *regs)
|
||||
#endif /* CONFIG_IRQSTACKS */
|
||||
|
||||
out:
|
||||
irq_exit();
|
||||
irq_exit_rcu();
|
||||
set_irq_regs(old_regs);
|
||||
return;
|
||||
|
||||
|
||||
@@ -112,8 +112,11 @@ static void *simple_realloc(void *ptr, unsigned long size)
|
||||
return ptr;
|
||||
|
||||
new = simple_malloc(size);
|
||||
memcpy(new, ptr, p->size);
|
||||
simple_free(ptr);
|
||||
if (new) {
|
||||
memcpy(new, ptr, p->size);
|
||||
simple_free(ptr);
|
||||
}
|
||||
|
||||
return new;
|
||||
}
|
||||
|
||||
|
||||
@@ -236,6 +236,8 @@ static int __init icp_native_map_one_cpu(int hw_id, unsigned long addr,
|
||||
rname = kasprintf(GFP_KERNEL, "CPU %d [0x%x] Interrupt Presentation",
|
||||
cpu, hw_id);
|
||||
|
||||
if (!rname)
|
||||
return -ENOMEM;
|
||||
if (!request_mem_region(addr, size, rname)) {
|
||||
pr_warn("icp_native: Could not reserve ICP MMIO for CPU %d, interrupt server #0x%x\n",
|
||||
cpu, hw_id);
|
||||
|
||||
@@ -816,7 +816,7 @@ static void __init create_kernel_page_table(pgd_t *pgdir,
|
||||
PMD_SIZE, PAGE_KERNEL_EXEC);
|
||||
|
||||
/* Map the data in RAM */
|
||||
end_va = kernel_map.virt_addr + XIP_OFFSET + kernel_map.size;
|
||||
end_va = kernel_map.virt_addr + kernel_map.size;
|
||||
for (va = kernel_map.virt_addr + XIP_OFFSET; va < end_va; va += PMD_SIZE)
|
||||
create_pgd_mapping(pgdir, va,
|
||||
kernel_map.phys_addr + (va - (kernel_map.virt_addr + XIP_OFFSET)),
|
||||
@@ -947,7 +947,7 @@ asmlinkage void __init setup_vm(uintptr_t dtb_pa)
|
||||
|
||||
phys_ram_base = CONFIG_PHYS_RAM_BASE;
|
||||
kernel_map.phys_addr = (uintptr_t)CONFIG_PHYS_RAM_BASE;
|
||||
kernel_map.size = (uintptr_t)(&_end) - (uintptr_t)(&_sdata);
|
||||
kernel_map.size = (uintptr_t)(&_end) - (uintptr_t)(&_start);
|
||||
|
||||
kernel_map.va_kernel_xip_pa_offset = kernel_map.virt_addr - kernel_map.xiprom;
|
||||
#else
|
||||
|
||||
@@ -387,7 +387,10 @@ static inline int share(unsigned long addr, u16 cmd)
|
||||
|
||||
if (!uv_call(0, (u64)&uvcb))
|
||||
return 0;
|
||||
return -EINVAL;
|
||||
pr_err("%s UVC failed (rc: 0x%x, rrc: 0x%x), possible hypervisor bug.\n",
|
||||
uvcb.header.cmd == UVC_CMD_SET_SHARED_ACCESS ? "Share" : "Unshare",
|
||||
uvcb.header.rc, uvcb.header.rrc);
|
||||
panic("System security cannot be guaranteed unless the system panics now.\n");
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -237,15 +237,9 @@ static inline void save_vector_registers(void)
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void setup_control_registers(void)
|
||||
static inline void setup_low_address_protection(void)
|
||||
{
|
||||
unsigned long reg;
|
||||
|
||||
__ctl_store(reg, 0, 0);
|
||||
reg |= CR0_LOW_ADDRESS_PROTECTION;
|
||||
reg |= CR0_EMERGENCY_SIGNAL_SUBMASK;
|
||||
reg |= CR0_EXTERNAL_CALL_SUBMASK;
|
||||
__ctl_load(reg, 0, 0);
|
||||
__ctl_set_bit(0, 28);
|
||||
}
|
||||
|
||||
static inline void setup_access_registers(void)
|
||||
@@ -304,7 +298,7 @@ void __init startup_init(void)
|
||||
save_vector_registers();
|
||||
setup_topology();
|
||||
sclp_early_detect();
|
||||
setup_control_registers();
|
||||
setup_low_address_protection();
|
||||
setup_access_registers();
|
||||
lockdep_on();
|
||||
}
|
||||
|
||||
@@ -1007,12 +1007,12 @@ void __init smp_fill_possible_mask(void)
|
||||
|
||||
void __init smp_prepare_cpus(unsigned int max_cpus)
|
||||
{
|
||||
/* request the 0x1201 emergency signal external interrupt */
|
||||
if (register_external_irq(EXT_IRQ_EMERGENCY_SIG, do_ext_call_interrupt))
|
||||
panic("Couldn't request external interrupt 0x1201");
|
||||
/* request the 0x1202 external call external interrupt */
|
||||
ctl_set_bit(0, 14);
|
||||
if (register_external_irq(EXT_IRQ_EXTERNAL_CALL, do_ext_call_interrupt))
|
||||
panic("Couldn't request external interrupt 0x1202");
|
||||
ctl_set_bit(0, 13);
|
||||
}
|
||||
|
||||
void __init smp_prepare_boot_cpu(void)
|
||||
|
||||
@@ -991,7 +991,10 @@ unsigned long arch_align_stack(unsigned long sp)
|
||||
|
||||
unsigned long arch_randomize_brk(struct mm_struct *mm)
|
||||
{
|
||||
return randomize_page(mm->brk, 0x02000000);
|
||||
if (mmap_is_ia32())
|
||||
return randomize_page(mm->brk, SZ_32M);
|
||||
|
||||
return randomize_page(mm->brk, SZ_1G);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -1843,8 +1843,12 @@ static bool set_target_expiration(struct kvm_lapic *apic, u32 count_reg)
|
||||
if (unlikely(count_reg != APIC_TMICT)) {
|
||||
deadline = tmict_to_ns(apic,
|
||||
kvm_lapic_get_reg(apic, count_reg));
|
||||
if (unlikely(deadline <= 0))
|
||||
deadline = apic->lapic_timer.period;
|
||||
if (unlikely(deadline <= 0)) {
|
||||
if (apic_lvtt_period(apic))
|
||||
deadline = apic->lapic_timer.period;
|
||||
else
|
||||
deadline = 0;
|
||||
}
|
||||
else if (unlikely(deadline > apic->lapic_timer.period)) {
|
||||
pr_info_ratelimited(
|
||||
"kvm: vcpu %i: requested lapic timer restore with "
|
||||
|
||||
@@ -1118,8 +1118,8 @@ dequeue_rx(struct idt77252_dev *card, struct rsq_entry *rsqe)
|
||||
rpp->len += skb->len;
|
||||
|
||||
if (stat & SAR_RSQE_EPDU) {
|
||||
unsigned int len, truesize;
|
||||
unsigned char *l1l2;
|
||||
unsigned int len;
|
||||
|
||||
l1l2 = (unsigned char *) ((unsigned long) skb->data + skb->len - 6);
|
||||
|
||||
@@ -1189,14 +1189,15 @@ dequeue_rx(struct idt77252_dev *card, struct rsq_entry *rsqe)
|
||||
ATM_SKB(skb)->vcc = vcc;
|
||||
__net_timestamp(skb);
|
||||
|
||||
truesize = skb->truesize;
|
||||
vcc->push(vcc, skb);
|
||||
atomic_inc(&vcc->stats->rx);
|
||||
|
||||
if (skb->truesize > SAR_FB_SIZE_3)
|
||||
if (truesize > SAR_FB_SIZE_3)
|
||||
add_rx_skb(card, 3, SAR_FB_SIZE_3, 1);
|
||||
else if (skb->truesize > SAR_FB_SIZE_2)
|
||||
else if (truesize > SAR_FB_SIZE_2)
|
||||
add_rx_skb(card, 2, SAR_FB_SIZE_2, 1);
|
||||
else if (skb->truesize > SAR_FB_SIZE_1)
|
||||
else if (truesize > SAR_FB_SIZE_1)
|
||||
add_rx_skb(card, 1, SAR_FB_SIZE_1, 1);
|
||||
else
|
||||
add_rx_skb(card, 0, SAR_FB_SIZE_0, 1);
|
||||
|
||||
@@ -770,7 +770,8 @@ static int hci_uart_tty_ioctl(struct tty_struct *tty, unsigned int cmd,
|
||||
break;
|
||||
|
||||
case HCIUARTGETPROTO:
|
||||
if (test_bit(HCI_UART_PROTO_SET, &hu->flags))
|
||||
if (test_bit(HCI_UART_PROTO_SET, &hu->flags) &&
|
||||
test_bit(HCI_UART_PROTO_READY, &hu->flags))
|
||||
err = hu->proto->id;
|
||||
else
|
||||
err = -EUNATCH;
|
||||
|
||||
@@ -50,6 +50,7 @@ MODULE_LICENSE("GPL v2");
|
||||
static const char xillyname[] = "xillyusb";
|
||||
|
||||
static unsigned int fifo_buf_order;
|
||||
static struct workqueue_struct *wakeup_wq;
|
||||
|
||||
#define USB_VENDOR_ID_XILINX 0x03fd
|
||||
#define USB_VENDOR_ID_ALTERA 0x09fb
|
||||
@@ -561,10 +562,6 @@ static void cleanup_dev(struct kref *kref)
|
||||
* errors if executed. The mechanism relies on that xdev->error is assigned
|
||||
* a non-zero value by report_io_error() prior to queueing wakeup_all(),
|
||||
* which prevents bulk_in_work() from calling process_bulk_in().
|
||||
*
|
||||
* The fact that wakeup_all() and bulk_in_work() are queued on the same
|
||||
* workqueue makes their concurrent execution very unlikely, however the
|
||||
* kernel's API doesn't seem to ensure this strictly.
|
||||
*/
|
||||
|
||||
static void wakeup_all(struct work_struct *work)
|
||||
@@ -619,7 +616,7 @@ static void report_io_error(struct xillyusb_dev *xdev,
|
||||
|
||||
if (do_once) {
|
||||
kref_get(&xdev->kref); /* xdev is used by work item */
|
||||
queue_work(xdev->workq, &xdev->wakeup_workitem);
|
||||
queue_work(wakeup_wq, &xdev->wakeup_workitem);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1892,6 +1889,13 @@ static const struct file_operations xillyusb_fops = {
|
||||
|
||||
static int xillyusb_setup_base_eps(struct xillyusb_dev *xdev)
|
||||
{
|
||||
struct usb_device *udev = xdev->udev;
|
||||
|
||||
/* Verify that device has the two fundamental bulk in/out endpoints */
|
||||
if (usb_pipe_type_check(udev, usb_sndbulkpipe(udev, MSG_EP_NUM)) ||
|
||||
usb_pipe_type_check(udev, usb_rcvbulkpipe(udev, IN_EP_NUM)))
|
||||
return -ENODEV;
|
||||
|
||||
xdev->msg_ep = endpoint_alloc(xdev, MSG_EP_NUM | USB_DIR_OUT,
|
||||
bulk_out_work, 1, 2);
|
||||
if (!xdev->msg_ep)
|
||||
@@ -1921,14 +1925,15 @@ static int setup_channels(struct xillyusb_dev *xdev,
|
||||
__le16 *chandesc,
|
||||
int num_channels)
|
||||
{
|
||||
struct xillyusb_channel *chan;
|
||||
struct usb_device *udev = xdev->udev;
|
||||
struct xillyusb_channel *chan, *new_channels;
|
||||
int i;
|
||||
|
||||
chan = kcalloc(num_channels, sizeof(*chan), GFP_KERNEL);
|
||||
if (!chan)
|
||||
return -ENOMEM;
|
||||
|
||||
xdev->channels = chan;
|
||||
new_channels = chan;
|
||||
|
||||
for (i = 0; i < num_channels; i++, chan++) {
|
||||
unsigned int in_desc = le16_to_cpu(*chandesc++);
|
||||
@@ -1957,6 +1962,15 @@ static int setup_channels(struct xillyusb_dev *xdev,
|
||||
*/
|
||||
|
||||
if ((out_desc & 0x80) && i < 14) { /* Entry is valid */
|
||||
if (usb_pipe_type_check(udev,
|
||||
usb_sndbulkpipe(udev, i + 2))) {
|
||||
dev_err(xdev->dev,
|
||||
"Missing BULK OUT endpoint %d\n",
|
||||
i + 2);
|
||||
kfree(new_channels);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
chan->writable = 1;
|
||||
chan->out_synchronous = !!(out_desc & 0x40);
|
||||
chan->out_seekable = !!(out_desc & 0x20);
|
||||
@@ -1966,6 +1980,7 @@ static int setup_channels(struct xillyusb_dev *xdev,
|
||||
}
|
||||
}
|
||||
|
||||
xdev->channels = new_channels;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -2082,9 +2097,11 @@ static int xillyusb_discovery(struct usb_interface *interface)
|
||||
* just after responding with the IDT, there is no reason for any
|
||||
* work item to be running now. To be sure that xdev->channels
|
||||
* is updated on anything that might run in parallel, flush the
|
||||
* workqueue, which rarely does anything.
|
||||
* device's workqueue and the wakeup work item. This rarely
|
||||
* does anything.
|
||||
*/
|
||||
flush_workqueue(xdev->workq);
|
||||
flush_work(&xdev->wakeup_workitem);
|
||||
|
||||
xdev->num_channels = num_channels;
|
||||
|
||||
@@ -2242,6 +2259,10 @@ static int __init xillyusb_init(void)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
wakeup_wq = alloc_workqueue(xillyname, 0, 0);
|
||||
if (!wakeup_wq)
|
||||
return -ENOMEM;
|
||||
|
||||
if (LOG2_INITIAL_FIFO_BUF_SIZE > PAGE_SHIFT)
|
||||
fifo_buf_order = LOG2_INITIAL_FIFO_BUF_SIZE - PAGE_SHIFT;
|
||||
else
|
||||
@@ -2249,12 +2270,17 @@ static int __init xillyusb_init(void)
|
||||
|
||||
rc = usb_register(&xillyusb_driver);
|
||||
|
||||
if (rc)
|
||||
destroy_workqueue(wakeup_wq);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void __exit xillyusb_exit(void)
|
||||
{
|
||||
usb_deregister(&xillyusb_driver);
|
||||
|
||||
destroy_workqueue(wakeup_wq);
|
||||
}
|
||||
|
||||
module_init(xillyusb_init);
|
||||
|
||||
@@ -329,12 +329,12 @@ struct visconti_pll_provider * __init visconti_init_pll(struct device_node *np,
|
||||
if (!ctx)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
for (i = 0; i < nr_plls; ++i)
|
||||
ctx->clk_data.hws[i] = ERR_PTR(-ENOENT);
|
||||
|
||||
ctx->node = np;
|
||||
ctx->reg_base = base;
|
||||
ctx->clk_data.num = nr_plls;
|
||||
|
||||
for (i = 0; i < nr_plls; ++i)
|
||||
ctx->clk_data.hws[i] = ERR_PTR(-ENOENT);
|
||||
|
||||
return ctx;
|
||||
}
|
||||
|
||||
@@ -290,18 +290,17 @@ static int gt_clk_rate_change_cb(struct notifier_block *nb,
|
||||
switch (event) {
|
||||
case PRE_RATE_CHANGE:
|
||||
{
|
||||
int psv;
|
||||
unsigned long psv;
|
||||
|
||||
psv = DIV_ROUND_CLOSEST(ndata->new_rate,
|
||||
gt_target_rate);
|
||||
|
||||
if (abs(gt_target_rate - (ndata->new_rate / psv)) > MAX_F_ERR)
|
||||
psv = DIV_ROUND_CLOSEST(ndata->new_rate, gt_target_rate);
|
||||
if (!psv ||
|
||||
abs(gt_target_rate - (ndata->new_rate / psv)) > MAX_F_ERR)
|
||||
return NOTIFY_BAD;
|
||||
|
||||
psv--;
|
||||
|
||||
/* prescaler within legal range? */
|
||||
if (psv < 0 || psv > GT_CONTROL_PRESCALER_MAX)
|
||||
if (psv > GT_CONTROL_PRESCALER_MAX)
|
||||
return NOTIFY_BAD;
|
||||
|
||||
/*
|
||||
|
||||
@@ -490,7 +490,7 @@ void cs_dsp_cleanup_debugfs(struct cs_dsp *dsp)
|
||||
{
|
||||
cs_dsp_debugfs_clear(dsp);
|
||||
debugfs_remove_recursive(dsp->debugfs_root);
|
||||
dsp->debugfs_root = NULL;
|
||||
dsp->debugfs_root = ERR_PTR(-ENODEV);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(cs_dsp_cleanup_debugfs);
|
||||
#else
|
||||
@@ -2300,6 +2300,11 @@ static int cs_dsp_common_init(struct cs_dsp *dsp)
|
||||
|
||||
mutex_init(&dsp->pwr_lock);
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
/* Ensure this is invalid if client never provides a debugfs root */
|
||||
dsp->debugfs_root = ERR_PTR(-ENODEV);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -286,6 +286,7 @@ int amdgpu_amdkfd_gpuvm_map_memory_to_gpu(struct amdgpu_device *adev,
|
||||
struct kgd_mem *mem, void *drm_priv);
|
||||
int amdgpu_amdkfd_gpuvm_unmap_memory_from_gpu(
|
||||
struct amdgpu_device *adev, struct kgd_mem *mem, void *drm_priv);
|
||||
int amdgpu_amdkfd_gpuvm_dmaunmap_mem(struct kgd_mem *mem, void *drm_priv);
|
||||
int amdgpu_amdkfd_gpuvm_sync_memory(
|
||||
struct amdgpu_device *adev, struct kgd_mem *mem, bool intr);
|
||||
int amdgpu_amdkfd_gpuvm_map_gtt_bo_to_kernel(struct kgd_mem *mem,
|
||||
|
||||
@@ -719,7 +719,7 @@ kfd_mem_dmaunmap_sg_bo(struct kgd_mem *mem,
|
||||
enum dma_data_direction dir;
|
||||
|
||||
if (unlikely(!ttm->sg)) {
|
||||
pr_err("SG Table of BO is UNEXPECTEDLY NULL");
|
||||
pr_debug("SG Table of BO is NULL");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1226,8 +1226,6 @@ static void unmap_bo_from_gpuvm(struct kgd_mem *mem,
|
||||
amdgpu_vm_clear_freed(adev, vm, &bo_va->last_pt_update);
|
||||
|
||||
amdgpu_sync_fence(sync, bo_va->last_pt_update);
|
||||
|
||||
kfd_mem_dmaunmap_attachment(mem, entry);
|
||||
}
|
||||
|
||||
static int update_gpuvm_pte(struct kgd_mem *mem,
|
||||
@@ -1282,6 +1280,7 @@ static int map_bo_to_gpuvm(struct kgd_mem *mem,
|
||||
|
||||
update_gpuvm_pte_failed:
|
||||
unmap_bo_from_gpuvm(mem, entry, sync);
|
||||
kfd_mem_dmaunmap_attachment(mem, entry);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -1852,8 +1851,10 @@ int amdgpu_amdkfd_gpuvm_free_memory_of_gpu(
|
||||
mem->va + bo_size * (1 + mem->aql_queue));
|
||||
|
||||
/* Remove from VM internal data structures */
|
||||
list_for_each_entry_safe(entry, tmp, &mem->attachments, list)
|
||||
list_for_each_entry_safe(entry, tmp, &mem->attachments, list) {
|
||||
kfd_mem_dmaunmap_attachment(mem, entry);
|
||||
kfd_mem_detach(entry);
|
||||
}
|
||||
|
||||
ret = unreserve_bo_and_vms(&ctx, false, false);
|
||||
|
||||
@@ -2024,6 +2025,37 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int amdgpu_amdkfd_gpuvm_dmaunmap_mem(struct kgd_mem *mem, void *drm_priv)
|
||||
{
|
||||
struct kfd_mem_attachment *entry;
|
||||
struct amdgpu_vm *vm;
|
||||
int ret;
|
||||
|
||||
vm = drm_priv_to_vm(drm_priv);
|
||||
|
||||
mutex_lock(&mem->lock);
|
||||
|
||||
ret = amdgpu_bo_reserve(mem->bo, true);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
list_for_each_entry(entry, &mem->attachments, list) {
|
||||
if (entry->bo_va->base.vm != vm)
|
||||
continue;
|
||||
if (entry->bo_va->base.bo->tbo.ttm &&
|
||||
!entry->bo_va->base.bo->tbo.ttm->sg)
|
||||
continue;
|
||||
|
||||
kfd_mem_dmaunmap_attachment(mem, entry);
|
||||
}
|
||||
|
||||
amdgpu_bo_unreserve(mem->bo);
|
||||
out:
|
||||
mutex_unlock(&mem->lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int amdgpu_amdkfd_gpuvm_unmap_memory_from_gpu(
|
||||
struct amdgpu_device *adev, struct kgd_mem *mem, void *drm_priv)
|
||||
{
|
||||
|
||||
@@ -656,16 +656,24 @@ int amdgpu_ctx_ioctl(struct drm_device *dev, void *data,
|
||||
|
||||
switch (args->in.op) {
|
||||
case AMDGPU_CTX_OP_ALLOC_CTX:
|
||||
if (args->in.flags)
|
||||
return -EINVAL;
|
||||
r = amdgpu_ctx_alloc(adev, fpriv, filp, priority, &id);
|
||||
args->out.alloc.ctx_id = id;
|
||||
break;
|
||||
case AMDGPU_CTX_OP_FREE_CTX:
|
||||
if (args->in.flags)
|
||||
return -EINVAL;
|
||||
r = amdgpu_ctx_free(fpriv, id);
|
||||
break;
|
||||
case AMDGPU_CTX_OP_QUERY_STATE:
|
||||
if (args->in.flags)
|
||||
return -EINVAL;
|
||||
r = amdgpu_ctx_query(adev, fpriv, id, &args->out);
|
||||
break;
|
||||
case AMDGPU_CTX_OP_QUERY_STATE2:
|
||||
if (args->in.flags)
|
||||
return -EINVAL;
|
||||
r = amdgpu_ctx_query2(adev, fpriv, id, &args->out);
|
||||
break;
|
||||
case AMDGPU_CTX_OP_GET_STABLE_PSTATE:
|
||||
|
||||
@@ -148,6 +148,9 @@ static ssize_t ta_if_load_debugfs_write(struct file *fp, const char *buf, size_t
|
||||
if (ret)
|
||||
return -EINVAL;
|
||||
|
||||
if (ta_bin_len > PSP_1_MEG)
|
||||
return -EINVAL;
|
||||
|
||||
copy_pos += sizeof(uint32_t);
|
||||
|
||||
ta_bin = kzalloc(ta_bin_len, GFP_KERNEL);
|
||||
|
||||
@@ -239,6 +239,10 @@ int amdgpu_vcn_sw_init(struct amdgpu_device *adev)
|
||||
return r;
|
||||
}
|
||||
|
||||
/* from vcn4 and above, only unified queue is used */
|
||||
adev->vcn.using_unified_queue =
|
||||
adev->ip_versions[UVD_HWIP][0] >= IP_VERSION(4, 0, 0);
|
||||
|
||||
hdr = (const struct common_firmware_header *)adev->vcn.fw->data;
|
||||
adev->vcn.fw_version = le32_to_cpu(hdr->ucode_version);
|
||||
|
||||
@@ -357,18 +361,6 @@ int amdgpu_vcn_sw_fini(struct amdgpu_device *adev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* from vcn4 and above, only unified queue is used */
|
||||
static bool amdgpu_vcn_using_unified_queue(struct amdgpu_ring *ring)
|
||||
{
|
||||
struct amdgpu_device *adev = ring->adev;
|
||||
bool ret = false;
|
||||
|
||||
if (adev->ip_versions[UVD_HWIP][0] >= IP_VERSION(4, 0, 0))
|
||||
ret = true;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool amdgpu_vcn_is_disabled_vcn(struct amdgpu_device *adev, enum vcn_ring_type type, uint32_t vcn_instance)
|
||||
{
|
||||
bool ret = false;
|
||||
@@ -480,7 +472,9 @@ static void amdgpu_vcn_idle_work_handler(struct work_struct *work)
|
||||
fence[j] += amdgpu_fence_count_emitted(&adev->vcn.inst[j].ring_enc[i]);
|
||||
}
|
||||
|
||||
if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) {
|
||||
/* Only set DPG pause for VCN3 or below, VCN4 and above will be handled by FW */
|
||||
if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG &&
|
||||
!adev->vcn.using_unified_queue) {
|
||||
struct dpg_pause_state new_state;
|
||||
|
||||
if (fence[j] ||
|
||||
@@ -526,7 +520,9 @@ void amdgpu_vcn_ring_begin_use(struct amdgpu_ring *ring)
|
||||
amdgpu_device_ip_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_VCN,
|
||||
AMD_PG_STATE_UNGATE);
|
||||
|
||||
if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) {
|
||||
/* Only set DPG pause for VCN3 or below, VCN4 and above will be handled by FW */
|
||||
if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG &&
|
||||
!adev->vcn.using_unified_queue) {
|
||||
struct dpg_pause_state new_state;
|
||||
|
||||
if (ring->funcs->type == AMDGPU_RING_TYPE_VCN_ENC) {
|
||||
@@ -552,8 +548,12 @@ void amdgpu_vcn_ring_begin_use(struct amdgpu_ring *ring)
|
||||
|
||||
void amdgpu_vcn_ring_end_use(struct amdgpu_ring *ring)
|
||||
{
|
||||
struct amdgpu_device *adev = ring->adev;
|
||||
|
||||
/* Only set DPG pause for VCN3 or below, VCN4 and above will be handled by FW */
|
||||
if (ring->adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG &&
|
||||
ring->funcs->type == AMDGPU_RING_TYPE_VCN_ENC)
|
||||
ring->funcs->type == AMDGPU_RING_TYPE_VCN_ENC &&
|
||||
!adev->vcn.using_unified_queue)
|
||||
atomic_dec(&ring->adev->vcn.inst[ring->me].dpg_enc_submission_cnt);
|
||||
|
||||
atomic_dec(&ring->adev->vcn.total_submission_cnt);
|
||||
@@ -806,12 +806,11 @@ static int amdgpu_vcn_dec_sw_send_msg(struct amdgpu_ring *ring,
|
||||
struct amdgpu_job *job;
|
||||
struct amdgpu_ib *ib;
|
||||
uint64_t addr = AMDGPU_GPU_PAGE_ALIGN(ib_msg->gpu_addr);
|
||||
bool sq = amdgpu_vcn_using_unified_queue(ring);
|
||||
uint32_t *ib_checksum;
|
||||
uint32_t ib_pack_in_dw;
|
||||
int i, r;
|
||||
|
||||
if (sq)
|
||||
if (adev->vcn.using_unified_queue)
|
||||
ib_size_dw += 8;
|
||||
|
||||
r = amdgpu_job_alloc_with_ib(adev, ib_size_dw * 4,
|
||||
@@ -823,7 +822,7 @@ static int amdgpu_vcn_dec_sw_send_msg(struct amdgpu_ring *ring,
|
||||
ib->length_dw = 0;
|
||||
|
||||
/* single queue headers */
|
||||
if (sq) {
|
||||
if (adev->vcn.using_unified_queue) {
|
||||
ib_pack_in_dw = sizeof(struct amdgpu_vcn_decode_buffer) / sizeof(uint32_t)
|
||||
+ 4 + 2; /* engine info + decoding ib in dw */
|
||||
ib_checksum = amdgpu_vcn_unified_ring_ib_header(ib, ib_pack_in_dw, false);
|
||||
@@ -842,7 +841,7 @@ static int amdgpu_vcn_dec_sw_send_msg(struct amdgpu_ring *ring,
|
||||
for (i = ib->length_dw; i < ib_size_dw; ++i)
|
||||
ib->ptr[i] = 0x0;
|
||||
|
||||
if (sq)
|
||||
if (adev->vcn.using_unified_queue)
|
||||
amdgpu_vcn_unified_ring_ib_checksum(&ib_checksum, ib_pack_in_dw);
|
||||
|
||||
r = amdgpu_job_submit_direct(job, ring, &f);
|
||||
@@ -932,15 +931,15 @@ static int amdgpu_vcn_enc_get_create_msg(struct amdgpu_ring *ring, uint32_t hand
|
||||
struct dma_fence **fence)
|
||||
{
|
||||
unsigned int ib_size_dw = 16;
|
||||
struct amdgpu_device *adev = ring->adev;
|
||||
struct amdgpu_job *job;
|
||||
struct amdgpu_ib *ib;
|
||||
struct dma_fence *f = NULL;
|
||||
uint32_t *ib_checksum = NULL;
|
||||
uint64_t addr;
|
||||
bool sq = amdgpu_vcn_using_unified_queue(ring);
|
||||
int i, r;
|
||||
|
||||
if (sq)
|
||||
if (adev->vcn.using_unified_queue)
|
||||
ib_size_dw += 8;
|
||||
|
||||
r = amdgpu_job_alloc_with_ib(ring->adev, ib_size_dw * 4,
|
||||
@@ -953,7 +952,7 @@ static int amdgpu_vcn_enc_get_create_msg(struct amdgpu_ring *ring, uint32_t hand
|
||||
|
||||
ib->length_dw = 0;
|
||||
|
||||
if (sq)
|
||||
if (adev->vcn.using_unified_queue)
|
||||
ib_checksum = amdgpu_vcn_unified_ring_ib_header(ib, 0x11, true);
|
||||
|
||||
ib->ptr[ib->length_dw++] = 0x00000018;
|
||||
@@ -975,7 +974,7 @@ static int amdgpu_vcn_enc_get_create_msg(struct amdgpu_ring *ring, uint32_t hand
|
||||
for (i = ib->length_dw; i < ib_size_dw; ++i)
|
||||
ib->ptr[i] = 0x0;
|
||||
|
||||
if (sq)
|
||||
if (adev->vcn.using_unified_queue)
|
||||
amdgpu_vcn_unified_ring_ib_checksum(&ib_checksum, 0x11);
|
||||
|
||||
r = amdgpu_job_submit_direct(job, ring, &f);
|
||||
@@ -998,15 +997,15 @@ static int amdgpu_vcn_enc_get_destroy_msg(struct amdgpu_ring *ring, uint32_t han
|
||||
struct dma_fence **fence)
|
||||
{
|
||||
unsigned int ib_size_dw = 16;
|
||||
struct amdgpu_device *adev = ring->adev;
|
||||
struct amdgpu_job *job;
|
||||
struct amdgpu_ib *ib;
|
||||
struct dma_fence *f = NULL;
|
||||
uint32_t *ib_checksum = NULL;
|
||||
uint64_t addr;
|
||||
bool sq = amdgpu_vcn_using_unified_queue(ring);
|
||||
int i, r;
|
||||
|
||||
if (sq)
|
||||
if (adev->vcn.using_unified_queue)
|
||||
ib_size_dw += 8;
|
||||
|
||||
r = amdgpu_job_alloc_with_ib(ring->adev, ib_size_dw * 4,
|
||||
@@ -1019,7 +1018,7 @@ static int amdgpu_vcn_enc_get_destroy_msg(struct amdgpu_ring *ring, uint32_t han
|
||||
|
||||
ib->length_dw = 0;
|
||||
|
||||
if (sq)
|
||||
if (adev->vcn.using_unified_queue)
|
||||
ib_checksum = amdgpu_vcn_unified_ring_ib_header(ib, 0x11, true);
|
||||
|
||||
ib->ptr[ib->length_dw++] = 0x00000018;
|
||||
@@ -1041,7 +1040,7 @@ static int amdgpu_vcn_enc_get_destroy_msg(struct amdgpu_ring *ring, uint32_t han
|
||||
for (i = ib->length_dw; i < ib_size_dw; ++i)
|
||||
ib->ptr[i] = 0x0;
|
||||
|
||||
if (sq)
|
||||
if (adev->vcn.using_unified_queue)
|
||||
amdgpu_vcn_unified_ring_ib_checksum(&ib_checksum, 0x11);
|
||||
|
||||
r = amdgpu_job_submit_direct(job, ring, &f);
|
||||
|
||||
@@ -271,6 +271,7 @@ struct amdgpu_vcn {
|
||||
|
||||
struct ras_common_if *ras_if;
|
||||
struct amdgpu_vcn_ras *ras;
|
||||
bool using_unified_queue;
|
||||
};
|
||||
|
||||
struct amdgpu_fw_shared_rb_ptrs_struct {
|
||||
|
||||
@@ -754,11 +754,15 @@ int amdgpu_vm_pde_update(struct amdgpu_vm_update_params *params,
|
||||
struct amdgpu_vm_bo_base *entry)
|
||||
{
|
||||
struct amdgpu_vm_bo_base *parent = amdgpu_vm_pt_parent(entry);
|
||||
struct amdgpu_bo *bo = parent->bo, *pbo;
|
||||
struct amdgpu_bo *bo, *pbo;
|
||||
struct amdgpu_vm *vm = params->vm;
|
||||
uint64_t pde, pt, flags;
|
||||
unsigned int level;
|
||||
|
||||
if (WARN_ON(!parent))
|
||||
return -EINVAL;
|
||||
|
||||
bo = parent->bo;
|
||||
for (level = 0, pbo = bo->parent; pbo; ++level)
|
||||
pbo = pbo->parent;
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@ MODULE_FIRMWARE("amdgpu/gc_11_0_3_imu.bin");
|
||||
|
||||
static int imu_v11_0_init_microcode(struct amdgpu_device *adev)
|
||||
{
|
||||
char fw_name[40];
|
||||
char fw_name[45];
|
||||
char ucode_prefix[30];
|
||||
int err;
|
||||
const struct imu_firmware_header_v1_0 *imu_hdr;
|
||||
|
||||
@@ -541,11 +541,11 @@ void jpeg_v2_0_dec_ring_emit_ib(struct amdgpu_ring *ring,
|
||||
|
||||
amdgpu_ring_write(ring, PACKETJ(mmUVD_LMI_JRBC_IB_VMID_INTERNAL_OFFSET,
|
||||
0, 0, PACKETJ_TYPE0));
|
||||
amdgpu_ring_write(ring, (vmid | (vmid << 4)));
|
||||
amdgpu_ring_write(ring, (vmid | (vmid << 4) | (vmid << 8)));
|
||||
|
||||
amdgpu_ring_write(ring, PACKETJ(mmUVD_LMI_JPEG_VMID_INTERNAL_OFFSET,
|
||||
0, 0, PACKETJ_TYPE0));
|
||||
amdgpu_ring_write(ring, (vmid | (vmid << 4)));
|
||||
amdgpu_ring_write(ring, (vmid | (vmid << 4) | (vmid << 8)));
|
||||
|
||||
amdgpu_ring_write(ring, PACKETJ(mmUVD_LMI_JRBC_IB_64BIT_BAR_LOW_INTERNAL_OFFSET,
|
||||
0, 0, PACKETJ_TYPE0));
|
||||
|
||||
@@ -1400,17 +1400,23 @@ static int kfd_ioctl_unmap_memory_from_gpu(struct file *filep,
|
||||
goto sync_memory_failed;
|
||||
}
|
||||
}
|
||||
|
||||
/* Flush TLBs after waiting for the page table updates to complete */
|
||||
for (i = 0; i < args->n_devices; i++) {
|
||||
peer_pdd = kfd_process_device_data_by_id(p, devices_arr[i]);
|
||||
if (WARN_ON_ONCE(!peer_pdd))
|
||||
continue;
|
||||
if (flush_tlb)
|
||||
kfd_flush_tlb(peer_pdd, TLB_FLUSH_HEAVYWEIGHT);
|
||||
|
||||
/* Remove dma mapping after tlb flush to avoid IO_PAGE_FAULT */
|
||||
err = amdgpu_amdkfd_gpuvm_dmaunmap_mem(mem, peer_pdd->drm_priv);
|
||||
if (err)
|
||||
goto sync_memory_failed;
|
||||
}
|
||||
|
||||
mutex_unlock(&p->mutex);
|
||||
|
||||
if (flush_tlb) {
|
||||
/* Flush TLBs after waiting for the page table updates to complete */
|
||||
for (i = 0; i < args->n_devices; i++) {
|
||||
peer_pdd = kfd_process_device_data_by_id(p, devices_arr[i]);
|
||||
if (WARN_ON_ONCE(!peer_pdd))
|
||||
continue;
|
||||
kfd_flush_tlb(peer_pdd, TLB_FLUSH_HEAVYWEIGHT);
|
||||
}
|
||||
}
|
||||
kfree(devices_arr);
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -3633,7 +3633,7 @@ void dcn10_set_cursor_position(struct pipe_ctx *pipe_ctx)
|
||||
(int)hubp->curs_attr.width || pos_cpy.x
|
||||
<= (int)hubp->curs_attr.width +
|
||||
pipe_ctx->plane_state->src_rect.x) {
|
||||
pos_cpy.x = 2 * viewport_width - temp_x;
|
||||
pos_cpy.x = temp_x + viewport_width;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/math64.h>
|
||||
#include <linux/media-bus-format.h>
|
||||
#include <linux/minmax.h>
|
||||
#include <linux/module.h>
|
||||
@@ -158,6 +159,7 @@ struct tc358768_priv {
|
||||
u32 frs; /* PLL Freqency range for HSCK (post divider) */
|
||||
|
||||
u32 dsiclk; /* pll_clk / 2 */
|
||||
u32 pclk; /* incoming pclk rate */
|
||||
};
|
||||
|
||||
static inline struct tc358768_priv *dsi_host_to_tc358768(struct mipi_dsi_host
|
||||
@@ -381,6 +383,7 @@ found:
|
||||
priv->prd = best_prd;
|
||||
priv->frs = frs;
|
||||
priv->dsiclk = best_pll / 2;
|
||||
priv->pclk = mode->clock * 1000;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -639,6 +642,28 @@ static u32 tc358768_ps_to_ns(u32 ps)
|
||||
return ps / 1000;
|
||||
}
|
||||
|
||||
static u32 tc358768_dpi_to_ns(u32 val, u32 pclk)
|
||||
{
|
||||
return (u32)div_u64((u64)val * NANO, pclk);
|
||||
}
|
||||
|
||||
/* Convert value in DPI pixel clock units to DSI byte count */
|
||||
static u32 tc358768_dpi_to_dsi_bytes(struct tc358768_priv *priv, u32 val)
|
||||
{
|
||||
u64 m = (u64)val * priv->dsiclk / 4 * priv->dsi_lanes;
|
||||
u64 n = priv->pclk;
|
||||
|
||||
return (u32)div_u64(m + n - 1, n);
|
||||
}
|
||||
|
||||
static u32 tc358768_dsi_bytes_to_ns(struct tc358768_priv *priv, u32 val)
|
||||
{
|
||||
u64 m = (u64)val * NANO;
|
||||
u64 n = priv->dsiclk / 4 * priv->dsi_lanes;
|
||||
|
||||
return (u32)div_u64(m, n);
|
||||
}
|
||||
|
||||
static void tc358768_bridge_pre_enable(struct drm_bridge *bridge)
|
||||
{
|
||||
struct tc358768_priv *priv = bridge_to_tc358768(bridge);
|
||||
@@ -648,11 +673,19 @@ static void tc358768_bridge_pre_enable(struct drm_bridge *bridge)
|
||||
s32 raw_val;
|
||||
const struct drm_display_mode *mode;
|
||||
u32 hsbyteclk_ps, dsiclk_ps, ui_ps;
|
||||
u32 dsiclk, hsbyteclk, video_start;
|
||||
const u32 internal_delay = 40;
|
||||
u32 dsiclk, hsbyteclk;
|
||||
int ret, i;
|
||||
struct videomode vm;
|
||||
struct device *dev = priv->dev;
|
||||
/* In pixelclock units */
|
||||
u32 dpi_htot, dpi_data_start;
|
||||
/* In byte units */
|
||||
u32 dsi_dpi_htot, dsi_dpi_data_start;
|
||||
u32 dsi_hsw, dsi_hbp, dsi_hact, dsi_hfp;
|
||||
const u32 dsi_hss = 4; /* HSS is a short packet (4 bytes) */
|
||||
/* In hsbyteclk units */
|
||||
u32 dsi_vsdly;
|
||||
const u32 internal_dly = 40;
|
||||
|
||||
if (mode_flags & MIPI_DSI_CLOCK_NON_CONTINUOUS) {
|
||||
dev_warn_once(dev, "Non-continuous mode unimplemented, falling back to continuous\n");
|
||||
@@ -687,27 +720,23 @@ static void tc358768_bridge_pre_enable(struct drm_bridge *bridge)
|
||||
case MIPI_DSI_FMT_RGB888:
|
||||
val |= (0x3 << 4);
|
||||
hact = vm.hactive * 3;
|
||||
video_start = (vm.hsync_len + vm.hback_porch) * 3;
|
||||
data_type = MIPI_DSI_PACKED_PIXEL_STREAM_24;
|
||||
break;
|
||||
case MIPI_DSI_FMT_RGB666:
|
||||
val |= (0x4 << 4);
|
||||
hact = vm.hactive * 3;
|
||||
video_start = (vm.hsync_len + vm.hback_porch) * 3;
|
||||
data_type = MIPI_DSI_PACKED_PIXEL_STREAM_18;
|
||||
break;
|
||||
|
||||
case MIPI_DSI_FMT_RGB666_PACKED:
|
||||
val |= (0x4 << 4) | BIT(3);
|
||||
hact = vm.hactive * 18 / 8;
|
||||
video_start = (vm.hsync_len + vm.hback_porch) * 18 / 8;
|
||||
data_type = MIPI_DSI_PIXEL_STREAM_3BYTE_18;
|
||||
break;
|
||||
|
||||
case MIPI_DSI_FMT_RGB565:
|
||||
val |= (0x5 << 4);
|
||||
hact = vm.hactive * 2;
|
||||
video_start = (vm.hsync_len + vm.hback_porch) * 2;
|
||||
data_type = MIPI_DSI_PACKED_PIXEL_STREAM_16;
|
||||
break;
|
||||
default:
|
||||
@@ -717,9 +746,152 @@ static void tc358768_bridge_pre_enable(struct drm_bridge *bridge)
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* There are three important things to make TC358768 work correctly,
|
||||
* which are not trivial to manage:
|
||||
*
|
||||
* 1. Keep the DPI line-time and the DSI line-time as close to each
|
||||
* other as possible.
|
||||
* 2. TC358768 goes to LP mode after each line's active area. The DSI
|
||||
* HFP period has to be long enough for entering and exiting LP mode.
|
||||
* But it is not clear how to calculate this.
|
||||
* 3. VSDly (video start delay) has to be long enough to ensure that the
|
||||
* DSI TX does not start transmitting until we have started receiving
|
||||
* pixel data from the DPI input. It is not clear how to calculate
|
||||
* this either.
|
||||
*/
|
||||
|
||||
dpi_htot = vm.hactive + vm.hfront_porch + vm.hsync_len + vm.hback_porch;
|
||||
dpi_data_start = vm.hsync_len + vm.hback_porch;
|
||||
|
||||
dev_dbg(dev, "dpi horiz timing (pclk): %u + %u + %u + %u = %u\n",
|
||||
vm.hsync_len, vm.hback_porch, vm.hactive, vm.hfront_porch,
|
||||
dpi_htot);
|
||||
|
||||
dev_dbg(dev, "dpi horiz timing (ns): %u + %u + %u + %u = %u\n",
|
||||
tc358768_dpi_to_ns(vm.hsync_len, vm.pixelclock),
|
||||
tc358768_dpi_to_ns(vm.hback_porch, vm.pixelclock),
|
||||
tc358768_dpi_to_ns(vm.hactive, vm.pixelclock),
|
||||
tc358768_dpi_to_ns(vm.hfront_porch, vm.pixelclock),
|
||||
tc358768_dpi_to_ns(dpi_htot, vm.pixelclock));
|
||||
|
||||
dev_dbg(dev, "dpi data start (ns): %u + %u = %u\n",
|
||||
tc358768_dpi_to_ns(vm.hsync_len, vm.pixelclock),
|
||||
tc358768_dpi_to_ns(vm.hback_porch, vm.pixelclock),
|
||||
tc358768_dpi_to_ns(dpi_data_start, vm.pixelclock));
|
||||
|
||||
dsi_dpi_htot = tc358768_dpi_to_dsi_bytes(priv, dpi_htot);
|
||||
dsi_dpi_data_start = tc358768_dpi_to_dsi_bytes(priv, dpi_data_start);
|
||||
|
||||
if (dsi_dev->mode_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE) {
|
||||
dsi_hsw = tc358768_dpi_to_dsi_bytes(priv, vm.hsync_len);
|
||||
dsi_hbp = tc358768_dpi_to_dsi_bytes(priv, vm.hback_porch);
|
||||
} else {
|
||||
/* HBP is included in HSW in event mode */
|
||||
dsi_hbp = 0;
|
||||
dsi_hsw = tc358768_dpi_to_dsi_bytes(priv,
|
||||
vm.hsync_len +
|
||||
vm.hback_porch);
|
||||
|
||||
/*
|
||||
* The pixel packet includes the actual pixel data, and:
|
||||
* DSI packet header = 4 bytes
|
||||
* DCS code = 1 byte
|
||||
* DSI packet footer = 2 bytes
|
||||
*/
|
||||
dsi_hact = hact + 4 + 1 + 2;
|
||||
|
||||
dsi_hfp = dsi_dpi_htot - dsi_hact - dsi_hsw - dsi_hss;
|
||||
|
||||
/*
|
||||
* Here we should check if HFP is long enough for entering LP
|
||||
* and exiting LP, but it's not clear how to calculate that.
|
||||
* Instead, this is a naive algorithm that just adjusts the HFP
|
||||
* and HSW so that HFP is (at least) roughly 2/3 of the total
|
||||
* blanking time.
|
||||
*/
|
||||
if (dsi_hfp < (dsi_hfp + dsi_hsw + dsi_hss) * 2 / 3) {
|
||||
u32 old_hfp = dsi_hfp;
|
||||
u32 old_hsw = dsi_hsw;
|
||||
u32 tot = dsi_hfp + dsi_hsw + dsi_hss;
|
||||
|
||||
dsi_hsw = tot / 3;
|
||||
|
||||
/*
|
||||
* Seems like sometimes HSW has to be divisible by num-lanes, but
|
||||
* not always...
|
||||
*/
|
||||
dsi_hsw = roundup(dsi_hsw, priv->dsi_lanes);
|
||||
|
||||
dsi_hfp = dsi_dpi_htot - dsi_hact - dsi_hsw - dsi_hss;
|
||||
|
||||
dev_dbg(dev,
|
||||
"hfp too short, adjusting dsi hfp and dsi hsw from %u, %u to %u, %u\n",
|
||||
old_hfp, old_hsw, dsi_hfp, dsi_hsw);
|
||||
}
|
||||
|
||||
dev_dbg(dev,
|
||||
"dsi horiz timing (bytes): %u, %u + %u + %u + %u = %u\n",
|
||||
dsi_hss, dsi_hsw, dsi_hbp, dsi_hact, dsi_hfp,
|
||||
dsi_hss + dsi_hsw + dsi_hbp + dsi_hact + dsi_hfp);
|
||||
|
||||
dev_dbg(dev, "dsi horiz timing (ns): %u + %u + %u + %u + %u = %u\n",
|
||||
tc358768_dsi_bytes_to_ns(priv, dsi_hss),
|
||||
tc358768_dsi_bytes_to_ns(priv, dsi_hsw),
|
||||
tc358768_dsi_bytes_to_ns(priv, dsi_hbp),
|
||||
tc358768_dsi_bytes_to_ns(priv, dsi_hact),
|
||||
tc358768_dsi_bytes_to_ns(priv, dsi_hfp),
|
||||
tc358768_dsi_bytes_to_ns(priv, dsi_hss + dsi_hsw +
|
||||
dsi_hbp + dsi_hact + dsi_hfp));
|
||||
}
|
||||
|
||||
/* VSDly calculation */
|
||||
|
||||
/* Start with the HW internal delay */
|
||||
dsi_vsdly = internal_dly;
|
||||
|
||||
/* Convert to byte units as the other variables are in byte units */
|
||||
dsi_vsdly *= priv->dsi_lanes;
|
||||
|
||||
/* Do we need more delay, in addition to the internal? */
|
||||
if (dsi_dpi_data_start > dsi_vsdly + dsi_hss + dsi_hsw + dsi_hbp) {
|
||||
dsi_vsdly = dsi_dpi_data_start - dsi_hss - dsi_hsw - dsi_hbp;
|
||||
dsi_vsdly = roundup(dsi_vsdly, priv->dsi_lanes);
|
||||
}
|
||||
|
||||
dev_dbg(dev, "dsi data start (bytes) %u + %u + %u + %u = %u\n",
|
||||
dsi_vsdly, dsi_hss, dsi_hsw, dsi_hbp,
|
||||
dsi_vsdly + dsi_hss + dsi_hsw + dsi_hbp);
|
||||
|
||||
dev_dbg(dev, "dsi data start (ns) %u + %u + %u + %u = %u\n",
|
||||
tc358768_dsi_bytes_to_ns(priv, dsi_vsdly),
|
||||
tc358768_dsi_bytes_to_ns(priv, dsi_hss),
|
||||
tc358768_dsi_bytes_to_ns(priv, dsi_hsw),
|
||||
tc358768_dsi_bytes_to_ns(priv, dsi_hbp),
|
||||
tc358768_dsi_bytes_to_ns(priv, dsi_vsdly + dsi_hss + dsi_hsw + dsi_hbp));
|
||||
|
||||
/* Convert back to hsbyteclk */
|
||||
dsi_vsdly /= priv->dsi_lanes;
|
||||
|
||||
/*
|
||||
* The docs say that there is an internal delay of 40 cycles.
|
||||
* However, we get underflows if we follow that rule. If we
|
||||
* instead ignore the internal delay, things work. So either
|
||||
* the docs are wrong or the calculations are wrong.
|
||||
*
|
||||
* As a temporary fix, add the internal delay here, to counter
|
||||
* the subtraction when writing the register.
|
||||
*/
|
||||
dsi_vsdly += internal_dly;
|
||||
|
||||
/* Clamp to the register max */
|
||||
if (dsi_vsdly - internal_dly > 0x3ff) {
|
||||
dev_warn(dev, "VSDly too high, underflows likely\n");
|
||||
dsi_vsdly = 0x3ff + internal_dly;
|
||||
}
|
||||
|
||||
/* VSDly[9:0] */
|
||||
video_start = max(video_start, internal_delay + 1) - internal_delay;
|
||||
tc358768_write(priv, TC358768_VSDLY, video_start);
|
||||
tc358768_write(priv, TC358768_VSDLY, dsi_vsdly - internal_dly);
|
||||
|
||||
tc358768_write(priv, TC358768_DATAFMT, val);
|
||||
tc358768_write(priv, TC358768_DSITX_DT, data_type);
|
||||
@@ -827,18 +999,6 @@ static void tc358768_bridge_pre_enable(struct drm_bridge *bridge)
|
||||
|
||||
/* vbp */
|
||||
tc358768_write(priv, TC358768_DSI_VBPR, vm.vback_porch);
|
||||
|
||||
/* hsw * byteclk * ndl / pclk */
|
||||
val = (u32)div_u64(vm.hsync_len *
|
||||
(u64)hsbyteclk * priv->dsi_lanes,
|
||||
vm.pixelclock);
|
||||
tc358768_write(priv, TC358768_DSI_HSW, val);
|
||||
|
||||
/* hbp * byteclk * ndl / pclk */
|
||||
val = (u32)div_u64(vm.hback_porch *
|
||||
(u64)hsbyteclk * priv->dsi_lanes,
|
||||
vm.pixelclock);
|
||||
tc358768_write(priv, TC358768_DSI_HBPR, val);
|
||||
} else {
|
||||
/* Set event mode */
|
||||
tc358768_write(priv, TC358768_DSI_EVENT, 1);
|
||||
@@ -852,17 +1012,14 @@ static void tc358768_bridge_pre_enable(struct drm_bridge *bridge)
|
||||
|
||||
/* vbp (not used in event mode) */
|
||||
tc358768_write(priv, TC358768_DSI_VBPR, 0);
|
||||
|
||||
/* (hsw + hbp) * byteclk * ndl / pclk */
|
||||
val = (u32)div_u64((vm.hsync_len + vm.hback_porch) *
|
||||
(u64)hsbyteclk * priv->dsi_lanes,
|
||||
vm.pixelclock);
|
||||
tc358768_write(priv, TC358768_DSI_HSW, val);
|
||||
|
||||
/* hbp (not used in event mode) */
|
||||
tc358768_write(priv, TC358768_DSI_HBPR, 0);
|
||||
}
|
||||
|
||||
/* hsw (bytes) */
|
||||
tc358768_write(priv, TC358768_DSI_HSW, dsi_hsw);
|
||||
|
||||
/* hbp (bytes) */
|
||||
tc358768_write(priv, TC358768_DSI_HBPR, dsi_hbp);
|
||||
|
||||
/* hact (bytes) */
|
||||
tc358768_write(priv, TC358768_DSI_HACT, hact);
|
||||
|
||||
|
||||
@@ -166,6 +166,11 @@ static void lima_gp_task_run(struct lima_sched_pipe *pipe,
|
||||
gp_write(LIMA_GP_CMD, cmd);
|
||||
}
|
||||
|
||||
static int lima_gp_bus_stop_poll(struct lima_ip *ip)
|
||||
{
|
||||
return !!(gp_read(LIMA_GP_STATUS) & LIMA_GP_STATUS_BUS_STOPPED);
|
||||
}
|
||||
|
||||
static int lima_gp_hard_reset_poll(struct lima_ip *ip)
|
||||
{
|
||||
gp_write(LIMA_GP_PERF_CNT_0_LIMIT, 0xC01A0000);
|
||||
@@ -179,6 +184,13 @@ static int lima_gp_hard_reset(struct lima_ip *ip)
|
||||
|
||||
gp_write(LIMA_GP_PERF_CNT_0_LIMIT, 0xC0FFE000);
|
||||
gp_write(LIMA_GP_INT_MASK, 0);
|
||||
|
||||
gp_write(LIMA_GP_CMD, LIMA_GP_CMD_STOP_BUS);
|
||||
ret = lima_poll_timeout(ip, lima_gp_bus_stop_poll, 10, 100);
|
||||
if (ret) {
|
||||
dev_err(dev->dev, "%s bus stop timeout\n", lima_ip_name(ip));
|
||||
return ret;
|
||||
}
|
||||
gp_write(LIMA_GP_CMD, LIMA_GP_CMD_RESET);
|
||||
ret = lima_poll_timeout(ip, lima_gp_hard_reset_poll, 10, 100);
|
||||
if (ret) {
|
||||
|
||||
@@ -31,24 +31,14 @@
|
||||
* @fmt: Pointer to format string
|
||||
*/
|
||||
#define DPU_DEBUG(fmt, ...) \
|
||||
do { \
|
||||
if (drm_debug_enabled(DRM_UT_KMS)) \
|
||||
DRM_DEBUG(fmt, ##__VA_ARGS__); \
|
||||
else \
|
||||
pr_debug(fmt, ##__VA_ARGS__); \
|
||||
} while (0)
|
||||
DRM_DEBUG_DRIVER(fmt, ##__VA_ARGS__)
|
||||
|
||||
/**
|
||||
* DPU_DEBUG_DRIVER - macro for hardware driver logging
|
||||
* @fmt: Pointer to format string
|
||||
*/
|
||||
#define DPU_DEBUG_DRIVER(fmt, ...) \
|
||||
do { \
|
||||
if (drm_debug_enabled(DRM_UT_DRIVER)) \
|
||||
DRM_ERROR(fmt, ##__VA_ARGS__); \
|
||||
else \
|
||||
pr_debug(fmt, ##__VA_ARGS__); \
|
||||
} while (0)
|
||||
DRM_DEBUG_DRIVER(fmt, ##__VA_ARGS__)
|
||||
|
||||
#define DPU_ERROR(fmt, ...) pr_err("[dpu error]" fmt, ##__VA_ARGS__)
|
||||
#define DPU_ERROR_RATELIMITED(fmt, ...) pr_err_ratelimited("[dpu error]" fmt, ##__VA_ARGS__)
|
||||
|
||||
@@ -889,6 +889,9 @@ static int dpu_plane_prepare_fb(struct drm_plane *plane,
|
||||
new_state->fb, &layout);
|
||||
if (ret) {
|
||||
DPU_ERROR_PLANE(pdpu, "failed to get format layout, %d\n", ret);
|
||||
if (pstate->aspace)
|
||||
msm_framebuffer_cleanup(new_state->fb, pstate->aspace,
|
||||
pstate->needs_dirtyfb);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -1248,6 +1248,8 @@ static int dp_ctrl_link_train(struct dp_ctrl_private *ctrl,
|
||||
link_info.rate = ctrl->link->link_params.rate;
|
||||
link_info.capabilities = DP_LINK_CAP_ENHANCED_FRAMING;
|
||||
|
||||
dp_link_reset_phy_params_vx_px(ctrl->link);
|
||||
|
||||
dp_aux_link_configure(ctrl->aux, &link_info);
|
||||
|
||||
if (drm_dp_max_downspread(dpcd))
|
||||
|
||||
@@ -113,22 +113,22 @@ end:
|
||||
static u32 dp_panel_get_supported_bpp(struct dp_panel *dp_panel,
|
||||
u32 mode_edid_bpp, u32 mode_pclk_khz)
|
||||
{
|
||||
struct dp_link_info *link_info;
|
||||
const struct dp_link_info *link_info;
|
||||
const u32 max_supported_bpp = 30, min_supported_bpp = 18;
|
||||
u32 bpp = 0, data_rate_khz = 0;
|
||||
u32 bpp, data_rate_khz;
|
||||
|
||||
bpp = min_t(u32, mode_edid_bpp, max_supported_bpp);
|
||||
bpp = min(mode_edid_bpp, max_supported_bpp);
|
||||
|
||||
link_info = &dp_panel->link_info;
|
||||
data_rate_khz = link_info->num_lanes * link_info->rate * 8;
|
||||
|
||||
while (bpp > min_supported_bpp) {
|
||||
do {
|
||||
if (mode_pclk_khz * bpp <= data_rate_khz)
|
||||
break;
|
||||
return bpp;
|
||||
bpp -= 6;
|
||||
}
|
||||
} while (bpp > min_supported_bpp);
|
||||
|
||||
return bpp;
|
||||
return min_supported_bpp;
|
||||
}
|
||||
|
||||
static int dp_panel_update_modes(struct drm_connector *connector,
|
||||
@@ -421,8 +421,9 @@ int dp_panel_init_panel_info(struct dp_panel *dp_panel)
|
||||
drm_mode->clock);
|
||||
drm_dbg_dp(panel->drm_dev, "bpp = %d\n", dp_panel->dp_mode.bpp);
|
||||
|
||||
dp_panel->dp_mode.bpp = max_t(u32, 18,
|
||||
min_t(u32, dp_panel->dp_mode.bpp, 30));
|
||||
dp_panel->dp_mode.bpp = dp_panel_get_mode_bpp(dp_panel, dp_panel->dp_mode.bpp,
|
||||
dp_panel->dp_mode.drm_mode.clock);
|
||||
|
||||
drm_dbg_dp(panel->drm_dev, "updated bpp = %d\n",
|
||||
dp_panel->dp_mode.bpp);
|
||||
|
||||
|
||||
@@ -76,7 +76,7 @@ static bool
|
||||
wait_for_idle(struct drm_gem_object *obj)
|
||||
{
|
||||
enum dma_resv_usage usage = dma_resv_usage_rw(true);
|
||||
return dma_resv_wait_timeout(obj->resv, usage, false, 1000) > 0;
|
||||
return dma_resv_wait_timeout(obj->resv, usage, false, 10) > 0;
|
||||
}
|
||||
|
||||
static bool
|
||||
|
||||
@@ -1258,6 +1258,11 @@ static void vop2_plane_atomic_update(struct drm_plane *plane,
|
||||
vop2_win_write(win, VOP2_WIN_AFBC_ROTATE_270, rotate_270);
|
||||
vop2_win_write(win, VOP2_WIN_AFBC_ROTATE_90, rotate_90);
|
||||
} else {
|
||||
if (vop2_cluster_window(win)) {
|
||||
vop2_win_write(win, VOP2_WIN_AFBC_ENABLE, 0);
|
||||
vop2_win_write(win, VOP2_WIN_AFBC_TRANSFORM_OFFSET, 0);
|
||||
}
|
||||
|
||||
vop2_win_write(win, VOP2_WIN_YRGB_VIR, DIV_ROUND_UP(fb->pitches[0], 4));
|
||||
}
|
||||
|
||||
|
||||
@@ -175,7 +175,7 @@ static void tegra_bo_unpin(struct host1x_bo_mapping *map)
|
||||
static void *tegra_bo_mmap(struct host1x_bo *bo)
|
||||
{
|
||||
struct tegra_bo *obj = host1x_to_tegra_bo(bo);
|
||||
struct iosys_map map;
|
||||
struct iosys_map map = { 0 };
|
||||
int ret;
|
||||
|
||||
if (obj->vaddr) {
|
||||
|
||||
@@ -924,7 +924,15 @@
|
||||
#define USB_DEVICE_ID_MS_TYPE_COVER_2 0x07a9
|
||||
#define USB_DEVICE_ID_MS_POWER_COVER 0x07da
|
||||
#define USB_DEVICE_ID_MS_SURFACE3_COVER 0x07de
|
||||
#define USB_DEVICE_ID_MS_XBOX_ONE_S_CONTROLLER 0x02fd
|
||||
/*
|
||||
* For a description of the Xbox controller models, refer to:
|
||||
* https://en.wikipedia.org/wiki/Xbox_Wireless_Controller#Summary
|
||||
*/
|
||||
#define USB_DEVICE_ID_MS_XBOX_CONTROLLER_MODEL_1708 0x02fd
|
||||
#define USB_DEVICE_ID_MS_XBOX_CONTROLLER_MODEL_1708_BLE 0x0b20
|
||||
#define USB_DEVICE_ID_MS_XBOX_CONTROLLER_MODEL_1914 0x0b13
|
||||
#define USB_DEVICE_ID_MS_XBOX_CONTROLLER_MODEL_1797 0x0b05
|
||||
#define USB_DEVICE_ID_MS_XBOX_CONTROLLER_MODEL_1797_BLE 0x0b22
|
||||
#define USB_DEVICE_ID_MS_PIXART_MOUSE 0x00cb
|
||||
#define USB_DEVICE_ID_8BITDO_SN30_PRO_PLUS 0x02e0
|
||||
#define USB_DEVICE_ID_MS_MOUSE_0783 0x0783
|
||||
|
||||
@@ -446,7 +446,16 @@ static const struct hid_device_id ms_devices[] = {
|
||||
.driver_data = MS_PRESENTER },
|
||||
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_MICROSOFT, 0x091B),
|
||||
.driver_data = MS_SURFACE_DIAL },
|
||||
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_XBOX_ONE_S_CONTROLLER),
|
||||
|
||||
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_XBOX_CONTROLLER_MODEL_1708),
|
||||
.driver_data = MS_QUIRK_FF },
|
||||
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_XBOX_CONTROLLER_MODEL_1708_BLE),
|
||||
.driver_data = MS_QUIRK_FF },
|
||||
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_XBOX_CONTROLLER_MODEL_1914),
|
||||
.driver_data = MS_QUIRK_FF },
|
||||
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_XBOX_CONTROLLER_MODEL_1797),
|
||||
.driver_data = MS_QUIRK_FF },
|
||||
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_XBOX_CONTROLLER_MODEL_1797_BLE),
|
||||
.driver_data = MS_QUIRK_FF },
|
||||
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_8BITDO_SN30_PRO_PLUS),
|
||||
.driver_data = MS_QUIRK_FF },
|
||||
|
||||
@@ -1921,12 +1921,14 @@ static void wacom_map_usage(struct input_dev *input, struct hid_usage *usage,
|
||||
int fmax = field->logical_maximum;
|
||||
unsigned int equivalent_usage = wacom_equivalent_usage(usage->hid);
|
||||
int resolution_code = code;
|
||||
int resolution = hidinput_calc_abs_res(field, resolution_code);
|
||||
int resolution;
|
||||
|
||||
if (equivalent_usage == HID_DG_TWIST) {
|
||||
resolution_code = ABS_RZ;
|
||||
}
|
||||
|
||||
resolution = hidinput_calc_abs_res(field, resolution_code);
|
||||
|
||||
if (equivalent_usage == HID_GD_X) {
|
||||
fmin += features->offset_left;
|
||||
fmax -= features->offset_right;
|
||||
|
||||
@@ -875,8 +875,14 @@ static int ltc2992_parse_dt(struct ltc2992_state *st)
|
||||
}
|
||||
|
||||
ret = fwnode_property_read_u32(child, "shunt-resistor-micro-ohms", &val);
|
||||
if (!ret)
|
||||
if (!ret) {
|
||||
if (!val) {
|
||||
fwnode_handle_put(child);
|
||||
return dev_err_probe(&st->client->dev, -EINVAL,
|
||||
"shunt resistor value cannot be zero\n");
|
||||
}
|
||||
st->r_sense_uohm[addr] = val;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -323,7 +323,11 @@ static struct pc87360_data *pc87360_update_device(struct device *dev)
|
||||
}
|
||||
|
||||
/* Voltages */
|
||||
for (i = 0; i < data->innr; i++) {
|
||||
/*
|
||||
* The min() below does not have any practical meaning and is
|
||||
* only needed to silence a warning observed with gcc 12+.
|
||||
*/
|
||||
for (i = 0; i < min(data->innr, ARRAY_SIZE(data->in)); i++) {
|
||||
data->in_status[i] = pc87360_read_value(data, LD_IN, i,
|
||||
PC87365_REG_IN_STATUS);
|
||||
/* Clear bits */
|
||||
|
||||
@@ -990,8 +990,10 @@ static int __maybe_unused geni_i2c_runtime_resume(struct device *dev)
|
||||
return ret;
|
||||
|
||||
ret = clk_prepare_enable(gi2c->core_clk);
|
||||
if (ret)
|
||||
if (ret) {
|
||||
geni_icc_disable(&gi2c->se);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = geni_se_resources_on(&gi2c->se);
|
||||
if (ret) {
|
||||
|
||||
@@ -314,7 +314,7 @@ static int riic_init_hw(struct riic_dev *riic, struct i2c_timings *t)
|
||||
* frequency with only 62 clock ticks max (31 high, 31 low).
|
||||
* Aim for a duty of 60% LOW, 40% HIGH.
|
||||
*/
|
||||
total_ticks = DIV_ROUND_UP(rate, t->bus_freq_hz);
|
||||
total_ticks = DIV_ROUND_UP(rate, t->bus_freq_hz ?: 1);
|
||||
|
||||
for (cks = 0; cks < 7; cks++) {
|
||||
/*
|
||||
|
||||
@@ -298,6 +298,9 @@ struct tegra_i2c_dev {
|
||||
bool is_vi;
|
||||
};
|
||||
|
||||
#define IS_DVC(dev) (IS_ENABLED(CONFIG_ARCH_TEGRA_2x_SOC) && (dev)->is_dvc)
|
||||
#define IS_VI(dev) (IS_ENABLED(CONFIG_ARCH_TEGRA_210_SOC) && (dev)->is_vi)
|
||||
|
||||
static void dvc_writel(struct tegra_i2c_dev *i2c_dev, u32 val,
|
||||
unsigned int reg)
|
||||
{
|
||||
@@ -315,9 +318,9 @@ static u32 dvc_readl(struct tegra_i2c_dev *i2c_dev, unsigned int reg)
|
||||
*/
|
||||
static u32 tegra_i2c_reg_addr(struct tegra_i2c_dev *i2c_dev, unsigned int reg)
|
||||
{
|
||||
if (i2c_dev->is_dvc)
|
||||
if (IS_DVC(i2c_dev))
|
||||
reg += (reg >= I2C_TX_FIFO) ? 0x10 : 0x40;
|
||||
else if (i2c_dev->is_vi)
|
||||
else if (IS_VI(i2c_dev))
|
||||
reg = 0xc00 + (reg << 2);
|
||||
|
||||
return reg;
|
||||
@@ -330,7 +333,7 @@ static void i2c_writel(struct tegra_i2c_dev *i2c_dev, u32 val, unsigned int reg)
|
||||
/* read back register to make sure that register writes completed */
|
||||
if (reg != I2C_TX_FIFO)
|
||||
readl_relaxed(i2c_dev->base + tegra_i2c_reg_addr(i2c_dev, reg));
|
||||
else if (i2c_dev->is_vi)
|
||||
else if (IS_VI(i2c_dev))
|
||||
readl_relaxed(i2c_dev->base + tegra_i2c_reg_addr(i2c_dev, I2C_INT_STATUS));
|
||||
}
|
||||
|
||||
@@ -446,7 +449,7 @@ static int tegra_i2c_init_dma(struct tegra_i2c_dev *i2c_dev)
|
||||
u32 *dma_buf;
|
||||
int err;
|
||||
|
||||
if (i2c_dev->is_vi)
|
||||
if (IS_VI(i2c_dev))
|
||||
return 0;
|
||||
|
||||
if (i2c_dev->hw->has_apb_dma) {
|
||||
@@ -639,7 +642,7 @@ static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev)
|
||||
|
||||
WARN_ON_ONCE(err);
|
||||
|
||||
if (i2c_dev->is_dvc)
|
||||
if (IS_DVC(i2c_dev))
|
||||
tegra_dvc_init(i2c_dev);
|
||||
|
||||
val = I2C_CNFG_NEW_MASTER_FSM | I2C_CNFG_PACKET_MODE_EN |
|
||||
@@ -651,7 +654,7 @@ static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev)
|
||||
i2c_writel(i2c_dev, val, I2C_CNFG);
|
||||
i2c_writel(i2c_dev, 0, I2C_INT_MASK);
|
||||
|
||||
if (i2c_dev->is_vi)
|
||||
if (IS_VI(i2c_dev))
|
||||
tegra_i2c_vi_init(i2c_dev);
|
||||
|
||||
switch (t->bus_freq_hz) {
|
||||
@@ -703,7 +706,7 @@ static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev)
|
||||
return err;
|
||||
}
|
||||
|
||||
if (!i2c_dev->is_dvc && !i2c_dev->is_vi) {
|
||||
if (!IS_DVC(i2c_dev) && !IS_VI(i2c_dev)) {
|
||||
u32 sl_cfg = i2c_readl(i2c_dev, I2C_SL_CNFG);
|
||||
|
||||
sl_cfg |= I2C_SL_CNFG_NACK | I2C_SL_CNFG_NEWSL;
|
||||
@@ -846,7 +849,7 @@ static int tegra_i2c_fill_tx_fifo(struct tegra_i2c_dev *i2c_dev)
|
||||
i2c_dev->msg_buf_remaining = buf_remaining;
|
||||
i2c_dev->msg_buf = buf + words_to_transfer * BYTES_PER_FIFO_WORD;
|
||||
|
||||
if (i2c_dev->is_vi)
|
||||
if (IS_VI(i2c_dev))
|
||||
i2c_writesl_vi(i2c_dev, buf, I2C_TX_FIFO, words_to_transfer);
|
||||
else
|
||||
i2c_writesl(i2c_dev, buf, I2C_TX_FIFO, words_to_transfer);
|
||||
@@ -933,7 +936,7 @@ static irqreturn_t tegra_i2c_isr(int irq, void *dev_id)
|
||||
}
|
||||
|
||||
i2c_writel(i2c_dev, status, I2C_INT_STATUS);
|
||||
if (i2c_dev->is_dvc)
|
||||
if (IS_DVC(i2c_dev))
|
||||
dvc_writel(i2c_dev, DVC_STATUS_I2C_DONE_INTR, DVC_STATUS);
|
||||
|
||||
/*
|
||||
@@ -972,7 +975,7 @@ err:
|
||||
|
||||
i2c_writel(i2c_dev, status, I2C_INT_STATUS);
|
||||
|
||||
if (i2c_dev->is_dvc)
|
||||
if (IS_DVC(i2c_dev))
|
||||
dvc_writel(i2c_dev, DVC_STATUS_I2C_DONE_INTR, DVC_STATUS);
|
||||
|
||||
if (i2c_dev->dma_mode) {
|
||||
@@ -1654,13 +1657,17 @@ static const struct tegra_i2c_hw_feature tegra194_i2c_hw = {
|
||||
static const struct of_device_id tegra_i2c_of_match[] = {
|
||||
{ .compatible = "nvidia,tegra194-i2c", .data = &tegra194_i2c_hw, },
|
||||
{ .compatible = "nvidia,tegra186-i2c", .data = &tegra186_i2c_hw, },
|
||||
#if IS_ENABLED(CONFIG_ARCH_TEGRA_210_SOC)
|
||||
{ .compatible = "nvidia,tegra210-i2c-vi", .data = &tegra210_i2c_hw, },
|
||||
#endif
|
||||
{ .compatible = "nvidia,tegra210-i2c", .data = &tegra210_i2c_hw, },
|
||||
{ .compatible = "nvidia,tegra124-i2c", .data = &tegra124_i2c_hw, },
|
||||
{ .compatible = "nvidia,tegra114-i2c", .data = &tegra114_i2c_hw, },
|
||||
{ .compatible = "nvidia,tegra30-i2c", .data = &tegra30_i2c_hw, },
|
||||
{ .compatible = "nvidia,tegra20-i2c", .data = &tegra20_i2c_hw, },
|
||||
#if IS_ENABLED(CONFIG_ARCH_TEGRA_2x_SOC)
|
||||
{ .compatible = "nvidia,tegra20-i2c-dvc", .data = &tegra20_i2c_hw, },
|
||||
#endif
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, tegra_i2c_of_match);
|
||||
@@ -1675,10 +1682,12 @@ static void tegra_i2c_parse_dt(struct tegra_i2c_dev *i2c_dev)
|
||||
multi_mode = device_property_read_bool(i2c_dev->dev, "multi-master");
|
||||
i2c_dev->multimaster_mode = multi_mode;
|
||||
|
||||
if (of_device_is_compatible(np, "nvidia,tegra20-i2c-dvc"))
|
||||
if (IS_ENABLED(CONFIG_ARCH_TEGRA_2x_SOC) &&
|
||||
of_device_is_compatible(np, "nvidia,tegra20-i2c-dvc"))
|
||||
i2c_dev->is_dvc = true;
|
||||
|
||||
if (of_device_is_compatible(np, "nvidia,tegra210-i2c-vi"))
|
||||
if (IS_ENABLED(CONFIG_ARCH_TEGRA_210_SOC) &&
|
||||
of_device_is_compatible(np, "nvidia,tegra210-i2c-vi"))
|
||||
i2c_dev->is_vi = true;
|
||||
}
|
||||
|
||||
@@ -1707,7 +1716,7 @@ static int tegra_i2c_init_clocks(struct tegra_i2c_dev *i2c_dev)
|
||||
if (i2c_dev->hw == &tegra20_i2c_hw || i2c_dev->hw == &tegra30_i2c_hw)
|
||||
i2c_dev->clocks[i2c_dev->nclocks++].id = "fast-clk";
|
||||
|
||||
if (i2c_dev->is_vi)
|
||||
if (IS_VI(i2c_dev))
|
||||
i2c_dev->clocks[i2c_dev->nclocks++].id = "slow";
|
||||
|
||||
err = devm_clk_bulk_get(i2c_dev->dev, i2c_dev->nclocks,
|
||||
@@ -1823,9 +1832,9 @@ static int tegra_i2c_probe(struct platform_device *pdev)
|
||||
* domain.
|
||||
*
|
||||
* VI I2C device shouldn't be marked as IRQ-safe because VI I2C won't
|
||||
* be used for atomic transfers.
|
||||
* be used for atomic transfers. ACPI device is not IRQ safe also.
|
||||
*/
|
||||
if (!i2c_dev->is_vi)
|
||||
if (!IS_VI(i2c_dev) && !has_acpi_companion(i2c_dev->dev))
|
||||
pm_runtime_irq_safe(i2c_dev->dev);
|
||||
|
||||
pm_runtime_enable(i2c_dev->dev);
|
||||
@@ -1898,7 +1907,7 @@ static int __maybe_unused tegra_i2c_runtime_resume(struct device *dev)
|
||||
* power ON/OFF during runtime PM resume/suspend, meaning that
|
||||
* controller needs to be re-initialized after power ON.
|
||||
*/
|
||||
if (i2c_dev->is_vi) {
|
||||
if (IS_VI(i2c_dev)) {
|
||||
err = tegra_i2c_init(i2c_dev);
|
||||
if (err)
|
||||
goto disable_clocks;
|
||||
|
||||
@@ -345,6 +345,8 @@ static void hci_dma_unmap_xfer(struct i3c_hci *hci,
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
xfer = xfer_list + i;
|
||||
if (!xfer->data)
|
||||
continue;
|
||||
dma_unmap_single(&hci->master.dev,
|
||||
xfer->data_dma, xfer->data_len,
|
||||
xfer->rnw ? DMA_FROM_DEVICE : DMA_TO_DEVICE);
|
||||
@@ -450,10 +452,9 @@ static bool hci_dma_dequeue_xfer(struct i3c_hci *hci,
|
||||
/*
|
||||
* We're deep in it if ever this condition is ever met.
|
||||
* Hardware might still be writing to memory, etc.
|
||||
* Better suspend the world than risking silent corruption.
|
||||
*/
|
||||
dev_crit(&hci->master.dev, "unable to abort the ring\n");
|
||||
BUG();
|
||||
WARN_ON(1);
|
||||
}
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
|
||||
@@ -13183,15 +13183,16 @@ static void read_mod_write(struct hfi1_devdata *dd, u16 src, u64 bits,
|
||||
{
|
||||
u64 reg;
|
||||
u16 idx = src / BITS_PER_REGISTER;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock(&dd->irq_src_lock);
|
||||
spin_lock_irqsave(&dd->irq_src_lock, flags);
|
||||
reg = read_csr(dd, CCE_INT_MASK + (8 * idx));
|
||||
if (set)
|
||||
reg |= bits;
|
||||
else
|
||||
reg &= ~bits;
|
||||
write_csr(dd, CCE_INT_MASK + (8 * idx), reg);
|
||||
spin_unlock(&dd->irq_src_lock);
|
||||
spin_unlock_irqrestore(&dd->irq_src_lock, flags);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -255,7 +255,7 @@ static int create_cq(struct rtrs_con *con, int cq_vector, int nr_cqe,
|
||||
static int create_qp(struct rtrs_con *con, struct ib_pd *pd,
|
||||
u32 max_send_wr, u32 max_recv_wr, u32 max_sge)
|
||||
{
|
||||
struct ib_qp_init_attr init_attr = {NULL};
|
||||
struct ib_qp_init_attr init_attr = {};
|
||||
struct rdma_cm_id *cm_id = con->cm_id;
|
||||
int ret;
|
||||
|
||||
|
||||
@@ -46,6 +46,9 @@ int input_mt_init_slots(struct input_dev *dev, unsigned int num_slots,
|
||||
return 0;
|
||||
if (mt)
|
||||
return mt->num_slots != num_slots ? -EINVAL : 0;
|
||||
/* Arbitrary limit for avoiding too large memory allocation. */
|
||||
if (num_slots > 1024)
|
||||
return -EINVAL;
|
||||
|
||||
mt = kzalloc(struct_size(mt, slots, num_slots), GFP_KERNEL);
|
||||
if (!mt)
|
||||
|
||||
@@ -83,6 +83,7 @@ static inline void i8042_write_command(int val)
|
||||
#define SERIO_QUIRK_KBDRESET BIT(12)
|
||||
#define SERIO_QUIRK_DRITEK BIT(13)
|
||||
#define SERIO_QUIRK_NOPNP BIT(14)
|
||||
#define SERIO_QUIRK_FORCENORESTORE BIT(15)
|
||||
|
||||
/* Quirk table for different mainboards. Options similar or identical to i8042
|
||||
* module parameters.
|
||||
@@ -1149,18 +1150,10 @@ static const struct dmi_system_id i8042_dmi_quirk_table[] __initconst = {
|
||||
SERIO_QUIRK_NOLOOP | SERIO_QUIRK_NOPNP)
|
||||
},
|
||||
{
|
||||
/*
|
||||
* Setting SERIO_QUIRK_NOMUX or SERIO_QUIRK_RESET_ALWAYS makes
|
||||
* the keyboard very laggy for ~5 seconds after boot and
|
||||
* sometimes also after resume.
|
||||
* However both are required for the keyboard to not fail
|
||||
* completely sometimes after boot or resume.
|
||||
*/
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_BOARD_NAME, "N150CU"),
|
||||
},
|
||||
.driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_RESET_ALWAYS |
|
||||
SERIO_QUIRK_NOLOOP | SERIO_QUIRK_NOPNP)
|
||||
.driver_data = (void *)(SERIO_QUIRK_FORCENORESTORE)
|
||||
},
|
||||
{
|
||||
.matches = {
|
||||
@@ -1685,6 +1678,8 @@ static void __init i8042_check_quirks(void)
|
||||
if (quirks & SERIO_QUIRK_NOPNP)
|
||||
i8042_nopnp = true;
|
||||
#endif
|
||||
if (quirks & SERIO_QUIRK_FORCENORESTORE)
|
||||
i8042_forcenorestore = true;
|
||||
}
|
||||
#else
|
||||
static inline void i8042_check_quirks(void) {}
|
||||
@@ -1718,7 +1713,7 @@ static int __init i8042_platform_init(void)
|
||||
|
||||
i8042_check_quirks();
|
||||
|
||||
pr_debug("Active quirks (empty means none):%s%s%s%s%s%s%s%s%s%s%s%s%s\n",
|
||||
pr_debug("Active quirks (empty means none):%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n",
|
||||
i8042_nokbd ? " nokbd" : "",
|
||||
i8042_noaux ? " noaux" : "",
|
||||
i8042_nomux ? " nomux" : "",
|
||||
@@ -1738,10 +1733,11 @@ static int __init i8042_platform_init(void)
|
||||
"",
|
||||
#endif
|
||||
#ifdef CONFIG_PNP
|
||||
i8042_nopnp ? " nopnp" : "");
|
||||
i8042_nopnp ? " nopnp" : "",
|
||||
#else
|
||||
"");
|
||||
"",
|
||||
#endif
|
||||
i8042_forcenorestore ? " forcenorestore" : "");
|
||||
|
||||
retval = i8042_pnp_init();
|
||||
if (retval)
|
||||
|
||||
@@ -115,6 +115,10 @@ module_param_named(nopnp, i8042_nopnp, bool, 0);
|
||||
MODULE_PARM_DESC(nopnp, "Do not use PNP to detect controller settings");
|
||||
#endif
|
||||
|
||||
static bool i8042_forcenorestore;
|
||||
module_param_named(forcenorestore, i8042_forcenorestore, bool, 0);
|
||||
MODULE_PARM_DESC(forcenorestore, "Force no restore on s3 resume, copying s2idle behaviour");
|
||||
|
||||
#define DEBUG
|
||||
#ifdef DEBUG
|
||||
static bool i8042_debug;
|
||||
@@ -1232,7 +1236,7 @@ static int i8042_pm_suspend(struct device *dev)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (pm_suspend_via_firmware())
|
||||
if (!i8042_forcenorestore && pm_suspend_via_firmware())
|
||||
i8042_controller_reset(true);
|
||||
|
||||
/* Set up serio interrupts for system wakeup. */
|
||||
@@ -1248,7 +1252,7 @@ static int i8042_pm_suspend(struct device *dev)
|
||||
|
||||
static int i8042_pm_resume_noirq(struct device *dev)
|
||||
{
|
||||
if (!pm_resume_via_firmware())
|
||||
if (i8042_forcenorestore || !pm_resume_via_firmware())
|
||||
i8042_interrupt(0, NULL);
|
||||
|
||||
return 0;
|
||||
@@ -1271,7 +1275,7 @@ static int i8042_pm_resume(struct device *dev)
|
||||
* not restore the controller state to whatever it had been at boot
|
||||
* time, so we do not need to do anything.
|
||||
*/
|
||||
if (!pm_suspend_via_firmware())
|
||||
if (i8042_forcenorestore || !pm_suspend_via_firmware())
|
||||
return 0;
|
||||
|
||||
/*
|
||||
|
||||
@@ -4476,8 +4476,6 @@ static int its_vpe_irq_domain_alloc(struct irq_domain *domain, unsigned int virq
|
||||
struct page *vprop_page;
|
||||
int base, nr_ids, i, err = 0;
|
||||
|
||||
BUG_ON(!vm);
|
||||
|
||||
bitmap = its_lpi_alloc(roundup_pow_of_two(nr_irqs), &base, &nr_ids);
|
||||
if (!bitmap)
|
||||
return -ENOMEM;
|
||||
|
||||
@@ -132,7 +132,7 @@ static void rzg2l_irqc_irq_disable(struct irq_data *d)
|
||||
|
||||
raw_spin_lock(&priv->lock);
|
||||
reg = readl_relaxed(priv->base + TSSR(tssr_index));
|
||||
reg &= ~(TSSEL_MASK << TSSEL_SHIFT(tssr_offset));
|
||||
reg &= ~(TIEN << TSSEL_SHIFT(tssr_offset));
|
||||
writel_relaxed(reg, priv->base + TSSR(tssr_index));
|
||||
raw_spin_unlock(&priv->lock);
|
||||
}
|
||||
@@ -145,7 +145,6 @@ static void rzg2l_irqc_irq_enable(struct irq_data *d)
|
||||
|
||||
if (hw_irq >= IRQC_TINT_START && hw_irq < IRQC_NUM_IRQ) {
|
||||
struct rzg2l_irqc_priv *priv = irq_data_to_priv(d);
|
||||
unsigned long tint = (uintptr_t)d->chip_data;
|
||||
u32 offset = hw_irq - IRQC_TINT_START;
|
||||
u32 tssr_offset = TSSR_OFFSET(offset);
|
||||
u8 tssr_index = TSSR_INDEX(offset);
|
||||
@@ -153,7 +152,7 @@ static void rzg2l_irqc_irq_enable(struct irq_data *d)
|
||||
|
||||
raw_spin_lock(&priv->lock);
|
||||
reg = readl_relaxed(priv->base + TSSR(tssr_index));
|
||||
reg |= (TIEN | tint) << TSSEL_SHIFT(tssr_offset);
|
||||
reg |= TIEN << TSSEL_SHIFT(tssr_offset);
|
||||
writel_relaxed(reg, priv->base + TSSR(tssr_index));
|
||||
raw_spin_unlock(&priv->lock);
|
||||
}
|
||||
|
||||
@@ -465,11 +465,6 @@ static void __destroy_persistent_data_structures(struct dm_clone_metadata *cmd)
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
static size_t bitmap_size(unsigned long nr_bits)
|
||||
{
|
||||
return BITS_TO_LONGS(nr_bits) * sizeof(long);
|
||||
}
|
||||
|
||||
static int __dirty_map_init(struct dirty_map *dmap, unsigned long nr_words,
|
||||
unsigned long nr_regions)
|
||||
{
|
||||
|
||||
@@ -1156,8 +1156,26 @@ static int do_resume(struct dm_ioctl *param)
|
||||
suspend_flags &= ~DM_SUSPEND_LOCKFS_FLAG;
|
||||
if (param->flags & DM_NOFLUSH_FLAG)
|
||||
suspend_flags |= DM_SUSPEND_NOFLUSH_FLAG;
|
||||
if (!dm_suspended_md(md))
|
||||
dm_suspend(md, suspend_flags);
|
||||
if (!dm_suspended_md(md)) {
|
||||
r = dm_suspend(md, suspend_flags);
|
||||
if (r) {
|
||||
down_write(&_hash_lock);
|
||||
hc = dm_get_mdptr(md);
|
||||
if (hc && !hc->new_map) {
|
||||
hc->new_map = new_map;
|
||||
new_map = NULL;
|
||||
} else {
|
||||
r = -ENXIO;
|
||||
}
|
||||
up_write(&_hash_lock);
|
||||
if (new_map) {
|
||||
dm_sync_table(md);
|
||||
dm_table_destroy(new_map);
|
||||
}
|
||||
dm_put(md);
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
old_size = dm_get_size(md);
|
||||
old_map = dm_swap_table(md, new_map);
|
||||
|
||||
@@ -2511,7 +2511,7 @@ static int dm_wait_for_bios_completion(struct mapped_device *md, unsigned int ta
|
||||
break;
|
||||
|
||||
if (signal_pending_state(task_state, current)) {
|
||||
r = -EINTR;
|
||||
r = -ERESTARTSYS;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -2536,7 +2536,7 @@ static int dm_wait_for_completion(struct mapped_device *md, unsigned int task_st
|
||||
break;
|
||||
|
||||
if (signal_pending_state(task_state, current)) {
|
||||
r = -EINTR;
|
||||
r = -ERESTARTSYS;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -7614,11 +7614,6 @@ static int md_ioctl(struct block_device *bdev, fmode_t mode,
|
||||
|
||||
mddev = bdev->bd_disk->private_data;
|
||||
|
||||
if (!mddev) {
|
||||
BUG();
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Some actions do not requires the mutex */
|
||||
switch (cmd) {
|
||||
case GET_ARRAY_INFO:
|
||||
|
||||
@@ -274,7 +274,7 @@ static void sm_metadata_destroy(struct dm_space_map *sm)
|
||||
{
|
||||
struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm);
|
||||
|
||||
kfree(smm);
|
||||
kvfree(smm);
|
||||
}
|
||||
|
||||
static int sm_metadata_get_nr_blocks(struct dm_space_map *sm, dm_block_t *count)
|
||||
@@ -768,7 +768,7 @@ struct dm_space_map *dm_sm_metadata_init(void)
|
||||
{
|
||||
struct sm_metadata *smm;
|
||||
|
||||
smm = kmalloc(sizeof(*smm), GFP_KERNEL);
|
||||
smm = kvmalloc(sizeof(*smm), GFP_KERNEL);
|
||||
if (!smm)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
|
||||
@@ -327,8 +327,9 @@ void r5l_wake_reclaim(struct r5l_log *log, sector_t space);
|
||||
void r5c_check_stripe_cache_usage(struct r5conf *conf)
|
||||
{
|
||||
int total_cached;
|
||||
struct r5l_log *log = READ_ONCE(conf->log);
|
||||
|
||||
if (!r5c_is_writeback(conf->log))
|
||||
if (!r5c_is_writeback(log))
|
||||
return;
|
||||
|
||||
total_cached = atomic_read(&conf->r5c_cached_partial_stripes) +
|
||||
@@ -344,7 +345,7 @@ void r5c_check_stripe_cache_usage(struct r5conf *conf)
|
||||
*/
|
||||
if (total_cached > conf->min_nr_stripes * 1 / 2 ||
|
||||
atomic_read(&conf->empty_inactive_list_nr) > 0)
|
||||
r5l_wake_reclaim(conf->log, 0);
|
||||
r5l_wake_reclaim(log, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -353,7 +354,9 @@ void r5c_check_stripe_cache_usage(struct r5conf *conf)
|
||||
*/
|
||||
void r5c_check_cached_full_stripe(struct r5conf *conf)
|
||||
{
|
||||
if (!r5c_is_writeback(conf->log))
|
||||
struct r5l_log *log = READ_ONCE(conf->log);
|
||||
|
||||
if (!r5c_is_writeback(log))
|
||||
return;
|
||||
|
||||
/*
|
||||
@@ -363,7 +366,7 @@ void r5c_check_cached_full_stripe(struct r5conf *conf)
|
||||
if (atomic_read(&conf->r5c_cached_full_stripes) >=
|
||||
min(R5C_FULL_STRIPE_FLUSH_BATCH(conf),
|
||||
conf->chunk_sectors >> RAID5_STRIPE_SHIFT(conf)))
|
||||
r5l_wake_reclaim(conf->log, 0);
|
||||
r5l_wake_reclaim(log, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -396,7 +399,7 @@ void r5c_check_cached_full_stripe(struct r5conf *conf)
|
||||
*/
|
||||
static sector_t r5c_log_required_to_flush_cache(struct r5conf *conf)
|
||||
{
|
||||
struct r5l_log *log = conf->log;
|
||||
struct r5l_log *log = READ_ONCE(conf->log);
|
||||
|
||||
if (!r5c_is_writeback(log))
|
||||
return 0;
|
||||
@@ -449,7 +452,7 @@ static inline void r5c_update_log_state(struct r5l_log *log)
|
||||
void r5c_make_stripe_write_out(struct stripe_head *sh)
|
||||
{
|
||||
struct r5conf *conf = sh->raid_conf;
|
||||
struct r5l_log *log = conf->log;
|
||||
struct r5l_log *log = READ_ONCE(conf->log);
|
||||
|
||||
BUG_ON(!r5c_is_writeback(log));
|
||||
|
||||
@@ -491,7 +494,7 @@ static void r5c_handle_parity_cached(struct stripe_head *sh)
|
||||
*/
|
||||
static void r5c_finish_cache_stripe(struct stripe_head *sh)
|
||||
{
|
||||
struct r5l_log *log = sh->raid_conf->log;
|
||||
struct r5l_log *log = READ_ONCE(sh->raid_conf->log);
|
||||
|
||||
if (log->r5c_journal_mode == R5C_JOURNAL_MODE_WRITE_THROUGH) {
|
||||
BUG_ON(test_bit(STRIPE_R5C_CACHING, &sh->state));
|
||||
@@ -692,7 +695,7 @@ static void r5c_disable_writeback_async(struct work_struct *work)
|
||||
|
||||
/* wait superblock change before suspend */
|
||||
wait_event(mddev->sb_wait,
|
||||
conf->log == NULL ||
|
||||
!READ_ONCE(conf->log) ||
|
||||
(!test_bit(MD_SB_CHANGE_PENDING, &mddev->sb_flags) &&
|
||||
(locked = mddev_trylock(mddev))));
|
||||
if (locked) {
|
||||
@@ -1151,7 +1154,7 @@ static void r5l_run_no_space_stripes(struct r5l_log *log)
|
||||
static sector_t r5c_calculate_new_cp(struct r5conf *conf)
|
||||
{
|
||||
struct stripe_head *sh;
|
||||
struct r5l_log *log = conf->log;
|
||||
struct r5l_log *log = READ_ONCE(conf->log);
|
||||
sector_t new_cp;
|
||||
unsigned long flags;
|
||||
|
||||
@@ -1159,12 +1162,12 @@ static sector_t r5c_calculate_new_cp(struct r5conf *conf)
|
||||
return log->next_checkpoint;
|
||||
|
||||
spin_lock_irqsave(&log->stripe_in_journal_lock, flags);
|
||||
if (list_empty(&conf->log->stripe_in_journal_list)) {
|
||||
if (list_empty(&log->stripe_in_journal_list)) {
|
||||
/* all stripes flushed */
|
||||
spin_unlock_irqrestore(&log->stripe_in_journal_lock, flags);
|
||||
return log->next_checkpoint;
|
||||
}
|
||||
sh = list_first_entry(&conf->log->stripe_in_journal_list,
|
||||
sh = list_first_entry(&log->stripe_in_journal_list,
|
||||
struct stripe_head, r5c);
|
||||
new_cp = sh->log_start;
|
||||
spin_unlock_irqrestore(&log->stripe_in_journal_lock, flags);
|
||||
@@ -1399,7 +1402,7 @@ void r5c_flush_cache(struct r5conf *conf, int num)
|
||||
struct stripe_head *sh, *next;
|
||||
|
||||
lockdep_assert_held(&conf->device_lock);
|
||||
if (!conf->log)
|
||||
if (!READ_ONCE(conf->log))
|
||||
return;
|
||||
|
||||
count = 0;
|
||||
@@ -1420,7 +1423,7 @@ void r5c_flush_cache(struct r5conf *conf, int num)
|
||||
|
||||
static void r5c_do_reclaim(struct r5conf *conf)
|
||||
{
|
||||
struct r5l_log *log = conf->log;
|
||||
struct r5l_log *log = READ_ONCE(conf->log);
|
||||
struct stripe_head *sh;
|
||||
int count = 0;
|
||||
unsigned long flags;
|
||||
@@ -1549,7 +1552,7 @@ static void r5l_reclaim_thread(struct md_thread *thread)
|
||||
{
|
||||
struct mddev *mddev = thread->mddev;
|
||||
struct r5conf *conf = mddev->private;
|
||||
struct r5l_log *log = conf->log;
|
||||
struct r5l_log *log = READ_ONCE(conf->log);
|
||||
|
||||
if (!log)
|
||||
return;
|
||||
@@ -1589,7 +1592,7 @@ void r5l_quiesce(struct r5l_log *log, int quiesce)
|
||||
|
||||
bool r5l_log_disk_error(struct r5conf *conf)
|
||||
{
|
||||
struct r5l_log *log = conf->log;
|
||||
struct r5l_log *log = READ_ONCE(conf->log);
|
||||
|
||||
/* don't allow write if journal disk is missing */
|
||||
if (!log)
|
||||
@@ -2633,7 +2636,7 @@ int r5c_try_caching_write(struct r5conf *conf,
|
||||
struct stripe_head_state *s,
|
||||
int disks)
|
||||
{
|
||||
struct r5l_log *log = conf->log;
|
||||
struct r5l_log *log = READ_ONCE(conf->log);
|
||||
int i;
|
||||
struct r5dev *dev;
|
||||
int to_cache = 0;
|
||||
@@ -2800,7 +2803,7 @@ void r5c_finish_stripe_write_out(struct r5conf *conf,
|
||||
struct stripe_head *sh,
|
||||
struct stripe_head_state *s)
|
||||
{
|
||||
struct r5l_log *log = conf->log;
|
||||
struct r5l_log *log = READ_ONCE(conf->log);
|
||||
int i;
|
||||
int do_wakeup = 0;
|
||||
sector_t tree_index;
|
||||
@@ -2939,7 +2942,7 @@ int r5c_cache_data(struct r5l_log *log, struct stripe_head *sh)
|
||||
/* check whether this big stripe is in write back cache. */
|
||||
bool r5c_big_stripe_cached(struct r5conf *conf, sector_t sect)
|
||||
{
|
||||
struct r5l_log *log = conf->log;
|
||||
struct r5l_log *log = READ_ONCE(conf->log);
|
||||
sector_t tree_index;
|
||||
void *slot;
|
||||
|
||||
@@ -3047,14 +3050,14 @@ int r5l_start(struct r5l_log *log)
|
||||
void r5c_update_on_rdev_error(struct mddev *mddev, struct md_rdev *rdev)
|
||||
{
|
||||
struct r5conf *conf = mddev->private;
|
||||
struct r5l_log *log = conf->log;
|
||||
struct r5l_log *log = READ_ONCE(conf->log);
|
||||
|
||||
if (!log)
|
||||
return;
|
||||
|
||||
if ((raid5_calc_degraded(conf) > 0 ||
|
||||
test_bit(Journal, &rdev->flags)) &&
|
||||
conf->log->r5c_journal_mode == R5C_JOURNAL_MODE_WRITE_BACK)
|
||||
log->r5c_journal_mode == R5C_JOURNAL_MODE_WRITE_BACK)
|
||||
schedule_work(&log->disable_writeback_work);
|
||||
}
|
||||
|
||||
@@ -3143,7 +3146,7 @@ int r5l_init_log(struct r5conf *conf, struct md_rdev *rdev)
|
||||
spin_lock_init(&log->stripe_in_journal_lock);
|
||||
atomic_set(&log->stripe_in_journal_count, 0);
|
||||
|
||||
conf->log = log;
|
||||
WRITE_ONCE(conf->log, log);
|
||||
|
||||
set_bit(MD_HAS_JOURNAL, &conf->mddev->flags);
|
||||
return 0;
|
||||
@@ -3171,7 +3174,7 @@ void r5l_exit_log(struct r5conf *conf)
|
||||
* 'reconfig_mutex' is held by caller, set 'confg->log' to NULL to
|
||||
* ensure disable_writeback_work wakes up and exits.
|
||||
*/
|
||||
conf->log = NULL;
|
||||
WRITE_ONCE(conf->log, NULL);
|
||||
wake_up(&conf->mddev->sb_wait);
|
||||
flush_work(&log->disable_writeback_work);
|
||||
|
||||
|
||||
@@ -2160,7 +2160,8 @@ static int dvb_frontend_handle_compat_ioctl(struct file *file, unsigned int cmd,
|
||||
if (!tvps->num || (tvps->num > DTV_IOCTL_MAX_MSGS))
|
||||
return -EINVAL;
|
||||
|
||||
tvp = memdup_user(compat_ptr(tvps->props), tvps->num * sizeof(*tvp));
|
||||
tvp = memdup_array_user(compat_ptr(tvps->props),
|
||||
tvps->num, sizeof(*tvp));
|
||||
if (IS_ERR(tvp))
|
||||
return PTR_ERR(tvp);
|
||||
|
||||
@@ -2191,7 +2192,8 @@ static int dvb_frontend_handle_compat_ioctl(struct file *file, unsigned int cmd,
|
||||
if (!tvps->num || (tvps->num > DTV_IOCTL_MAX_MSGS))
|
||||
return -EINVAL;
|
||||
|
||||
tvp = memdup_user(compat_ptr(tvps->props), tvps->num * sizeof(*tvp));
|
||||
tvp = memdup_array_user(compat_ptr(tvps->props),
|
||||
tvps->num, sizeof(*tvp));
|
||||
if (IS_ERR(tvp))
|
||||
return PTR_ERR(tvp);
|
||||
|
||||
@@ -2368,7 +2370,8 @@ static int dvb_get_property(struct dvb_frontend *fe, struct file *file,
|
||||
if (!tvps->num || tvps->num > DTV_IOCTL_MAX_MSGS)
|
||||
return -EINVAL;
|
||||
|
||||
tvp = memdup_user((void __user *)tvps->props, tvps->num * sizeof(*tvp));
|
||||
tvp = memdup_array_user((void __user *)tvps->props,
|
||||
tvps->num, sizeof(*tvp));
|
||||
if (IS_ERR(tvp))
|
||||
return PTR_ERR(tvp);
|
||||
|
||||
@@ -2446,7 +2449,8 @@ static int dvb_frontend_handle_ioctl(struct file *file,
|
||||
if (!tvps->num || (tvps->num > DTV_IOCTL_MAX_MSGS))
|
||||
return -EINVAL;
|
||||
|
||||
tvp = memdup_user((void __user *)tvps->props, tvps->num * sizeof(*tvp));
|
||||
tvp = memdup_array_user((void __user *)tvps->props,
|
||||
tvps->num, sizeof(*tvp));
|
||||
if (IS_ERR(tvp))
|
||||
return PTR_ERR(tvp);
|
||||
|
||||
|
||||
@@ -1354,6 +1354,10 @@ int cx23885_video_register(struct cx23885_dev *dev)
|
||||
/* register Video device */
|
||||
dev->video_dev = cx23885_vdev_init(dev, dev->pci,
|
||||
&cx23885_video_template, "video");
|
||||
if (!dev->video_dev) {
|
||||
err = -ENOMEM;
|
||||
goto fail_unreg;
|
||||
}
|
||||
dev->video_dev->queue = &dev->vb2_vidq;
|
||||
dev->video_dev->device_caps = V4L2_CAP_READWRITE | V4L2_CAP_STREAMING |
|
||||
V4L2_CAP_AUDIO | V4L2_CAP_VIDEO_CAPTURE;
|
||||
@@ -1382,6 +1386,10 @@ int cx23885_video_register(struct cx23885_dev *dev)
|
||||
/* register VBI device */
|
||||
dev->vbi_dev = cx23885_vdev_init(dev, dev->pci,
|
||||
&cx23885_vbi_template, "vbi");
|
||||
if (!dev->vbi_dev) {
|
||||
err = -ENOMEM;
|
||||
goto fail_unreg;
|
||||
}
|
||||
dev->vbi_dev->queue = &dev->vb2_vbiq;
|
||||
dev->vbi_dev->device_caps = V4L2_CAP_READWRITE | V4L2_CAP_STREAMING |
|
||||
V4L2_CAP_AUDIO | V4L2_CAP_VBI_CAPTURE;
|
||||
|
||||
@@ -57,16 +57,16 @@
|
||||
#define SOLO_MP4E_EXT_ADDR(__solo) \
|
||||
(SOLO_EREF_EXT_ADDR(__solo) + SOLO_EREF_EXT_AREA(__solo))
|
||||
#define SOLO_MP4E_EXT_SIZE(__solo) \
|
||||
max((__solo->nr_chans * 0x00080000), \
|
||||
min(((__solo->sdram_size - SOLO_MP4E_EXT_ADDR(__solo)) - \
|
||||
__SOLO_JPEG_MIN_SIZE(__solo)), 0x00ff0000))
|
||||
clamp(__solo->sdram_size - SOLO_MP4E_EXT_ADDR(__solo) - \
|
||||
__SOLO_JPEG_MIN_SIZE(__solo), \
|
||||
__solo->nr_chans * 0x00080000, 0x00ff0000)
|
||||
|
||||
#define __SOLO_JPEG_MIN_SIZE(__solo) (__solo->nr_chans * 0x00080000)
|
||||
#define SOLO_JPEG_EXT_ADDR(__solo) \
|
||||
(SOLO_MP4E_EXT_ADDR(__solo) + SOLO_MP4E_EXT_SIZE(__solo))
|
||||
#define SOLO_JPEG_EXT_SIZE(__solo) \
|
||||
max(__SOLO_JPEG_MIN_SIZE(__solo), \
|
||||
min((__solo->sdram_size - SOLO_JPEG_EXT_ADDR(__solo)), 0x00ff0000))
|
||||
clamp(__solo->sdram_size - SOLO_JPEG_EXT_ADDR(__solo), \
|
||||
__SOLO_JPEG_MIN_SIZE(__solo), 0x00ff0000)
|
||||
|
||||
#define SOLO_SDRAM_END(__solo) \
|
||||
(SOLO_JPEG_EXT_ADDR(__solo) + SOLO_JPEG_EXT_SIZE(__solo))
|
||||
|
||||
@@ -870,7 +870,7 @@ static int vcodec_domains_get(struct venus_core *core)
|
||||
pd = dev_pm_domain_attach_by_name(dev,
|
||||
res->vcodec_pmdomains[i]);
|
||||
if (IS_ERR_OR_NULL(pd))
|
||||
return PTR_ERR(pd) ? : -ENODATA;
|
||||
return pd ? PTR_ERR(pd) : -ENODATA;
|
||||
core->pmdomains[i] = pd;
|
||||
}
|
||||
|
||||
|
||||
@@ -1297,7 +1297,7 @@ static int enc_post_frame_start(struct s5p_mfc_ctx *ctx)
|
||||
if (ctx->state == MFCINST_FINISHING && ctx->ref_queue_cnt == 0)
|
||||
src_ready = false;
|
||||
if (!src_ready || ctx->dst_queue_cnt == 0)
|
||||
clear_work_bit(ctx);
|
||||
clear_work_bit_irqsave(ctx);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ static int radio_isa_querycap(struct file *file, void *priv,
|
||||
|
||||
strscpy(v->driver, isa->drv->driver.driver.name, sizeof(v->driver));
|
||||
strscpy(v->card, isa->drv->card, sizeof(v->card));
|
||||
snprintf(v->bus_info, sizeof(v->bus_info), "ISA:%s", isa->v4l2_dev.name);
|
||||
snprintf(v->bus_info, sizeof(v->bus_info), "ISA:%s", dev_name(isa->v4l2_dev.dev));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -179,8 +179,11 @@ static int stm32_fmc2_ebi_check_mux(struct stm32_fmc2_ebi *ebi,
|
||||
int cs)
|
||||
{
|
||||
u32 bcr;
|
||||
int ret;
|
||||
|
||||
regmap_read(ebi->regmap, FMC2_BCR(cs), &bcr);
|
||||
ret = regmap_read(ebi->regmap, FMC2_BCR(cs), &bcr);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (bcr & FMC2_BCR_MTYP)
|
||||
return 0;
|
||||
@@ -193,8 +196,11 @@ static int stm32_fmc2_ebi_check_waitcfg(struct stm32_fmc2_ebi *ebi,
|
||||
int cs)
|
||||
{
|
||||
u32 bcr, val = FIELD_PREP(FMC2_BCR_MTYP, FMC2_BCR_MTYP_NOR);
|
||||
int ret;
|
||||
|
||||
regmap_read(ebi->regmap, FMC2_BCR(cs), &bcr);
|
||||
ret = regmap_read(ebi->regmap, FMC2_BCR(cs), &bcr);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if ((bcr & FMC2_BCR_MTYP) == val && bcr & FMC2_BCR_BURSTEN)
|
||||
return 0;
|
||||
@@ -207,8 +213,11 @@ static int stm32_fmc2_ebi_check_sync_trans(struct stm32_fmc2_ebi *ebi,
|
||||
int cs)
|
||||
{
|
||||
u32 bcr;
|
||||
int ret;
|
||||
|
||||
regmap_read(ebi->regmap, FMC2_BCR(cs), &bcr);
|
||||
ret = regmap_read(ebi->regmap, FMC2_BCR(cs), &bcr);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (bcr & FMC2_BCR_BURSTEN)
|
||||
return 0;
|
||||
@@ -221,8 +230,11 @@ static int stm32_fmc2_ebi_check_async_trans(struct stm32_fmc2_ebi *ebi,
|
||||
int cs)
|
||||
{
|
||||
u32 bcr;
|
||||
int ret;
|
||||
|
||||
regmap_read(ebi->regmap, FMC2_BCR(cs), &bcr);
|
||||
ret = regmap_read(ebi->regmap, FMC2_BCR(cs), &bcr);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (!(bcr & FMC2_BCR_BURSTEN) || !(bcr & FMC2_BCR_CBURSTRW))
|
||||
return 0;
|
||||
@@ -235,8 +247,11 @@ static int stm32_fmc2_ebi_check_cpsize(struct stm32_fmc2_ebi *ebi,
|
||||
int cs)
|
||||
{
|
||||
u32 bcr, val = FIELD_PREP(FMC2_BCR_MTYP, FMC2_BCR_MTYP_PSRAM);
|
||||
int ret;
|
||||
|
||||
regmap_read(ebi->regmap, FMC2_BCR(cs), &bcr);
|
||||
ret = regmap_read(ebi->regmap, FMC2_BCR(cs), &bcr);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if ((bcr & FMC2_BCR_MTYP) == val && bcr & FMC2_BCR_BURSTEN)
|
||||
return 0;
|
||||
@@ -249,12 +264,18 @@ static int stm32_fmc2_ebi_check_address_hold(struct stm32_fmc2_ebi *ebi,
|
||||
int cs)
|
||||
{
|
||||
u32 bcr, bxtr, val = FIELD_PREP(FMC2_BXTR_ACCMOD, FMC2_BXTR_EXTMOD_D);
|
||||
int ret;
|
||||
|
||||
ret = regmap_read(ebi->regmap, FMC2_BCR(cs), &bcr);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
regmap_read(ebi->regmap, FMC2_BCR(cs), &bcr);
|
||||
if (prop->reg_type == FMC2_REG_BWTR)
|
||||
regmap_read(ebi->regmap, FMC2_BWTR(cs), &bxtr);
|
||||
ret = regmap_read(ebi->regmap, FMC2_BWTR(cs), &bxtr);
|
||||
else
|
||||
regmap_read(ebi->regmap, FMC2_BTR(cs), &bxtr);
|
||||
ret = regmap_read(ebi->regmap, FMC2_BTR(cs), &bxtr);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if ((!(bcr & FMC2_BCR_BURSTEN) || !(bcr & FMC2_BCR_CBURSTRW)) &&
|
||||
((bxtr & FMC2_BXTR_ACCMOD) == val || bcr & FMC2_BCR_MUXEN))
|
||||
@@ -268,12 +289,19 @@ static int stm32_fmc2_ebi_check_clk_period(struct stm32_fmc2_ebi *ebi,
|
||||
int cs)
|
||||
{
|
||||
u32 bcr, bcr1;
|
||||
int ret;
|
||||
|
||||
regmap_read(ebi->regmap, FMC2_BCR(cs), &bcr);
|
||||
if (cs)
|
||||
regmap_read(ebi->regmap, FMC2_BCR1, &bcr1);
|
||||
else
|
||||
ret = regmap_read(ebi->regmap, FMC2_BCR(cs), &bcr);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (cs) {
|
||||
ret = regmap_read(ebi->regmap, FMC2_BCR1, &bcr1);
|
||||
if (ret)
|
||||
return ret;
|
||||
} else {
|
||||
bcr1 = bcr;
|
||||
}
|
||||
|
||||
if (bcr & FMC2_BCR_BURSTEN && (!cs || !(bcr1 & FMC2_BCR1_CCLKEN)))
|
||||
return 0;
|
||||
@@ -305,12 +333,18 @@ static u32 stm32_fmc2_ebi_ns_to_clk_period(struct stm32_fmc2_ebi *ebi,
|
||||
{
|
||||
u32 nb_clk_cycles = stm32_fmc2_ebi_ns_to_clock_cycles(ebi, cs, setup);
|
||||
u32 bcr, btr, clk_period;
|
||||
int ret;
|
||||
|
||||
ret = regmap_read(ebi->regmap, FMC2_BCR1, &bcr);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
regmap_read(ebi->regmap, FMC2_BCR1, &bcr);
|
||||
if (bcr & FMC2_BCR1_CCLKEN || !cs)
|
||||
regmap_read(ebi->regmap, FMC2_BTR1, &btr);
|
||||
ret = regmap_read(ebi->regmap, FMC2_BTR1, &btr);
|
||||
else
|
||||
regmap_read(ebi->regmap, FMC2_BTR(cs), &btr);
|
||||
ret = regmap_read(ebi->regmap, FMC2_BTR(cs), &btr);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
clk_period = FIELD_GET(FMC2_BTR_CLKDIV, btr) + 1;
|
||||
|
||||
@@ -569,11 +603,16 @@ static int stm32_fmc2_ebi_set_address_setup(struct stm32_fmc2_ebi *ebi,
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
regmap_read(ebi->regmap, FMC2_BCR(cs), &bcr);
|
||||
ret = regmap_read(ebi->regmap, FMC2_BCR(cs), &bcr);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (prop->reg_type == FMC2_REG_BWTR)
|
||||
regmap_read(ebi->regmap, FMC2_BWTR(cs), &bxtr);
|
||||
ret = regmap_read(ebi->regmap, FMC2_BWTR(cs), &bxtr);
|
||||
else
|
||||
regmap_read(ebi->regmap, FMC2_BTR(cs), &bxtr);
|
||||
ret = regmap_read(ebi->regmap, FMC2_BTR(cs), &bxtr);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if ((bxtr & FMC2_BXTR_ACCMOD) == val || bcr & FMC2_BCR_MUXEN)
|
||||
val = clamp_val(setup, 1, FMC2_BXTR_ADDSET_MAX);
|
||||
@@ -691,11 +730,14 @@ static int stm32_fmc2_ebi_set_max_low_pulse(struct stm32_fmc2_ebi *ebi,
|
||||
int cs, u32 setup)
|
||||
{
|
||||
u32 old_val, new_val, pcscntr;
|
||||
int ret;
|
||||
|
||||
if (setup < 1)
|
||||
return 0;
|
||||
|
||||
regmap_read(ebi->regmap, FMC2_PCSCNTR, &pcscntr);
|
||||
ret = regmap_read(ebi->regmap, FMC2_PCSCNTR, &pcscntr);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Enable counter for the bank */
|
||||
regmap_update_bits(ebi->regmap, FMC2_PCSCNTR,
|
||||
@@ -942,17 +984,20 @@ static void stm32_fmc2_ebi_disable_bank(struct stm32_fmc2_ebi *ebi, int cs)
|
||||
regmap_update_bits(ebi->regmap, FMC2_BCR(cs), FMC2_BCR_MBKEN, 0);
|
||||
}
|
||||
|
||||
static void stm32_fmc2_ebi_save_setup(struct stm32_fmc2_ebi *ebi)
|
||||
static int stm32_fmc2_ebi_save_setup(struct stm32_fmc2_ebi *ebi)
|
||||
{
|
||||
unsigned int cs;
|
||||
int ret;
|
||||
|
||||
for (cs = 0; cs < FMC2_MAX_EBI_CE; cs++) {
|
||||
regmap_read(ebi->regmap, FMC2_BCR(cs), &ebi->bcr[cs]);
|
||||
regmap_read(ebi->regmap, FMC2_BTR(cs), &ebi->btr[cs]);
|
||||
regmap_read(ebi->regmap, FMC2_BWTR(cs), &ebi->bwtr[cs]);
|
||||
ret = regmap_read(ebi->regmap, FMC2_BCR(cs), &ebi->bcr[cs]);
|
||||
ret |= regmap_read(ebi->regmap, FMC2_BTR(cs), &ebi->btr[cs]);
|
||||
ret |= regmap_read(ebi->regmap, FMC2_BWTR(cs), &ebi->bwtr[cs]);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
regmap_read(ebi->regmap, FMC2_PCSCNTR, &ebi->pcscntr);
|
||||
return regmap_read(ebi->regmap, FMC2_PCSCNTR, &ebi->pcscntr);
|
||||
}
|
||||
|
||||
static void stm32_fmc2_ebi_set_setup(struct stm32_fmc2_ebi *ebi)
|
||||
@@ -981,22 +1026,29 @@ static void stm32_fmc2_ebi_disable_banks(struct stm32_fmc2_ebi *ebi)
|
||||
}
|
||||
|
||||
/* NWAIT signal can not be connected to EBI controller and NAND controller */
|
||||
static bool stm32_fmc2_ebi_nwait_used_by_ctrls(struct stm32_fmc2_ebi *ebi)
|
||||
static int stm32_fmc2_ebi_nwait_used_by_ctrls(struct stm32_fmc2_ebi *ebi)
|
||||
{
|
||||
struct device *dev = ebi->dev;
|
||||
unsigned int cs;
|
||||
u32 bcr;
|
||||
int ret;
|
||||
|
||||
for (cs = 0; cs < FMC2_MAX_EBI_CE; cs++) {
|
||||
if (!(ebi->bank_assigned & BIT(cs)))
|
||||
continue;
|
||||
|
||||
regmap_read(ebi->regmap, FMC2_BCR(cs), &bcr);
|
||||
ret = regmap_read(ebi->regmap, FMC2_BCR(cs), &bcr);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if ((bcr & FMC2_BCR_WAITEN || bcr & FMC2_BCR_ASYNCWAIT) &&
|
||||
ebi->bank_assigned & BIT(FMC2_NAND))
|
||||
return true;
|
||||
ebi->bank_assigned & BIT(FMC2_NAND)) {
|
||||
dev_err(dev, "NWAIT signal connected to EBI and NAND controllers\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void stm32_fmc2_ebi_enable(struct stm32_fmc2_ebi *ebi)
|
||||
@@ -1083,10 +1135,9 @@ static int stm32_fmc2_ebi_parse_dt(struct stm32_fmc2_ebi *ebi)
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (stm32_fmc2_ebi_nwait_used_by_ctrls(ebi)) {
|
||||
dev_err(dev, "NWAIT signal connected to EBI and NAND controllers\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
ret = stm32_fmc2_ebi_nwait_used_by_ctrls(ebi);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
stm32_fmc2_ebi_enable(ebi);
|
||||
|
||||
@@ -1131,7 +1182,10 @@ static int stm32_fmc2_ebi_probe(struct platform_device *pdev)
|
||||
if (ret)
|
||||
goto err_release;
|
||||
|
||||
stm32_fmc2_ebi_save_setup(ebi);
|
||||
ret = stm32_fmc2_ebi_save_setup(ebi);
|
||||
if (ret)
|
||||
goto err_release;
|
||||
|
||||
platform_set_drvdata(pdev, ebi);
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -74,6 +74,9 @@ static void tegra186_mc_client_sid_override(struct tegra_mc *mc,
|
||||
{
|
||||
u32 value, old;
|
||||
|
||||
if (client->regs.sid.security == 0 && client->regs.sid.override == 0)
|
||||
return;
|
||||
|
||||
value = readl(mc->regs + client->regs.sid.security);
|
||||
if ((value & MC_SID_STREAMID_SECURITY_OVERRIDE) == 0) {
|
||||
/*
|
||||
|
||||
@@ -3109,13 +3109,13 @@ static ssize_t mtf_test_write(struct file *file, const char __user *buf,
|
||||
test->buffer = kzalloc(BUFFER_SIZE, GFP_KERNEL);
|
||||
#ifdef CONFIG_HIGHMEM
|
||||
test->highmem = alloc_pages(GFP_KERNEL | __GFP_HIGHMEM, BUFFER_ORDER);
|
||||
if (!test->highmem) {
|
||||
count = -ENOMEM;
|
||||
goto free_test_buffer;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_HIGHMEM
|
||||
if (test->buffer && test->highmem) {
|
||||
#else
|
||||
if (test->buffer) {
|
||||
#endif
|
||||
mutex_lock(&mmc_test_lock);
|
||||
mmc_test_run(test, testcase);
|
||||
mutex_unlock(&mmc_test_lock);
|
||||
@@ -3123,6 +3123,7 @@ static ssize_t mtf_test_write(struct file *file, const char __user *buf,
|
||||
|
||||
#ifdef CONFIG_HIGHMEM
|
||||
__free_pages(test->highmem, BUFFER_ORDER);
|
||||
free_test_buffer:
|
||||
#endif
|
||||
kfree(test->buffer);
|
||||
kfree(test);
|
||||
|
||||
@@ -3295,6 +3295,10 @@ int dw_mci_probe(struct dw_mci *host)
|
||||
host->biu_clk = devm_clk_get(host->dev, "biu");
|
||||
if (IS_ERR(host->biu_clk)) {
|
||||
dev_dbg(host->dev, "biu clock not available\n");
|
||||
ret = PTR_ERR(host->biu_clk);
|
||||
if (ret == -EPROBE_DEFER)
|
||||
return ret;
|
||||
|
||||
} else {
|
||||
ret = clk_prepare_enable(host->biu_clk);
|
||||
if (ret) {
|
||||
@@ -3306,6 +3310,10 @@ int dw_mci_probe(struct dw_mci *host)
|
||||
host->ciu_clk = devm_clk_get(host->dev, "ciu");
|
||||
if (IS_ERR(host->ciu_clk)) {
|
||||
dev_dbg(host->dev, "ciu clock not available\n");
|
||||
ret = PTR_ERR(host->ciu_clk);
|
||||
if (ret == -EPROBE_DEFER)
|
||||
goto err_clk_biu;
|
||||
|
||||
host->bus_hz = host->pdata->bus_hz;
|
||||
} else {
|
||||
ret = clk_prepare_enable(host->ciu_clk);
|
||||
|
||||
@@ -578,7 +578,6 @@ static void bond_ipsec_del_sa_all(struct bonding *bond)
|
||||
} else {
|
||||
slave->dev->xfrmdev_ops->xdo_dev_state_delete(ipsec->xs);
|
||||
}
|
||||
ipsec->xs->xso.real_dev = NULL;
|
||||
}
|
||||
spin_unlock_bh(&bond->ipsec_lock);
|
||||
rcu_read_unlock();
|
||||
@@ -595,34 +594,30 @@ static bool bond_ipsec_offload_ok(struct sk_buff *skb, struct xfrm_state *xs)
|
||||
struct net_device *real_dev;
|
||||
struct slave *curr_active;
|
||||
struct bonding *bond;
|
||||
int err;
|
||||
bool ok = false;
|
||||
|
||||
bond = netdev_priv(bond_dev);
|
||||
rcu_read_lock();
|
||||
curr_active = rcu_dereference(bond->curr_active_slave);
|
||||
if (!curr_active)
|
||||
goto out;
|
||||
real_dev = curr_active->dev;
|
||||
|
||||
if (BOND_MODE(bond) != BOND_MODE_ACTIVEBACKUP) {
|
||||
err = false;
|
||||
if (BOND_MODE(bond) != BOND_MODE_ACTIVEBACKUP)
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!xs->xso.real_dev) {
|
||||
err = false;
|
||||
if (!xs->xso.real_dev)
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!real_dev->xfrmdev_ops ||
|
||||
!real_dev->xfrmdev_ops->xdo_dev_offload_ok ||
|
||||
netif_is_bond_master(real_dev)) {
|
||||
err = false;
|
||||
netif_is_bond_master(real_dev))
|
||||
goto out;
|
||||
}
|
||||
|
||||
err = real_dev->xfrmdev_ops->xdo_dev_offload_ok(skb, xs);
|
||||
ok = real_dev->xfrmdev_ops->xdo_dev_offload_ok(skb, xs);
|
||||
out:
|
||||
rcu_read_unlock();
|
||||
return err;
|
||||
return ok;
|
||||
}
|
||||
|
||||
static const struct xfrmdev_ops bond_xfrmdev_ops = {
|
||||
|
||||
@@ -932,7 +932,7 @@ static int bond_option_active_slave_set(struct bonding *bond,
|
||||
/* check to see if we are clearing active */
|
||||
if (!slave_dev) {
|
||||
netdev_dbg(bond->dev, "Clearing current active slave\n");
|
||||
RCU_INIT_POINTER(bond->curr_active_slave, NULL);
|
||||
bond_change_active_slave(bond, NULL);
|
||||
bond_select_active_slave(bond);
|
||||
} else {
|
||||
struct slave *old_active = rtnl_dereference(bond->curr_active_slave);
|
||||
|
||||
@@ -453,7 +453,8 @@ static irqreturn_t mv88e6xxx_g1_atu_prob_irq_thread_fn(int irq, void *dev_id)
|
||||
trace_mv88e6xxx_atu_full_violation(chip->dev, spid,
|
||||
entry.portvec, entry.mac,
|
||||
fid);
|
||||
chip->ports[spid].atu_full_violation++;
|
||||
if (spid < ARRAY_SIZE(chip->ports))
|
||||
chip->ports[spid].atu_full_violation++;
|
||||
}
|
||||
mv88e6xxx_reg_unlock(chip);
|
||||
|
||||
|
||||
@@ -528,7 +528,9 @@ static int felix_tag_8021q_setup(struct dsa_switch *ds)
|
||||
* so we need to be careful that there are no extra frames to be
|
||||
* dequeued over MMIO, since we would never know to discard them.
|
||||
*/
|
||||
ocelot_lock_xtr_grp_bh(ocelot, 0);
|
||||
ocelot_drain_cpu_queue(ocelot, 0);
|
||||
ocelot_unlock_xtr_grp_bh(ocelot, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1493,6 +1495,8 @@ static void felix_port_deferred_xmit(struct kthread_work *work)
|
||||
int port = xmit_work->dp->index;
|
||||
int retries = 10;
|
||||
|
||||
ocelot_lock_inj_grp(ocelot, 0);
|
||||
|
||||
do {
|
||||
if (ocelot_can_inject(ocelot, 0))
|
||||
break;
|
||||
@@ -1501,6 +1505,7 @@ static void felix_port_deferred_xmit(struct kthread_work *work)
|
||||
} while (--retries);
|
||||
|
||||
if (!retries) {
|
||||
ocelot_unlock_inj_grp(ocelot, 0);
|
||||
dev_err(ocelot->dev, "port %d failed to inject skb\n",
|
||||
port);
|
||||
ocelot_port_purge_txtstamp_skb(ocelot, port, skb);
|
||||
@@ -1510,6 +1515,8 @@ static void felix_port_deferred_xmit(struct kthread_work *work)
|
||||
|
||||
ocelot_port_inject_frame(ocelot, port, 0, rew_op, skb);
|
||||
|
||||
ocelot_unlock_inj_grp(ocelot, 0);
|
||||
|
||||
consume_skb(skb);
|
||||
kfree(xmit_work);
|
||||
}
|
||||
@@ -1658,6 +1665,8 @@ static bool felix_check_xtr_pkt(struct ocelot *ocelot)
|
||||
if (!felix->info->quirk_no_xtr_irq)
|
||||
return false;
|
||||
|
||||
ocelot_lock_xtr_grp(ocelot, grp);
|
||||
|
||||
while (ocelot_read(ocelot, QS_XTR_DATA_PRESENT) & BIT(grp)) {
|
||||
struct sk_buff *skb;
|
||||
unsigned int type;
|
||||
@@ -1694,6 +1703,8 @@ out:
|
||||
ocelot_drain_cpu_queue(ocelot, 0);
|
||||
}
|
||||
|
||||
ocelot_unlock_xtr_grp(ocelot, grp);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/iopoll.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of_mdio.h>
|
||||
@@ -38,6 +39,10 @@
|
||||
#define VSC73XX_BLOCK_ARBITER 0x5 /* Only subblock 0 */
|
||||
#define VSC73XX_BLOCK_SYSTEM 0x7 /* Only subblock 0 */
|
||||
|
||||
/* MII Block subblock */
|
||||
#define VSC73XX_BLOCK_MII_INTERNAL 0x0 /* Internal MDIO subblock */
|
||||
#define VSC73XX_BLOCK_MII_EXTERNAL 0x1 /* External MDIO subblock */
|
||||
|
||||
#define CPU_PORT 6 /* CPU port */
|
||||
|
||||
/* MAC Block registers */
|
||||
@@ -196,6 +201,8 @@
|
||||
#define VSC73XX_MII_CMD 0x1
|
||||
#define VSC73XX_MII_DATA 0x2
|
||||
|
||||
#define VSC73XX_MII_STAT_BUSY BIT(3)
|
||||
|
||||
/* Arbiter block 5 registers */
|
||||
#define VSC73XX_ARBEMPTY 0x0c
|
||||
#define VSC73XX_ARBDISC 0x0e
|
||||
@@ -269,6 +276,10 @@
|
||||
#define IS_7398(a) ((a)->chipid == VSC73XX_CHIPID_ID_7398)
|
||||
#define IS_739X(a) (IS_7395(a) || IS_7398(a))
|
||||
|
||||
#define VSC73XX_POLL_SLEEP_US 1000
|
||||
#define VSC73XX_MDIO_POLL_SLEEP_US 5
|
||||
#define VSC73XX_POLL_TIMEOUT_US 10000
|
||||
|
||||
struct vsc73xx_counter {
|
||||
u8 counter;
|
||||
const char *name;
|
||||
@@ -484,6 +495,22 @@ static int vsc73xx_detect(struct vsc73xx *vsc)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int vsc73xx_mdio_busy_check(struct vsc73xx *vsc)
|
||||
{
|
||||
int ret, err;
|
||||
u32 val;
|
||||
|
||||
ret = read_poll_timeout(vsc73xx_read, err,
|
||||
err < 0 || !(val & VSC73XX_MII_STAT_BUSY),
|
||||
VSC73XX_MDIO_POLL_SLEEP_US,
|
||||
VSC73XX_POLL_TIMEOUT_US, false, vsc,
|
||||
VSC73XX_BLOCK_MII, VSC73XX_BLOCK_MII_INTERNAL,
|
||||
VSC73XX_MII_STAT, &val);
|
||||
if (ret)
|
||||
return ret;
|
||||
return err;
|
||||
}
|
||||
|
||||
static int vsc73xx_phy_read(struct dsa_switch *ds, int phy, int regnum)
|
||||
{
|
||||
struct vsc73xx *vsc = ds->priv;
|
||||
@@ -491,12 +518,20 @@ static int vsc73xx_phy_read(struct dsa_switch *ds, int phy, int regnum)
|
||||
u32 val;
|
||||
int ret;
|
||||
|
||||
ret = vsc73xx_mdio_busy_check(vsc);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Setting bit 26 means "read" */
|
||||
cmd = BIT(26) | (phy << 21) | (regnum << 16);
|
||||
ret = vsc73xx_write(vsc, VSC73XX_BLOCK_MII, 0, 1, cmd);
|
||||
if (ret)
|
||||
return ret;
|
||||
msleep(2);
|
||||
|
||||
ret = vsc73xx_mdio_busy_check(vsc);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = vsc73xx_read(vsc, VSC73XX_BLOCK_MII, 0, 2, &val);
|
||||
if (ret)
|
||||
return ret;
|
||||
@@ -520,6 +555,10 @@ static int vsc73xx_phy_write(struct dsa_switch *ds, int phy, int regnum,
|
||||
u32 cmd;
|
||||
int ret;
|
||||
|
||||
ret = vsc73xx_mdio_busy_check(vsc);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* It was found through tedious experiments that this router
|
||||
* chip really hates to have it's PHYs reset. They
|
||||
* never recover if that happens: autonegotiation stops
|
||||
@@ -531,7 +570,7 @@ static int vsc73xx_phy_write(struct dsa_switch *ds, int phy, int regnum,
|
||||
return 0;
|
||||
}
|
||||
|
||||
cmd = (phy << 21) | (regnum << 16);
|
||||
cmd = (phy << 21) | (regnum << 16) | val;
|
||||
ret = vsc73xx_write(vsc, VSC73XX_BLOCK_MII, 0, 1, cmd);
|
||||
if (ret)
|
||||
return ret;
|
||||
@@ -780,7 +819,7 @@ static void vsc73xx_adjust_link(struct dsa_switch *ds, int port,
|
||||
* after a PHY or the CPU port comes up or down.
|
||||
*/
|
||||
if (!phydev->link) {
|
||||
int maxloop = 10;
|
||||
int ret, err;
|
||||
|
||||
dev_dbg(vsc->dev, "port %d: went down\n",
|
||||
port);
|
||||
@@ -795,19 +834,17 @@ static void vsc73xx_adjust_link(struct dsa_switch *ds, int port,
|
||||
VSC73XX_ARBDISC, BIT(port), BIT(port));
|
||||
|
||||
/* Wait until queue is empty */
|
||||
vsc73xx_read(vsc, VSC73XX_BLOCK_ARBITER, 0,
|
||||
VSC73XX_ARBEMPTY, &val);
|
||||
while (!(val & BIT(port))) {
|
||||
msleep(1);
|
||||
vsc73xx_read(vsc, VSC73XX_BLOCK_ARBITER, 0,
|
||||
VSC73XX_ARBEMPTY, &val);
|
||||
if (--maxloop == 0) {
|
||||
dev_err(vsc->dev,
|
||||
"timeout waiting for block arbiter\n");
|
||||
/* Continue anyway */
|
||||
break;
|
||||
}
|
||||
}
|
||||
ret = read_poll_timeout(vsc73xx_read, err,
|
||||
err < 0 || (val & BIT(port)),
|
||||
VSC73XX_POLL_SLEEP_US,
|
||||
VSC73XX_POLL_TIMEOUT_US, false,
|
||||
vsc, VSC73XX_BLOCK_ARBITER, 0,
|
||||
VSC73XX_ARBEMPTY, &val);
|
||||
if (ret)
|
||||
dev_err(vsc->dev,
|
||||
"timeout waiting for block arbiter\n");
|
||||
else if (err < 0)
|
||||
dev_err(vsc->dev, "error reading arbiter\n");
|
||||
|
||||
/* Put this port into reset */
|
||||
vsc73xx_write(vsc, VSC73XX_BLOCK_MAC, port, VSC73XX_MAC_CFG,
|
||||
|
||||
@@ -1244,7 +1244,8 @@ static u64 hash_filter_ntuple(struct ch_filter_specification *fs,
|
||||
* in the Compressed Filter Tuple.
|
||||
*/
|
||||
if (tp->vlan_shift >= 0 && fs->mask.ivlan)
|
||||
ntuple |= (FT_VLAN_VLD_F | fs->val.ivlan) << tp->vlan_shift;
|
||||
ntuple |= (u64)(FT_VLAN_VLD_F |
|
||||
fs->val.ivlan) << tp->vlan_shift;
|
||||
|
||||
if (tp->port_shift >= 0 && fs->mask.iport)
|
||||
ntuple |= (u64)fs->val.iport << tp->port_shift;
|
||||
|
||||
@@ -2583,13 +2583,14 @@ static int dpaa2_switch_refill_bp(struct ethsw_core *ethsw)
|
||||
|
||||
static int dpaa2_switch_seed_bp(struct ethsw_core *ethsw)
|
||||
{
|
||||
int *count, i;
|
||||
int *count, ret, i;
|
||||
|
||||
for (i = 0; i < DPAA2_ETHSW_NUM_BUFS; i += BUFS_PER_CMD) {
|
||||
ret = dpaa2_switch_add_bufs(ethsw, ethsw->bpid);
|
||||
count = ðsw->buf_count;
|
||||
*count += dpaa2_switch_add_bufs(ethsw, ethsw->bpid);
|
||||
*count += ret;
|
||||
|
||||
if (unlikely(*count < BUFS_PER_CMD))
|
||||
if (unlikely(ret < BUFS_PER_CMD))
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
|
||||
@@ -5728,6 +5728,9 @@ static int hns3_reset_notify_uninit_enet(struct hnae3_handle *handle)
|
||||
struct net_device *netdev = handle->kinfo.netdev;
|
||||
struct hns3_nic_priv *priv = netdev_priv(netdev);
|
||||
|
||||
if (!test_bit(HNS3_NIC_STATE_DOWN, &priv->state))
|
||||
hns3_nic_net_stop(netdev);
|
||||
|
||||
if (!test_and_clear_bit(HNS3_NIC_STATE_INITED, &priv->state)) {
|
||||
netdev_warn(netdev, "already uninitialized\n");
|
||||
return 0;
|
||||
|
||||
@@ -2696,8 +2696,17 @@ static int hclge_cfg_mac_speed_dup_h(struct hnae3_handle *handle, int speed,
|
||||
{
|
||||
struct hclge_vport *vport = hclge_get_vport(handle);
|
||||
struct hclge_dev *hdev = vport->back;
|
||||
int ret;
|
||||
|
||||
return hclge_cfg_mac_speed_dup(hdev, speed, duplex, lane_num);
|
||||
ret = hclge_cfg_mac_speed_dup(hdev, speed, duplex, lane_num);
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
hdev->hw.mac.req_speed = speed;
|
||||
hdev->hw.mac.req_duplex = duplex;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int hclge_set_autoneg_en(struct hclge_dev *hdev, bool enable)
|
||||
@@ -2999,17 +3008,20 @@ static int hclge_mac_init(struct hclge_dev *hdev)
|
||||
if (!test_bit(HCLGE_STATE_RST_HANDLING, &hdev->state))
|
||||
hdev->hw.mac.duplex = HCLGE_MAC_FULL;
|
||||
|
||||
ret = hclge_cfg_mac_speed_dup_hw(hdev, hdev->hw.mac.speed,
|
||||
hdev->hw.mac.duplex, hdev->hw.mac.lane_num);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (hdev->hw.mac.support_autoneg) {
|
||||
ret = hclge_set_autoneg_en(hdev, hdev->hw.mac.autoneg);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (!hdev->hw.mac.autoneg) {
|
||||
ret = hclge_cfg_mac_speed_dup_hw(hdev, hdev->hw.mac.req_speed,
|
||||
hdev->hw.mac.req_duplex,
|
||||
hdev->hw.mac.lane_num);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
mac->link = 0;
|
||||
|
||||
if (mac->user_fec_mode & BIT(HNAE3_FEC_USER_DEF)) {
|
||||
@@ -11538,8 +11550,8 @@ static void hclge_reset_done(struct hnae3_ae_dev *ae_dev)
|
||||
dev_err(&hdev->pdev->dev, "fail to rebuild, ret=%d\n", ret);
|
||||
|
||||
hdev->reset_type = HNAE3_NONE_RESET;
|
||||
clear_bit(HCLGE_STATE_RST_HANDLING, &hdev->state);
|
||||
up(&hdev->reset_sem);
|
||||
if (test_and_clear_bit(HCLGE_STATE_RST_HANDLING, &hdev->state))
|
||||
up(&hdev->reset_sem);
|
||||
}
|
||||
|
||||
static void hclge_clear_resetting_state(struct hclge_dev *hdev)
|
||||
|
||||
@@ -1124,10 +1124,11 @@ void hclge_mbx_handler(struct hclge_dev *hdev)
|
||||
req = (struct hclge_mbx_vf_to_pf_cmd *)desc->data;
|
||||
|
||||
flag = le16_to_cpu(crq->desc[crq->next_to_use].flag);
|
||||
if (unlikely(!hnae3_get_bit(flag, HCLGE_CMDQ_RX_OUTVLD_B))) {
|
||||
if (unlikely(!hnae3_get_bit(flag, HCLGE_CMDQ_RX_OUTVLD_B) ||
|
||||
req->mbx_src_vfid > hdev->num_req_vfs)) {
|
||||
dev_warn(&hdev->pdev->dev,
|
||||
"dropped invalid mailbox message, code = %u\n",
|
||||
req->msg.code);
|
||||
"dropped invalid mailbox message, code = %u, vfid = %u\n",
|
||||
req->msg.code, req->mbx_src_vfid);
|
||||
|
||||
/* dropping/not processing this invalid message */
|
||||
crq->desc[crq->next_to_use].flag = 0;
|
||||
|
||||
@@ -191,6 +191,9 @@ static void hclge_mac_adjust_link(struct net_device *netdev)
|
||||
if (ret)
|
||||
netdev_err(netdev, "failed to adjust link.\n");
|
||||
|
||||
hdev->hw.mac.req_speed = (u32)speed;
|
||||
hdev->hw.mac.req_duplex = (u8)duplex;
|
||||
|
||||
ret = hclge_cfg_flowctrl(hdev);
|
||||
if (ret)
|
||||
netdev_err(netdev, "failed to configure flow control.\n");
|
||||
|
||||
@@ -1764,8 +1764,8 @@ static void hclgevf_reset_done(struct hnae3_ae_dev *ae_dev)
|
||||
ret);
|
||||
|
||||
hdev->reset_type = HNAE3_NONE_RESET;
|
||||
clear_bit(HCLGEVF_STATE_RST_HANDLING, &hdev->state);
|
||||
up(&hdev->reset_sem);
|
||||
if (test_and_clear_bit(HCLGEVF_STATE_RST_HANDLING, &hdev->state))
|
||||
up(&hdev->reset_sem);
|
||||
}
|
||||
|
||||
static u32 hclgevf_get_fw_version(struct hnae3_handle *handle)
|
||||
|
||||
@@ -986,7 +986,7 @@ static void sun3_82586_timeout(struct net_device *dev, unsigned int txqueue)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
printk("%s: xmitter timed out, try to restart! stat: %02x\n",dev->name,p->scb->cus);
|
||||
printk("%s: command-stats: %04x %04x\n",dev->name,swab16(p->xmit_cmds[0]->cmd_status),swab16(p->xmit_cmds[1]->cmd_status));
|
||||
printk("%s: command-stats: %04x\n", dev->name, swab16(p->xmit_cmds[0]->cmd_status));
|
||||
printk("%s: check, whether you set the right interrupt number!\n",dev->name);
|
||||
#endif
|
||||
sun3_82586_close(dev);
|
||||
|
||||
@@ -355,9 +355,6 @@ static unsigned int ice_rx_offset(struct ice_rx_ring *rx_ring)
|
||||
{
|
||||
if (ice_ring_uses_build_skb(rx_ring))
|
||||
return ICE_SKB_PAD;
|
||||
else if (ice_is_xdp_ena_vsi(rx_ring->vsi))
|
||||
return XDP_PACKET_HEADROOM;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -537,6 +534,7 @@ int ice_vsi_cfg_rxq(struct ice_rx_ring *ring)
|
||||
}
|
||||
}
|
||||
|
||||
xdp_init_buff(&ring->xdp, ice_rx_pg_size(ring) / 2, &ring->xdp_rxq);
|
||||
err = ice_setup_rx_ctx(ring);
|
||||
if (err) {
|
||||
dev_err(dev, "ice_setup_rx_ctx failed for RxQ %d, err %d\n",
|
||||
|
||||
@@ -1818,8 +1818,8 @@ void ice_update_eth_stats(struct ice_vsi *vsi)
|
||||
void ice_vsi_cfg_frame_size(struct ice_vsi *vsi)
|
||||
{
|
||||
if (!vsi->netdev || test_bit(ICE_FLAG_LEGACY_RX, vsi->back->flags)) {
|
||||
vsi->max_frame = ICE_AQ_SET_MAC_FRAME_SIZE_MAX;
|
||||
vsi->rx_buf_len = ICE_RXBUF_2048;
|
||||
vsi->max_frame = ICE_MAX_FRAME_LEGACY_RX;
|
||||
vsi->rx_buf_len = ICE_RXBUF_1664;
|
||||
#if (PAGE_SIZE < 8192)
|
||||
} else if (!ICE_2K_TOO_SMALL_WITH_PADDING &&
|
||||
(vsi->netdev->mtu <= ETH_DATA_LEN)) {
|
||||
@@ -1828,11 +1828,7 @@ void ice_vsi_cfg_frame_size(struct ice_vsi *vsi)
|
||||
#endif
|
||||
} else {
|
||||
vsi->max_frame = ICE_AQ_SET_MAC_FRAME_SIZE_MAX;
|
||||
#if (PAGE_SIZE < 8192)
|
||||
vsi->rx_buf_len = ICE_RXBUF_3072;
|
||||
#else
|
||||
vsi->rx_buf_len = ICE_RXBUF_2048;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -7328,8 +7328,8 @@ clear_recovery:
|
||||
*/
|
||||
static int ice_max_xdp_frame_size(struct ice_vsi *vsi)
|
||||
{
|
||||
if (PAGE_SIZE >= 8192 || test_bit(ICE_FLAG_LEGACY_RX, vsi->back->flags))
|
||||
return ICE_RXBUF_2048 - XDP_PACKET_HEADROOM;
|
||||
if (test_bit(ICE_FLAG_LEGACY_RX, vsi->back->flags))
|
||||
return ICE_RXBUF_1664;
|
||||
else
|
||||
return ICE_RXBUF_3072;
|
||||
}
|
||||
@@ -7362,6 +7362,12 @@ static int ice_change_mtu(struct net_device *netdev, int new_mtu)
|
||||
frame_size - ICE_ETH_PKT_HDR_PAD);
|
||||
return -EINVAL;
|
||||
}
|
||||
} else if (test_bit(ICE_FLAG_LEGACY_RX, pf->flags)) {
|
||||
if (new_mtu + ICE_ETH_PKT_HDR_PAD > ICE_MAX_FRAME_LEGACY_RX) {
|
||||
netdev_err(netdev, "Too big MTU for legacy-rx; Max is %d\n",
|
||||
ICE_MAX_FRAME_LEGACY_RX - ICE_ETH_PKT_HDR_PAD);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
/* if a reset is in progress, wait for some time for it to complete */
|
||||
|
||||
@@ -523,8 +523,16 @@ err:
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_rx_frame_truesize
|
||||
* @rx_ring: ptr to Rx ring
|
||||
* @size: size
|
||||
*
|
||||
* calculate the truesize with taking into the account PAGE_SIZE of
|
||||
* underlying arch
|
||||
*/
|
||||
static unsigned int
|
||||
ice_rx_frame_truesize(struct ice_rx_ring *rx_ring, unsigned int __maybe_unused size)
|
||||
ice_rx_frame_truesize(struct ice_rx_ring *rx_ring, const unsigned int size)
|
||||
{
|
||||
unsigned int truesize;
|
||||
|
||||
@@ -783,7 +791,6 @@ ice_rx_buf_adjust_pg_offset(struct ice_rx_buf *rx_buf, unsigned int size)
|
||||
/**
|
||||
* ice_can_reuse_rx_page - Determine if page can be reused for another Rx
|
||||
* @rx_buf: buffer containing the page
|
||||
* @rx_buf_pgcnt: rx_buf page refcount pre xdp_do_redirect() call
|
||||
*
|
||||
* If page is reusable, we have a green light for calling ice_reuse_rx_page,
|
||||
* which will assign the current buffer to the buffer that next_to_alloc is
|
||||
@@ -791,7 +798,7 @@ ice_rx_buf_adjust_pg_offset(struct ice_rx_buf *rx_buf, unsigned int size)
|
||||
* page freed
|
||||
*/
|
||||
static bool
|
||||
ice_can_reuse_rx_page(struct ice_rx_buf *rx_buf, int rx_buf_pgcnt)
|
||||
ice_can_reuse_rx_page(struct ice_rx_buf *rx_buf)
|
||||
{
|
||||
unsigned int pagecnt_bias = rx_buf->pagecnt_bias;
|
||||
struct page *page = rx_buf->page;
|
||||
@@ -800,16 +807,15 @@ ice_can_reuse_rx_page(struct ice_rx_buf *rx_buf, int rx_buf_pgcnt)
|
||||
if (!dev_page_is_reusable(page))
|
||||
return false;
|
||||
|
||||
#if (PAGE_SIZE < 8192)
|
||||
/* if we are only owner of page we can reuse it */
|
||||
if (unlikely((rx_buf_pgcnt - pagecnt_bias) > 1))
|
||||
if (unlikely(rx_buf->pgcnt - pagecnt_bias > 1))
|
||||
return false;
|
||||
#else
|
||||
#if (PAGE_SIZE >= 8192)
|
||||
#define ICE_LAST_OFFSET \
|
||||
(SKB_WITH_OVERHEAD(PAGE_SIZE) - ICE_RXBUF_2048)
|
||||
(SKB_WITH_OVERHEAD(PAGE_SIZE) - ICE_RXBUF_3072)
|
||||
if (rx_buf->page_offset > ICE_LAST_OFFSET)
|
||||
return false;
|
||||
#endif /* PAGE_SIZE < 8192) */
|
||||
#endif /* PAGE_SIZE >= 8192) */
|
||||
|
||||
/* If we have drained the page fragment pool we need to update
|
||||
* the pagecnt_bias and page count so that we fully restock the
|
||||
@@ -886,24 +892,19 @@ ice_reuse_rx_page(struct ice_rx_ring *rx_ring, struct ice_rx_buf *old_buf)
|
||||
* ice_get_rx_buf - Fetch Rx buffer and synchronize data for use
|
||||
* @rx_ring: Rx descriptor ring to transact packets on
|
||||
* @size: size of buffer to add to skb
|
||||
* @rx_buf_pgcnt: rx_buf page refcount
|
||||
* @ntc: index of next to clean element
|
||||
*
|
||||
* This function will pull an Rx buffer from the ring and synchronize it
|
||||
* for use by the CPU.
|
||||
*/
|
||||
static struct ice_rx_buf *
|
||||
ice_get_rx_buf(struct ice_rx_ring *rx_ring, const unsigned int size,
|
||||
int *rx_buf_pgcnt)
|
||||
const unsigned int ntc)
|
||||
{
|
||||
struct ice_rx_buf *rx_buf;
|
||||
|
||||
rx_buf = &rx_ring->rx_buf[rx_ring->next_to_clean];
|
||||
*rx_buf_pgcnt =
|
||||
#if (PAGE_SIZE < 8192)
|
||||
page_count(rx_buf->page);
|
||||
#else
|
||||
0;
|
||||
#endif
|
||||
rx_buf = &rx_ring->rx_buf[ntc];
|
||||
rx_buf->pgcnt = page_count(rx_buf->page);
|
||||
prefetchw(rx_buf->page);
|
||||
|
||||
if (!size)
|
||||
@@ -973,7 +974,6 @@ ice_build_skb(struct ice_rx_ring *rx_ring, struct ice_rx_buf *rx_buf,
|
||||
/**
|
||||
* ice_construct_skb - Allocate skb and populate it
|
||||
* @rx_ring: Rx descriptor ring to transact packets on
|
||||
* @rx_buf: Rx buffer to pull data from
|
||||
* @xdp: xdp_buff pointing to the data
|
||||
*
|
||||
* This function allocates an skb. It then populates it with the page
|
||||
@@ -984,17 +984,15 @@ static struct sk_buff *
|
||||
ice_construct_skb(struct ice_rx_ring *rx_ring, struct ice_rx_buf *rx_buf,
|
||||
struct xdp_buff *xdp)
|
||||
{
|
||||
unsigned int metasize = xdp->data - xdp->data_meta;
|
||||
unsigned int size = xdp->data_end - xdp->data;
|
||||
unsigned int headlen;
|
||||
struct sk_buff *skb;
|
||||
|
||||
/* prefetch first cache line of first page */
|
||||
net_prefetch(xdp->data_meta);
|
||||
net_prefetch(xdp->data);
|
||||
|
||||
/* allocate a skb to store the frags */
|
||||
skb = __napi_alloc_skb(&rx_ring->q_vector->napi,
|
||||
ICE_RX_HDR_SIZE + metasize,
|
||||
skb = __napi_alloc_skb(&rx_ring->q_vector->napi, ICE_RX_HDR_SIZE,
|
||||
GFP_ATOMIC | __GFP_NOWARN);
|
||||
if (unlikely(!skb))
|
||||
return NULL;
|
||||
@@ -1006,13 +1004,8 @@ ice_construct_skb(struct ice_rx_ring *rx_ring, struct ice_rx_buf *rx_buf,
|
||||
headlen = eth_get_headlen(skb->dev, xdp->data, ICE_RX_HDR_SIZE);
|
||||
|
||||
/* align pull length to size of long to optimize memcpy performance */
|
||||
memcpy(__skb_put(skb, headlen + metasize), xdp->data_meta,
|
||||
ALIGN(headlen + metasize, sizeof(long)));
|
||||
|
||||
if (metasize) {
|
||||
skb_metadata_set(skb, metasize);
|
||||
__skb_pull(skb, metasize);
|
||||
}
|
||||
memcpy(__skb_put(skb, headlen), xdp->data, ALIGN(headlen,
|
||||
sizeof(long)));
|
||||
|
||||
/* if we exhaust the linear part then add what is left as a frag */
|
||||
size -= headlen;
|
||||
@@ -1041,26 +1034,17 @@ ice_construct_skb(struct ice_rx_ring *rx_ring, struct ice_rx_buf *rx_buf,
|
||||
* ice_put_rx_buf - Clean up used buffer and either recycle or free
|
||||
* @rx_ring: Rx descriptor ring to transact packets on
|
||||
* @rx_buf: Rx buffer to pull data from
|
||||
* @rx_buf_pgcnt: Rx buffer page count pre xdp_do_redirect()
|
||||
*
|
||||
* This function will update next_to_clean and then clean up the contents
|
||||
* of the rx_buf. It will either recycle the buffer or unmap it and free
|
||||
* the associated resources.
|
||||
* This function will clean up the contents of the rx_buf. It will either
|
||||
* recycle the buffer or unmap it and free the associated resources.
|
||||
*/
|
||||
static void
|
||||
ice_put_rx_buf(struct ice_rx_ring *rx_ring, struct ice_rx_buf *rx_buf,
|
||||
int rx_buf_pgcnt)
|
||||
ice_put_rx_buf(struct ice_rx_ring *rx_ring, struct ice_rx_buf *rx_buf)
|
||||
{
|
||||
u16 ntc = rx_ring->next_to_clean + 1;
|
||||
|
||||
/* fetch, update, and store next to clean */
|
||||
ntc = (ntc < rx_ring->count) ? ntc : 0;
|
||||
rx_ring->next_to_clean = ntc;
|
||||
|
||||
if (!rx_buf)
|
||||
return;
|
||||
|
||||
if (ice_can_reuse_rx_page(rx_buf, rx_buf_pgcnt)) {
|
||||
if (ice_can_reuse_rx_page(rx_buf)) {
|
||||
/* hand second half of page back to the ring */
|
||||
ice_reuse_rx_page(rx_ring, rx_buf);
|
||||
} else {
|
||||
@@ -1110,21 +1094,22 @@ ice_is_non_eop(struct ice_rx_ring *rx_ring, union ice_32b_rx_flex_desc *rx_desc)
|
||||
*/
|
||||
int ice_clean_rx_irq(struct ice_rx_ring *rx_ring, int budget)
|
||||
{
|
||||
unsigned int total_rx_bytes = 0, total_rx_pkts = 0, frame_sz = 0;
|
||||
unsigned int total_rx_bytes = 0, total_rx_pkts = 0;
|
||||
u16 cleaned_count = ICE_DESC_UNUSED(rx_ring);
|
||||
unsigned int offset = rx_ring->rx_offset;
|
||||
struct xdp_buff *xdp = &rx_ring->xdp;
|
||||
struct ice_tx_ring *xdp_ring = NULL;
|
||||
unsigned int xdp_res, xdp_xmit = 0;
|
||||
struct sk_buff *skb = rx_ring->skb;
|
||||
struct bpf_prog *xdp_prog = NULL;
|
||||
struct xdp_buff xdp;
|
||||
u32 ntc = rx_ring->next_to_clean;
|
||||
u32 cnt = rx_ring->count;
|
||||
bool failure;
|
||||
|
||||
/* Frame size depend on rx_ring setup when PAGE_SIZE=4K */
|
||||
#if (PAGE_SIZE < 8192)
|
||||
frame_sz = ice_rx_frame_truesize(rx_ring, 0);
|
||||
xdp->frame_sz = ice_rx_frame_truesize(rx_ring, 0);
|
||||
#endif
|
||||
xdp_init_buff(&xdp, frame_sz, &rx_ring->xdp_rxq);
|
||||
|
||||
xdp_prog = READ_ONCE(rx_ring->xdp_prog);
|
||||
if (xdp_prog)
|
||||
@@ -1137,12 +1122,11 @@ int ice_clean_rx_irq(struct ice_rx_ring *rx_ring, int budget)
|
||||
unsigned char *hard_start;
|
||||
unsigned int size;
|
||||
u16 stat_err_bits;
|
||||
int rx_buf_pgcnt;
|
||||
u16 vlan_tag = 0;
|
||||
u16 rx_ptype;
|
||||
|
||||
/* get the Rx desc from Rx ring based on 'next_to_clean' */
|
||||
rx_desc = ICE_RX_DESC(rx_ring, rx_ring->next_to_clean);
|
||||
rx_desc = ICE_RX_DESC(rx_ring, ntc);
|
||||
|
||||
/* status_error_len will always be zero for unused descriptors
|
||||
* because it's cleared in cleanup, and overlaps with hdr_addr
|
||||
@@ -1166,7 +1150,9 @@ int ice_clean_rx_irq(struct ice_rx_ring *rx_ring, int budget)
|
||||
if (rx_desc->wb.rxdid == FDIR_DESC_RXDID &&
|
||||
ctrl_vsi->vf)
|
||||
ice_vc_fdir_irq_handler(ctrl_vsi, rx_desc);
|
||||
ice_put_rx_buf(rx_ring, NULL, 0);
|
||||
if (++ntc == cnt)
|
||||
ntc = 0;
|
||||
ice_put_rx_buf(rx_ring, NULL);
|
||||
cleaned_count++;
|
||||
continue;
|
||||
}
|
||||
@@ -1175,33 +1161,33 @@ int ice_clean_rx_irq(struct ice_rx_ring *rx_ring, int budget)
|
||||
ICE_RX_FLX_DESC_PKT_LEN_M;
|
||||
|
||||
/* retrieve a buffer from the ring */
|
||||
rx_buf = ice_get_rx_buf(rx_ring, size, &rx_buf_pgcnt);
|
||||
rx_buf = ice_get_rx_buf(rx_ring, size, ntc);
|
||||
|
||||
if (!size) {
|
||||
xdp.data = NULL;
|
||||
xdp.data_end = NULL;
|
||||
xdp.data_hard_start = NULL;
|
||||
xdp.data_meta = NULL;
|
||||
xdp->data = NULL;
|
||||
xdp->data_end = NULL;
|
||||
xdp->data_hard_start = NULL;
|
||||
xdp->data_meta = NULL;
|
||||
goto construct_skb;
|
||||
}
|
||||
|
||||
hard_start = page_address(rx_buf->page) + rx_buf->page_offset -
|
||||
offset;
|
||||
xdp_prepare_buff(&xdp, hard_start, offset, size, true);
|
||||
xdp_prepare_buff(xdp, hard_start, offset, size, !!offset);
|
||||
#if (PAGE_SIZE > 4096)
|
||||
/* At larger PAGE_SIZE, frame_sz depend on len size */
|
||||
xdp.frame_sz = ice_rx_frame_truesize(rx_ring, size);
|
||||
xdp->frame_sz = ice_rx_frame_truesize(rx_ring, size);
|
||||
#endif
|
||||
|
||||
if (!xdp_prog)
|
||||
goto construct_skb;
|
||||
|
||||
xdp_res = ice_run_xdp(rx_ring, &xdp, xdp_prog, xdp_ring);
|
||||
xdp_res = ice_run_xdp(rx_ring, xdp, xdp_prog, xdp_ring);
|
||||
if (!xdp_res)
|
||||
goto construct_skb;
|
||||
if (xdp_res & (ICE_XDP_TX | ICE_XDP_REDIR)) {
|
||||
xdp_xmit |= xdp_res;
|
||||
ice_rx_buf_adjust_pg_offset(rx_buf, xdp.frame_sz);
|
||||
ice_rx_buf_adjust_pg_offset(rx_buf, xdp->frame_sz);
|
||||
} else {
|
||||
rx_buf->pagecnt_bias++;
|
||||
}
|
||||
@@ -1209,16 +1195,18 @@ int ice_clean_rx_irq(struct ice_rx_ring *rx_ring, int budget)
|
||||
total_rx_pkts++;
|
||||
|
||||
cleaned_count++;
|
||||
ice_put_rx_buf(rx_ring, rx_buf, rx_buf_pgcnt);
|
||||
if (++ntc == cnt)
|
||||
ntc = 0;
|
||||
ice_put_rx_buf(rx_ring, rx_buf);
|
||||
continue;
|
||||
construct_skb:
|
||||
if (skb) {
|
||||
ice_add_rx_frag(rx_ring, rx_buf, skb, size);
|
||||
} else if (likely(xdp.data)) {
|
||||
} else if (likely(xdp->data)) {
|
||||
if (ice_ring_uses_build_skb(rx_ring))
|
||||
skb = ice_build_skb(rx_ring, rx_buf, &xdp);
|
||||
skb = ice_build_skb(rx_ring, rx_buf, xdp);
|
||||
else
|
||||
skb = ice_construct_skb(rx_ring, rx_buf, &xdp);
|
||||
skb = ice_construct_skb(rx_ring, rx_buf, xdp);
|
||||
}
|
||||
/* exit if we failed to retrieve a buffer */
|
||||
if (!skb) {
|
||||
@@ -1228,7 +1216,9 @@ construct_skb:
|
||||
break;
|
||||
}
|
||||
|
||||
ice_put_rx_buf(rx_ring, rx_buf, rx_buf_pgcnt);
|
||||
if (++ntc == cnt)
|
||||
ntc = 0;
|
||||
ice_put_rx_buf(rx_ring, rx_buf);
|
||||
cleaned_count++;
|
||||
|
||||
/* skip if it is NOP desc */
|
||||
@@ -1268,6 +1258,7 @@ construct_skb:
|
||||
total_rx_pkts++;
|
||||
}
|
||||
|
||||
rx_ring->next_to_clean = ntc;
|
||||
/* return up to cleaned_count buffers to hardware */
|
||||
failure = ice_alloc_rx_bufs(rx_ring, cleaned_count);
|
||||
|
||||
|
||||
@@ -9,10 +9,12 @@
|
||||
#define ICE_DFLT_IRQ_WORK 256
|
||||
#define ICE_RXBUF_3072 3072
|
||||
#define ICE_RXBUF_2048 2048
|
||||
#define ICE_RXBUF_1664 1664
|
||||
#define ICE_RXBUF_1536 1536
|
||||
#define ICE_MAX_CHAINED_RX_BUFS 5
|
||||
#define ICE_MAX_BUF_TXD 8
|
||||
#define ICE_MIN_TX_LEN 17
|
||||
#define ICE_MAX_FRAME_LEGACY_RX 8320
|
||||
|
||||
/* The size limit for a transmit buffer in a descriptor is (16K - 1).
|
||||
* In order to align with the read requests we will align the value to
|
||||
@@ -170,7 +172,8 @@ struct ice_rx_buf {
|
||||
dma_addr_t dma;
|
||||
struct page *page;
|
||||
unsigned int page_offset;
|
||||
u16 pagecnt_bias;
|
||||
unsigned int pgcnt;
|
||||
unsigned int pagecnt_bias;
|
||||
};
|
||||
|
||||
struct ice_q_stats {
|
||||
@@ -293,6 +296,7 @@ struct ice_rx_ring {
|
||||
struct bpf_prog *xdp_prog;
|
||||
struct ice_tx_ring *xdp_ring;
|
||||
struct xsk_buff_pool *xsk_pool;
|
||||
struct xdp_buff xdp;
|
||||
struct sk_buff *skb;
|
||||
dma_addr_t dma; /* physical address of ring */
|
||||
u64 cached_phctime;
|
||||
|
||||
@@ -349,6 +349,7 @@ int ice_xmit_xdp_buff(struct xdp_buff *xdp, struct ice_tx_ring *xdp_ring)
|
||||
* ice_finalize_xdp_rx - Bump XDP Tx tail and/or flush redirect map
|
||||
* @xdp_ring: XDP ring
|
||||
* @xdp_res: Result of the receive batch
|
||||
* @first_idx: index to write from caller
|
||||
*
|
||||
* This function bumps XDP Tx tail and/or flush redirect map, and
|
||||
* should be called when a batch of packets has been processed in the
|
||||
|
||||
@@ -402,6 +402,21 @@
|
||||
#define IGC_DTXMXPKTSZ_TSN 0x19 /* 1600 bytes of max TX DMA packet size */
|
||||
#define IGC_DTXMXPKTSZ_DEFAULT 0x98 /* 9728-byte Jumbo frames */
|
||||
|
||||
/* Retry Buffer Control */
|
||||
#define IGC_RETX_CTL 0x041C
|
||||
#define IGC_RETX_CTL_WATERMARK_MASK 0xF
|
||||
#define IGC_RETX_CTL_QBVFULLTH_SHIFT 8 /* QBV Retry Buffer Full Threshold */
|
||||
#define IGC_RETX_CTL_QBVFULLEN 0x1000 /* Enable QBV Retry Buffer Full Threshold */
|
||||
|
||||
/* Transmit Scheduling Latency */
|
||||
/* Latency between transmission scheduling (LaunchTime) and the time
|
||||
* the packet is transmitted to the network in nanosecond.
|
||||
*/
|
||||
#define IGC_TXOFFSET_SPEED_10 0x000034BC
|
||||
#define IGC_TXOFFSET_SPEED_100 0x00000578
|
||||
#define IGC_TXOFFSET_SPEED_1000 0x0000012C
|
||||
#define IGC_TXOFFSET_SPEED_2500 0x00000578
|
||||
|
||||
/* Time Sync Interrupt Causes */
|
||||
#define IGC_TSICR_SYS_WRAP BIT(0) /* SYSTIM Wrap around. */
|
||||
#define IGC_TSICR_TXTS BIT(1) /* Transmit Timestamp. */
|
||||
|
||||
@@ -5586,6 +5586,13 @@ static void igc_watchdog_task(struct work_struct *work)
|
||||
break;
|
||||
}
|
||||
|
||||
/* Once the launch time has been set on the wire, there
|
||||
* is a delay before the link speed can be determined
|
||||
* based on link-up activity. Write into the register
|
||||
* as soon as we know the correct link speed.
|
||||
*/
|
||||
igc_tsn_adjust_txtime_offset(adapter);
|
||||
|
||||
if (adapter->link_speed != SPEED_1000)
|
||||
goto no_wait;
|
||||
|
||||
|
||||
@@ -224,6 +224,7 @@
|
||||
/* Transmit Scheduling Registers */
|
||||
#define IGC_TQAVCTRL 0x3570
|
||||
#define IGC_TXQCTL(_n) (0x3344 + 0x4 * (_n))
|
||||
#define IGC_GTXOFFSET 0x3310
|
||||
#define IGC_BASET_L 0x3314
|
||||
#define IGC_BASET_H 0x3318
|
||||
#define IGC_QBVCYCLET 0x331C
|
||||
|
||||
@@ -49,6 +49,44 @@ static unsigned int igc_tsn_new_flags(struct igc_adapter *adapter)
|
||||
return new_flags;
|
||||
}
|
||||
|
||||
void igc_tsn_adjust_txtime_offset(struct igc_adapter *adapter)
|
||||
{
|
||||
struct igc_hw *hw = &adapter->hw;
|
||||
u16 txoffset;
|
||||
|
||||
if (!is_any_launchtime(adapter))
|
||||
return;
|
||||
|
||||
switch (adapter->link_speed) {
|
||||
case SPEED_10:
|
||||
txoffset = IGC_TXOFFSET_SPEED_10;
|
||||
break;
|
||||
case SPEED_100:
|
||||
txoffset = IGC_TXOFFSET_SPEED_100;
|
||||
break;
|
||||
case SPEED_1000:
|
||||
txoffset = IGC_TXOFFSET_SPEED_1000;
|
||||
break;
|
||||
case SPEED_2500:
|
||||
txoffset = IGC_TXOFFSET_SPEED_2500;
|
||||
break;
|
||||
default:
|
||||
txoffset = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
wr32(IGC_GTXOFFSET, txoffset);
|
||||
}
|
||||
|
||||
static void igc_tsn_restore_retx_default(struct igc_adapter *adapter)
|
||||
{
|
||||
struct igc_hw *hw = &adapter->hw;
|
||||
u32 retxctl;
|
||||
|
||||
retxctl = rd32(IGC_RETX_CTL) & IGC_RETX_CTL_WATERMARK_MASK;
|
||||
wr32(IGC_RETX_CTL, retxctl);
|
||||
}
|
||||
|
||||
/* Returns the TSN specific registers to their default values after
|
||||
* the adapter is reset.
|
||||
*/
|
||||
@@ -58,9 +96,13 @@ static int igc_tsn_disable_offload(struct igc_adapter *adapter)
|
||||
u32 tqavctrl;
|
||||
int i;
|
||||
|
||||
wr32(IGC_GTXOFFSET, 0);
|
||||
wr32(IGC_TXPBS, I225_TXPBSIZE_DEFAULT);
|
||||
wr32(IGC_DTXMXPKTSZ, IGC_DTXMXPKTSZ_DEFAULT);
|
||||
|
||||
if (igc_is_device_id_i226(hw))
|
||||
igc_tsn_restore_retx_default(adapter);
|
||||
|
||||
tqavctrl = rd32(IGC_TQAVCTRL);
|
||||
tqavctrl &= ~(IGC_TQAVCTRL_TRANSMIT_MODE_TSN |
|
||||
IGC_TQAVCTRL_ENHANCED_QAV | IGC_TQAVCTRL_FUTSCDDIS);
|
||||
@@ -81,6 +123,25 @@ static int igc_tsn_disable_offload(struct igc_adapter *adapter)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* To partially fix i226 HW errata, reduce MAC internal buffering from 192 Bytes
|
||||
* to 88 Bytes by setting RETX_CTL register using the recommendation from:
|
||||
* a) Ethernet Controller I225/I226 Specification Update Rev 2.1
|
||||
* Item 9: TSN: Packet Transmission Might Cross the Qbv Window
|
||||
* b) I225/6 SW User Manual Rev 1.2.4: Section 8.11.5 Retry Buffer Control
|
||||
*/
|
||||
static void igc_tsn_set_retx_qbvfullthreshold(struct igc_adapter *adapter)
|
||||
{
|
||||
struct igc_hw *hw = &adapter->hw;
|
||||
u32 retxctl, watermark;
|
||||
|
||||
retxctl = rd32(IGC_RETX_CTL);
|
||||
watermark = retxctl & IGC_RETX_CTL_WATERMARK_MASK;
|
||||
/* Set QBVFULLTH value using watermark and set QBVFULLEN */
|
||||
retxctl |= (watermark << IGC_RETX_CTL_QBVFULLTH_SHIFT) |
|
||||
IGC_RETX_CTL_QBVFULLEN;
|
||||
wr32(IGC_RETX_CTL, retxctl);
|
||||
}
|
||||
|
||||
static int igc_tsn_enable_offload(struct igc_adapter *adapter)
|
||||
{
|
||||
struct igc_hw *hw = &adapter->hw;
|
||||
@@ -94,6 +155,9 @@ static int igc_tsn_enable_offload(struct igc_adapter *adapter)
|
||||
wr32(IGC_DTXMXPKTSZ, IGC_DTXMXPKTSZ_TSN);
|
||||
wr32(IGC_TXPBS, IGC_TXPBSIZE_TSN);
|
||||
|
||||
if (igc_is_device_id_i226(hw))
|
||||
igc_tsn_set_retx_qbvfullthreshold(adapter);
|
||||
|
||||
for (i = 0; i < adapter->num_tx_queues; i++) {
|
||||
struct igc_ring *ring = adapter->tx_ring[i];
|
||||
u32 txqctl = 0;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user