Merge 6.1.95 into android14-6.1-lts

Changes in 6.1.95
	wifi: mac80211: mesh: Fix leak of mesh_preq_queue objects
	wifi: mac80211: Fix deadlock in ieee80211_sta_ps_deliver_wakeup()
	wifi: cfg80211: fully move wiphy work to unbound workqueue
	wifi: cfg80211: Lock wiphy in cfg80211_get_station
	wifi: cfg80211: pmsr: use correct nla_get_uX functions
	wifi: iwlwifi: mvm: revert gen2 TX A-MPDU size to 64
	wifi: iwlwifi: dbg_ini: move iwl_dbg_tlv_free outside of debugfs ifdef
	wifi: iwlwifi: mvm: check n_ssids before accessing the ssids
	wifi: iwlwifi: mvm: don't read past the mfuart notifcation
	wifi: mac80211: correctly parse Spatial Reuse Parameter Set element
	ax25: Fix refcount imbalance on inbound connections
	ax25: Replace kfree() in ax25_dev_free() with ax25_dev_put()
	net/ncsi: Simplify Kconfig/dts control flow
	net/ncsi: Fix the multi thread manner of NCSI driver
	ipv6: ioam: block BH from ioam6_output()
	ipv6: sr: block BH in seg6_output_core() and seg6_input_core()
	bpf: Set run context for rawtp test_run callback
	octeontx2-af: Always allocate PF entries from low prioriy zone
	net/smc: avoid overwriting when adjusting sock bufsizes
	net: sched: sch_multiq: fix possible OOB write in multiq_tune()
	vxlan: Fix regression when dropping packets due to invalid src addresses
	tcp: count CLOSE-WAIT sockets for TCP_MIB_CURRESTAB
	net/mlx5: Stop waiting for PCI up if teardown was triggered
	net/mlx5: Stop waiting for PCI if pci channel is offline
	net/mlx5: Split function_setup() to enable and open functions
	net/mlx5: Always stop health timer during driver removal
	net/mlx5: Fix tainted pointer delete is case of flow rules creation fail
	net/sched: taprio: always validate TCA_TAPRIO_ATTR_PRIOMAP
	ptp: Fix error message on failed pin verification
	ice: fix iteration of TLVs in Preserved Fields Area
	ice: Introduce new parameters in ice_sched_node
	ice: remove null checks before devm_kfree() calls
	ice: remove af_xdp_zc_qps bitmap
	net: wwan: iosm: Fix tainted pointer delete is case of region creation fail
	af_unix: Set sk->sk_state under unix_state_lock() for truly disconencted peer.
	af_unix: Annodate data-races around sk->sk_state for writers.
	af_unix: Annotate data-race of sk->sk_state in unix_inq_len().
	af_unix: Annotate data-races around sk->sk_state in unix_write_space() and poll().
	af_unix: Annotate data-race of sk->sk_state in unix_stream_connect().
	af_unix: Annotate data-races around sk->sk_state in sendmsg() and recvmsg().
	af_unix: Annotate data-race of sk->sk_state in unix_stream_read_skb().
	af_unix: Annotate data-races around sk->sk_state in UNIX_DIAG.
	af_unix: Annotate data-race of net->unx.sysctl_max_dgram_qlen.
	af_unix: Use unix_recvq_full_lockless() in unix_stream_connect().
	af_unix: annotate lockless accesses to sk->sk_err
	af_unix: Use skb_queue_empty_lockless() in unix_release_sock().
	af_unix: Use skb_queue_len_lockless() in sk_diag_show_rqlen().
	af_unix: Annotate data-race of sk->sk_shutdown in sk_diag_fill().
	ipv6: fix possible race in __fib6_drop_pcpu_from()
	Bluetooth: qca: fix invalid device address check
	btrfs: fix wrong block_start calculation for btrfs_drop_extent_map_range()
	usb: gadget: f_fs: use io_data->status consistently
	usb: gadget: f_fs: Fix race between aio_cancel() and AIO request complete
	iio: accel: mxc4005: allow module autoloading via OF compatible
	iio: accel: mxc4005: Reset chip on probe() and resume()
	xtensa: stacktrace: include <asm/ftrace.h> for prototype
	xtensa: fix MAKE_PC_FROM_RA second argument
	drm/amd/display: drop unnecessary NULL checks in debugfs
	drm/amd/display: Fix incorrect DSC instance for MST
	arm64: dts: qcom: sm8150: align TLMM pin configuration with DT schema
	arm64: dts: qcom: sa8155p-adp: fix SDHC2 CD pin configuration
	misc/pvpanic: deduplicate common code
	misc/pvpanic-pci: register attributes via pci_driver
	serial: sc16is7xx: replace hardcoded divisor value with BIT() macro
	serial: sc16is7xx: fix bug in sc16is7xx_set_baud() when using prescaler
	mmc: davinci: Don't strip remove function when driver is builtin
	firmware: qcom_scm: disable clocks if qcom_scm_bw_enable() fails
	HID: i2c-hid: elan: Add ili9882t timing
	HID: i2c-hid: elan: fix reset suspend current leakage
	i2c: add fwnode APIs
	i2c: acpi: Unbind mux adapters before delete
	mm, vmalloc: fix high order __GFP_NOFAIL allocations
	mm/vmalloc: fix vmalloc which may return null if called with __GFP_NOFAIL
	selftests/mm: compaction_test: fix incorrect write of zero to nr_hugepages
	selftests/mm: conform test to TAP format output
	selftests/mm: log a consistent test name for check_compaction
	selftests/mm: compaction_test: fix bogus test success on Aarch64
	wifi: ath10k: fix QCOM_RPROC_COMMON dependency
	btrfs: remove unnecessary prototype declarations at disk-io.c
	btrfs: make btrfs_destroy_delayed_refs() return void
	btrfs: fix leak of qgroup extent records after transaction abort
	nilfs2: return the mapped address from nilfs_get_page()
	nilfs2: fix nilfs_empty_dir() misjudgment and long loop on I/O errors
	io_uring: check for non-NULL file pointer in io_file_can_poll()
	USB: class: cdc-wdm: Fix CPU lockup caused by excessive log messages
	USB: xen-hcd: Traverse host/ when CONFIG_USB_XEN_HCD is selected
	usb: typec: tcpm: fix use-after-free case in tcpm_register_source_caps
	usb: typec: tcpm: Ignore received Hard Reset in TOGGLING state
	mei: me: release irq in mei_me_pci_resume error path
	tty: n_tty: Fix buffer offsets when lookahead is used
	landlock: Fix d_parent walk
	jfs: xattr: fix buffer overflow for invalid xattr
	xhci: Set correct transferred length for cancelled bulk transfers
	xhci: Apply reset resume quirk to Etron EJ188 xHCI host
	xhci: Handle TD clearing for multiple streams case
	xhci: Apply broken streams quirk to Etron EJ188 xHCI host
	thunderbolt: debugfs: Fix margin debugfs node creation condition
	scsi: mpi3mr: Fix ATA NCQ priority support
	scsi: mpt3sas: Avoid test/set_bit() operating in non-allocated memory
	scsi: sd: Use READ(16) when reading block zero on large capacity disks
	gve: Clear napi->skb before dev_kfree_skb_any()
	powerpc/uaccess: Fix build errors seen with GCC 13/14
	Input: try trimming too long modalias strings
	cxl/test: Add missing vmalloc.h for tools/testing/cxl/test/mem.c
	cachefiles: add output string to cachefiles_obj_[get|put]_ondemand_fd
	cachefiles: remove requests from xarray during flushing requests
	cachefiles: introduce object ondemand state
	cachefiles: extract ondemand info field from cachefiles_object
	cachefiles: resend an open request if the read request's object is closed
	cachefiles: add spin_lock for cachefiles_ondemand_info
	cachefiles: add restore command to recover inflight ondemand read requests
	cachefiles: fix slab-use-after-free in cachefiles_ondemand_get_fd()
	cachefiles: fix slab-use-after-free in cachefiles_ondemand_daemon_read()
	cachefiles: remove err_put_fd label in cachefiles_ondemand_daemon_read()
	cachefiles: never get a new anonymous fd if ondemand_id is valid
	cachefiles: defer exposing anon_fd until after copy_to_user() succeeds
	cachefiles: flush all requests after setting CACHEFILES_DEAD
	selftests/ftrace: Fix to check required event file
	clk: sifive: Do not register clkdevs for PRCI clocks
	NFSv4.1 enforce rootpath check in fs_location query
	SUNRPC: return proper error from gss_wrap_req_priv
	NFS: add barriers when testing for NFS_FSDATA_BLOCKED
	platform/x86: dell-smbios: Fix wrong token data in sysfs
	gpio: tqmx86: fix typo in Kconfig label
	gpio: tqmx86: remove unneeded call to platform_set_drvdata()
	gpio: tqmx86: introduce shadow register for GPIO output value
	gpio: tqmx86: Convert to immutable irq_chip
	gpio: tqmx86: store IRQ trigger type and unmask status separately
	gpio: tqmx86: fix broken IRQ_TYPE_EDGE_BOTH interrupt type
	HID: core: remove unnecessary WARN_ON() in implement()
	iommu/amd: Fix sysfs leak in iommu init
	HID: logitech-dj: Fix memory leak in logi_dj_recv_switch_to_dj_mode()
	drm/vmwgfx: Port the framebuffer code to drm fb helpers
	drm/vmwgfx: Refactor drm connector probing for display modes
	drm/vmwgfx: Filter modes which exceed graphics memory
	drm/vmwgfx: 3D disabled should not effect STDU memory limits
	drm/vmwgfx: Remove STDU logic from generic mode_valid function
	net: sfp: Always call `sfp_sm_mod_remove()` on remove
	net: hns3: fix kernel crash problem in concurrent scenario
	net: hns3: add cond_resched() to hns3 ring buffer init process
	liquidio: Adjust a NULL pointer handling path in lio_vf_rep_copy_packet
	drm/komeda: check for error-valued pointer
	drm/bridge/panel: Fix runtime warning on panel bridge release
	tcp: fix race in tcp_v6_syn_recv_sock()
	geneve: Fix incorrect inner network header offset when innerprotoinherit is set
	net/mlx5e: Fix features validation check for tunneled UDP (non-VXLAN) packets
	Bluetooth: L2CAP: Fix rejecting L2CAP_CONN_PARAM_UPDATE_REQ
	netfilter: ipset: Fix race between namespace cleanup and gc in the list:set type
	net: pse-pd: Use EOPNOTSUPP error code instead of ENOTSUPP
	gve: ignore nonrelevant GSO type bits when processing TSO headers
	net: stmmac: replace priv->speed with the portTransmitRate from the tc-cbs parameters
	nvmet-passthru: propagate status from id override functions
	net/ipv6: Fix the RT cache flush via sysctl using a previous delay
	net: bridge: mst: pass vlan group directly to br_mst_vlan_set_state
	net: bridge: mst: fix suspicious rcu usage in br_mst_set_state
	ionic: fix use after netif_napi_del()
	af_unix: Read with MSG_PEEK loops if the first unread byte is OOB
	bnxt_en: Adjust logging of firmware messages in case of released token in __hwrm_send()
	misc: microchip: pci1xxxx: fix double free in the error handling of gp_aux_bus_probe()
	x86/boot: Don't add the EFI stub to targets, again
	iio: adc: ad9467: fix scan type sign
	iio: dac: ad5592r: fix temperature channel scaling value
	iio: imu: inv_icm42600: delete unneeded update watermark call
	drivers: core: synchronize really_probe() and dev_uevent()
	drm/exynos/vidi: fix memory leak in .get_modes()
	drm/exynos: hdmi: report safe 640x480 mode as a fallback when no EDID found
	mptcp: ensure snd_una is properly initialized on connect
	mptcp: pm: inc RmAddr MIB counter once per RM_ADDR ID
	irqchip/gic-v3-its: Fix potential race condition in its_vlpi_prop_update()
	x86/amd_nb: Check for invalid SMN reads
	perf/core: Fix missing wakeup when waiting for context reference
	riscv: fix overlap of allocated page and PTR_ERR
	tracing/selftests: Fix kprobe event name test for .isra. functions
	null_blk: Print correct max open zones limit in null_init_zoned_dev()
	sock_map: avoid race between sock_map_close and sk_psock_put
	vmci: prevent speculation leaks by sanitizing event in event_deliver()
	spmi: hisi-spmi-controller: Do not override device identifier
	knfsd: LOOKUP can return an illegal error value
	fs/proc: fix softlockup in __read_vmcore
	ocfs2: use coarse time for new created files
	ocfs2: fix races between hole punching and AIO+DIO
	PCI: rockchip-ep: Remove wrong mask on subsys_vendor_id
	dmaengine: axi-dmac: fix possible race in remove()
	remoteproc: k3-r5: Wait for core0 power-up before powering up core1
	remoteproc: k3-r5: Do not allow core1 to power up before core0 via sysfs
	riscv: rewrite __kernel_map_pages() to fix sleeping in invalid context
	drm/i915/gt: Disarm breadcrumbs if engines are already idle
	drm/i915/dpt: Make DPT object unshrinkable
	intel_th: pci: Add Granite Rapids support
	intel_th: pci: Add Granite Rapids SOC support
	intel_th: pci: Add Sapphire Rapids SOC support
	intel_th: pci: Add Meteor Lake-S support
	intel_th: pci: Add Lunar Lake support
	btrfs: zoned: introduce a zone_info struct in btrfs_load_block_group_zone_info
	btrfs: zoned: factor out per-zone logic from btrfs_load_block_group_zone_info
	btrfs: zoned: factor out single bg handling from btrfs_load_block_group_zone_info
	btrfs: zoned: factor out DUP bg handling from btrfs_load_block_group_zone_info
	btrfs: zoned: fix use-after-free due to race with dev replace
	nilfs2: fix potential kernel bug due to lack of writeback flag waiting
	tick/nohz_full: Don't abuse smp_call_function_single() in tick_setup_device()
	mm/huge_memory: don't unpoison huge_zero_folio
	mm/memory-failure: fix handling of dissolved but not taken off from buddy pages
	serial: 8250_pxa: Configure tx_loadsz to match FIFO IRQ level
	mptcp: pm: update add_addr counters after connect
	Revert "fork: defer linking file vma until vma is fully initialized"
	remoteproc: k3-r5: Jump to error handling labels in start/stop errors
	cachefiles, erofs: Fix NULL deref in when cachefiles is not doing ondemand-mode
	Bluetooth: qca: fix wcn3991 device address check
	Bluetooth: qca: generalise device address check
	greybus: Fix use-after-free bug in gb_interface_release due to race condition.
	serial: 8250_dw: fall back to poll if there's no interrupt
	serial: core: Add UPIO_UNKNOWN constant for unknown port type
	usb-storage: alauda: Check whether the media is initialized
	misc: microchip: pci1xxxx: Fix a memory leak in the error handling of gp_aux_bus_probe()
	i2c: at91: Fix the functionality flags of the slave-only interface
	i2c: designware: Fix the functionality flags of the slave-only interface
	zap_pid_ns_processes: clear TIF_NOTIFY_SIGNAL along with TIF_SIGPENDING
	Linux 6.1.95

Change-Id: I73161b2d10f7fd687ca753f1780ccdf53eeccb0e
Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
This commit is contained in:
Greg Kroah-Hartman
2024-07-24 17:19:08 +00:00
193 changed files with 2925 additions and 3026 deletions

View File

@@ -1,7 +1,7 @@
# SPDX-License-Identifier: GPL-2.0
VERSION = 6
PATCHLEVEL = 1
SUBLEVEL = 94
SUBLEVEL = 95
EXTRAVERSION =
NAME = Curry Ramen

View File

@@ -372,6 +372,16 @@
};
};
&pmm8155au_1_gpios {
pmm8155au_1_sdc2_cd: sdc2-cd-default-state {
pins = "gpio4";
function = "normal";
input-enable;
bias-pull-up;
power-source = <0>;
};
};
&qupv3_id_1 {
status = "okay";
};
@@ -389,10 +399,10 @@
&sdhc_2 {
status = "okay";
cd-gpios = <&tlmm 4 GPIO_ACTIVE_LOW>;
cd-gpios = <&pmm8155au_1_gpios 4 GPIO_ACTIVE_LOW>;
pinctrl-names = "default", "sleep";
pinctrl-0 = <&sdc2_on>;
pinctrl-1 = <&sdc2_off>;
pinctrl-0 = <&sdc2_on &pmm8155au_1_sdc2_cd>;
pinctrl-1 = <&sdc2_off &pmm8155au_1_sdc2_cd>;
vqmmc-supply = <&vreg_l13c_2p96>; /* IO line power */
vmmc-supply = <&vreg_l17a_2p96>; /* Card power line */
bus-width = <4>;
@@ -488,120 +498,102 @@
&tlmm {
gpio-reserved-ranges = <0 4>;
sdc2_on: sdc2_on {
clk {
sdc2_on: sdc2-on-state {
clk-pins {
pins = "sdc2_clk";
bias-disable; /* No pull */
drive-strength = <16>; /* 16 MA */
};
cmd {
cmd-pins {
pins = "sdc2_cmd";
bias-pull-up; /* pull up */
drive-strength = <16>; /* 16 MA */
};
data {
data-pins {
pins = "sdc2_data";
bias-pull-up; /* pull up */
drive-strength = <16>; /* 16 MA */
};
sd-cd {
pins = "gpio96";
function = "gpio";
bias-pull-up; /* pull up */
drive-strength = <2>; /* 2 MA */
};
};
sdc2_off: sdc2_off {
clk {
sdc2_off: sdc2-off-state {
clk-pins {
pins = "sdc2_clk";
bias-disable; /* No pull */
drive-strength = <2>; /* 2 MA */
};
cmd {
cmd-pins {
pins = "sdc2_cmd";
bias-pull-up; /* pull up */
drive-strength = <2>; /* 2 MA */
};
data {
data-pins {
pins = "sdc2_data";
bias-pull-up; /* pull up */
drive-strength = <2>; /* 2 MA */
};
sd-cd {
pins = "gpio96";
function = "gpio";
bias-pull-up; /* pull up */
drive-strength = <2>; /* 2 MA */
};
};
usb2phy_ac_en1_default: usb2phy_ac_en1_default {
mux {
pins = "gpio113";
function = "usb2phy_ac";
bias-disable;
drive-strength = <2>;
};
usb2phy_ac_en1_default: usb2phy-ac-en1-default-state {
pins = "gpio113";
function = "usb2phy_ac";
bias-disable;
drive-strength = <2>;
};
usb2phy_ac_en2_default: usb2phy_ac_en2_default {
mux {
pins = "gpio123";
function = "usb2phy_ac";
bias-disable;
drive-strength = <2>;
};
usb2phy_ac_en2_default: usb2phy-ac-en2-default-state {
pins = "gpio123";
function = "usb2phy_ac";
bias-disable;
drive-strength = <2>;
};
ethernet_defaults: ethernet-defaults {
mdc {
ethernet_defaults: ethernet-defaults-state {
mdc-pins {
pins = "gpio7";
function = "rgmii";
bias-pull-up;
};
mdio {
mdio-pins {
pins = "gpio59";
function = "rgmii";
bias-pull-up;
};
rgmii-rx {
rgmii-rx-pins {
pins = "gpio117", "gpio118", "gpio119", "gpio120", "gpio115", "gpio116";
function = "rgmii";
bias-disable;
drive-strength = <2>;
};
rgmii-tx {
rgmii-tx-pins {
pins = "gpio122", "gpio4", "gpio5", "gpio6", "gpio114", "gpio121";
function = "rgmii";
bias-pull-up;
drive-strength = <16>;
};
phy-intr {
phy-intr-pins {
pins = "gpio124";
function = "emac_phy";
bias-disable;
drive-strength = <8>;
};
pps {
pps-pins {
pins = "gpio81";
function = "emac_pps";
bias-disable;
drive-strength = <8>;
};
phy-reset {
phy-reset-pins {
pins = "gpio79";
function = "gpio";
bias-pull-up;

View File

@@ -475,7 +475,7 @@
&tlmm {
gpio-reserved-ranges = <126 4>;
da7280_intr_default: da7280-intr-default {
da7280_intr_default: da7280-intr-default-state {
pins = "gpio42";
function = "gpio";
bias-pull-up;

View File

@@ -2284,422 +2284,302 @@
#interrupt-cells = <2>;
wakeup-parent = <&pdc>;
qup_i2c0_default: qup-i2c0-default {
mux {
pins = "gpio0", "gpio1";
function = "qup0";
};
config {
pins = "gpio0", "gpio1";
drive-strength = <0x02>;
bias-disable;
};
qup_i2c0_default: qup-i2c0-default-state {
pins = "gpio0", "gpio1";
function = "qup0";
drive-strength = <0x02>;
bias-disable;
};
qup_spi0_default: qup-spi0-default {
qup_spi0_default: qup-spi0-default-state {
pins = "gpio0", "gpio1", "gpio2", "gpio3";
function = "qup0";
drive-strength = <6>;
bias-disable;
};
qup_i2c1_default: qup-i2c1-default {
mux {
pins = "gpio114", "gpio115";
function = "qup1";
};
config {
pins = "gpio114", "gpio115";
drive-strength = <0x02>;
bias-disable;
};
qup_i2c1_default: qup-i2c1-default-state {
pins = "gpio114", "gpio115";
function = "qup1";
drive-strength = <2>;
bias-disable;
};
qup_spi1_default: qup-spi1-default {
qup_spi1_default: qup-spi1-default-state {
pins = "gpio114", "gpio115", "gpio116", "gpio117";
function = "qup1";
drive-strength = <6>;
bias-disable;
};
qup_i2c2_default: qup-i2c2-default {
mux {
pins = "gpio126", "gpio127";
function = "qup2";
};
config {
pins = "gpio126", "gpio127";
drive-strength = <0x02>;
bias-disable;
};
qup_i2c2_default: qup-i2c2-default-state {
pins = "gpio126", "gpio127";
function = "qup2";
drive-strength = <2>;
bias-disable;
};
qup_spi2_default: qup-spi2-default {
qup_spi2_default: qup-spi2-default-state {
pins = "gpio126", "gpio127", "gpio128", "gpio129";
function = "qup2";
drive-strength = <6>;
bias-disable;
};
qup_i2c3_default: qup-i2c3-default {
mux {
pins = "gpio144", "gpio145";
function = "qup3";
};
config {
pins = "gpio144", "gpio145";
drive-strength = <0x02>;
bias-disable;
};
qup_i2c3_default: qup-i2c3-default-state {
pins = "gpio144", "gpio145";
function = "qup3";
drive-strength = <2>;
bias-disable;
};
qup_spi3_default: qup-spi3-default {
qup_spi3_default: qup-spi3-default-state {
pins = "gpio144", "gpio145", "gpio146", "gpio147";
function = "qup3";
drive-strength = <6>;
bias-disable;
};
qup_i2c4_default: qup-i2c4-default {
mux {
pins = "gpio51", "gpio52";
function = "qup4";
};
config {
pins = "gpio51", "gpio52";
drive-strength = <0x02>;
bias-disable;
};
qup_i2c4_default: qup-i2c4-default-state {
pins = "gpio51", "gpio52";
function = "qup4";
drive-strength = <2>;
bias-disable;
};
qup_spi4_default: qup-spi4-default {
qup_spi4_default: qup-spi4-default-state {
pins = "gpio51", "gpio52", "gpio53", "gpio54";
function = "qup4";
drive-strength = <6>;
bias-disable;
};
qup_i2c5_default: qup-i2c5-default {
mux {
pins = "gpio121", "gpio122";
function = "qup5";
};
config {
pins = "gpio121", "gpio122";
drive-strength = <0x02>;
bias-disable;
};
qup_i2c5_default: qup-i2c5-default-state {
pins = "gpio121", "gpio122";
function = "qup5";
drive-strength = <2>;
bias-disable;
};
qup_spi5_default: qup-spi5-default {
qup_spi5_default: qup-spi5-default-state {
pins = "gpio119", "gpio120", "gpio121", "gpio122";
function = "qup5";
drive-strength = <6>;
bias-disable;
};
qup_i2c6_default: qup-i2c6-default {
mux {
pins = "gpio6", "gpio7";
function = "qup6";
};
config {
pins = "gpio6", "gpio7";
drive-strength = <0x02>;
bias-disable;
};
qup_i2c6_default: qup-i2c6-default-state {
pins = "gpio6", "gpio7";
function = "qup6";
drive-strength = <2>;
bias-disable;
};
qup_spi6_default: qup-spi6_default {
qup_spi6_default: qup-spi6_default-state {
pins = "gpio4", "gpio5", "gpio6", "gpio7";
function = "qup6";
drive-strength = <6>;
bias-disable;
};
qup_i2c7_default: qup-i2c7-default {
mux {
pins = "gpio98", "gpio99";
function = "qup7";
};
config {
pins = "gpio98", "gpio99";
drive-strength = <0x02>;
bias-disable;
};
qup_i2c7_default: qup-i2c7-default-state {
pins = "gpio98", "gpio99";
function = "qup7";
drive-strength = <2>;
bias-disable;
};
qup_spi7_default: qup-spi7_default {
qup_spi7_default: qup-spi7_default-state {
pins = "gpio98", "gpio99", "gpio100", "gpio101";
function = "qup7";
drive-strength = <6>;
bias-disable;
};
qup_i2c8_default: qup-i2c8-default {
mux {
pins = "gpio88", "gpio89";
function = "qup8";
};
config {
pins = "gpio88", "gpio89";
drive-strength = <0x02>;
bias-disable;
};
qup_i2c8_default: qup-i2c8-default-state {
pins = "gpio88", "gpio89";
function = "qup8";
drive-strength = <2>;
bias-disable;
};
qup_spi8_default: qup-spi8-default {
qup_spi8_default: qup-spi8-default-state {
pins = "gpio88", "gpio89", "gpio90", "gpio91";
function = "qup8";
drive-strength = <6>;
bias-disable;
};
qup_i2c9_default: qup-i2c9-default {
mux {
pins = "gpio39", "gpio40";
function = "qup9";
};
config {
pins = "gpio39", "gpio40";
drive-strength = <0x02>;
bias-disable;
};
qup_i2c9_default: qup-i2c9-default-state {
pins = "gpio39", "gpio40";
function = "qup9";
drive-strength = <2>;
bias-disable;
};
qup_spi9_default: qup-spi9-default {
qup_spi9_default: qup-spi9-default-state {
pins = "gpio39", "gpio40", "gpio41", "gpio42";
function = "qup9";
drive-strength = <6>;
bias-disable;
};
qup_i2c10_default: qup-i2c10-default {
mux {
pins = "gpio9", "gpio10";
function = "qup10";
};
config {
pins = "gpio9", "gpio10";
drive-strength = <0x02>;
bias-disable;
};
qup_i2c10_default: qup-i2c10-default-state {
pins = "gpio9", "gpio10";
function = "qup10";
drive-strength = <2>;
bias-disable;
};
qup_spi10_default: qup-spi10-default {
qup_spi10_default: qup-spi10-default-state {
pins = "gpio9", "gpio10", "gpio11", "gpio12";
function = "qup10";
drive-strength = <6>;
bias-disable;
};
qup_i2c11_default: qup-i2c11-default {
mux {
pins = "gpio94", "gpio95";
function = "qup11";
};
config {
pins = "gpio94", "gpio95";
drive-strength = <0x02>;
bias-disable;
};
qup_i2c11_default: qup-i2c11-default-state {
pins = "gpio94", "gpio95";
function = "qup11";
drive-strength = <2>;
bias-disable;
};
qup_spi11_default: qup-spi11-default {
qup_spi11_default: qup-spi11-default-state {
pins = "gpio92", "gpio93", "gpio94", "gpio95";
function = "qup11";
drive-strength = <6>;
bias-disable;
};
qup_i2c12_default: qup-i2c12-default {
mux {
pins = "gpio83", "gpio84";
function = "qup12";
};
config {
pins = "gpio83", "gpio84";
drive-strength = <0x02>;
bias-disable;
};
qup_i2c12_default: qup-i2c12-default-state {
pins = "gpio83", "gpio84";
function = "qup12";
drive-strength = <2>;
bias-disable;
};
qup_spi12_default: qup-spi12-default {
qup_spi12_default: qup-spi12-default-state {
pins = "gpio83", "gpio84", "gpio85", "gpio86";
function = "qup12";
drive-strength = <6>;
bias-disable;
};
qup_i2c13_default: qup-i2c13-default {
mux {
pins = "gpio43", "gpio44";
function = "qup13";
};
config {
pins = "gpio43", "gpio44";
drive-strength = <0x02>;
bias-disable;
};
qup_i2c13_default: qup-i2c13-default-state {
pins = "gpio43", "gpio44";
function = "qup13";
drive-strength = <2>;
bias-disable;
};
qup_spi13_default: qup-spi13-default {
qup_spi13_default: qup-spi13-default-state {
pins = "gpio43", "gpio44", "gpio45", "gpio46";
function = "qup13";
drive-strength = <6>;
bias-disable;
};
qup_i2c14_default: qup-i2c14-default {
mux {
pins = "gpio47", "gpio48";
function = "qup14";
};
config {
pins = "gpio47", "gpio48";
drive-strength = <0x02>;
bias-disable;
};
qup_i2c14_default: qup-i2c14-default-state {
pins = "gpio47", "gpio48";
function = "qup14";
drive-strength = <2>;
bias-disable;
};
qup_spi14_default: qup-spi14-default {
qup_spi14_default: qup-spi14-default-state {
pins = "gpio47", "gpio48", "gpio49", "gpio50";
function = "qup14";
drive-strength = <6>;
bias-disable;
};
qup_i2c15_default: qup-i2c15-default {
mux {
pins = "gpio27", "gpio28";
function = "qup15";
};
config {
pins = "gpio27", "gpio28";
drive-strength = <0x02>;
bias-disable;
};
qup_i2c15_default: qup-i2c15-default-state {
pins = "gpio27", "gpio28";
function = "qup15";
drive-strength = <2>;
bias-disable;
};
qup_spi15_default: qup-spi15-default {
qup_spi15_default: qup-spi15-default-state {
pins = "gpio27", "gpio28", "gpio29", "gpio30";
function = "qup15";
drive-strength = <6>;
bias-disable;
};
qup_i2c16_default: qup-i2c16-default {
mux {
pins = "gpio86", "gpio85";
function = "qup16";
};
config {
pins = "gpio86", "gpio85";
drive-strength = <0x02>;
bias-disable;
};
qup_i2c16_default: qup-i2c16-default-state {
pins = "gpio86", "gpio85";
function = "qup16";
drive-strength = <2>;
bias-disable;
};
qup_spi16_default: qup-spi16-default {
qup_spi16_default: qup-spi16-default-state {
pins = "gpio83", "gpio84", "gpio85", "gpio86";
function = "qup16";
drive-strength = <6>;
bias-disable;
};
qup_i2c17_default: qup-i2c17-default {
mux {
pins = "gpio55", "gpio56";
function = "qup17";
};
config {
pins = "gpio55", "gpio56";
drive-strength = <0x02>;
bias-disable;
};
qup_i2c17_default: qup-i2c17-default-state {
pins = "gpio55", "gpio56";
function = "qup17";
drive-strength = <2>;
bias-disable;
};
qup_spi17_default: qup-spi17-default {
qup_spi17_default: qup-spi17-default-state {
pins = "gpio55", "gpio56", "gpio57", "gpio58";
function = "qup17";
drive-strength = <6>;
bias-disable;
};
qup_i2c18_default: qup-i2c18-default {
mux {
pins = "gpio23", "gpio24";
function = "qup18";
};
config {
pins = "gpio23", "gpio24";
drive-strength = <0x02>;
bias-disable;
};
qup_i2c18_default: qup-i2c18-default-state {
pins = "gpio23", "gpio24";
function = "qup18";
drive-strength = <2>;
bias-disable;
};
qup_spi18_default: qup-spi18-default {
qup_spi18_default: qup-spi18-default-state {
pins = "gpio23", "gpio24", "gpio25", "gpio26";
function = "qup18";
drive-strength = <6>;
bias-disable;
};
qup_i2c19_default: qup-i2c19-default {
mux {
pins = "gpio57", "gpio58";
function = "qup19";
};
config {
pins = "gpio57", "gpio58";
drive-strength = <0x02>;
bias-disable;
};
qup_i2c19_default: qup-i2c19-default-state {
pins = "gpio57", "gpio58";
function = "qup19";
drive-strength = <2>;
bias-disable;
};
qup_spi19_default: qup-spi19-default {
qup_spi19_default: qup-spi19-default-state {
pins = "gpio55", "gpio56", "gpio57", "gpio58";
function = "qup19";
drive-strength = <6>;
bias-disable;
};
pcie0_default_state: pcie0-default {
perst {
pcie0_default_state: pcie0-default-state {
perst-pins {
pins = "gpio35";
function = "gpio";
drive-strength = <2>;
bias-pull-down;
};
clkreq {
clkreq-pins {
pins = "gpio36";
function = "pci_e0";
drive-strength = <2>;
bias-pull-up;
};
wake {
wake-pins {
pins = "gpio37";
function = "gpio";
drive-strength = <2>;
@@ -2707,22 +2587,22 @@
};
};
pcie1_default_state: pcie1-default {
perst {
pcie1_default_state: pcie1-default-state {
perst-pins {
pins = "gpio102";
function = "gpio";
drive-strength = <2>;
bias-pull-down;
};
clkreq {
clkreq-pins {
pins = "gpio103";
function = "pci_e1";
drive-strength = <2>;
bias-pull-up;
};
wake {
wake-pins {
pins = "gpio104";
function = "gpio";
drive-strength = <2>;

View File

@@ -80,9 +80,20 @@ __pu_failed: \
: \
: label)
#ifdef CONFIG_CC_IS_CLANG
#define DS_FORM_CONSTRAINT "Z<>"
#else
#define DS_FORM_CONSTRAINT "YZ<>"
#endif
#ifdef __powerpc64__
#define __put_user_asm2_goto(x, ptr, label) \
__put_user_asm_goto(x, ptr, label, "std")
#define __put_user_asm2_goto(x, addr, label) \
asm goto ("1: std%U1%X1 %0,%1 # put_user\n" \
EX_TABLE(1b, %l2) \
: \
: "r" (x), DS_FORM_CONSTRAINT (*addr) \
: \
: label)
#else /* __powerpc64__ */
#define __put_user_asm2_goto(x, addr, label) \
asm goto( \

View File

@@ -213,18 +213,19 @@ static void __init setup_bootmem(void)
if (!IS_ENABLED(CONFIG_XIP_KERNEL))
phys_ram_base = memblock_start_of_DRAM();
/*
* memblock allocator is not aware of the fact that last 4K bytes of
* the addressable memory can not be mapped because of IS_ERR_VALUE
* macro. Make sure that last 4k bytes are not usable by memblock
* if end of dram is equal to maximum addressable memory. For 64-bit
* kernel, this problem can't happen here as the end of the virtual
* address space is occupied by the kernel mapping then this check must
* be done as soon as the kernel mapping base address is determined.
* Reserve physical address space that would be mapped to virtual
* addresses greater than (void *)(-PAGE_SIZE) because:
* - This memory would overlap with ERR_PTR
* - This memory belongs to high memory, which is not supported
*
* This is not applicable to 64-bit kernel, because virtual addresses
* after (void *)(-PAGE_SIZE) are not linearly mapped: they are
* occupied by kernel mapping. Also it is unrealistic for high memory
* to exist on 64-bit platforms.
*/
if (!IS_ENABLED(CONFIG_64BIT)) {
max_mapped_addr = __pa(~(ulong)0);
if (max_mapped_addr == (phys_ram_end - 1))
memblock_set_current_limit(max_mapped_addr - 4096);
max_mapped_addr = __va_to_pa_nodebug(-PAGE_SIZE);
memblock_reserve(max_mapped_addr, (phys_addr_t)-max_mapped_addr);
}
min_low_pfn = PFN_UP(phys_ram_base);

View File

@@ -387,17 +387,33 @@ int set_direct_map_default_noflush(struct page *page)
}
#ifdef CONFIG_DEBUG_PAGEALLOC
static int debug_pagealloc_set_page(pte_t *pte, unsigned long addr, void *data)
{
int enable = *(int *)data;
unsigned long val = pte_val(ptep_get(pte));
if (enable)
val |= _PAGE_PRESENT;
else
val &= ~_PAGE_PRESENT;
set_pte(pte, __pte(val));
return 0;
}
void __kernel_map_pages(struct page *page, int numpages, int enable)
{
if (!debug_pagealloc_enabled())
return;
if (enable)
__set_memory((unsigned long)page_address(page), numpages,
__pgprot(_PAGE_PRESENT), __pgprot(0));
else
__set_memory((unsigned long)page_address(page), numpages,
__pgprot(0), __pgprot(_PAGE_PRESENT));
unsigned long start = (unsigned long)page_address(page);
unsigned long size = PAGE_SIZE * numpages;
apply_to_existing_page_range(&init_mm, start, size, debug_pagealloc_set_page, &enable);
flush_tlb_kernel_range(start, start + size);
}
#endif

View File

@@ -115,9 +115,9 @@ vmlinux-objs-$(CONFIG_INTEL_TDX_GUEST) += $(obj)/tdx.o $(obj)/tdcall.o
vmlinux-objs-$(CONFIG_EFI) += $(obj)/efi.o
vmlinux-objs-$(CONFIG_EFI_MIXED) += $(obj)/efi_mixed.o
vmlinux-objs-$(CONFIG_EFI_STUB) += $(objtree)/drivers/firmware/efi/libstub/lib.a
vmlinux-libs-$(CONFIG_EFI_STUB) += $(objtree)/drivers/firmware/efi/libstub/lib.a
$(obj)/vmlinux: $(vmlinux-objs-y) FORCE
$(obj)/vmlinux: $(vmlinux-objs-y) $(vmlinux-libs-y) FORCE
$(call if_changed,ld)
OBJCOPYFLAGS_vmlinux.bin := -R .comment -S

View File

@@ -195,7 +195,14 @@ out:
int amd_smn_read(u16 node, u32 address, u32 *value)
{
return __amd_smn_rw(node, address, value, false);
int err = __amd_smn_rw(node, address, value, false);
if (PCI_POSSIBLE_ERROR(*value)) {
err = -ENODEV;
*value = 0;
}
return err;
}
EXPORT_SYMBOL_GPL(amd_smn_read);

View File

@@ -113,9 +113,9 @@
#define MAKE_RA_FOR_CALL(ra,ws) (((ra) & 0x3fffffff) | (ws) << 30)
/* Convert return address to a valid pc
* Note: We assume that the stack pointer is in the same 1GB ranges as the ra
* Note: 'text' is the address within the same 1GB range as the ra
*/
#define MAKE_PC_FROM_RA(ra,sp) (((ra) & 0x3fffffff) | ((sp) & 0xc0000000))
#define MAKE_PC_FROM_RA(ra, text) (((ra) & 0x3fffffff) | ((unsigned long)(text) & 0xc0000000))
#elif defined(__XTENSA_CALL0_ABI__)
@@ -125,9 +125,9 @@
#define MAKE_RA_FOR_CALL(ra, ws) (ra)
/* Convert return address to a valid pc
* Note: We assume that the stack pointer is in the same 1GB ranges as the ra
* Note: 'text' is not used as 'ra' is always the full address
*/
#define MAKE_PC_FROM_RA(ra, sp) (ra)
#define MAKE_PC_FROM_RA(ra, text) (ra)
#else
#error Unsupported Xtensa ABI

View File

@@ -87,7 +87,7 @@ struct pt_regs {
# define user_mode(regs) (((regs)->ps & 0x00000020)!=0)
# define instruction_pointer(regs) ((regs)->pc)
# define return_pointer(regs) (MAKE_PC_FROM_RA((regs)->areg[0], \
(regs)->areg[1]))
(regs)->pc))
# ifndef CONFIG_SMP
# define profile_pc(regs) instruction_pointer(regs)

View File

@@ -47,6 +47,7 @@
#include <asm/asm-offsets.h>
#include <asm/regs.h>
#include <asm/hw_breakpoint.h>
#include <asm/sections.h>
#include <asm/traps.h>
extern void ret_from_fork(void);
@@ -379,7 +380,7 @@ unsigned long __get_wchan(struct task_struct *p)
int count = 0;
sp = p->thread.sp;
pc = MAKE_PC_FROM_RA(p->thread.ra, p->thread.sp);
pc = MAKE_PC_FROM_RA(p->thread.ra, _text);
do {
if (sp < stack_page + sizeof(struct task_struct) ||
@@ -391,7 +392,7 @@ unsigned long __get_wchan(struct task_struct *p)
/* Stack layout: sp-4: ra, sp-3: sp' */
pc = MAKE_PC_FROM_RA(SPILL_SLOT(sp, 0), sp);
pc = MAKE_PC_FROM_RA(SPILL_SLOT(sp, 0), _text);
sp = SPILL_SLOT(sp, 1);
} while (count++ < 16);
return 0;

View File

@@ -12,6 +12,8 @@
#include <linux/sched.h>
#include <linux/stacktrace.h>
#include <asm/ftrace.h>
#include <asm/sections.h>
#include <asm/stacktrace.h>
#include <asm/traps.h>
#include <linux/uaccess.h>
@@ -188,7 +190,7 @@ void walk_stackframe(unsigned long *sp,
if (a1 <= (unsigned long)sp)
break;
frame.pc = MAKE_PC_FROM_RA(a0, a1);
frame.pc = MAKE_PC_FROM_RA(a0, _text);
frame.sp = a1;
if (fn(&frame, data))

View File

@@ -2657,8 +2657,11 @@ static ssize_t uevent_show(struct device *dev, struct device_attribute *attr,
if (!env)
return -ENOMEM;
/* Synchronize with really_probe() */
device_lock(dev);
/* let the kset specific function add its keys */
retval = kset->uevent_ops->uevent(&dev->kobj, env);
device_unlock(dev);
if (retval)
goto out;

View File

@@ -112,7 +112,7 @@ int null_init_zoned_dev(struct nullb_device *dev, struct request_queue *q)
if (dev->zone_max_active && dev->zone_max_open > dev->zone_max_active) {
dev->zone_max_open = dev->zone_max_active;
pr_info("changed the maximum number of open zones to %u\n",
dev->nr_zones);
dev->zone_max_open);
} else if (dev->zone_max_open >= dev->nr_zones - dev->zone_nr_conv) {
dev->zone_max_open = 0;
pr_info("zone_max_open limit disabled, limit >= zone count\n");

View File

@@ -365,6 +365,14 @@ static int qca_tlv_check_data(struct hci_dev *hdev,
/* Update NVM tags as needed */
switch (tag_id) {
case EDL_TAG_ID_BD_ADDR:
if (tag_len != sizeof(bdaddr_t))
return -EINVAL;
memcpy(&config->bdaddr, tlv_nvm->data, sizeof(bdaddr_t));
break;
case EDL_TAG_ID_HCI:
if (tag_len < 3)
return -EINVAL;
@@ -639,11 +647,43 @@ int qca_set_bdaddr_rome(struct hci_dev *hdev, const bdaddr_t *bdaddr)
}
EXPORT_SYMBOL_GPL(qca_set_bdaddr_rome);
static int qca_check_bdaddr(struct hci_dev *hdev, const struct qca_fw_config *config)
{
struct hci_rp_read_bd_addr *bda;
struct sk_buff *skb;
int err;
if (bacmp(&hdev->public_addr, BDADDR_ANY))
return 0;
skb = __hci_cmd_sync(hdev, HCI_OP_READ_BD_ADDR, 0, NULL,
HCI_INIT_TIMEOUT);
if (IS_ERR(skb)) {
err = PTR_ERR(skb);
bt_dev_err(hdev, "Failed to read device address (%d)", err);
return err;
}
if (skb->len != sizeof(*bda)) {
bt_dev_err(hdev, "Device address length mismatch");
kfree_skb(skb);
return -EIO;
}
bda = (struct hci_rp_read_bd_addr *)skb->data;
if (!bacmp(&bda->bdaddr, &config->bdaddr))
set_bit(HCI_QUIRK_USE_BDADDR_PROPERTY, &hdev->quirks);
kfree_skb(skb);
return 0;
}
int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate,
enum qca_btsoc_type soc_type, struct qca_btsoc_version ver,
const char *firmware_name)
{
struct qca_fw_config config;
struct qca_fw_config config = {};
int err;
u8 rom_ver = 0;
u32 soc_ver;
@@ -757,6 +797,10 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate,
return err;
}
err = qca_check_bdaddr(hdev, &config);
if (err)
return err;
bt_dev_info(hdev, "QCA setup on UART is completed");
return 0;

View File

@@ -28,6 +28,7 @@
#define EDL_PATCH_CONFIG_RES_EVT (0x00)
#define QCA_DISABLE_LOGGING_SUB_OP (0x14)
#define EDL_TAG_ID_BD_ADDR 2
#define EDL_TAG_ID_HCI (17)
#define EDL_TAG_ID_DEEP_SLEEP (27)
@@ -89,6 +90,7 @@ struct qca_fw_config {
uint8_t user_baud_rate;
enum qca_tlv_dnld_mode dnld_mode;
enum qca_tlv_dnld_mode dnld_type;
bdaddr_t bdaddr;
};
struct edl_event_hdr {

View File

@@ -4,7 +4,6 @@
* Copyright (C) 2020 Zong Li
*/
#include <linux/clkdev.h>
#include <linux/delay.h>
#include <linux/io.h>
#include <linux/of_device.h>
@@ -536,13 +535,6 @@ static int __prci_register_clocks(struct device *dev, struct __prci_data *pd,
return r;
}
r = clk_hw_register_clkdev(&pic->hw, pic->name, dev_name(dev));
if (r) {
dev_warn(dev, "Failed to register clkdev for %s: %d\n",
init.name, r);
return r;
}
pd->hw_clks.hws[i] = &pic->hw;
}

View File

@@ -1036,8 +1036,8 @@ static int axi_dmac_remove(struct platform_device *pdev)
{
struct axi_dmac *dmac = platform_get_drvdata(pdev);
of_dma_controller_free(pdev->dev.of_node);
free_irq(dmac->irq, dmac);
of_dma_controller_free(pdev->dev.of_node);
tasklet_kill(&dmac->chan.vchan.task);
dma_async_device_unregister(&dmac->dma_dev);
clk_disable_unprepare(dmac->clk);

View File

@@ -495,13 +495,14 @@ int qcom_scm_pas_init_image(u32 peripheral, const void *metadata, size_t size,
ret = qcom_scm_bw_enable();
if (ret)
return ret;
goto disable_clk;
desc.args[1] = mdata_phys;
ret = qcom_scm_call(__scm->dev, &desc, &res);
qcom_scm_bw_disable();
disable_clk:
qcom_scm_clk_disable();
out:
@@ -563,10 +564,12 @@ int qcom_scm_pas_mem_setup(u32 peripheral, phys_addr_t addr, phys_addr_t size)
ret = qcom_scm_bw_enable();
if (ret)
return ret;
goto disable_clk;
ret = qcom_scm_call(__scm->dev, &desc, &res);
qcom_scm_bw_disable();
disable_clk:
qcom_scm_clk_disable();
return ret ? : res.result[0];
@@ -598,10 +601,12 @@ int qcom_scm_pas_auth_and_reset(u32 peripheral)
ret = qcom_scm_bw_enable();
if (ret)
return ret;
goto disable_clk;
ret = qcom_scm_call(__scm->dev, &desc, &res);
qcom_scm_bw_disable();
disable_clk:
qcom_scm_clk_disable();
return ret ? : res.result[0];
@@ -632,11 +637,12 @@ int qcom_scm_pas_shutdown(u32 peripheral)
ret = qcom_scm_bw_enable();
if (ret)
return ret;
goto disable_clk;
ret = qcom_scm_call(__scm->dev, &desc, &res);
qcom_scm_bw_disable();
disable_clk:
qcom_scm_clk_disable();
return ret ? : res.result[0];

View File

@@ -1415,7 +1415,7 @@ config GPIO_TPS68470
are "output only" GPIOs.
config GPIO_TQMX86
tristate "TQ-Systems QTMX86 GPIO"
tristate "TQ-Systems TQMx86 GPIO"
depends on MFD_TQMX86 || COMPILE_TEST
depends on HAS_IOPORT_MAP
select GPIOLIB_IRQCHIP

View File

@@ -6,6 +6,7 @@
* Vadim V.Vlasov <vvlasov@dev.rtsoft.ru>
*/
#include <linux/bitmap.h>
#include <linux/bitops.h>
#include <linux/errno.h>
#include <linux/gpio/driver.h>
@@ -15,6 +16,7 @@
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/seq_file.h>
#include <linux/slab.h>
#define TQMX86_NGPIO 8
@@ -27,17 +29,25 @@
#define TQMX86_GPIIC 3 /* GPI Interrupt Configuration Register */
#define TQMX86_GPIIS 4 /* GPI Interrupt Status Register */
#define TQMX86_GPII_NONE 0
#define TQMX86_GPII_FALLING BIT(0)
#define TQMX86_GPII_RISING BIT(1)
/* Stored in irq_type as a trigger type, but not actually valid as a register
* value, so the name doesn't use "GPII"
*/
#define TQMX86_INT_BOTH (BIT(0) | BIT(1))
#define TQMX86_GPII_MASK (BIT(0) | BIT(1))
#define TQMX86_GPII_BITS 2
/* Stored in irq_type with GPII bits */
#define TQMX86_INT_UNMASKED BIT(2)
struct tqmx86_gpio_data {
struct gpio_chip chip;
struct irq_chip irq_chip;
void __iomem *io_base;
int irq;
/* Lock must be held for accessing output and irq_type fields */
raw_spinlock_t spinlock;
DECLARE_BITMAP(output, TQMX86_NGPIO);
u8 irq_type[TQMX86_NGPI];
};
@@ -64,15 +74,10 @@ static void tqmx86_gpio_set(struct gpio_chip *chip, unsigned int offset,
{
struct tqmx86_gpio_data *gpio = gpiochip_get_data(chip);
unsigned long flags;
u8 val;
raw_spin_lock_irqsave(&gpio->spinlock, flags);
val = tqmx86_gpio_read(gpio, TQMX86_GPIOD);
if (value)
val |= BIT(offset);
else
val &= ~BIT(offset);
tqmx86_gpio_write(gpio, val, TQMX86_GPIOD);
__assign_bit(offset, gpio->output, value);
tqmx86_gpio_write(gpio, bitmap_get_value8(gpio->output, 0), TQMX86_GPIOD);
raw_spin_unlock_irqrestore(&gpio->spinlock, flags);
}
@@ -107,21 +112,39 @@ static int tqmx86_gpio_get_direction(struct gpio_chip *chip,
return GPIO_LINE_DIRECTION_OUT;
}
static void tqmx86_gpio_irq_config(struct tqmx86_gpio_data *gpio, int offset)
__must_hold(&gpio->spinlock)
{
u8 type = TQMX86_GPII_NONE, gpiic;
if (gpio->irq_type[offset] & TQMX86_INT_UNMASKED) {
type = gpio->irq_type[offset] & TQMX86_GPII_MASK;
if (type == TQMX86_INT_BOTH)
type = tqmx86_gpio_get(&gpio->chip, offset + TQMX86_NGPO)
? TQMX86_GPII_FALLING
: TQMX86_GPII_RISING;
}
gpiic = tqmx86_gpio_read(gpio, TQMX86_GPIIC);
gpiic &= ~(TQMX86_GPII_MASK << (offset * TQMX86_GPII_BITS));
gpiic |= type << (offset * TQMX86_GPII_BITS);
tqmx86_gpio_write(gpio, gpiic, TQMX86_GPIIC);
}
static void tqmx86_gpio_irq_mask(struct irq_data *data)
{
unsigned int offset = (data->hwirq - TQMX86_NGPO);
struct tqmx86_gpio_data *gpio = gpiochip_get_data(
irq_data_get_irq_chip_data(data));
unsigned long flags;
u8 gpiic, mask;
mask = TQMX86_GPII_MASK << (offset * TQMX86_GPII_BITS);
raw_spin_lock_irqsave(&gpio->spinlock, flags);
gpiic = tqmx86_gpio_read(gpio, TQMX86_GPIIC);
gpiic &= ~mask;
tqmx86_gpio_write(gpio, gpiic, TQMX86_GPIIC);
gpio->irq_type[offset] &= ~TQMX86_INT_UNMASKED;
tqmx86_gpio_irq_config(gpio, offset);
raw_spin_unlock_irqrestore(&gpio->spinlock, flags);
gpiochip_disable_irq(&gpio->chip, irqd_to_hwirq(data));
}
static void tqmx86_gpio_irq_unmask(struct irq_data *data)
@@ -130,15 +153,12 @@ static void tqmx86_gpio_irq_unmask(struct irq_data *data)
struct tqmx86_gpio_data *gpio = gpiochip_get_data(
irq_data_get_irq_chip_data(data));
unsigned long flags;
u8 gpiic, mask;
mask = TQMX86_GPII_MASK << (offset * TQMX86_GPII_BITS);
gpiochip_enable_irq(&gpio->chip, irqd_to_hwirq(data));
raw_spin_lock_irqsave(&gpio->spinlock, flags);
gpiic = tqmx86_gpio_read(gpio, TQMX86_GPIIC);
gpiic &= ~mask;
gpiic |= gpio->irq_type[offset] << (offset * TQMX86_GPII_BITS);
tqmx86_gpio_write(gpio, gpiic, TQMX86_GPIIC);
gpio->irq_type[offset] |= TQMX86_INT_UNMASKED;
tqmx86_gpio_irq_config(gpio, offset);
raw_spin_unlock_irqrestore(&gpio->spinlock, flags);
}
@@ -149,7 +169,7 @@ static int tqmx86_gpio_irq_set_type(struct irq_data *data, unsigned int type)
unsigned int offset = (data->hwirq - TQMX86_NGPO);
unsigned int edge_type = type & IRQF_TRIGGER_MASK;
unsigned long flags;
u8 new_type, gpiic;
u8 new_type;
switch (edge_type) {
case IRQ_TYPE_EDGE_RISING:
@@ -159,19 +179,16 @@ static int tqmx86_gpio_irq_set_type(struct irq_data *data, unsigned int type)
new_type = TQMX86_GPII_FALLING;
break;
case IRQ_TYPE_EDGE_BOTH:
new_type = TQMX86_GPII_FALLING | TQMX86_GPII_RISING;
new_type = TQMX86_INT_BOTH;
break;
default:
return -EINVAL; /* not supported */
}
gpio->irq_type[offset] = new_type;
raw_spin_lock_irqsave(&gpio->spinlock, flags);
gpiic = tqmx86_gpio_read(gpio, TQMX86_GPIIC);
gpiic &= ~((TQMX86_GPII_MASK) << (offset * TQMX86_GPII_BITS));
gpiic |= new_type << (offset * TQMX86_GPII_BITS);
tqmx86_gpio_write(gpio, gpiic, TQMX86_GPIIC);
gpio->irq_type[offset] &= ~TQMX86_GPII_MASK;
gpio->irq_type[offset] |= new_type;
tqmx86_gpio_irq_config(gpio, offset);
raw_spin_unlock_irqrestore(&gpio->spinlock, flags);
return 0;
@@ -182,8 +199,8 @@ static void tqmx86_gpio_irq_handler(struct irq_desc *desc)
struct gpio_chip *chip = irq_desc_get_handler_data(desc);
struct tqmx86_gpio_data *gpio = gpiochip_get_data(chip);
struct irq_chip *irq_chip = irq_desc_get_chip(desc);
unsigned long irq_bits;
int i = 0;
unsigned long irq_bits, flags;
int i;
u8 irq_status;
chained_irq_enter(irq_chip, desc);
@@ -192,6 +209,34 @@ static void tqmx86_gpio_irq_handler(struct irq_desc *desc)
tqmx86_gpio_write(gpio, irq_status, TQMX86_GPIIS);
irq_bits = irq_status;
raw_spin_lock_irqsave(&gpio->spinlock, flags);
for_each_set_bit(i, &irq_bits, TQMX86_NGPI) {
/*
* Edge-both triggers are implemented by flipping the edge
* trigger after each interrupt, as the controller only supports
* either rising or falling edge triggers, but not both.
*
* Internally, the TQMx86 GPIO controller has separate status
* registers for rising and falling edge interrupts. GPIIC
* configures which bits from which register are visible in the
* interrupt status register GPIIS and defines what triggers the
* parent IRQ line. Writing to GPIIS always clears both rising
* and falling interrupt flags internally, regardless of the
* currently configured trigger.
*
* In consequence, we can cleanly implement the edge-both
* trigger in software by first clearing the interrupt and then
* setting the new trigger based on the current GPIO input in
* tqmx86_gpio_irq_config() - even if an edge arrives between
* reading the input and setting the trigger, we will have a new
* interrupt pending.
*/
if ((gpio->irq_type[i] & TQMX86_GPII_MASK) == TQMX86_INT_BOTH)
tqmx86_gpio_irq_config(gpio, i);
}
raw_spin_unlock_irqrestore(&gpio->spinlock, flags);
for_each_set_bit(i, &irq_bits, TQMX86_NGPI)
generic_handle_domain_irq(gpio->chip.irq.domain,
i + TQMX86_NGPO);
@@ -226,6 +271,22 @@ static void tqmx86_init_irq_valid_mask(struct gpio_chip *chip,
clear_bit(3, valid_mask);
}
static void tqmx86_gpio_irq_print_chip(struct irq_data *d, struct seq_file *p)
{
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
seq_printf(p, gc->label);
}
static const struct irq_chip tqmx86_gpio_irq_chip = {
.irq_mask = tqmx86_gpio_irq_mask,
.irq_unmask = tqmx86_gpio_irq_unmask,
.irq_set_type = tqmx86_gpio_irq_set_type,
.irq_print_chip = tqmx86_gpio_irq_print_chip,
.flags = IRQCHIP_IMMUTABLE,
GPIOCHIP_IRQ_RESOURCE_HELPERS,
};
static int tqmx86_gpio_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
@@ -259,7 +320,12 @@ static int tqmx86_gpio_probe(struct platform_device *pdev)
tqmx86_gpio_write(gpio, (u8)~TQMX86_DIR_INPUT_MASK, TQMX86_GPIODD);
platform_set_drvdata(pdev, gpio);
/*
* Reading the previous output state is not possible with TQMx86 hardware.
* Initialize all outputs to 0 to have a defined state that matches the
* shadow register.
*/
tqmx86_gpio_write(gpio, 0, TQMX86_GPIOD);
chip = &gpio->chip;
chip->label = "gpio-tqmx86";
@@ -277,14 +343,8 @@ static int tqmx86_gpio_probe(struct platform_device *pdev)
pm_runtime_enable(&pdev->dev);
if (irq > 0) {
struct irq_chip *irq_chip = &gpio->irq_chip;
u8 irq_status;
irq_chip->name = chip->label;
irq_chip->irq_mask = tqmx86_gpio_irq_mask;
irq_chip->irq_unmask = tqmx86_gpio_irq_unmask;
irq_chip->irq_set_type = tqmx86_gpio_irq_set_type;
/* Mask all interrupts */
tqmx86_gpio_write(gpio, 0, TQMX86_GPIIC);
@@ -293,7 +353,7 @@ static int tqmx86_gpio_probe(struct platform_device *pdev)
tqmx86_gpio_write(gpio, irq_status, TQMX86_GPIIS);
girq = &chip->irq;
girq->chip = irq_chip;
gpio_irq_chip_set_chip(girq, &tqmx86_gpio_irq_chip);
girq->parent_handler = tqmx86_gpio_irq_handler;
girq->num_parents = 1;
girq->parents = devm_kcalloc(&pdev->dev, 1,

View File

@@ -1369,16 +1369,13 @@ static ssize_t dp_dsc_clock_en_read(struct file *f, char __user *buf,
for (i = 0; i < MAX_PIPES; i++) {
pipe_ctx = &aconnector->dc_link->dc->current_state->res_ctx.pipe_ctx[i];
if (pipe_ctx && pipe_ctx->stream &&
pipe_ctx->stream->link == aconnector->dc_link)
if (pipe_ctx->stream &&
pipe_ctx->stream->link == aconnector->dc_link &&
pipe_ctx->stream->sink &&
pipe_ctx->stream->sink == aconnector->dc_sink)
break;
}
if (!pipe_ctx) {
kfree(rd_buf);
return -ENXIO;
}
dsc = pipe_ctx->stream_res.dsc;
if (dsc)
dsc->funcs->dsc_read_state(dsc, &dsc_state);
@@ -1475,12 +1472,14 @@ static ssize_t dp_dsc_clock_en_write(struct file *f, const char __user *buf,
for (i = 0; i < MAX_PIPES; i++) {
pipe_ctx = &aconnector->dc_link->dc->current_state->res_ctx.pipe_ctx[i];
if (pipe_ctx && pipe_ctx->stream &&
pipe_ctx->stream->link == aconnector->dc_link)
if (pipe_ctx->stream &&
pipe_ctx->stream->link == aconnector->dc_link &&
pipe_ctx->stream->sink &&
pipe_ctx->stream->sink == aconnector->dc_sink)
break;
}
if (!pipe_ctx || !pipe_ctx->stream)
if (!pipe_ctx->stream)
goto done;
// Get CRTC state
@@ -1560,16 +1559,13 @@ static ssize_t dp_dsc_slice_width_read(struct file *f, char __user *buf,
for (i = 0; i < MAX_PIPES; i++) {
pipe_ctx = &aconnector->dc_link->dc->current_state->res_ctx.pipe_ctx[i];
if (pipe_ctx && pipe_ctx->stream &&
pipe_ctx->stream->link == aconnector->dc_link)
if (pipe_ctx->stream &&
pipe_ctx->stream->link == aconnector->dc_link &&
pipe_ctx->stream->sink &&
pipe_ctx->stream->sink == aconnector->dc_sink)
break;
}
if (!pipe_ctx) {
kfree(rd_buf);
return -ENXIO;
}
dsc = pipe_ctx->stream_res.dsc;
if (dsc)
dsc->funcs->dsc_read_state(dsc, &dsc_state);
@@ -1664,12 +1660,14 @@ static ssize_t dp_dsc_slice_width_write(struct file *f, const char __user *buf,
for (i = 0; i < MAX_PIPES; i++) {
pipe_ctx = &aconnector->dc_link->dc->current_state->res_ctx.pipe_ctx[i];
if (pipe_ctx && pipe_ctx->stream &&
pipe_ctx->stream->link == aconnector->dc_link)
if (pipe_ctx->stream &&
pipe_ctx->stream->link == aconnector->dc_link &&
pipe_ctx->stream->sink &&
pipe_ctx->stream->sink == aconnector->dc_sink)
break;
}
if (!pipe_ctx || !pipe_ctx->stream)
if (!pipe_ctx->stream)
goto done;
// Safely get CRTC state
@@ -1749,16 +1747,13 @@ static ssize_t dp_dsc_slice_height_read(struct file *f, char __user *buf,
for (i = 0; i < MAX_PIPES; i++) {
pipe_ctx = &aconnector->dc_link->dc->current_state->res_ctx.pipe_ctx[i];
if (pipe_ctx && pipe_ctx->stream &&
pipe_ctx->stream->link == aconnector->dc_link)
if (pipe_ctx->stream &&
pipe_ctx->stream->link == aconnector->dc_link &&
pipe_ctx->stream->sink &&
pipe_ctx->stream->sink == aconnector->dc_sink)
break;
}
if (!pipe_ctx) {
kfree(rd_buf);
return -ENXIO;
}
dsc = pipe_ctx->stream_res.dsc;
if (dsc)
dsc->funcs->dsc_read_state(dsc, &dsc_state);
@@ -1853,12 +1848,14 @@ static ssize_t dp_dsc_slice_height_write(struct file *f, const char __user *buf,
for (i = 0; i < MAX_PIPES; i++) {
pipe_ctx = &aconnector->dc_link->dc->current_state->res_ctx.pipe_ctx[i];
if (pipe_ctx && pipe_ctx->stream &&
pipe_ctx->stream->link == aconnector->dc_link)
if (pipe_ctx->stream &&
pipe_ctx->stream->link == aconnector->dc_link &&
pipe_ctx->stream->sink &&
pipe_ctx->stream->sink == aconnector->dc_sink)
break;
}
if (!pipe_ctx || !pipe_ctx->stream)
if (!pipe_ctx->stream)
goto done;
// Get CRTC state
@@ -1934,16 +1931,13 @@ static ssize_t dp_dsc_bits_per_pixel_read(struct file *f, char __user *buf,
for (i = 0; i < MAX_PIPES; i++) {
pipe_ctx = &aconnector->dc_link->dc->current_state->res_ctx.pipe_ctx[i];
if (pipe_ctx && pipe_ctx->stream &&
pipe_ctx->stream->link == aconnector->dc_link)
if (pipe_ctx->stream &&
pipe_ctx->stream->link == aconnector->dc_link &&
pipe_ctx->stream->sink &&
pipe_ctx->stream->sink == aconnector->dc_sink)
break;
}
if (!pipe_ctx) {
kfree(rd_buf);
return -ENXIO;
}
dsc = pipe_ctx->stream_res.dsc;
if (dsc)
dsc->funcs->dsc_read_state(dsc, &dsc_state);
@@ -2035,12 +2029,14 @@ static ssize_t dp_dsc_bits_per_pixel_write(struct file *f, const char __user *bu
for (i = 0; i < MAX_PIPES; i++) {
pipe_ctx = &aconnector->dc_link->dc->current_state->res_ctx.pipe_ctx[i];
if (pipe_ctx && pipe_ctx->stream &&
pipe_ctx->stream->link == aconnector->dc_link)
if (pipe_ctx->stream &&
pipe_ctx->stream->link == aconnector->dc_link &&
pipe_ctx->stream->sink &&
pipe_ctx->stream->sink == aconnector->dc_sink)
break;
}
if (!pipe_ctx || !pipe_ctx->stream)
if (!pipe_ctx->stream)
goto done;
// Get CRTC state
@@ -2114,16 +2110,13 @@ static ssize_t dp_dsc_pic_width_read(struct file *f, char __user *buf,
for (i = 0; i < MAX_PIPES; i++) {
pipe_ctx = &aconnector->dc_link->dc->current_state->res_ctx.pipe_ctx[i];
if (pipe_ctx && pipe_ctx->stream &&
pipe_ctx->stream->link == aconnector->dc_link)
if (pipe_ctx->stream &&
pipe_ctx->stream->link == aconnector->dc_link &&
pipe_ctx->stream->sink &&
pipe_ctx->stream->sink == aconnector->dc_sink)
break;
}
if (!pipe_ctx) {
kfree(rd_buf);
return -ENXIO;
}
dsc = pipe_ctx->stream_res.dsc;
if (dsc)
dsc->funcs->dsc_read_state(dsc, &dsc_state);
@@ -2175,16 +2168,13 @@ static ssize_t dp_dsc_pic_height_read(struct file *f, char __user *buf,
for (i = 0; i < MAX_PIPES; i++) {
pipe_ctx = &aconnector->dc_link->dc->current_state->res_ctx.pipe_ctx[i];
if (pipe_ctx && pipe_ctx->stream &&
pipe_ctx->stream->link == aconnector->dc_link)
if (pipe_ctx->stream &&
pipe_ctx->stream->link == aconnector->dc_link &&
pipe_ctx->stream->sink &&
pipe_ctx->stream->sink == aconnector->dc_sink)
break;
}
if (!pipe_ctx) {
kfree(rd_buf);
return -ENXIO;
}
dsc = pipe_ctx->stream_res.dsc;
if (dsc)
dsc->funcs->dsc_read_state(dsc, &dsc_state);
@@ -2251,16 +2241,13 @@ static ssize_t dp_dsc_chunk_size_read(struct file *f, char __user *buf,
for (i = 0; i < MAX_PIPES; i++) {
pipe_ctx = &aconnector->dc_link->dc->current_state->res_ctx.pipe_ctx[i];
if (pipe_ctx && pipe_ctx->stream &&
pipe_ctx->stream->link == aconnector->dc_link)
if (pipe_ctx->stream &&
pipe_ctx->stream->link == aconnector->dc_link &&
pipe_ctx->stream->sink &&
pipe_ctx->stream->sink == aconnector->dc_sink)
break;
}
if (!pipe_ctx) {
kfree(rd_buf);
return -ENXIO;
}
dsc = pipe_ctx->stream_res.dsc;
if (dsc)
dsc->funcs->dsc_read_state(dsc, &dsc_state);
@@ -2327,16 +2314,13 @@ static ssize_t dp_dsc_slice_bpg_offset_read(struct file *f, char __user *buf,
for (i = 0; i < MAX_PIPES; i++) {
pipe_ctx = &aconnector->dc_link->dc->current_state->res_ctx.pipe_ctx[i];
if (pipe_ctx && pipe_ctx->stream &&
pipe_ctx->stream->link == aconnector->dc_link)
if (pipe_ctx->stream &&
pipe_ctx->stream->link == aconnector->dc_link &&
pipe_ctx->stream->sink &&
pipe_ctx->stream->sink == aconnector->dc_sink)
break;
}
if (!pipe_ctx) {
kfree(rd_buf);
return -ENXIO;
}
dsc = pipe_ctx->stream_res.dsc;
if (dsc)
dsc->funcs->dsc_read_state(dsc, &dsc_state);

View File

@@ -259,7 +259,7 @@ komeda_component_get_avail_scaler(struct komeda_component *c,
u32 avail_scalers;
pipe_st = komeda_pipeline_get_state(c->pipeline, state);
if (!pipe_st)
if (IS_ERR_OR_NULL(pipe_st))
return NULL;
avail_scalers = (pipe_st->active_comps & KOMEDA_PIPELINE_SCALERS) ^

View File

@@ -306,9 +306,12 @@ EXPORT_SYMBOL(drm_panel_bridge_set_orientation);
static void devm_drm_panel_bridge_release(struct device *dev, void *res)
{
struct drm_bridge **bridge = res;
struct drm_bridge *bridge = *(struct drm_bridge **)res;
drm_panel_bridge_remove(*bridge);
if (!bridge)
return;
drm_bridge_remove(bridge);
}
/**

View File

@@ -309,6 +309,7 @@ static int vidi_get_modes(struct drm_connector *connector)
struct vidi_context *ctx = ctx_from_connector(connector);
struct edid *edid;
int edid_len;
int count;
/*
* the edid data comes from user side and it would be set
@@ -328,7 +329,11 @@ static int vidi_get_modes(struct drm_connector *connector)
drm_connector_update_edid_property(connector, edid);
return drm_add_edid_modes(connector, edid);
count = drm_add_edid_modes(connector, edid);
kfree(edid);
return count;
}
static const struct drm_connector_helper_funcs vidi_connector_helper_funcs = {

View File

@@ -887,11 +887,11 @@ static int hdmi_get_modes(struct drm_connector *connector)
int ret;
if (!hdata->ddc_adpt)
return 0;
goto no_edid;
edid = drm_get_edid(connector, hdata->ddc_adpt);
if (!edid)
return 0;
goto no_edid;
hdata->dvi_mode = !connector->display_info.is_hdmi;
DRM_DEV_DEBUG_KMS(hdata->dev, "%s : width[%d] x height[%d]\n",
@@ -906,6 +906,9 @@ static int hdmi_get_modes(struct drm_connector *connector)
kfree(edid);
return ret;
no_edid:
return drm_add_modes_noedid(connector, 640, 480);
}
static int hdmi_find_phy_conf(struct hdmi_context *hdata, u32 pixel_clock)

View File

@@ -295,7 +295,9 @@ bool i915_gem_object_has_iomem(const struct drm_i915_gem_object *obj);
static inline bool
i915_gem_object_is_shrinkable(const struct drm_i915_gem_object *obj)
{
return i915_gem_object_type_has(obj, I915_GEM_OBJECT_IS_SHRINKABLE);
/* TODO: make DPT shrinkable when it has no bound vmas */
return i915_gem_object_type_has(obj, I915_GEM_OBJECT_IS_SHRINKABLE) &&
!obj->is_dpt;
}
static inline bool

View File

@@ -258,8 +258,13 @@ static void signal_irq_work(struct irq_work *work)
i915_request_put(rq);
}
/* Lazy irq enabling after HW submission */
if (!READ_ONCE(b->irq_armed) && !list_empty(&b->signalers))
intel_breadcrumbs_arm_irq(b);
/* And confirm that we still want irqs enabled before we yield */
if (READ_ONCE(b->irq_armed) && !atomic_read(&b->active))
intel_breadcrumbs_disarm_irq(b);
}
struct intel_breadcrumbs *
@@ -310,13 +315,7 @@ void __intel_breadcrumbs_park(struct intel_breadcrumbs *b)
return;
/* Kick the work once more to drain the signalers, and disarm the irq */
irq_work_sync(&b->irq_work);
while (READ_ONCE(b->irq_armed) && !atomic_read(&b->active)) {
local_irq_disable();
signal_irq_work(&b->irq_work);
local_irq_enable();
cond_resched();
}
irq_work_queue(&b->irq_work);
}
void intel_breadcrumbs_free(struct kref *kref)
@@ -399,7 +398,7 @@ static void insert_breadcrumb(struct i915_request *rq)
* the request as it may have completed and raised the interrupt as
* we were attaching it into the lists.
*/
if (!b->irq_armed || __i915_request_is_complete(rq))
if (!READ_ONCE(b->irq_armed) || __i915_request_is_complete(rq))
irq_work_queue(&b->irq_work);
}

View File

@@ -16,13 +16,6 @@ config DRM_VMWGFX
virtual hardware.
The compiled module will be called "vmwgfx.ko".
config DRM_VMWGFX_FBCON
depends on DRM_VMWGFX && DRM_FBDEV_EMULATION
bool "Enable framebuffer console under vmwgfx by default"
help
Choose this option if you are shipping a new vmwgfx
userspace driver that supports using the kernel driver.
config DRM_VMWGFX_MKSSTATS
bool "Enable mksGuestStats instrumentation of vmwgfx by default"
depends on DRM_VMWGFX

View File

@@ -12,6 +12,4 @@ vmwgfx-y := vmwgfx_execbuf.o vmwgfx_gmr.o vmwgfx_kms.o vmwgfx_drv.o \
vmwgfx_devcaps.o ttm_object.o vmwgfx_system_manager.o \
vmwgfx_gem.o
vmwgfx-$(CONFIG_DRM_FBDEV_EMULATION) += vmwgfx_fb.o
obj-$(CONFIG_DRM_VMWGFX) := vmwgfx.o

View File

@@ -35,6 +35,7 @@
#include <drm/drm_aperture.h>
#include <drm/drm_drv.h>
#include <drm/drm_fb_helper.h>
#include <drm/drm_gem_ttm_helper.h>
#include <drm/drm_ioctl.h>
#include <drm/drm_module.h>
@@ -52,9 +53,6 @@
#define VMWGFX_DRIVER_DESC "Linux drm driver for VMware graphics devices"
#define VMW_MIN_INITIAL_WIDTH 800
#define VMW_MIN_INITIAL_HEIGHT 600
/*
* Fully encoded drm commands. Might move to vmw_drm.h
*/
@@ -265,7 +263,6 @@ static const struct pci_device_id vmw_pci_id_list[] = {
};
MODULE_DEVICE_TABLE(pci, vmw_pci_id_list);
static int enable_fbdev = IS_ENABLED(CONFIG_DRM_VMWGFX_FBCON);
static int vmw_restrict_iommu;
static int vmw_force_coherent;
static int vmw_restrict_dma_mask;
@@ -275,8 +272,6 @@ static int vmw_probe(struct pci_dev *, const struct pci_device_id *);
static int vmwgfx_pm_notifier(struct notifier_block *nb, unsigned long val,
void *ptr);
MODULE_PARM_DESC(enable_fbdev, "Enable vmwgfx fbdev");
module_param_named(enable_fbdev, enable_fbdev, int, 0600);
MODULE_PARM_DESC(restrict_iommu, "Try to limit IOMMU usage for TTM pages");
module_param_named(restrict_iommu, vmw_restrict_iommu, int, 0600);
MODULE_PARM_DESC(force_coherent, "Force coherent TTM pages");
@@ -626,8 +621,8 @@ static void vmw_get_initial_size(struct vmw_private *dev_priv)
width = vmw_read(dev_priv, SVGA_REG_WIDTH);
height = vmw_read(dev_priv, SVGA_REG_HEIGHT);
width = max_t(uint32_t, width, VMW_MIN_INITIAL_WIDTH);
height = max_t(uint32_t, height, VMW_MIN_INITIAL_HEIGHT);
width = max_t(uint32_t, width, VMWGFX_MIN_INITIAL_WIDTH);
height = max_t(uint32_t, height, VMWGFX_MIN_INITIAL_HEIGHT);
if (width > dev_priv->fb_max_width ||
height > dev_priv->fb_max_height) {
@@ -636,8 +631,8 @@ static void vmw_get_initial_size(struct vmw_private *dev_priv)
* This is a host error and shouldn't occur.
*/
width = VMW_MIN_INITIAL_WIDTH;
height = VMW_MIN_INITIAL_HEIGHT;
width = VMWGFX_MIN_INITIAL_WIDTH;
height = VMWGFX_MIN_INITIAL_HEIGHT;
}
dev_priv->initial_width = width;
@@ -887,9 +882,6 @@ static int vmw_driver_load(struct vmw_private *dev_priv, u32 pci_id)
dev_priv->assume_16bpp = !!vmw_assume_16bpp;
dev_priv->enable_fb = enable_fbdev;
dev_priv->capabilities = vmw_read(dev_priv, SVGA_REG_CAPABILITIES);
vmw_print_bitmap(&dev_priv->drm, "Capabilities",
dev_priv->capabilities,
@@ -946,13 +938,6 @@ static int vmw_driver_load(struct vmw_private *dev_priv, u32 pci_id)
vmw_read(dev_priv,
SVGA_REG_SUGGESTED_GBOBJECT_MEM_SIZE_KB);
/*
* Workaround for low memory 2D VMs to compensate for the
* allocation taken by fbdev
*/
if (!(dev_priv->capabilities & SVGA_CAP_3D))
mem_size *= 3;
dev_priv->max_mob_pages = mem_size * 1024 / PAGE_SIZE;
dev_priv->max_primary_mem =
vmw_read(dev_priv, SVGA_REG_MAX_PRIMARY_MEM);
@@ -1136,12 +1121,6 @@ static int vmw_driver_load(struct vmw_private *dev_priv, u32 pci_id)
VMWGFX_DRIVER_PATCHLEVEL, UTS_RELEASE);
vmw_write_driver_id(dev_priv);
if (dev_priv->enable_fb) {
vmw_fifo_resource_inc(dev_priv);
vmw_svga_enable(dev_priv);
vmw_fb_init(dev_priv);
}
dev_priv->pm_nb.notifier_call = vmwgfx_pm_notifier;
register_pm_notifier(&dev_priv->pm_nb);
@@ -1188,12 +1167,9 @@ static void vmw_driver_unload(struct drm_device *dev)
unregister_pm_notifier(&dev_priv->pm_nb);
vmw_sw_context_fini(dev_priv);
if (dev_priv->enable_fb) {
vmw_fb_off(dev_priv);
vmw_fb_close(dev_priv);
vmw_fifo_resource_dec(dev_priv);
vmw_svga_disable(dev_priv);
}
vmw_fifo_resource_dec(dev_priv);
vmw_svga_disable(dev_priv);
vmw_kms_close(dev_priv);
vmw_overlay_close(dev_priv);
@@ -1331,8 +1307,6 @@ static void vmw_master_drop(struct drm_device *dev,
struct vmw_private *dev_priv = vmw_priv(dev);
vmw_kms_legacy_hotspot_clear(dev_priv);
if (!dev_priv->enable_fb)
vmw_svga_disable(dev_priv);
}
/**
@@ -1528,25 +1502,19 @@ static int vmw_pm_freeze(struct device *kdev)
DRM_ERROR("Failed to freeze modesetting.\n");
return ret;
}
if (dev_priv->enable_fb)
vmw_fb_off(dev_priv);
vmw_execbuf_release_pinned_bo(dev_priv);
vmw_resource_evict_all(dev_priv);
vmw_release_device_early(dev_priv);
while (ttm_device_swapout(&dev_priv->bdev, &ctx, GFP_KERNEL) > 0);
if (dev_priv->enable_fb)
vmw_fifo_resource_dec(dev_priv);
vmw_fifo_resource_dec(dev_priv);
if (atomic_read(&dev_priv->num_fifo_resources) != 0) {
DRM_ERROR("Can't hibernate while 3D resources are active.\n");
if (dev_priv->enable_fb)
vmw_fifo_resource_inc(dev_priv);
vmw_fifo_resource_inc(dev_priv);
WARN_ON(vmw_request_device_late(dev_priv));
dev_priv->suspend_locked = false;
if (dev_priv->suspend_state)
vmw_kms_resume(dev);
if (dev_priv->enable_fb)
vmw_fb_on(dev_priv);
return -EBUSY;
}
@@ -1566,24 +1534,19 @@ static int vmw_pm_restore(struct device *kdev)
vmw_detect_version(dev_priv);
if (dev_priv->enable_fb)
vmw_fifo_resource_inc(dev_priv);
vmw_fifo_resource_inc(dev_priv);
ret = vmw_request_device(dev_priv);
if (ret)
return ret;
if (dev_priv->enable_fb)
__vmw_svga_enable(dev_priv);
__vmw_svga_enable(dev_priv);
vmw_fence_fifo_up(dev_priv->fman);
dev_priv->suspend_locked = false;
if (dev_priv->suspend_state)
vmw_kms_resume(&dev_priv->drm);
if (dev_priv->enable_fb)
vmw_fb_on(dev_priv);
return 0;
}
@@ -1674,6 +1637,10 @@ static int vmw_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
if (ret)
goto out_unload;
vmw_fifo_resource_inc(vmw);
vmw_svga_enable(vmw);
drm_fbdev_generic_setup(&vmw->drm, 0);
vmw_debugfs_gem_init(vmw);
vmw_debugfs_resource_managers_init(vmw);

View File

@@ -62,6 +62,9 @@
#define VMWGFX_MAX_DISPLAYS 16
#define VMWGFX_CMD_BOUNCE_INIT_SIZE 32768
#define VMWGFX_MIN_INITIAL_WIDTH 1280
#define VMWGFX_MIN_INITIAL_HEIGHT 800
#define VMWGFX_PCI_ID_SVGA2 0x0405
#define VMWGFX_PCI_ID_SVGA3 0x0406
@@ -551,7 +554,6 @@ struct vmw_private {
* Framebuffer info.
*/
void *fb_info;
enum vmw_display_unit_type active_display_unit;
struct vmw_legacy_display *ldu_priv;
struct vmw_overlay *overlay_priv;
@@ -610,8 +612,6 @@ struct vmw_private {
struct mutex cmdbuf_mutex;
struct mutex binding_mutex;
bool enable_fb;
/**
* PM management.
*/
@@ -1178,35 +1178,6 @@ extern void vmw_generic_waiter_add(struct vmw_private *dev_priv, u32 flag,
extern void vmw_generic_waiter_remove(struct vmw_private *dev_priv,
u32 flag, int *waiter_count);
/**
* Kernel framebuffer - vmwgfx_fb.c
*/
#ifdef CONFIG_DRM_FBDEV_EMULATION
int vmw_fb_init(struct vmw_private *vmw_priv);
int vmw_fb_close(struct vmw_private *dev_priv);
int vmw_fb_off(struct vmw_private *vmw_priv);
int vmw_fb_on(struct vmw_private *vmw_priv);
#else
static inline int vmw_fb_init(struct vmw_private *vmw_priv)
{
return 0;
}
static inline int vmw_fb_close(struct vmw_private *dev_priv)
{
return 0;
}
static inline int vmw_fb_off(struct vmw_private *vmw_priv)
{
return 0;
}
static inline int vmw_fb_on(struct vmw_private *vmw_priv)
{
return 0;
}
#endif
/**
* Kernel modesetting - vmwgfx_kms.c
*/
@@ -1223,9 +1194,6 @@ void vmw_kms_cursor_snoop(struct vmw_surface *srf,
int vmw_kms_write_svga(struct vmw_private *vmw_priv,
unsigned width, unsigned height, unsigned pitch,
unsigned bpp, unsigned depth);
bool vmw_kms_validate_mode_vram(struct vmw_private *dev_priv,
uint32_t pitch,
uint32_t height);
int vmw_kms_present(struct vmw_private *dev_priv,
struct drm_file *file_priv,
struct vmw_framebuffer *vfb,

View File

@@ -1,831 +0,0 @@
/**************************************************************************
*
* Copyright © 2007 David Airlie
* Copyright © 2009-2015 VMware, Inc., Palo Alto, CA., USA
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
* THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
* USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
#include <linux/fb.h>
#include <linux/pci.h>
#include <drm/drm_fourcc.h>
#include <drm/ttm/ttm_placement.h>
#include "vmwgfx_drv.h"
#include "vmwgfx_kms.h"
#define VMW_DIRTY_DELAY (HZ / 30)
struct vmw_fb_par {
struct vmw_private *vmw_priv;
void *vmalloc;
struct mutex bo_mutex;
struct vmw_buffer_object *vmw_bo;
unsigned bo_size;
struct drm_framebuffer *set_fb;
struct drm_display_mode *set_mode;
u32 fb_x;
u32 fb_y;
bool bo_iowrite;
u32 pseudo_palette[17];
unsigned max_width;
unsigned max_height;
struct {
spinlock_t lock;
bool active;
unsigned x1;
unsigned y1;
unsigned x2;
unsigned y2;
} dirty;
struct drm_crtc *crtc;
struct drm_connector *con;
struct delayed_work local_work;
};
static int vmw_fb_setcolreg(unsigned regno, unsigned red, unsigned green,
unsigned blue, unsigned transp,
struct fb_info *info)
{
struct vmw_fb_par *par = info->par;
u32 *pal = par->pseudo_palette;
if (regno > 15) {
DRM_ERROR("Bad regno %u.\n", regno);
return 1;
}
switch (par->set_fb->format->depth) {
case 24:
case 32:
pal[regno] = ((red & 0xff00) << 8) |
(green & 0xff00) |
((blue & 0xff00) >> 8);
break;
default:
DRM_ERROR("Bad depth %u, bpp %u.\n",
par->set_fb->format->depth,
par->set_fb->format->cpp[0] * 8);
return 1;
}
return 0;
}
static int vmw_fb_check_var(struct fb_var_screeninfo *var,
struct fb_info *info)
{
int depth = var->bits_per_pixel;
struct vmw_fb_par *par = info->par;
struct vmw_private *vmw_priv = par->vmw_priv;
switch (var->bits_per_pixel) {
case 32:
depth = (var->transp.length > 0) ? 32 : 24;
break;
default:
DRM_ERROR("Bad bpp %u.\n", var->bits_per_pixel);
return -EINVAL;
}
switch (depth) {
case 24:
var->red.offset = 16;
var->green.offset = 8;
var->blue.offset = 0;
var->red.length = 8;
var->green.length = 8;
var->blue.length = 8;
var->transp.length = 0;
var->transp.offset = 0;
break;
case 32:
var->red.offset = 16;
var->green.offset = 8;
var->blue.offset = 0;
var->red.length = 8;
var->green.length = 8;
var->blue.length = 8;
var->transp.length = 8;
var->transp.offset = 24;
break;
default:
DRM_ERROR("Bad depth %u.\n", depth);
return -EINVAL;
}
if ((var->xoffset + var->xres) > par->max_width ||
(var->yoffset + var->yres) > par->max_height) {
DRM_ERROR("Requested geom can not fit in framebuffer\n");
return -EINVAL;
}
if (!vmw_kms_validate_mode_vram(vmw_priv,
var->xres * var->bits_per_pixel/8,
var->yoffset + var->yres)) {
DRM_ERROR("Requested geom can not fit in framebuffer\n");
return -EINVAL;
}
return 0;
}
static int vmw_fb_blank(int blank, struct fb_info *info)
{
return 0;
}
/**
* vmw_fb_dirty_flush - flush dirty regions to the kms framebuffer
*
* @work: The struct work_struct associated with this task.
*
* This function flushes the dirty regions of the vmalloc framebuffer to the
* kms framebuffer, and if the kms framebuffer is visible, also updated the
* corresponding displays. Note that this function runs even if the kms
* framebuffer is not bound to a crtc and thus not visible, but it's turned
* off during hibernation using the par->dirty.active bool.
*/
static void vmw_fb_dirty_flush(struct work_struct *work)
{
struct vmw_fb_par *par = container_of(work, struct vmw_fb_par,
local_work.work);
struct vmw_private *vmw_priv = par->vmw_priv;
struct fb_info *info = vmw_priv->fb_info;
unsigned long irq_flags;
s32 dst_x1, dst_x2, dst_y1, dst_y2, w = 0, h = 0;
u32 cpp, max_x, max_y;
struct drm_clip_rect clip;
struct drm_framebuffer *cur_fb;
u8 *src_ptr, *dst_ptr;
struct vmw_buffer_object *vbo = par->vmw_bo;
void *virtual;
if (!READ_ONCE(par->dirty.active))
return;
mutex_lock(&par->bo_mutex);
cur_fb = par->set_fb;
if (!cur_fb)
goto out_unlock;
(void) ttm_bo_reserve(&vbo->base, false, false, NULL);
virtual = vmw_bo_map_and_cache(vbo);
if (!virtual)
goto out_unreserve;
spin_lock_irqsave(&par->dirty.lock, irq_flags);
if (!par->dirty.active) {
spin_unlock_irqrestore(&par->dirty.lock, irq_flags);
goto out_unreserve;
}
/*
* Handle panning when copying from vmalloc to framebuffer.
* Clip dirty area to framebuffer.
*/
cpp = cur_fb->format->cpp[0];
max_x = par->fb_x + cur_fb->width;
max_y = par->fb_y + cur_fb->height;
dst_x1 = par->dirty.x1 - par->fb_x;
dst_y1 = par->dirty.y1 - par->fb_y;
dst_x1 = max_t(s32, dst_x1, 0);
dst_y1 = max_t(s32, dst_y1, 0);
dst_x2 = par->dirty.x2 - par->fb_x;
dst_y2 = par->dirty.y2 - par->fb_y;
dst_x2 = min_t(s32, dst_x2, max_x);
dst_y2 = min_t(s32, dst_y2, max_y);
w = dst_x2 - dst_x1;
h = dst_y2 - dst_y1;
w = max_t(s32, 0, w);
h = max_t(s32, 0, h);
par->dirty.x1 = par->dirty.x2 = 0;
par->dirty.y1 = par->dirty.y2 = 0;
spin_unlock_irqrestore(&par->dirty.lock, irq_flags);
if (w && h) {
dst_ptr = (u8 *)virtual +
(dst_y1 * par->set_fb->pitches[0] + dst_x1 * cpp);
src_ptr = (u8 *)par->vmalloc +
((dst_y1 + par->fb_y) * info->fix.line_length +
(dst_x1 + par->fb_x) * cpp);
while (h-- > 0) {
memcpy(dst_ptr, src_ptr, w*cpp);
dst_ptr += par->set_fb->pitches[0];
src_ptr += info->fix.line_length;
}
clip.x1 = dst_x1;
clip.x2 = dst_x2;
clip.y1 = dst_y1;
clip.y2 = dst_y2;
}
out_unreserve:
ttm_bo_unreserve(&vbo->base);
if (w && h) {
WARN_ON_ONCE(par->set_fb->funcs->dirty(cur_fb, NULL, 0, 0,
&clip, 1));
vmw_cmd_flush(vmw_priv, false);
}
out_unlock:
mutex_unlock(&par->bo_mutex);
}
static void vmw_fb_dirty_mark(struct vmw_fb_par *par,
unsigned x1, unsigned y1,
unsigned width, unsigned height)
{
unsigned long flags;
unsigned x2 = x1 + width;
unsigned y2 = y1 + height;
spin_lock_irqsave(&par->dirty.lock, flags);
if (par->dirty.x1 == par->dirty.x2) {
par->dirty.x1 = x1;
par->dirty.y1 = y1;
par->dirty.x2 = x2;
par->dirty.y2 = y2;
/* if we are active start the dirty work
* we share the work with the defio system */
if (par->dirty.active)
schedule_delayed_work(&par->local_work,
VMW_DIRTY_DELAY);
} else {
if (x1 < par->dirty.x1)
par->dirty.x1 = x1;
if (y1 < par->dirty.y1)
par->dirty.y1 = y1;
if (x2 > par->dirty.x2)
par->dirty.x2 = x2;
if (y2 > par->dirty.y2)
par->dirty.y2 = y2;
}
spin_unlock_irqrestore(&par->dirty.lock, flags);
}
static int vmw_fb_pan_display(struct fb_var_screeninfo *var,
struct fb_info *info)
{
struct vmw_fb_par *par = info->par;
if ((var->xoffset + var->xres) > var->xres_virtual ||
(var->yoffset + var->yres) > var->yres_virtual) {
DRM_ERROR("Requested panning can not fit in framebuffer\n");
return -EINVAL;
}
mutex_lock(&par->bo_mutex);
par->fb_x = var->xoffset;
par->fb_y = var->yoffset;
if (par->set_fb)
vmw_fb_dirty_mark(par, par->fb_x, par->fb_y, par->set_fb->width,
par->set_fb->height);
mutex_unlock(&par->bo_mutex);
return 0;
}
static void vmw_deferred_io(struct fb_info *info, struct list_head *pagereflist)
{
struct vmw_fb_par *par = info->par;
unsigned long start, end, min, max;
unsigned long flags;
struct fb_deferred_io_pageref *pageref;
int y1, y2;
min = ULONG_MAX;
max = 0;
list_for_each_entry(pageref, pagereflist, list) {
start = pageref->offset;
end = start + PAGE_SIZE - 1;
min = min(min, start);
max = max(max, end);
}
if (min < max) {
y1 = min / info->fix.line_length;
y2 = (max / info->fix.line_length) + 1;
spin_lock_irqsave(&par->dirty.lock, flags);
par->dirty.x1 = 0;
par->dirty.y1 = y1;
par->dirty.x2 = info->var.xres;
par->dirty.y2 = y2;
spin_unlock_irqrestore(&par->dirty.lock, flags);
/*
* Since we've already waited on this work once, try to
* execute asap.
*/
cancel_delayed_work(&par->local_work);
schedule_delayed_work(&par->local_work, 0);
}
};
static struct fb_deferred_io vmw_defio = {
.delay = VMW_DIRTY_DELAY,
.deferred_io = vmw_deferred_io,
};
/*
* Draw code
*/
static void vmw_fb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
{
cfb_fillrect(info, rect);
vmw_fb_dirty_mark(info->par, rect->dx, rect->dy,
rect->width, rect->height);
}
static void vmw_fb_copyarea(struct fb_info *info, const struct fb_copyarea *region)
{
cfb_copyarea(info, region);
vmw_fb_dirty_mark(info->par, region->dx, region->dy,
region->width, region->height);
}
static void vmw_fb_imageblit(struct fb_info *info, const struct fb_image *image)
{
cfb_imageblit(info, image);
vmw_fb_dirty_mark(info->par, image->dx, image->dy,
image->width, image->height);
}
/*
* Bring up code
*/
static int vmw_fb_create_bo(struct vmw_private *vmw_priv,
size_t size, struct vmw_buffer_object **out)
{
struct vmw_buffer_object *vmw_bo;
int ret;
ret = vmw_bo_create(vmw_priv, size,
&vmw_sys_placement,
false, false,
&vmw_bo_bo_free, &vmw_bo);
if (unlikely(ret != 0))
return ret;
*out = vmw_bo;
return ret;
}
static int vmw_fb_compute_depth(struct fb_var_screeninfo *var,
int *depth)
{
switch (var->bits_per_pixel) {
case 32:
*depth = (var->transp.length > 0) ? 32 : 24;
break;
default:
DRM_ERROR("Bad bpp %u.\n", var->bits_per_pixel);
return -EINVAL;
}
return 0;
}
static int vmwgfx_set_config_internal(struct drm_mode_set *set)
{
struct drm_crtc *crtc = set->crtc;
struct drm_modeset_acquire_ctx ctx;
int ret;
drm_modeset_acquire_init(&ctx, 0);
restart:
ret = crtc->funcs->set_config(set, &ctx);
if (ret == -EDEADLK) {
drm_modeset_backoff(&ctx);
goto restart;
}
drm_modeset_drop_locks(&ctx);
drm_modeset_acquire_fini(&ctx);
return ret;
}
static int vmw_fb_kms_detach(struct vmw_fb_par *par,
bool detach_bo,
bool unref_bo)
{
struct drm_framebuffer *cur_fb = par->set_fb;
int ret;
/* Detach the KMS framebuffer from crtcs */
if (par->set_mode) {
struct drm_mode_set set;
set.crtc = par->crtc;
set.x = 0;
set.y = 0;
set.mode = NULL;
set.fb = NULL;
set.num_connectors = 0;
set.connectors = &par->con;
ret = vmwgfx_set_config_internal(&set);
if (ret) {
DRM_ERROR("Could not unset a mode.\n");
return ret;
}
drm_mode_destroy(&par->vmw_priv->drm, par->set_mode);
par->set_mode = NULL;
}
if (cur_fb) {
drm_framebuffer_put(cur_fb);
par->set_fb = NULL;
}
if (par->vmw_bo && detach_bo && unref_bo)
vmw_bo_unreference(&par->vmw_bo);
return 0;
}
static int vmw_fb_kms_framebuffer(struct fb_info *info)
{
struct drm_mode_fb_cmd2 mode_cmd = {0};
struct vmw_fb_par *par = info->par;
struct fb_var_screeninfo *var = &info->var;
struct drm_framebuffer *cur_fb;
struct vmw_framebuffer *vfb;
int ret = 0, depth;
size_t new_bo_size;
ret = vmw_fb_compute_depth(var, &depth);
if (ret)
return ret;
mode_cmd.width = var->xres;
mode_cmd.height = var->yres;
mode_cmd.pitches[0] = ((var->bits_per_pixel + 7) / 8) * mode_cmd.width;
mode_cmd.pixel_format =
drm_mode_legacy_fb_format(var->bits_per_pixel, depth);
cur_fb = par->set_fb;
if (cur_fb && cur_fb->width == mode_cmd.width &&
cur_fb->height == mode_cmd.height &&
cur_fb->format->format == mode_cmd.pixel_format &&
cur_fb->pitches[0] == mode_cmd.pitches[0])
return 0;
/* Need new buffer object ? */
new_bo_size = (size_t) mode_cmd.pitches[0] * (size_t) mode_cmd.height;
ret = vmw_fb_kms_detach(par,
par->bo_size < new_bo_size ||
par->bo_size > 2*new_bo_size,
true);
if (ret)
return ret;
if (!par->vmw_bo) {
ret = vmw_fb_create_bo(par->vmw_priv, new_bo_size,
&par->vmw_bo);
if (ret) {
DRM_ERROR("Failed creating a buffer object for "
"fbdev.\n");
return ret;
}
par->bo_size = new_bo_size;
}
vfb = vmw_kms_new_framebuffer(par->vmw_priv, par->vmw_bo, NULL,
true, &mode_cmd);
if (IS_ERR(vfb))
return PTR_ERR(vfb);
par->set_fb = &vfb->base;
return 0;
}
static int vmw_fb_set_par(struct fb_info *info)
{
struct vmw_fb_par *par = info->par;
struct vmw_private *vmw_priv = par->vmw_priv;
struct drm_mode_set set;
struct fb_var_screeninfo *var = &info->var;
struct drm_display_mode new_mode = { DRM_MODE("fb_mode",
DRM_MODE_TYPE_DRIVER,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC)
};
struct drm_display_mode *mode;
int ret;
mode = drm_mode_duplicate(&vmw_priv->drm, &new_mode);
if (!mode) {
DRM_ERROR("Could not create new fb mode.\n");
return -ENOMEM;
}
mode->hdisplay = var->xres;
mode->vdisplay = var->yres;
vmw_guess_mode_timing(mode);
if (!vmw_kms_validate_mode_vram(vmw_priv,
mode->hdisplay *
DIV_ROUND_UP(var->bits_per_pixel, 8),
mode->vdisplay)) {
drm_mode_destroy(&vmw_priv->drm, mode);
return -EINVAL;
}
mutex_lock(&par->bo_mutex);
ret = vmw_fb_kms_framebuffer(info);
if (ret)
goto out_unlock;
par->fb_x = var->xoffset;
par->fb_y = var->yoffset;
set.crtc = par->crtc;
set.x = 0;
set.y = 0;
set.mode = mode;
set.fb = par->set_fb;
set.num_connectors = 1;
set.connectors = &par->con;
ret = vmwgfx_set_config_internal(&set);
if (ret)
goto out_unlock;
vmw_fb_dirty_mark(par, par->fb_x, par->fb_y,
par->set_fb->width, par->set_fb->height);
/* If there already was stuff dirty we wont
* schedule a new work, so lets do it now */
schedule_delayed_work(&par->local_work, 0);
out_unlock:
if (par->set_mode)
drm_mode_destroy(&vmw_priv->drm, par->set_mode);
par->set_mode = mode;
mutex_unlock(&par->bo_mutex);
return ret;
}
static const struct fb_ops vmw_fb_ops = {
.owner = THIS_MODULE,
.fb_check_var = vmw_fb_check_var,
.fb_set_par = vmw_fb_set_par,
.fb_setcolreg = vmw_fb_setcolreg,
.fb_fillrect = vmw_fb_fillrect,
.fb_copyarea = vmw_fb_copyarea,
.fb_imageblit = vmw_fb_imageblit,
.fb_pan_display = vmw_fb_pan_display,
.fb_blank = vmw_fb_blank,
.fb_mmap = fb_deferred_io_mmap,
};
int vmw_fb_init(struct vmw_private *vmw_priv)
{
struct device *device = vmw_priv->drm.dev;
struct vmw_fb_par *par;
struct fb_info *info;
unsigned fb_width, fb_height;
unsigned int fb_bpp, fb_pitch, fb_size;
struct drm_display_mode *init_mode;
int ret;
fb_bpp = 32;
/* XXX As shouldn't these be as well. */
fb_width = min(vmw_priv->fb_max_width, (unsigned)2048);
fb_height = min(vmw_priv->fb_max_height, (unsigned)2048);
fb_pitch = fb_width * fb_bpp / 8;
fb_size = fb_pitch * fb_height;
info = framebuffer_alloc(sizeof(*par), device);
if (!info)
return -ENOMEM;
/*
* Par
*/
vmw_priv->fb_info = info;
par = info->par;
memset(par, 0, sizeof(*par));
INIT_DELAYED_WORK(&par->local_work, &vmw_fb_dirty_flush);
par->vmw_priv = vmw_priv;
par->vmalloc = NULL;
par->max_width = fb_width;
par->max_height = fb_height;
ret = vmw_kms_fbdev_init_data(vmw_priv, 0, par->max_width,
par->max_height, &par->con,
&par->crtc, &init_mode);
if (ret)
goto err_kms;
info->var.xres = init_mode->hdisplay;
info->var.yres = init_mode->vdisplay;
/*
* Create buffers and alloc memory
*/
par->vmalloc = vzalloc(fb_size);
if (unlikely(par->vmalloc == NULL)) {
ret = -ENOMEM;
goto err_free;
}
/*
* Fixed and var
*/
strcpy(info->fix.id, "svgadrmfb");
info->fix.type = FB_TYPE_PACKED_PIXELS;
info->fix.visual = FB_VISUAL_TRUECOLOR;
info->fix.type_aux = 0;
info->fix.xpanstep = 1; /* doing it in hw */
info->fix.ypanstep = 1; /* doing it in hw */
info->fix.ywrapstep = 0;
info->fix.accel = FB_ACCEL_NONE;
info->fix.line_length = fb_pitch;
info->fix.smem_start = 0;
info->fix.smem_len = fb_size;
info->pseudo_palette = par->pseudo_palette;
info->screen_base = (char __iomem *)par->vmalloc;
info->screen_size = fb_size;
info->fbops = &vmw_fb_ops;
/* 24 depth per default */
info->var.red.offset = 16;
info->var.green.offset = 8;
info->var.blue.offset = 0;
info->var.red.length = 8;
info->var.green.length = 8;
info->var.blue.length = 8;
info->var.transp.offset = 0;
info->var.transp.length = 0;
info->var.xres_virtual = fb_width;
info->var.yres_virtual = fb_height;
info->var.bits_per_pixel = fb_bpp;
info->var.xoffset = 0;
info->var.yoffset = 0;
info->var.activate = FB_ACTIVATE_NOW;
info->var.height = -1;
info->var.width = -1;
/* Use default scratch pixmap (info->pixmap.flags = FB_PIXMAP_SYSTEM) */
info->apertures = alloc_apertures(1);
if (!info->apertures) {
ret = -ENOMEM;
goto err_aper;
}
info->apertures->ranges[0].base = vmw_priv->vram_start;
info->apertures->ranges[0].size = vmw_priv->vram_size;
/*
* Dirty & Deferred IO
*/
par->dirty.x1 = par->dirty.x2 = 0;
par->dirty.y1 = par->dirty.y2 = 0;
par->dirty.active = true;
spin_lock_init(&par->dirty.lock);
mutex_init(&par->bo_mutex);
info->fbdefio = &vmw_defio;
fb_deferred_io_init(info);
ret = register_framebuffer(info);
if (unlikely(ret != 0))
goto err_defio;
vmw_fb_set_par(info);
return 0;
err_defio:
fb_deferred_io_cleanup(info);
err_aper:
err_free:
vfree(par->vmalloc);
err_kms:
framebuffer_release(info);
vmw_priv->fb_info = NULL;
return ret;
}
int vmw_fb_close(struct vmw_private *vmw_priv)
{
struct fb_info *info;
struct vmw_fb_par *par;
if (!vmw_priv->fb_info)
return 0;
info = vmw_priv->fb_info;
par = info->par;
/* ??? order */
fb_deferred_io_cleanup(info);
cancel_delayed_work_sync(&par->local_work);
unregister_framebuffer(info);
mutex_lock(&par->bo_mutex);
(void) vmw_fb_kms_detach(par, true, true);
mutex_unlock(&par->bo_mutex);
vfree(par->vmalloc);
framebuffer_release(info);
return 0;
}
int vmw_fb_off(struct vmw_private *vmw_priv)
{
struct fb_info *info;
struct vmw_fb_par *par;
unsigned long flags;
if (!vmw_priv->fb_info)
return -EINVAL;
info = vmw_priv->fb_info;
par = info->par;
spin_lock_irqsave(&par->dirty.lock, flags);
par->dirty.active = false;
spin_unlock_irqrestore(&par->dirty.lock, flags);
flush_delayed_work(&info->deferred_work);
flush_delayed_work(&par->local_work);
return 0;
}
int vmw_fb_on(struct vmw_private *vmw_priv)
{
struct fb_info *info;
struct vmw_fb_par *par;
unsigned long flags;
if (!vmw_priv->fb_info)
return -EINVAL;
info = vmw_priv->fb_info;
par = info->par;
spin_lock_irqsave(&par->dirty.lock, flags);
par->dirty.active = true;
spin_unlock_irqrestore(&par->dirty.lock, flags);
/*
* Need to reschedule a dirty update, because otherwise that's
* only done in dirty_mark() if the previous coalesced
* dirty region was empty.
*/
schedule_delayed_work(&par->local_work, 0);
return 0;
}

View File

@@ -31,6 +31,7 @@
#include <drm/drm_fourcc.h>
#include <drm/drm_rect.h>
#include <drm/drm_sysfs.h>
#include <drm/drm_edid.h>
#include "vmwgfx_kms.h"
@@ -1988,6 +1989,8 @@ int vmw_kms_init(struct vmw_private *dev_priv)
dev->mode_config.min_height = 1;
dev->mode_config.max_width = dev_priv->texture_max_width;
dev->mode_config.max_height = dev_priv->texture_max_height;
dev->mode_config.preferred_depth = dev_priv->assume_16bpp ? 16 : 32;
dev->mode_config.prefer_shadow_fbdev = !dev_priv->has_mob;
drm_mode_create_suggested_offset_properties(dev);
vmw_kms_create_hotplug_mode_update_property(dev_priv);
@@ -2082,13 +2085,12 @@ int vmw_kms_write_svga(struct vmw_private *vmw_priv,
return 0;
}
static
bool vmw_kms_validate_mode_vram(struct vmw_private *dev_priv,
uint32_t pitch,
uint32_t height)
u64 pitch,
u64 height)
{
return ((u64) pitch * (u64) height) < (u64)
((dev_priv->active_display_unit == vmw_du_screen_target) ?
dev_priv->max_primary_mem : dev_priv->vram_size);
return (pitch * height) < (u64)dev_priv->vram_size;
}
/**
@@ -2134,8 +2136,8 @@ retry:
du->gui_x = rects[du->unit].x1;
du->gui_y = rects[du->unit].y1;
} else {
du->pref_width = 800;
du->pref_height = 600;
du->pref_width = VMWGFX_MIN_INITIAL_WIDTH;
du->pref_height = VMWGFX_MIN_INITIAL_HEIGHT;
du->pref_active = false;
du->gui_x = 0;
du->gui_y = 0;
@@ -2162,13 +2164,13 @@ retry:
}
con->status = vmw_du_connector_detect(con, true);
}
drm_sysfs_hotplug_event(dev);
out_fini:
drm_modeset_drop_locks(&ctx);
drm_modeset_acquire_fini(&ctx);
mutex_unlock(&dev->mode_config.mutex);
drm_sysfs_hotplug_event(dev);
return 0;
}
@@ -2211,107 +2213,6 @@ vmw_du_connector_detect(struct drm_connector *connector, bool force)
connector_status_connected : connector_status_disconnected);
}
static struct drm_display_mode vmw_kms_connector_builtin[] = {
/* 640x480@60Hz */
{ DRM_MODE("640x480", DRM_MODE_TYPE_DRIVER, 25175, 640, 656,
752, 800, 0, 480, 489, 492, 525, 0,
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) },
/* 800x600@60Hz */
{ DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 40000, 800, 840,
968, 1056, 0, 600, 601, 605, 628, 0,
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
/* 1024x768@60Hz */
{ DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 65000, 1024, 1048,
1184, 1344, 0, 768, 771, 777, 806, 0,
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) },
/* 1152x864@75Hz */
{ DRM_MODE("1152x864", DRM_MODE_TYPE_DRIVER, 108000, 1152, 1216,
1344, 1600, 0, 864, 865, 868, 900, 0,
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
/* 1280x720@60Hz */
{ DRM_MODE("1280x720", DRM_MODE_TYPE_DRIVER, 74500, 1280, 1344,
1472, 1664, 0, 720, 723, 728, 748, 0,
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
/* 1280x768@60Hz */
{ DRM_MODE("1280x768", DRM_MODE_TYPE_DRIVER, 79500, 1280, 1344,
1472, 1664, 0, 768, 771, 778, 798, 0,
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
/* 1280x800@60Hz */
{ DRM_MODE("1280x800", DRM_MODE_TYPE_DRIVER, 83500, 1280, 1352,
1480, 1680, 0, 800, 803, 809, 831, 0,
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) },
/* 1280x960@60Hz */
{ DRM_MODE("1280x960", DRM_MODE_TYPE_DRIVER, 108000, 1280, 1376,
1488, 1800, 0, 960, 961, 964, 1000, 0,
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
/* 1280x1024@60Hz */
{ DRM_MODE("1280x1024", DRM_MODE_TYPE_DRIVER, 108000, 1280, 1328,
1440, 1688, 0, 1024, 1025, 1028, 1066, 0,
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
/* 1360x768@60Hz */
{ DRM_MODE("1360x768", DRM_MODE_TYPE_DRIVER, 85500, 1360, 1424,
1536, 1792, 0, 768, 771, 777, 795, 0,
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
/* 1440x1050@60Hz */
{ DRM_MODE("1400x1050", DRM_MODE_TYPE_DRIVER, 121750, 1400, 1488,
1632, 1864, 0, 1050, 1053, 1057, 1089, 0,
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
/* 1440x900@60Hz */
{ DRM_MODE("1440x900", DRM_MODE_TYPE_DRIVER, 106500, 1440, 1520,
1672, 1904, 0, 900, 903, 909, 934, 0,
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
/* 1600x1200@60Hz */
{ DRM_MODE("1600x1200", DRM_MODE_TYPE_DRIVER, 162000, 1600, 1664,
1856, 2160, 0, 1200, 1201, 1204, 1250, 0,
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
/* 1680x1050@60Hz */
{ DRM_MODE("1680x1050", DRM_MODE_TYPE_DRIVER, 146250, 1680, 1784,
1960, 2240, 0, 1050, 1053, 1059, 1089, 0,
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
/* 1792x1344@60Hz */
{ DRM_MODE("1792x1344", DRM_MODE_TYPE_DRIVER, 204750, 1792, 1920,
2120, 2448, 0, 1344, 1345, 1348, 1394, 0,
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
/* 1853x1392@60Hz */
{ DRM_MODE("1856x1392", DRM_MODE_TYPE_DRIVER, 218250, 1856, 1952,
2176, 2528, 0, 1392, 1393, 1396, 1439, 0,
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
/* 1920x1080@60Hz */
{ DRM_MODE("1920x1080", DRM_MODE_TYPE_DRIVER, 173000, 1920, 2048,
2248, 2576, 0, 1080, 1083, 1088, 1120, 0,
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
/* 1920x1200@60Hz */
{ DRM_MODE("1920x1200", DRM_MODE_TYPE_DRIVER, 193250, 1920, 2056,
2256, 2592, 0, 1200, 1203, 1209, 1245, 0,
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
/* 1920x1440@60Hz */
{ DRM_MODE("1920x1440", DRM_MODE_TYPE_DRIVER, 234000, 1920, 2048,
2256, 2600, 0, 1440, 1441, 1444, 1500, 0,
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
/* 2560x1440@60Hz */
{ DRM_MODE("2560x1440", DRM_MODE_TYPE_DRIVER, 241500, 2560, 2608,
2640, 2720, 0, 1440, 1443, 1448, 1481, 0,
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) },
/* 2560x1600@60Hz */
{ DRM_MODE("2560x1600", DRM_MODE_TYPE_DRIVER, 348500, 2560, 2752,
3032, 3504, 0, 1600, 1603, 1609, 1658, 0,
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) },
/* 2880x1800@60Hz */
{ DRM_MODE("2880x1800", DRM_MODE_TYPE_DRIVER, 337500, 2880, 2928,
2960, 3040, 0, 1800, 1803, 1809, 1852, 0,
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) },
/* 3840x2160@60Hz */
{ DRM_MODE("3840x2160", DRM_MODE_TYPE_DRIVER, 533000, 3840, 3888,
3920, 4000, 0, 2160, 2163, 2168, 2222, 0,
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) },
/* 3840x2400@60Hz */
{ DRM_MODE("3840x2400", DRM_MODE_TYPE_DRIVER, 592250, 3840, 3888,
3920, 4000, 0, 2400, 2403, 2409, 2469, 0,
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) },
/* Terminate */
{ DRM_MODE("", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) },
};
/**
* vmw_guess_mode_timing - Provide fake timings for a
* 60Hz vrefresh mode.
@@ -2333,88 +2234,6 @@ void vmw_guess_mode_timing(struct drm_display_mode *mode)
}
int vmw_du_connector_fill_modes(struct drm_connector *connector,
uint32_t max_width, uint32_t max_height)
{
struct vmw_display_unit *du = vmw_connector_to_du(connector);
struct drm_device *dev = connector->dev;
struct vmw_private *dev_priv = vmw_priv(dev);
struct drm_display_mode *mode = NULL;
struct drm_display_mode *bmode;
struct drm_display_mode prefmode = { DRM_MODE("preferred",
DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC)
};
int i;
u32 assumed_bpp = 4;
if (dev_priv->assume_16bpp)
assumed_bpp = 2;
max_width = min(max_width, dev_priv->texture_max_width);
max_height = min(max_height, dev_priv->texture_max_height);
/*
* For STDU extra limit for a mode on SVGA_REG_SCREENTARGET_MAX_WIDTH/
* HEIGHT registers.
*/
if (dev_priv->active_display_unit == vmw_du_screen_target) {
max_width = min(max_width, dev_priv->stdu_max_width);
max_height = min(max_height, dev_priv->stdu_max_height);
}
/* Add preferred mode */
mode = drm_mode_duplicate(dev, &prefmode);
if (!mode)
return 0;
mode->hdisplay = du->pref_width;
mode->vdisplay = du->pref_height;
vmw_guess_mode_timing(mode);
drm_mode_set_name(mode);
if (vmw_kms_validate_mode_vram(dev_priv,
mode->hdisplay * assumed_bpp,
mode->vdisplay)) {
drm_mode_probed_add(connector, mode);
} else {
drm_mode_destroy(dev, mode);
mode = NULL;
}
if (du->pref_mode) {
list_del_init(&du->pref_mode->head);
drm_mode_destroy(dev, du->pref_mode);
}
/* mode might be null here, this is intended */
du->pref_mode = mode;
for (i = 0; vmw_kms_connector_builtin[i].type != 0; i++) {
bmode = &vmw_kms_connector_builtin[i];
if (bmode->hdisplay > max_width ||
bmode->vdisplay > max_height)
continue;
if (!vmw_kms_validate_mode_vram(dev_priv,
bmode->hdisplay * assumed_bpp,
bmode->vdisplay))
continue;
mode = drm_mode_duplicate(dev, bmode);
if (!mode)
return 0;
drm_mode_probed_add(connector, mode);
}
drm_connector_list_update(connector);
/* Move the prefered mode first, help apps pick the right mode. */
drm_mode_sort(&connector->modes);
return 1;
}
/**
* vmw_kms_update_layout_ioctl - Handler for DRM_VMW_UPDATE_LAYOUT ioctl
* @dev: drm device for the ioctl
@@ -2448,10 +2267,9 @@ int vmw_kms_update_layout_ioctl(struct drm_device *dev, void *data,
int ret, i;
if (!arg->num_outputs) {
struct drm_rect def_rect = {0, 0, 800, 600};
VMW_DEBUG_KMS("Default layout x1 = %d y1 = %d x2 = %d y2 = %d\n",
def_rect.x1, def_rect.y1,
def_rect.x2, def_rect.y2);
struct drm_rect def_rect = {0, 0,
VMWGFX_MIN_INITIAL_WIDTH,
VMWGFX_MIN_INITIAL_HEIGHT};
vmw_du_update_layout(dev_priv, 1, &def_rect);
return 0;
}
@@ -2746,68 +2564,6 @@ int vmw_kms_update_proxy(struct vmw_resource *res,
return 0;
}
int vmw_kms_fbdev_init_data(struct vmw_private *dev_priv,
unsigned unit,
u32 max_width,
u32 max_height,
struct drm_connector **p_con,
struct drm_crtc **p_crtc,
struct drm_display_mode **p_mode)
{
struct drm_connector *con;
struct vmw_display_unit *du;
struct drm_display_mode *mode;
int i = 0;
int ret = 0;
mutex_lock(&dev_priv->drm.mode_config.mutex);
list_for_each_entry(con, &dev_priv->drm.mode_config.connector_list,
head) {
if (i == unit)
break;
++i;
}
if (&con->head == &dev_priv->drm.mode_config.connector_list) {
DRM_ERROR("Could not find initial display unit.\n");
ret = -EINVAL;
goto out_unlock;
}
if (list_empty(&con->modes))
(void) vmw_du_connector_fill_modes(con, max_width, max_height);
if (list_empty(&con->modes)) {
DRM_ERROR("Could not find initial display mode.\n");
ret = -EINVAL;
goto out_unlock;
}
du = vmw_connector_to_du(con);
*p_con = con;
*p_crtc = &du->crtc;
list_for_each_entry(mode, &con->modes, head) {
if (mode->type & DRM_MODE_TYPE_PREFERRED)
break;
}
if (&mode->head == &con->modes) {
WARN_ONCE(true, "Could not find initial preferred mode.\n");
*p_mode = list_first_entry(&con->modes,
struct drm_display_mode,
head);
} else {
*p_mode = mode;
}
out_unlock:
mutex_unlock(&dev_priv->drm.mode_config.mutex);
return ret;
}
/**
* vmw_kms_create_implicit_placement_property - Set up the implicit placement
* property.
@@ -3006,3 +2762,84 @@ out_unref:
vmw_validation_unref_lists(&val_ctx);
return ret;
}
/**
* vmw_connector_mode_valid - implements drm_connector_helper_funcs.mode_valid callback
*
* @connector: the drm connector, part of a DU container
* @mode: drm mode to check
*
* Returns MODE_OK on success, or a drm_mode_status error code.
*/
enum drm_mode_status vmw_connector_mode_valid(struct drm_connector *connector,
struct drm_display_mode *mode)
{
enum drm_mode_status ret;
struct drm_device *dev = connector->dev;
struct vmw_private *dev_priv = vmw_priv(dev);
u32 assumed_cpp = 4;
if (dev_priv->assume_16bpp)
assumed_cpp = 2;
ret = drm_mode_validate_size(mode, dev_priv->texture_max_width,
dev_priv->texture_max_height);
if (ret != MODE_OK)
return ret;
if (!vmw_kms_validate_mode_vram(dev_priv,
mode->hdisplay * assumed_cpp,
mode->vdisplay))
return MODE_MEM;
return MODE_OK;
}
/**
* vmw_connector_get_modes - implements drm_connector_helper_funcs.get_modes callback
*
* @connector: the drm connector, part of a DU container
*
* Returns the number of added modes.
*/
int vmw_connector_get_modes(struct drm_connector *connector)
{
struct vmw_display_unit *du = vmw_connector_to_du(connector);
struct drm_device *dev = connector->dev;
struct vmw_private *dev_priv = vmw_priv(dev);
struct drm_display_mode *mode = NULL;
struct drm_display_mode prefmode = { DRM_MODE("preferred",
DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC)
};
u32 max_width;
u32 max_height;
u32 num_modes;
/* Add preferred mode */
mode = drm_mode_duplicate(dev, &prefmode);
if (!mode)
return 0;
mode->hdisplay = du->pref_width;
mode->vdisplay = du->pref_height;
vmw_guess_mode_timing(mode);
drm_mode_set_name(mode);
drm_mode_probed_add(connector, mode);
drm_dbg_kms(dev, "preferred mode " DRM_MODE_FMT "\n", DRM_MODE_ARG(mode));
/* Probe connector for all modes not exceeding our geom limits */
max_width = dev_priv->texture_max_width;
max_height = dev_priv->texture_max_height;
if (dev_priv->active_display_unit == vmw_du_screen_target) {
max_width = min(dev_priv->stdu_max_width, max_width);
max_height = min(dev_priv->stdu_max_height, max_height);
}
num_modes = 1 + drm_add_modes_noedid(connector, max_width, max_height);
return num_modes;
}

View File

@@ -379,7 +379,6 @@ struct vmw_display_unit {
unsigned pref_width;
unsigned pref_height;
bool pref_active;
struct drm_display_mode *pref_mode;
/*
* Gui positioning
@@ -429,8 +428,6 @@ void vmw_du_connector_save(struct drm_connector *connector);
void vmw_du_connector_restore(struct drm_connector *connector);
enum drm_connector_status
vmw_du_connector_detect(struct drm_connector *connector, bool force);
int vmw_du_connector_fill_modes(struct drm_connector *connector,
uint32_t max_width, uint32_t max_height);
int vmw_kms_helper_dirty(struct vmw_private *dev_priv,
struct vmw_framebuffer *framebuffer,
const struct drm_clip_rect *clips,
@@ -439,6 +436,9 @@ int vmw_kms_helper_dirty(struct vmw_private *dev_priv,
int num_clips,
int increment,
struct vmw_kms_dirty *dirty);
enum drm_mode_status vmw_connector_mode_valid(struct drm_connector *connector,
struct drm_display_mode *mode);
int vmw_connector_get_modes(struct drm_connector *connector);
void vmw_kms_helper_validation_finish(struct vmw_private *dev_priv,
struct drm_file *file_priv,
@@ -458,13 +458,6 @@ vmw_kms_new_framebuffer(struct vmw_private *dev_priv,
struct vmw_surface *surface,
bool only_2d,
const struct drm_mode_fb_cmd2 *mode_cmd);
int vmw_kms_fbdev_init_data(struct vmw_private *dev_priv,
unsigned unit,
u32 max_width,
u32 max_height,
struct drm_connector **p_con,
struct drm_crtc **p_crtc,
struct drm_display_mode **p_mode);
void vmw_guess_mode_timing(struct drm_display_mode *mode);
void vmw_kms_update_implicit_fb(struct vmw_private *dev_priv);
void vmw_kms_create_implicit_placement_property(struct vmw_private *dev_priv);

View File

@@ -263,7 +263,7 @@ static void vmw_ldu_connector_destroy(struct drm_connector *connector)
static const struct drm_connector_funcs vmw_legacy_connector_funcs = {
.dpms = vmw_du_connector_dpms,
.detect = vmw_du_connector_detect,
.fill_modes = vmw_du_connector_fill_modes,
.fill_modes = drm_helper_probe_single_connector_modes,
.destroy = vmw_ldu_connector_destroy,
.reset = vmw_du_connector_reset,
.atomic_duplicate_state = vmw_du_connector_duplicate_state,
@@ -272,6 +272,8 @@ static const struct drm_connector_funcs vmw_legacy_connector_funcs = {
static const struct
drm_connector_helper_funcs vmw_ldu_connector_helper_funcs = {
.get_modes = vmw_connector_get_modes,
.mode_valid = vmw_connector_mode_valid
};
static int vmw_kms_ldu_do_bo_dirty(struct vmw_private *dev_priv,
@@ -408,7 +410,6 @@ static int vmw_ldu_init(struct vmw_private *dev_priv, unsigned unit)
ldu->base.pref_active = (unit == 0);
ldu->base.pref_width = dev_priv->initial_width;
ldu->base.pref_height = dev_priv->initial_height;
ldu->base.pref_mode = NULL;
/*
* Remove this after enabling atomic because property values can

View File

@@ -346,7 +346,7 @@ static void vmw_sou_connector_destroy(struct drm_connector *connector)
static const struct drm_connector_funcs vmw_sou_connector_funcs = {
.dpms = vmw_du_connector_dpms,
.detect = vmw_du_connector_detect,
.fill_modes = vmw_du_connector_fill_modes,
.fill_modes = drm_helper_probe_single_connector_modes,
.destroy = vmw_sou_connector_destroy,
.reset = vmw_du_connector_reset,
.atomic_duplicate_state = vmw_du_connector_duplicate_state,
@@ -356,6 +356,8 @@ static const struct drm_connector_funcs vmw_sou_connector_funcs = {
static const struct
drm_connector_helper_funcs vmw_sou_connector_helper_funcs = {
.get_modes = vmw_connector_get_modes,
.mode_valid = vmw_connector_mode_valid
};
@@ -827,7 +829,6 @@ static int vmw_sou_init(struct vmw_private *dev_priv, unsigned unit)
sou->base.pref_active = (unit == 0);
sou->base.pref_width = dev_priv->initial_width;
sou->base.pref_height = dev_priv->initial_height;
sou->base.pref_mode = NULL;
/*
* Remove this after enabling atomic because property values can

View File

@@ -40,7 +40,14 @@
#define vmw_connector_to_stdu(x) \
container_of(x, struct vmw_screen_target_display_unit, base.connector)
/*
* Some renderers such as llvmpipe will align the width and height of their
* buffers to match their tile size. We need to keep this in mind when exposing
* modes to userspace so that this possible over-allocation will not exceed
* graphics memory. 64x64 pixels seems to be a reasonable upper bound for the
* tile size of current renderers.
*/
#define GPU_TILE_SIZE 64
enum stdu_content_type {
SAME_AS_DISPLAY = 0,
@@ -972,12 +979,46 @@ static void vmw_stdu_connector_destroy(struct drm_connector *connector)
vmw_stdu_destroy(vmw_connector_to_stdu(connector));
}
static enum drm_mode_status
vmw_stdu_connector_mode_valid(struct drm_connector *connector,
struct drm_display_mode *mode)
{
enum drm_mode_status ret;
struct drm_device *dev = connector->dev;
struct vmw_private *dev_priv = vmw_priv(dev);
u64 assumed_cpp = dev_priv->assume_16bpp ? 2 : 4;
/* Align width and height to account for GPU tile over-alignment */
u64 required_mem = ALIGN(mode->hdisplay, GPU_TILE_SIZE) *
ALIGN(mode->vdisplay, GPU_TILE_SIZE) *
assumed_cpp;
required_mem = ALIGN(required_mem, PAGE_SIZE);
ret = drm_mode_validate_size(mode, dev_priv->stdu_max_width,
dev_priv->stdu_max_height);
if (ret != MODE_OK)
return ret;
ret = drm_mode_validate_size(mode, dev_priv->texture_max_width,
dev_priv->texture_max_height);
if (ret != MODE_OK)
return ret;
if (required_mem > dev_priv->max_primary_mem)
return MODE_MEM;
if (required_mem > dev_priv->max_mob_pages * PAGE_SIZE)
return MODE_MEM;
if (required_mem > dev_priv->max_mob_size)
return MODE_MEM;
return MODE_OK;
}
static const struct drm_connector_funcs vmw_stdu_connector_funcs = {
.dpms = vmw_du_connector_dpms,
.detect = vmw_du_connector_detect,
.fill_modes = vmw_du_connector_fill_modes,
.fill_modes = drm_helper_probe_single_connector_modes,
.destroy = vmw_stdu_connector_destroy,
.reset = vmw_du_connector_reset,
.atomic_duplicate_state = vmw_du_connector_duplicate_state,
@@ -987,6 +1028,8 @@ static const struct drm_connector_funcs vmw_stdu_connector_funcs = {
static const struct
drm_connector_helper_funcs vmw_stdu_connector_helper_funcs = {
.get_modes = vmw_connector_get_modes,
.mode_valid = vmw_stdu_connector_mode_valid
};

View File

@@ -694,6 +694,7 @@ static void gb_interface_release(struct device *dev)
trace_gb_interface_release(intf);
cancel_work_sync(&intf->mode_switch_work);
kfree(intf);
}

View File

@@ -1445,7 +1445,6 @@ static void implement(const struct hid_device *hid, u8 *report,
hid_warn(hid,
"%s() called with too large value %d (n: %d)! (%s)\n",
__func__, value, n, current->comm);
WARN_ON(1);
value &= m;
}
}

View File

@@ -1284,8 +1284,10 @@ static int logi_dj_recv_switch_to_dj_mode(struct dj_receiver_dev *djrcv_dev,
*/
msleep(50);
if (retval)
if (retval) {
kfree(dj_report);
return retval;
}
}
/*

View File

@@ -18,9 +18,11 @@
#include "i2c-hid.h"
struct elan_i2c_hid_chip_data {
unsigned int post_gpio_reset_delay_ms;
unsigned int post_gpio_reset_on_delay_ms;
unsigned int post_gpio_reset_off_delay_ms;
unsigned int post_power_delay_ms;
u16 hid_descriptor_address;
const char *main_supply_name;
};
struct i2c_hid_of_elan {
@@ -29,6 +31,7 @@ struct i2c_hid_of_elan {
struct regulator *vcc33;
struct regulator *vccio;
struct gpio_desc *reset_gpio;
bool no_reset_on_power_off;
const struct elan_i2c_hid_chip_data *chip_data;
};
@@ -38,24 +41,35 @@ static int elan_i2c_hid_power_up(struct i2chid_ops *ops)
container_of(ops, struct i2c_hid_of_elan, ops);
int ret;
ret = regulator_enable(ihid_elan->vcc33);
if (ret)
return ret;
gpiod_set_value_cansleep(ihid_elan->reset_gpio, 1);
if (ihid_elan->vcc33) {
ret = regulator_enable(ihid_elan->vcc33);
if (ret)
goto err_deassert_reset;
}
ret = regulator_enable(ihid_elan->vccio);
if (ret) {
regulator_disable(ihid_elan->vcc33);
return ret;
}
if (ret)
goto err_disable_vcc33;
if (ihid_elan->chip_data->post_power_delay_ms)
msleep(ihid_elan->chip_data->post_power_delay_ms);
gpiod_set_value_cansleep(ihid_elan->reset_gpio, 0);
if (ihid_elan->chip_data->post_gpio_reset_delay_ms)
msleep(ihid_elan->chip_data->post_gpio_reset_delay_ms);
if (ihid_elan->chip_data->post_gpio_reset_on_delay_ms)
msleep(ihid_elan->chip_data->post_gpio_reset_on_delay_ms);
return 0;
err_disable_vcc33:
if (ihid_elan->vcc33)
regulator_disable(ihid_elan->vcc33);
err_deassert_reset:
if (ihid_elan->no_reset_on_power_off)
gpiod_set_value_cansleep(ihid_elan->reset_gpio, 0);
return ret;
}
static void elan_i2c_hid_power_down(struct i2chid_ops *ops)
@@ -63,15 +77,27 @@ static void elan_i2c_hid_power_down(struct i2chid_ops *ops)
struct i2c_hid_of_elan *ihid_elan =
container_of(ops, struct i2c_hid_of_elan, ops);
gpiod_set_value_cansleep(ihid_elan->reset_gpio, 1);
/*
* Do not assert reset when the hardware allows for it to remain
* deasserted regardless of the state of the (shared) power supply to
* avoid wasting power when the supply is left on.
*/
if (!ihid_elan->no_reset_on_power_off)
gpiod_set_value_cansleep(ihid_elan->reset_gpio, 1);
if (ihid_elan->chip_data->post_gpio_reset_off_delay_ms)
msleep(ihid_elan->chip_data->post_gpio_reset_off_delay_ms);
regulator_disable(ihid_elan->vccio);
regulator_disable(ihid_elan->vcc33);
if (ihid_elan->vcc33)
regulator_disable(ihid_elan->vcc33);
}
static int i2c_hid_of_elan_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct i2c_hid_of_elan *ihid_elan;
int ret;
ihid_elan = devm_kzalloc(&client->dev, sizeof(*ihid_elan), GFP_KERNEL);
if (!ihid_elan)
@@ -86,28 +112,63 @@ static int i2c_hid_of_elan_probe(struct i2c_client *client,
if (IS_ERR(ihid_elan->reset_gpio))
return PTR_ERR(ihid_elan->reset_gpio);
ihid_elan->vccio = devm_regulator_get(&client->dev, "vccio");
if (IS_ERR(ihid_elan->vccio))
return PTR_ERR(ihid_elan->vccio);
ihid_elan->no_reset_on_power_off = of_property_read_bool(client->dev.of_node,
"no-reset-on-power-off");
ihid_elan->vcc33 = devm_regulator_get(&client->dev, "vcc33");
if (IS_ERR(ihid_elan->vcc33))
return PTR_ERR(ihid_elan->vcc33);
ihid_elan->vccio = devm_regulator_get(&client->dev, "vccio");
if (IS_ERR(ihid_elan->vccio)) {
ret = PTR_ERR(ihid_elan->vccio);
goto err_deassert_reset;
}
ihid_elan->chip_data = device_get_match_data(&client->dev);
return i2c_hid_core_probe(client, &ihid_elan->ops,
ihid_elan->chip_data->hid_descriptor_address, 0);
if (ihid_elan->chip_data->main_supply_name) {
ihid_elan->vcc33 = devm_regulator_get(&client->dev,
ihid_elan->chip_data->main_supply_name);
if (IS_ERR(ihid_elan->vcc33)) {
ret = PTR_ERR(ihid_elan->vcc33);
goto err_deassert_reset;
}
}
ret = i2c_hid_core_probe(client, &ihid_elan->ops,
ihid_elan->chip_data->hid_descriptor_address, 0);
if (ret)
goto err_deassert_reset;
return 0;
err_deassert_reset:
if (ihid_elan->no_reset_on_power_off)
gpiod_set_value_cansleep(ihid_elan->reset_gpio, 0);
return ret;
}
static const struct elan_i2c_hid_chip_data elan_ekth6915_chip_data = {
.post_power_delay_ms = 1,
.post_gpio_reset_delay_ms = 300,
.post_gpio_reset_on_delay_ms = 300,
.hid_descriptor_address = 0x0001,
.main_supply_name = "vcc33",
};
static const struct elan_i2c_hid_chip_data ilitek_ili9882t_chip_data = {
.post_power_delay_ms = 1,
.post_gpio_reset_on_delay_ms = 200,
.post_gpio_reset_off_delay_ms = 65,
.hid_descriptor_address = 0x0001,
/*
* this touchscreen is tightly integrated with the panel and assumes
* that the relevant power rails (other than the IO rail) have already
* been turned on by the panel driver because we're a panel follower.
*/
.main_supply_name = NULL,
};
static const struct of_device_id elan_i2c_hid_of_match[] = {
{ .compatible = "elan,ekth6915", .data = &elan_ekth6915_chip_data },
{ .compatible = "ilitek,ili9882t", .data = &ilitek_ili9882t_chip_data },
{ }
};
MODULE_DEVICE_TABLE(of, elan_i2c_hid_of_match);

View File

@@ -294,6 +294,11 @@ static const struct pci_device_id intel_th_pci_id_table[] = {
PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xae24),
.driver_data = (kernel_ulong_t)&intel_th_2x,
},
{
/* Meteor Lake-S */
PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x7f26),
.driver_data = (kernel_ulong_t)&intel_th_2x,
},
{
/* Raptor Lake-S */
PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x7a26),
@@ -304,6 +309,26 @@ static const struct pci_device_id intel_th_pci_id_table[] = {
PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xa76f),
.driver_data = (kernel_ulong_t)&intel_th_2x,
},
{
/* Granite Rapids */
PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x0963),
.driver_data = (kernel_ulong_t)&intel_th_2x,
},
{
/* Granite Rapids SOC */
PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x3256),
.driver_data = (kernel_ulong_t)&intel_th_2x,
},
{
/* Sapphire Rapids SOC */
PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x3456),
.driver_data = (kernel_ulong_t)&intel_th_2x,
},
{
/* Lunar Lake */
PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xa824),
.driver_data = (kernel_ulong_t)&intel_th_2x,
},
{
/* Alder Lake CPU */
PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x466f),

View File

@@ -106,8 +106,7 @@ static int at91_unreg_slave(struct i2c_client *slave)
static u32 at91_twi_func(struct i2c_adapter *adapter)
{
return I2C_FUNC_SLAVE | I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL
| I2C_FUNC_SMBUS_READ_BLOCK_DATA;
return I2C_FUNC_SLAVE;
}
static const struct i2c_algorithm at91_twi_algorithm_slave = {

View File

@@ -232,7 +232,7 @@ static const struct i2c_algorithm i2c_dw_algo = {
void i2c_dw_configure_slave(struct dw_i2c_dev *dev)
{
dev->functionality = I2C_FUNC_SLAVE | DW_IC_DEFAULT_FUNCTIONALITY;
dev->functionality = I2C_FUNC_SLAVE;
dev->slave_cfg = DW_IC_CON_RX_FIFO_FULL_HLD_CTRL |
DW_IC_CON_RESTART_EN | DW_IC_CON_STOP_DET_IFADDRESSED;

View File

@@ -442,18 +442,12 @@ EXPORT_SYMBOL_GPL(i2c_acpi_find_adapter_by_handle);
static struct i2c_client *i2c_acpi_find_client_by_adev(struct acpi_device *adev)
{
struct device *dev;
struct i2c_client *client;
return i2c_find_device_by_fwnode(acpi_fwnode_handle(adev));
}
dev = bus_find_device_by_acpi_dev(&i2c_bus_type, adev);
if (!dev)
return NULL;
client = i2c_verify_client(dev);
if (!client)
put_device(dev);
return client;
static struct i2c_adapter *i2c_acpi_find_adapter_by_adev(struct acpi_device *adev)
{
return i2c_find_adapter_by_fwnode(acpi_fwnode_handle(adev));
}
static int i2c_acpi_notify(struct notifier_block *nb, unsigned long value,
@@ -482,11 +476,17 @@ static int i2c_acpi_notify(struct notifier_block *nb, unsigned long value,
break;
client = i2c_acpi_find_client_by_adev(adev);
if (!client)
break;
if (client) {
i2c_unregister_device(client);
put_device(&client->dev);
}
adapter = i2c_acpi_find_adapter_by_adev(adev);
if (adapter) {
acpi_unbind_one(&adapter->dev);
put_device(&adapter->dev);
}
i2c_unregister_device(client);
put_device(&client->dev);
break;
}

View File

@@ -1017,6 +1017,35 @@ void i2c_unregister_device(struct i2c_client *client)
}
EXPORT_SYMBOL_GPL(i2c_unregister_device);
/**
* i2c_find_device_by_fwnode() - find an i2c_client for the fwnode
* @fwnode: &struct fwnode_handle corresponding to the &struct i2c_client
*
* Look up and return the &struct i2c_client corresponding to the @fwnode.
* If no client can be found, or @fwnode is NULL, this returns NULL.
*
* The user must call put_device(&client->dev) once done with the i2c client.
*/
struct i2c_client *i2c_find_device_by_fwnode(struct fwnode_handle *fwnode)
{
struct i2c_client *client;
struct device *dev;
if (!fwnode)
return NULL;
dev = bus_find_device_by_fwnode(&i2c_bus_type, fwnode);
if (!dev)
return NULL;
client = i2c_verify_client(dev);
if (!client)
put_device(dev);
return client;
}
EXPORT_SYMBOL(i2c_find_device_by_fwnode);
static const struct i2c_device_id dummy_id[] = {
{ "dummy", 0 },
@@ -1767,6 +1796,75 @@ int devm_i2c_add_adapter(struct device *dev, struct i2c_adapter *adapter)
}
EXPORT_SYMBOL_GPL(devm_i2c_add_adapter);
static int i2c_dev_or_parent_fwnode_match(struct device *dev, const void *data)
{
if (dev_fwnode(dev) == data)
return 1;
if (dev->parent && dev_fwnode(dev->parent) == data)
return 1;
return 0;
}
/**
* i2c_find_adapter_by_fwnode() - find an i2c_adapter for the fwnode
* @fwnode: &struct fwnode_handle corresponding to the &struct i2c_adapter
*
* Look up and return the &struct i2c_adapter corresponding to the @fwnode.
* If no adapter can be found, or @fwnode is NULL, this returns NULL.
*
* The user must call put_device(&adapter->dev) once done with the i2c adapter.
*/
struct i2c_adapter *i2c_find_adapter_by_fwnode(struct fwnode_handle *fwnode)
{
struct i2c_adapter *adapter;
struct device *dev;
if (!fwnode)
return NULL;
dev = bus_find_device(&i2c_bus_type, NULL, fwnode,
i2c_dev_or_parent_fwnode_match);
if (!dev)
return NULL;
adapter = i2c_verify_adapter(dev);
if (!adapter)
put_device(dev);
return adapter;
}
EXPORT_SYMBOL(i2c_find_adapter_by_fwnode);
/**
* i2c_get_adapter_by_fwnode() - find an i2c_adapter for the fwnode
* @fwnode: &struct fwnode_handle corresponding to the &struct i2c_adapter
*
* Look up and return the &struct i2c_adapter corresponding to the @fwnode,
* and increment the adapter module's use count. If no adapter can be found,
* or @fwnode is NULL, this returns NULL.
*
* The user must call i2c_put_adapter(adapter) once done with the i2c adapter.
* Note that this is different from i2c_find_adapter_by_node().
*/
struct i2c_adapter *i2c_get_adapter_by_fwnode(struct fwnode_handle *fwnode)
{
struct i2c_adapter *adapter;
adapter = i2c_find_adapter_by_fwnode(fwnode);
if (!adapter)
return NULL;
if (!try_module_get(adapter->owner)) {
put_device(&adapter->dev);
adapter = NULL;
}
return adapter;
}
EXPORT_SYMBOL(i2c_get_adapter_by_fwnode);
static void i2c_parse_timing(struct device *dev, char *prop_name, u32 *cur_val_p,
u32 def_val, bool use_def)
{

View File

@@ -113,72 +113,6 @@ void of_i2c_register_devices(struct i2c_adapter *adap)
of_node_put(bus);
}
static int of_dev_or_parent_node_match(struct device *dev, const void *data)
{
if (dev->of_node == data)
return 1;
if (dev->parent)
return dev->parent->of_node == data;
return 0;
}
/* must call put_device() when done with returned i2c_client device */
struct i2c_client *of_find_i2c_device_by_node(struct device_node *node)
{
struct device *dev;
struct i2c_client *client;
dev = bus_find_device_by_of_node(&i2c_bus_type, node);
if (!dev)
return NULL;
client = i2c_verify_client(dev);
if (!client)
put_device(dev);
return client;
}
EXPORT_SYMBOL(of_find_i2c_device_by_node);
/* must call put_device() when done with returned i2c_adapter device */
struct i2c_adapter *of_find_i2c_adapter_by_node(struct device_node *node)
{
struct device *dev;
struct i2c_adapter *adapter;
dev = bus_find_device(&i2c_bus_type, NULL, node,
of_dev_or_parent_node_match);
if (!dev)
return NULL;
adapter = i2c_verify_adapter(dev);
if (!adapter)
put_device(dev);
return adapter;
}
EXPORT_SYMBOL(of_find_i2c_adapter_by_node);
/* must call i2c_put_adapter() when done with returned i2c_adapter device */
struct i2c_adapter *of_get_i2c_adapter_by_node(struct device_node *node)
{
struct i2c_adapter *adapter;
adapter = of_find_i2c_adapter_by_node(node);
if (!adapter)
return NULL;
if (!try_module_get(adapter->owner)) {
put_device(&adapter->dev);
adapter = NULL;
}
return adapter;
}
EXPORT_SYMBOL(of_get_i2c_adapter_by_node);
static const struct of_device_id*
i2c_of_match_device_sysfs(const struct of_device_id *matches,
struct i2c_client *client)

View File

@@ -5,6 +5,7 @@
* Copyright (c) 2014, Intel Corporation.
*/
#include <linux/delay.h>
#include <linux/module.h>
#include <linux/i2c.h>
#include <linux/iio/iio.h>
@@ -36,6 +37,7 @@
#define MXC4005_REG_INT_CLR1 0x01
#define MXC4005_REG_INT_CLR1_BIT_DRDYC 0x01
#define MXC4005_REG_INT_CLR1_SW_RST 0x10
#define MXC4005_REG_CONTROL 0x0D
#define MXC4005_REG_CONTROL_MASK_FSR GENMASK(6, 5)
@@ -43,6 +45,9 @@
#define MXC4005_REG_DEVICE_ID 0x0E
/* Datasheet does not specify a reset time, this is a conservative guess */
#define MXC4005_RESET_TIME_US 2000
enum mxc4005_axis {
AXIS_X,
AXIS_Y,
@@ -66,6 +71,8 @@ struct mxc4005_data {
s64 timestamp __aligned(8);
} scan;
bool trigger_enabled;
unsigned int control;
unsigned int int_mask1;
};
/*
@@ -349,6 +356,7 @@ static int mxc4005_set_trigger_state(struct iio_trigger *trig,
return ret;
}
data->int_mask1 = val;
data->trigger_enabled = state;
mutex_unlock(&data->mutex);
@@ -384,6 +392,13 @@ static int mxc4005_chip_init(struct mxc4005_data *data)
dev_dbg(data->dev, "MXC4005 chip id %02x\n", reg);
ret = regmap_write(data->regmap, MXC4005_REG_INT_CLR1,
MXC4005_REG_INT_CLR1_SW_RST);
if (ret < 0)
return dev_err_probe(data->dev, ret, "resetting chip\n");
fsleep(MXC4005_RESET_TIME_US);
ret = regmap_write(data->regmap, MXC4005_REG_INT_MASK0, 0);
if (ret < 0)
return dev_err_probe(data->dev, ret, "writing INT_MASK0\n");
@@ -480,6 +495,58 @@ static int mxc4005_probe(struct i2c_client *client,
return devm_iio_device_register(&client->dev, indio_dev);
}
static int mxc4005_suspend(struct device *dev)
{
struct iio_dev *indio_dev = dev_get_drvdata(dev);
struct mxc4005_data *data = iio_priv(indio_dev);
int ret;
/* Save control to restore it on resume */
ret = regmap_read(data->regmap, MXC4005_REG_CONTROL, &data->control);
if (ret < 0)
dev_err(data->dev, "failed to read reg_control\n");
return ret;
}
static int mxc4005_resume(struct device *dev)
{
struct iio_dev *indio_dev = dev_get_drvdata(dev);
struct mxc4005_data *data = iio_priv(indio_dev);
int ret;
ret = regmap_write(data->regmap, MXC4005_REG_INT_CLR1,
MXC4005_REG_INT_CLR1_SW_RST);
if (ret) {
dev_err(data->dev, "failed to reset chip: %d\n", ret);
return ret;
}
fsleep(MXC4005_RESET_TIME_US);
ret = regmap_write(data->regmap, MXC4005_REG_CONTROL, data->control);
if (ret) {
dev_err(data->dev, "failed to restore control register\n");
return ret;
}
ret = regmap_write(data->regmap, MXC4005_REG_INT_MASK0, 0);
if (ret) {
dev_err(data->dev, "failed to restore interrupt 0 mask\n");
return ret;
}
ret = regmap_write(data->regmap, MXC4005_REG_INT_MASK1, data->int_mask1);
if (ret) {
dev_err(data->dev, "failed to restore interrupt 1 mask\n");
return ret;
}
return 0;
}
static DEFINE_SIMPLE_DEV_PM_OPS(mxc4005_pm_ops, mxc4005_suspend, mxc4005_resume);
static const struct acpi_device_id mxc4005_acpi_match[] = {
{"MXC4005", 0},
{"MXC6655", 0},
@@ -487,6 +554,13 @@ static const struct acpi_device_id mxc4005_acpi_match[] = {
};
MODULE_DEVICE_TABLE(acpi, mxc4005_acpi_match);
static const struct of_device_id mxc4005_of_match[] = {
{ .compatible = "memsic,mxc4005", },
{ .compatible = "memsic,mxc6655", },
{ },
};
MODULE_DEVICE_TABLE(of, mxc4005_of_match);
static const struct i2c_device_id mxc4005_id[] = {
{"mxc4005", 0},
{"mxc6655", 0},
@@ -498,6 +572,8 @@ static struct i2c_driver mxc4005_driver = {
.driver = {
.name = MXC4005_DRV_NAME,
.acpi_match_table = ACPI_PTR(mxc4005_acpi_match),
.of_match_table = mxc4005_of_match,
.pm = pm_sleep_ptr(&mxc4005_pm_ops),
},
.probe = mxc4005_probe,
.id_table = mxc4005_id,

View File

@@ -223,11 +223,11 @@ static void __ad9467_get_scale(struct adi_axi_adc_conv *conv, int index,
}
static const struct iio_chan_spec ad9434_channels[] = {
AD9467_CHAN(0, 0, 12, 'S'),
AD9467_CHAN(0, 0, 12, 's'),
};
static const struct iio_chan_spec ad9467_channels[] = {
AD9467_CHAN(0, 0, 16, 'S'),
AD9467_CHAN(0, 0, 16, 's'),
};
static const struct ad9467_chip_info ad9467_chip_tbl[] = {

View File

@@ -410,7 +410,7 @@ static int ad5592r_read_raw(struct iio_dev *iio_dev,
s64 tmp = *val * (3767897513LL / 25LL);
*val = div_s64_rem(tmp, 1000000000LL, val2);
return IIO_VAL_INT_PLUS_MICRO;
return IIO_VAL_INT_PLUS_NANO;
}
mutex_lock(&st->lock);

View File

@@ -128,10 +128,6 @@ static int inv_icm42600_accel_update_scan_mode(struct iio_dev *indio_dev,
/* update data FIFO write */
inv_icm42600_timestamp_apply_odr(ts, 0, 0, 0);
ret = inv_icm42600_buffer_set_fifo_en(st, fifo_en | st->fifo.en);
if (ret)
goto out_unlock;
ret = inv_icm42600_buffer_update_watermark(st);
out_unlock:
mutex_unlock(&st->lock);

View File

@@ -128,10 +128,6 @@ static int inv_icm42600_gyro_update_scan_mode(struct iio_dev *indio_dev,
/* update data FIFO write */
inv_icm42600_timestamp_apply_odr(ts, 0, 0, 0);
ret = inv_icm42600_buffer_set_fifo_en(st, fifo_en | st->fifo.en);
if (ret)
goto out_unlock;
ret = inv_icm42600_buffer_update_watermark(st);
out_unlock:
mutex_unlock(&st->lock);

View File

@@ -1374,19 +1374,19 @@ static int input_print_modalias_bits(char *buf, int size,
char name, unsigned long *bm,
unsigned int min_bit, unsigned int max_bit)
{
int len = 0, i;
int bit = min_bit;
int len = 0;
len += snprintf(buf, max(size, 0), "%c", name);
for (i = min_bit; i < max_bit; i++)
if (bm[BIT_WORD(i)] & BIT_MASK(i))
len += snprintf(buf + len, max(size - len, 0), "%X,", i);
for_each_set_bit_from(bit, bm, max_bit)
len += snprintf(buf + len, max(size - len, 0), "%X,", bit);
return len;
}
static int input_print_modalias(char *buf, int size, struct input_dev *id,
int add_cr)
static int input_print_modalias_parts(char *buf, int size, int full_len,
struct input_dev *id)
{
int len;
int len, klen, remainder, space;
len = snprintf(buf, max(size, 0),
"input:b%04Xv%04Xp%04Xe%04X-",
@@ -1395,8 +1395,48 @@ static int input_print_modalias(char *buf, int size, struct input_dev *id,
len += input_print_modalias_bits(buf + len, size - len,
'e', id->evbit, 0, EV_MAX);
len += input_print_modalias_bits(buf + len, size - len,
/*
* Calculate the remaining space in the buffer making sure we
* have place for the terminating 0.
*/
space = max(size - (len + 1), 0);
klen = input_print_modalias_bits(buf + len, size - len,
'k', id->keybit, KEY_MIN_INTERESTING, KEY_MAX);
len += klen;
/*
* If we have more data than we can fit in the buffer, check
* if we can trim key data to fit in the rest. We will indicate
* that key data is incomplete by adding "+" sign at the end, like
* this: * "k1,2,3,45,+,".
*
* Note that we shortest key info (if present) is "k+," so we
* can only try to trim if key data is longer than that.
*/
if (full_len && size < full_len + 1 && klen > 3) {
remainder = full_len - len;
/*
* We can only trim if we have space for the remainder
* and also for at least "k+," which is 3 more characters.
*/
if (remainder <= space - 3) {
/*
* We are guaranteed to have 'k' in the buffer, so
* we need at least 3 additional bytes for storing
* "+," in addition to the remainder.
*/
for (int i = size - 1 - remainder - 3; i >= 0; i--) {
if (buf[i] == 'k' || buf[i] == ',') {
strcpy(buf + i + 1, "+,");
len = i + 3; /* Not counting '\0' */
break;
}
}
}
}
len += input_print_modalias_bits(buf + len, size - len,
'r', id->relbit, 0, REL_MAX);
len += input_print_modalias_bits(buf + len, size - len,
@@ -1412,12 +1452,25 @@ static int input_print_modalias(char *buf, int size, struct input_dev *id,
len += input_print_modalias_bits(buf + len, size - len,
'w', id->swbit, 0, SW_MAX);
if (add_cr)
len += snprintf(buf + len, max(size - len, 0), "\n");
return len;
}
static int input_print_modalias(char *buf, int size, struct input_dev *id)
{
int full_len;
/*
* Printing is done in 2 passes: first one figures out total length
* needed for the modalias string, second one will try to trim key
* data in case when buffer is too small for the entire modalias.
* If the buffer is too small regardless, it will fill as much as it
* can (without trimming key data) into the buffer and leave it to
* the caller to figure out what to do with the result.
*/
full_len = input_print_modalias_parts(NULL, 0, 0, id);
return input_print_modalias_parts(buf, size, full_len, id);
}
static ssize_t input_dev_show_modalias(struct device *dev,
struct device_attribute *attr,
char *buf)
@@ -1425,7 +1478,9 @@ static ssize_t input_dev_show_modalias(struct device *dev,
struct input_dev *id = to_input_dev(dev);
ssize_t len;
len = input_print_modalias(buf, PAGE_SIZE, id, 1);
len = input_print_modalias(buf, PAGE_SIZE, id);
if (len < PAGE_SIZE - 2)
len += snprintf(buf + len, PAGE_SIZE - len, "\n");
return min_t(int, len, PAGE_SIZE);
}
@@ -1637,6 +1692,23 @@ static int input_add_uevent_bm_var(struct kobj_uevent_env *env,
return 0;
}
/*
* This is a pretty gross hack. When building uevent data the driver core
* may try adding more environment variables to kobj_uevent_env without
* telling us, so we have no idea how much of the buffer we can use to
* avoid overflows/-ENOMEM elsewhere. To work around this let's artificially
* reduce amount of memory we will use for the modalias environment variable.
*
* The potential additions are:
*
* SEQNUM=18446744073709551615 - (%llu - 28 bytes)
* HOME=/ (6 bytes)
* PATH=/sbin:/bin:/usr/sbin:/usr/bin (34 bytes)
*
* 68 bytes total. Allow extra buffer - 96 bytes
*/
#define UEVENT_ENV_EXTRA_LEN 96
static int input_add_uevent_modalias_var(struct kobj_uevent_env *env,
struct input_dev *dev)
{
@@ -1646,9 +1718,11 @@ static int input_add_uevent_modalias_var(struct kobj_uevent_env *env,
return -ENOMEM;
len = input_print_modalias(&env->buf[env->buflen - 1],
sizeof(env->buf) - env->buflen,
dev, 0);
if (len >= (sizeof(env->buf) - env->buflen))
(int)sizeof(env->buf) - env->buflen -
UEVENT_ENV_EXTRA_LEN,
dev);
if (len >= ((int)sizeof(env->buf) - env->buflen -
UEVENT_ENV_EXTRA_LEN))
return -ENOMEM;
env->buflen += len;

View File

@@ -1655,8 +1655,17 @@ static void __init free_pci_segments(void)
}
}
static void __init free_sysfs(struct amd_iommu *iommu)
{
if (iommu->iommu.dev) {
iommu_device_unregister(&iommu->iommu);
iommu_device_sysfs_remove(&iommu->iommu);
}
}
static void __init free_iommu_one(struct amd_iommu *iommu)
{
free_sysfs(iommu);
free_cwwb_sem(iommu);
free_command_buffer(iommu);
free_event_buffer(iommu);

View File

@@ -1837,28 +1837,22 @@ static int its_vlpi_map(struct irq_data *d, struct its_cmd_info *info)
{
struct its_device *its_dev = irq_data_get_irq_chip_data(d);
u32 event = its_get_event_id(d);
int ret = 0;
if (!info->map)
return -EINVAL;
raw_spin_lock(&its_dev->event_map.vlpi_lock);
if (!its_dev->event_map.vm) {
struct its_vlpi_map *maps;
maps = kcalloc(its_dev->event_map.nr_lpis, sizeof(*maps),
GFP_ATOMIC);
if (!maps) {
ret = -ENOMEM;
goto out;
}
if (!maps)
return -ENOMEM;
its_dev->event_map.vm = info->map->vm;
its_dev->event_map.vlpi_maps = maps;
} else if (its_dev->event_map.vm != info->map->vm) {
ret = -EINVAL;
goto out;
return -EINVAL;
}
/* Get our private copy of the mapping information */
@@ -1890,46 +1884,32 @@ static int its_vlpi_map(struct irq_data *d, struct its_cmd_info *info)
its_dev->event_map.nr_vlpis++;
}
out:
raw_spin_unlock(&its_dev->event_map.vlpi_lock);
return ret;
return 0;
}
static int its_vlpi_get(struct irq_data *d, struct its_cmd_info *info)
{
struct its_device *its_dev = irq_data_get_irq_chip_data(d);
struct its_vlpi_map *map;
int ret = 0;
raw_spin_lock(&its_dev->event_map.vlpi_lock);
map = get_vlpi_map(d);
if (!its_dev->event_map.vm || !map) {
ret = -EINVAL;
goto out;
}
if (!its_dev->event_map.vm || !map)
return -EINVAL;
/* Copy our mapping information to the incoming request */
*info->map = *map;
out:
raw_spin_unlock(&its_dev->event_map.vlpi_lock);
return ret;
return 0;
}
static int its_vlpi_unmap(struct irq_data *d)
{
struct its_device *its_dev = irq_data_get_irq_chip_data(d);
u32 event = its_get_event_id(d);
int ret = 0;
raw_spin_lock(&its_dev->event_map.vlpi_lock);
if (!its_dev->event_map.vm || !irqd_is_forwarded_to_vcpu(d)) {
ret = -EINVAL;
goto out;
}
if (!its_dev->event_map.vm || !irqd_is_forwarded_to_vcpu(d))
return -EINVAL;
/* Drop the virtual mapping */
its_send_discard(its_dev, event);
@@ -1953,9 +1933,7 @@ static int its_vlpi_unmap(struct irq_data *d)
kfree(its_dev->event_map.vlpi_maps);
}
out:
raw_spin_unlock(&its_dev->event_map.vlpi_lock);
return ret;
return 0;
}
static int its_vlpi_prop_update(struct irq_data *d, struct its_cmd_info *info)
@@ -1983,6 +1961,8 @@ static int its_irq_set_vcpu_affinity(struct irq_data *d, void *vcpu_info)
if (!is_v4(its_dev->its))
return -EINVAL;
guard(raw_spinlock_irq)(&its_dev->event_map.vlpi_lock);
/* Unmap request? */
if (!info)
return its_vlpi_unmap(d);

View File

@@ -69,8 +69,10 @@ static int gp_aux_bus_probe(struct pci_dev *pdev, const struct pci_device_id *id
aux_bus->aux_device_wrapper[1] = kzalloc(sizeof(*aux_bus->aux_device_wrapper[1]),
GFP_KERNEL);
if (!aux_bus->aux_device_wrapper[1])
return -ENOMEM;
if (!aux_bus->aux_device_wrapper[1]) {
retval = -ENOMEM;
goto err_aux_dev_add_0;
}
retval = ida_alloc(&gp_client_ida, GFP_KERNEL);
if (retval < 0)
@@ -111,6 +113,7 @@ static int gp_aux_bus_probe(struct pci_dev *pdev, const struct pci_device_id *id
err_aux_dev_add_1:
auxiliary_device_uninit(&aux_bus->aux_device_wrapper[1]->aux_dev);
goto err_aux_dev_add_0;
err_aux_dev_init_1:
ida_free(&gp_client_ida, aux_bus->aux_device_wrapper[1]->aux_dev.id);
@@ -120,6 +123,7 @@ err_ida_alloc_1:
err_aux_dev_add_0:
auxiliary_device_uninit(&aux_bus->aux_device_wrapper[0]->aux_dev);
goto err_ret;
err_aux_dev_init_0:
ida_free(&gp_client_ida, aux_bus->aux_device_wrapper[0]->aux_dev.id);
@@ -127,6 +131,7 @@ err_aux_dev_init_0:
err_ida_alloc_0:
kfree(aux_bus->aux_device_wrapper[0]);
err_ret:
return retval;
}

View File

@@ -394,8 +394,10 @@ static int mei_me_pci_resume(struct device *device)
}
err = mei_restart(dev);
if (err)
if (err) {
free_irq(pdev->irq, dev);
return err;
}
/* Start timer if stopped in suspend */
schedule_delayed_work(&dev->timer_work, HZ);

View File

@@ -24,52 +24,9 @@ MODULE_AUTHOR("Hu Tao <hutao@cn.fujitsu.com>");
MODULE_DESCRIPTION("pvpanic-mmio device driver");
MODULE_LICENSE("GPL");
static ssize_t capability_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct pvpanic_instance *pi = dev_get_drvdata(dev);
return sysfs_emit(buf, "%x\n", pi->capability);
}
static DEVICE_ATTR_RO(capability);
static ssize_t events_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct pvpanic_instance *pi = dev_get_drvdata(dev);
return sysfs_emit(buf, "%x\n", pi->events);
}
static ssize_t events_store(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
struct pvpanic_instance *pi = dev_get_drvdata(dev);
unsigned int tmp;
int err;
err = kstrtouint(buf, 16, &tmp);
if (err)
return err;
if ((tmp & pi->capability) != tmp)
return -EINVAL;
pi->events = tmp;
return count;
}
static DEVICE_ATTR_RW(events);
static struct attribute *pvpanic_mmio_dev_attrs[] = {
&dev_attr_capability.attr,
&dev_attr_events.attr,
NULL
};
ATTRIBUTE_GROUPS(pvpanic_mmio_dev);
static int pvpanic_mmio_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct pvpanic_instance *pi;
struct resource *res;
void __iomem *base;
@@ -92,18 +49,7 @@ static int pvpanic_mmio_probe(struct platform_device *pdev)
return -EINVAL;
}
pi = devm_kmalloc(dev, sizeof(*pi), GFP_KERNEL);
if (!pi)
return -ENOMEM;
pi->base = base;
pi->capability = PVPANIC_PANICKED | PVPANIC_CRASH_LOADED;
/* initialize capability by RDPT */
pi->capability &= ioread8(base);
pi->events = pi->capability;
return devm_pvpanic_probe(dev, pi);
return devm_pvpanic_probe(dev, base);
}
static const struct of_device_id pvpanic_mmio_match[] = {
@@ -123,7 +69,7 @@ static struct platform_driver pvpanic_mmio_driver = {
.name = "pvpanic-mmio",
.of_match_table = pvpanic_mmio_match,
.acpi_match_table = pvpanic_device_ids,
.dev_groups = pvpanic_mmio_dev_groups,
.dev_groups = pvpanic_dev_groups,
},
.probe = pvpanic_mmio_probe,
};

View File

@@ -22,51 +22,8 @@ MODULE_AUTHOR("Mihai Carabas <mihai.carabas@oracle.com>");
MODULE_DESCRIPTION("pvpanic device driver");
MODULE_LICENSE("GPL");
static ssize_t capability_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct pvpanic_instance *pi = dev_get_drvdata(dev);
return sysfs_emit(buf, "%x\n", pi->capability);
}
static DEVICE_ATTR_RO(capability);
static ssize_t events_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct pvpanic_instance *pi = dev_get_drvdata(dev);
return sysfs_emit(buf, "%x\n", pi->events);
}
static ssize_t events_store(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
struct pvpanic_instance *pi = dev_get_drvdata(dev);
unsigned int tmp;
int err;
err = kstrtouint(buf, 16, &tmp);
if (err)
return err;
if ((tmp & pi->capability) != tmp)
return -EINVAL;
pi->events = tmp;
return count;
}
static DEVICE_ATTR_RW(events);
static struct attribute *pvpanic_pci_dev_attrs[] = {
&dev_attr_capability.attr,
&dev_attr_events.attr,
NULL
};
ATTRIBUTE_GROUPS(pvpanic_pci_dev);
static int pvpanic_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
{
struct pvpanic_instance *pi;
void __iomem *base;
int ret;
@@ -78,18 +35,7 @@ static int pvpanic_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
if (!base)
return -ENOMEM;
pi = devm_kmalloc(&pdev->dev, sizeof(*pi), GFP_KERNEL);
if (!pi)
return -ENOMEM;
pi->base = base;
pi->capability = PVPANIC_PANICKED | PVPANIC_CRASH_LOADED;
/* initlize capability by RDPT */
pi->capability &= ioread8(base);
pi->events = pi->capability;
return devm_pvpanic_probe(&pdev->dev, pi);
return devm_pvpanic_probe(&pdev->dev, base);
}
static const struct pci_device_id pvpanic_pci_id_tbl[] = {
@@ -102,8 +48,6 @@ static struct pci_driver pvpanic_pci_driver = {
.name = "pvpanic-pci",
.id_table = pvpanic_pci_id_tbl,
.probe = pvpanic_pci_probe,
.driver = {
.dev_groups = pvpanic_pci_dev_groups,
},
.dev_groups = pvpanic_dev_groups,
};
module_pci_driver(pvpanic_pci_driver);

View File

@@ -7,6 +7,7 @@
* Copyright (C) 2021 Oracle.
*/
#include <linux/device.h>
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/kexec.h>
@@ -26,6 +27,13 @@ MODULE_AUTHOR("Mihai Carabas <mihai.carabas@oracle.com>");
MODULE_DESCRIPTION("pvpanic device driver");
MODULE_LICENSE("GPL");
struct pvpanic_instance {
void __iomem *base;
unsigned int capability;
unsigned int events;
struct list_head list;
};
static struct list_head pvpanic_list;
static spinlock_t pvpanic_lock;
@@ -81,11 +89,75 @@ static void pvpanic_remove(void *param)
spin_unlock(&pvpanic_lock);
}
int devm_pvpanic_probe(struct device *dev, struct pvpanic_instance *pi)
static ssize_t capability_show(struct device *dev, struct device_attribute *attr, char *buf)
{
if (!pi || !pi->base)
struct pvpanic_instance *pi = dev_get_drvdata(dev);
return sysfs_emit(buf, "%x\n", pi->capability);
}
static DEVICE_ATTR_RO(capability);
static ssize_t events_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct pvpanic_instance *pi = dev_get_drvdata(dev);
return sysfs_emit(buf, "%x\n", pi->events);
}
static ssize_t events_store(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
struct pvpanic_instance *pi = dev_get_drvdata(dev);
unsigned int tmp;
int err;
err = kstrtouint(buf, 16, &tmp);
if (err)
return err;
if ((tmp & pi->capability) != tmp)
return -EINVAL;
pi->events = tmp;
return count;
}
static DEVICE_ATTR_RW(events);
static struct attribute *pvpanic_dev_attrs[] = {
&dev_attr_capability.attr,
&dev_attr_events.attr,
NULL
};
static const struct attribute_group pvpanic_dev_group = {
.attrs = pvpanic_dev_attrs,
};
const struct attribute_group *pvpanic_dev_groups[] = {
&pvpanic_dev_group,
NULL
};
EXPORT_SYMBOL_GPL(pvpanic_dev_groups);
int devm_pvpanic_probe(struct device *dev, void __iomem *base)
{
struct pvpanic_instance *pi;
if (!base)
return -EINVAL;
pi = devm_kmalloc(dev, sizeof(*pi), GFP_KERNEL);
if (!pi)
return -ENOMEM;
pi->base = base;
pi->capability = PVPANIC_PANICKED | PVPANIC_CRASH_LOADED;
/* initlize capability by RDPT */
pi->capability &= ioread8(base);
pi->events = pi->capability;
spin_lock(&pvpanic_lock);
list_add(&pi->list, &pvpanic_list);
spin_unlock(&pvpanic_lock);

View File

@@ -8,13 +8,7 @@
#ifndef PVPANIC_H_
#define PVPANIC_H_
struct pvpanic_instance {
void __iomem *base;
unsigned int capability;
unsigned int events;
struct list_head list;
};
int devm_pvpanic_probe(struct device *dev, struct pvpanic_instance *pi);
int devm_pvpanic_probe(struct device *dev, void __iomem *base);
extern const struct attribute_group *pvpanic_dev_groups[];
#endif /* PVPANIC_H_ */

View File

@@ -9,6 +9,7 @@
#include <linux/vmw_vmci_api.h>
#include <linux/list.h>
#include <linux/module.h>
#include <linux/nospec.h>
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/rculist.h>
@@ -86,9 +87,12 @@ static void event_deliver(struct vmci_event_msg *event_msg)
{
struct vmci_subscription *cur;
struct list_head *subscriber_list;
u32 sanitized_event, max_vmci_event;
rcu_read_lock();
subscriber_list = &subscriber_array[event_msg->event_data.event];
max_vmci_event = ARRAY_SIZE(subscriber_array);
sanitized_event = array_index_nospec(event_msg->event_data.event, max_vmci_event);
subscriber_list = &subscriber_array[sanitized_event];
list_for_each_entry_rcu(cur, subscriber_list, node) {
cur->callback(cur->id, &event_msg->event_data,
cur->callback_data);

View File

@@ -1345,7 +1345,7 @@ ioremap_fail:
return ret;
}
static int __exit davinci_mmcsd_remove(struct platform_device *pdev)
static int davinci_mmcsd_remove(struct platform_device *pdev)
{
struct mmc_davinci_host *host = platform_get_drvdata(pdev);
@@ -1402,7 +1402,7 @@ static struct platform_driver davinci_mmcsd_driver = {
.of_match_table = davinci_mmc_dt_ids,
},
.probe = davinci_mmcsd_probe,
.remove = __exit_p(davinci_mmcsd_remove),
.remove = davinci_mmcsd_remove,
.id_table = davinci_mmc_devtype,
};

View File

@@ -678,7 +678,7 @@ static int __hwrm_send(struct bnxt *bp, struct bnxt_hwrm_ctx *ctx)
req_type);
else if (rc && rc != HWRM_ERR_CODE_PF_UNAVAILABLE)
hwrm_err(bp, ctx, "hwrm req_type 0x%x seq id 0x%x error 0x%x\n",
req_type, token->seq_id, rc);
req_type, le16_to_cpu(ctx->req->seq_id), rc);
rc = __hwrm_to_stderr(rc);
exit:
if (token)

View File

@@ -272,13 +272,12 @@ lio_vf_rep_copy_packet(struct octeon_device *oct,
pg_info->page_offset;
memcpy(skb->data, va, MIN_SKB_SIZE);
skb_put(skb, MIN_SKB_SIZE);
skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags,
pg_info->page,
pg_info->page_offset + MIN_SKB_SIZE,
len - MIN_SKB_SIZE,
LIO_RXBUFFER_SZ);
}
skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags,
pg_info->page,
pg_info->page_offset + MIN_SKB_SIZE,
len - MIN_SKB_SIZE,
LIO_RXBUFFER_SZ);
} else {
struct octeon_skb_page_info *pg_info =
((struct octeon_skb_page_info *)(skb->cb));

View File

@@ -465,11 +465,13 @@ static void gve_rx_skb_hash(struct sk_buff *skb,
skb_set_hash(skb, le32_to_cpu(compl_desc->hash), hash_type);
}
static void gve_rx_free_skb(struct gve_rx_ring *rx)
static void gve_rx_free_skb(struct napi_struct *napi, struct gve_rx_ring *rx)
{
if (!rx->ctx.skb_head)
return;
if (rx->ctx.skb_head == napi->skb)
napi->skb = NULL;
dev_kfree_skb_any(rx->ctx.skb_head);
rx->ctx.skb_head = NULL;
rx->ctx.skb_tail = NULL;
@@ -693,7 +695,7 @@ int gve_rx_poll_dqo(struct gve_notify_block *block, int budget)
err = gve_rx_dqo(napi, rx, compl_desc, rx->q_num);
if (err < 0) {
gve_rx_free_skb(rx);
gve_rx_free_skb(napi, rx);
u64_stats_update_begin(&rx->statss);
if (err == -ENOMEM)
rx->rx_skb_alloc_fail++;
@@ -736,7 +738,7 @@ int gve_rx_poll_dqo(struct gve_notify_block *block, int budget)
/* gve_rx_complete_skb() will consume skb if successful */
if (gve_rx_complete_skb(rx, napi, compl_desc, feat) != 0) {
gve_rx_free_skb(rx);
gve_rx_free_skb(napi, rx);
u64_stats_update_begin(&rx->statss);
rx->rx_desc_err_dropped_pkt++;
u64_stats_update_end(&rx->statss);

View File

@@ -370,28 +370,18 @@ static int gve_prep_tso(struct sk_buff *skb)
if (unlikely(skb_shinfo(skb)->gso_size < GVE_TX_MIN_TSO_MSS_DQO))
return -1;
if (!(skb_shinfo(skb)->gso_type & (SKB_GSO_TCPV4 | SKB_GSO_TCPV6)))
return -EINVAL;
/* Needed because we will modify header. */
err = skb_cow_head(skb, 0);
if (err < 0)
return err;
tcp = tcp_hdr(skb);
/* Remove payload length from checksum. */
paylen = skb->len - skb_transport_offset(skb);
switch (skb_shinfo(skb)->gso_type) {
case SKB_GSO_TCPV4:
case SKB_GSO_TCPV6:
csum_replace_by_diff(&tcp->check,
(__force __wsum)htonl(paylen));
/* Compute length of segmentation header. */
header_len = skb_tcp_all_headers(skb);
break;
default:
return -EINVAL;
}
csum_replace_by_diff(&tcp->check, (__force __wsum)htonl(paylen));
header_len = skb_tcp_all_headers(skb);
if (unlikely(header_len > GVE_TX_MAX_HDR_SIZE_DQO))
return -EINVAL;

View File

@@ -3538,6 +3538,9 @@ static int hns3_alloc_ring_buffers(struct hns3_enet_ring *ring)
ret = hns3_alloc_and_attach_buffer(ring, i);
if (ret)
goto out_buffer_fail;
if (!(i % HNS3_RESCHED_BD_NUM))
cond_resched();
}
return 0;
@@ -5111,6 +5114,7 @@ int hns3_init_all_ring(struct hns3_nic_priv *priv)
}
u64_stats_init(&priv->ring[i].syncp);
cond_resched();
}
return 0;

View File

@@ -214,6 +214,8 @@ enum hns3_nic_state {
#define HNS3_CQ_MODE_EQE 1U
#define HNS3_CQ_MODE_CQE 0U
#define HNS3_RESCHED_BD_NUM 1024
enum hns3_pkt_l2t_type {
HNS3_L2_TYPE_UNICAST,
HNS3_L2_TYPE_MULTICAST,

View File

@@ -3129,9 +3129,7 @@ static void hclge_push_link_status(struct hclge_dev *hdev)
static void hclge_update_link_status(struct hclge_dev *hdev)
{
struct hnae3_handle *rhandle = &hdev->vport[0].roce;
struct hnae3_handle *handle = &hdev->vport[0].nic;
struct hnae3_client *rclient = hdev->roce_client;
struct hnae3_client *client = hdev->nic_client;
int state;
int ret;
@@ -3155,8 +3153,15 @@ static void hclge_update_link_status(struct hclge_dev *hdev)
client->ops->link_status_change(handle, state);
hclge_config_mac_tnl_int(hdev, state);
if (rclient && rclient->ops->link_status_change)
rclient->ops->link_status_change(rhandle, state);
if (test_bit(HCLGE_STATE_ROCE_REGISTERED, &hdev->state)) {
struct hnae3_handle *rhandle = &hdev->vport[0].roce;
struct hnae3_client *rclient = hdev->roce_client;
if (rclient && rclient->ops->link_status_change)
rclient->ops->link_status_change(rhandle,
state);
}
hclge_push_link_status(hdev);
}
@@ -11339,6 +11344,12 @@ clear_roce:
return ret;
}
static bool hclge_uninit_need_wait(struct hclge_dev *hdev)
{
return test_bit(HCLGE_STATE_RST_HANDLING, &hdev->state) ||
test_bit(HCLGE_STATE_LINK_UPDATING, &hdev->state);
}
static void hclge_uninit_client_instance(struct hnae3_client *client,
struct hnae3_ae_dev *ae_dev)
{
@@ -11347,7 +11358,7 @@ static void hclge_uninit_client_instance(struct hnae3_client *client,
if (hdev->roce_client) {
clear_bit(HCLGE_STATE_ROCE_REGISTERED, &hdev->state);
while (test_bit(HCLGE_STATE_RST_HANDLING, &hdev->state))
while (hclge_uninit_need_wait(hdev))
msleep(HCLGE_WAIT_RESET_DONE);
hdev->roce_client->ops->uninit_instance(&vport->roce, 0);

View File

@@ -388,7 +388,6 @@ struct ice_vsi {
struct ice_tc_cfg tc_cfg;
struct bpf_prog *xdp_prog;
struct ice_tx_ring **xdp_rings; /* XDP ring array */
unsigned long *af_xdp_zc_qps; /* tracks AF_XDP ZC enabled qps */
u16 num_xdp_txq; /* Used XDP queues */
u8 xdp_mapping_mode; /* ICE_MAP_MODE_[CONTIG|SCATTER] */
@@ -688,6 +687,25 @@ static inline void ice_set_ring_xdp(struct ice_tx_ring *ring)
ring->flags |= ICE_TX_FLAGS_RING_XDP;
}
/**
* ice_get_xp_from_qid - get ZC XSK buffer pool bound to a queue ID
* @vsi: pointer to VSI
* @qid: index of a queue to look at XSK buff pool presence
*
* Return: A pointer to xsk_buff_pool structure if there is a buffer pool
* attached and configured as zero-copy, NULL otherwise.
*/
static inline struct xsk_buff_pool *ice_get_xp_from_qid(struct ice_vsi *vsi,
u16 qid)
{
struct xsk_buff_pool *pool = xsk_get_pool_from_qid(vsi->netdev, qid);
if (!ice_is_xdp_ena_vsi(vsi))
return NULL;
return (pool && pool->dev) ? pool : NULL;
}
/**
* ice_xsk_pool - get XSK buffer pool bound to a ring
* @ring: Rx ring to use
@@ -700,10 +718,7 @@ static inline struct xsk_buff_pool *ice_xsk_pool(struct ice_rx_ring *ring)
struct ice_vsi *vsi = ring->vsi;
u16 qid = ring->q_index;
if (!ice_is_xdp_ena_vsi(vsi) || !test_bit(qid, vsi->af_xdp_zc_qps))
return NULL;
return xsk_get_pool_from_qid(vsi->netdev, qid);
return ice_get_xp_from_qid(vsi, qid);
}
/**
@@ -728,12 +743,7 @@ static inline void ice_tx_xsk_pool(struct ice_vsi *vsi, u16 qid)
if (!ring)
return;
if (!ice_is_xdp_ena_vsi(vsi) || !test_bit(qid, vsi->af_xdp_zc_qps)) {
ring->xsk_pool = NULL;
return;
}
ring->xsk_pool = xsk_get_pool_from_qid(vsi->netdev, qid);
ring->xsk_pool = ice_get_xp_from_qid(vsi, qid);
}
/**

View File

@@ -848,9 +848,9 @@ struct ice_aqc_txsched_elem {
u8 generic;
#define ICE_AQC_ELEM_GENERIC_MODE_M 0x1
#define ICE_AQC_ELEM_GENERIC_PRIO_S 0x1
#define ICE_AQC_ELEM_GENERIC_PRIO_M (0x7 << ICE_AQC_ELEM_GENERIC_PRIO_S)
#define ICE_AQC_ELEM_GENERIC_PRIO_M GENMASK(3, 1)
#define ICE_AQC_ELEM_GENERIC_SP_S 0x4
#define ICE_AQC_ELEM_GENERIC_SP_M (0x1 << ICE_AQC_ELEM_GENERIC_SP_S)
#define ICE_AQC_ELEM_GENERIC_SP_M GENMASK(4, 4)
#define ICE_AQC_ELEM_GENERIC_ADJUST_VAL_S 0x5
#define ICE_AQC_ELEM_GENERIC_ADJUST_VAL_M \
(0x3 << ICE_AQC_ELEM_GENERIC_ADJUST_VAL_S)

View File

@@ -789,8 +789,7 @@ static void ice_cleanup_fltr_mgmt_struct(struct ice_hw *hw)
devm_kfree(ice_hw_to_dev(hw), lst_itr);
}
}
if (recps[i].root_buf)
devm_kfree(ice_hw_to_dev(hw), recps[i].root_buf);
devm_kfree(ice_hw_to_dev(hw), recps[i].root_buf);
}
ice_rm_all_sw_replay_rule_info(hw);
devm_kfree(ice_hw_to_dev(hw), sw->recp_list);
@@ -986,8 +985,7 @@ static int ice_cfg_fw_log(struct ice_hw *hw, bool enable)
}
out:
if (data)
devm_kfree(ice_hw_to_dev(hw), data);
devm_kfree(ice_hw_to_dev(hw), data);
return status;
}
@@ -1105,6 +1103,9 @@ int ice_init_hw(struct ice_hw *hw)
hw->evb_veb = true;
/* init xarray for identifying scheduling nodes uniquely */
xa_init_flags(&hw->port_info->sched_node_ids, XA_FLAGS_ALLOC);
/* Query the allocated resources for Tx scheduler */
status = ice_sched_query_res_alloc(hw);
if (status) {

View File

@@ -339,8 +339,7 @@ do { \
} \
} \
/* free the buffer info list */ \
if ((qi)->ring.cmd_buf) \
devm_kfree(ice_hw_to_dev(hw), (qi)->ring.cmd_buf); \
devm_kfree(ice_hw_to_dev(hw), (qi)->ring.cmd_buf); \
/* free DMA head */ \
devm_kfree(ice_hw_to_dev(hw), (qi)->ring.dma_head); \
} while (0)

View File

@@ -1303,23 +1303,6 @@ ice_flow_find_prof_id(struct ice_hw *hw, enum ice_block blk, u64 prof_id)
return NULL;
}
/**
* ice_dealloc_flow_entry - Deallocate flow entry memory
* @hw: pointer to the HW struct
* @entry: flow entry to be removed
*/
static void
ice_dealloc_flow_entry(struct ice_hw *hw, struct ice_flow_entry *entry)
{
if (!entry)
return;
if (entry->entry)
devm_kfree(ice_hw_to_dev(hw), entry->entry);
devm_kfree(ice_hw_to_dev(hw), entry);
}
/**
* ice_flow_rem_entry_sync - Remove a flow entry
* @hw: pointer to the HW struct
@@ -1335,7 +1318,8 @@ ice_flow_rem_entry_sync(struct ice_hw *hw, enum ice_block __always_unused blk,
list_del(&entry->l_entry);
ice_dealloc_flow_entry(hw, entry);
devm_kfree(ice_hw_to_dev(hw), entry->entry);
devm_kfree(ice_hw_to_dev(hw), entry);
return 0;
}
@@ -1662,8 +1646,7 @@ ice_flow_add_entry(struct ice_hw *hw, enum ice_block blk, u64 prof_id,
out:
if (status && e) {
if (e->entry)
devm_kfree(ice_hw_to_dev(hw), e->entry);
devm_kfree(ice_hw_to_dev(hw), e->entry);
devm_kfree(ice_hw_to_dev(hw), e);
}

View File

@@ -117,14 +117,8 @@ static int ice_vsi_alloc_arrays(struct ice_vsi *vsi)
if (!vsi->q_vectors)
goto err_vectors;
vsi->af_xdp_zc_qps = bitmap_zalloc(max_t(int, vsi->alloc_txq, vsi->alloc_rxq), GFP_KERNEL);
if (!vsi->af_xdp_zc_qps)
goto err_zc_qps;
return 0;
err_zc_qps:
devm_kfree(dev, vsi->q_vectors);
err_vectors:
devm_kfree(dev, vsi->rxq_map);
err_rxq_map:
@@ -320,31 +314,17 @@ static void ice_vsi_free_arrays(struct ice_vsi *vsi)
dev = ice_pf_to_dev(pf);
if (vsi->af_xdp_zc_qps) {
bitmap_free(vsi->af_xdp_zc_qps);
vsi->af_xdp_zc_qps = NULL;
}
/* free the ring and vector containers */
if (vsi->q_vectors) {
devm_kfree(dev, vsi->q_vectors);
vsi->q_vectors = NULL;
}
if (vsi->tx_rings) {
devm_kfree(dev, vsi->tx_rings);
vsi->tx_rings = NULL;
}
if (vsi->rx_rings) {
devm_kfree(dev, vsi->rx_rings);
vsi->rx_rings = NULL;
}
if (vsi->txq_map) {
devm_kfree(dev, vsi->txq_map);
vsi->txq_map = NULL;
}
if (vsi->rxq_map) {
devm_kfree(dev, vsi->rxq_map);
vsi->rxq_map = NULL;
}
devm_kfree(dev, vsi->q_vectors);
vsi->q_vectors = NULL;
devm_kfree(dev, vsi->tx_rings);
vsi->tx_rings = NULL;
devm_kfree(dev, vsi->rx_rings);
vsi->rx_rings = NULL;
devm_kfree(dev, vsi->txq_map);
vsi->txq_map = NULL;
devm_kfree(dev, vsi->rxq_map);
vsi->rxq_map = NULL;
}
/**
@@ -787,10 +767,8 @@ static void ice_rss_clean(struct ice_vsi *vsi)
dev = ice_pf_to_dev(pf);
if (vsi->rss_hkey_user)
devm_kfree(dev, vsi->rss_hkey_user);
if (vsi->rss_lut_user)
devm_kfree(dev, vsi->rss_lut_user);
devm_kfree(dev, vsi->rss_hkey_user);
devm_kfree(dev, vsi->rss_lut_user);
ice_vsi_clean_rss_flow_fld(vsi);
/* remove RSS replay list */

View File

@@ -441,8 +441,7 @@ int
ice_get_pfa_module_tlv(struct ice_hw *hw, u16 *module_tlv, u16 *module_tlv_len,
u16 module_type)
{
u16 pfa_len, pfa_ptr;
u16 next_tlv;
u16 pfa_len, pfa_ptr, next_tlv, max_tlv;
int status;
status = ice_read_sr_word(hw, ICE_SR_PFA_PTR, &pfa_ptr);
@@ -455,11 +454,23 @@ ice_get_pfa_module_tlv(struct ice_hw *hw, u16 *module_tlv, u16 *module_tlv_len,
ice_debug(hw, ICE_DBG_INIT, "Failed to read PFA length.\n");
return status;
}
/* The Preserved Fields Area contains a sequence of Type-Length-Value
* structures which define its contents. The PFA length includes all
* of the TLVs, plus the initial length word itself, *and* one final
* word at the end after all of the TLVs.
*/
if (check_add_overflow(pfa_ptr, pfa_len - 1, &max_tlv)) {
dev_warn(ice_hw_to_dev(hw), "PFA starts at offset %u. PFA length of %u caused 16-bit arithmetic overflow.\n",
pfa_ptr, pfa_len);
return -EINVAL;
}
/* Starting with first TLV after PFA length, iterate through the list
* of TLVs to find the requested one.
*/
next_tlv = pfa_ptr + 1;
while (next_tlv < pfa_ptr + pfa_len) {
while (next_tlv < max_tlv) {
u16 tlv_sub_module_type;
u16 tlv_len;
@@ -483,10 +494,13 @@ ice_get_pfa_module_tlv(struct ice_hw *hw, u16 *module_tlv, u16 *module_tlv_len,
}
return -EINVAL;
}
/* Check next TLV, i.e. current TLV pointer + length + 2 words
* (for current TLV's type and length)
*/
next_tlv = next_tlv + tlv_len + 2;
if (check_add_overflow(next_tlv, 2, &next_tlv) ||
check_add_overflow(next_tlv, tlv_len, &next_tlv)) {
dev_warn(ice_hw_to_dev(hw), "TLV of type %u and length 0x%04x caused 16-bit arithmetic overflow. The PFA starts at 0x%04x and has length of 0x%04x\n",
tlv_sub_module_type, tlv_len, pfa_ptr, pfa_len);
return -EINVAL;
}
}
/* Module does not exist */
return -ENOENT;

View File

@@ -1,6 +1,7 @@
// SPDX-License-Identifier: GPL-2.0
/* Copyright (c) 2018, Intel Corporation. */
#include <net/devlink.h>
#include "ice_sched.h"
/**
@@ -352,9 +353,9 @@ void ice_free_sched_node(struct ice_port_info *pi, struct ice_sched_node *node)
node->sibling;
}
/* leaf nodes have no children */
if (node->children)
devm_kfree(ice_hw_to_dev(hw), node->children);
devm_kfree(ice_hw_to_dev(hw), node->children);
kfree(node->name);
xa_erase(&pi->sched_node_ids, node->id);
devm_kfree(ice_hw_to_dev(hw), node);
}
@@ -850,10 +851,8 @@ void ice_sched_cleanup_all(struct ice_hw *hw)
if (!hw)
return;
if (hw->layer_info) {
devm_kfree(ice_hw_to_dev(hw), hw->layer_info);
hw->layer_info = NULL;
}
devm_kfree(ice_hw_to_dev(hw), hw->layer_info);
hw->layer_info = NULL;
ice_sched_clear_port(hw->port_info);
@@ -875,7 +874,7 @@ void ice_sched_cleanup_all(struct ice_hw *hw)
*
* This function add nodes to HW as well as to SW DB for a given layer
*/
static int
int
ice_sched_add_elems(struct ice_port_info *pi, struct ice_sched_node *tc_node,
struct ice_sched_node *parent, u8 layer, u16 num_nodes,
u16 *num_nodes_added, u32 *first_node_teid)
@@ -940,6 +939,22 @@ ice_sched_add_elems(struct ice_port_info *pi, struct ice_sched_node *tc_node,
new_node->sibling = NULL;
new_node->tc_num = tc_node->tc_num;
new_node->tx_weight = ICE_SCHED_DFLT_BW_WT;
new_node->tx_share = ICE_SCHED_DFLT_BW;
new_node->tx_max = ICE_SCHED_DFLT_BW;
new_node->name = kzalloc(SCHED_NODE_NAME_MAX_LEN, GFP_KERNEL);
if (!new_node->name)
return -ENOMEM;
status = xa_alloc(&pi->sched_node_ids, &new_node->id, NULL, XA_LIMIT(0, UINT_MAX),
GFP_KERNEL);
if (status) {
ice_debug(hw, ICE_DBG_SCHED, "xa_alloc failed for sched node status =%d\n",
status);
break;
}
snprintf(new_node->name, SCHED_NODE_NAME_MAX_LEN, "node_%u", new_node->id);
/* add it to previous node sibling pointer */
/* Note: siblings are not linked across branches */
@@ -2154,7 +2169,7 @@ ice_sched_get_free_vsi_parent(struct ice_hw *hw, struct ice_sched_node *node,
* This function removes the child from the old parent and adds it to a new
* parent
*/
static void
void
ice_sched_update_parent(struct ice_sched_node *new_parent,
struct ice_sched_node *node)
{
@@ -2188,7 +2203,7 @@ ice_sched_update_parent(struct ice_sched_node *new_parent,
*
* This function move the child nodes to a given parent.
*/
static int
int
ice_sched_move_nodes(struct ice_port_info *pi, struct ice_sched_node *parent,
u16 num_items, u32 *list)
{
@@ -3562,7 +3577,7 @@ ice_sched_set_eir_srl_excl(struct ice_port_info *pi,
* node's RL profile ID of type CIR, EIR, or SRL, and removes old profile
* ID from local database. The caller needs to hold scheduler lock.
*/
static int
int
ice_sched_set_node_bw(struct ice_port_info *pi, struct ice_sched_node *node,
enum ice_rl_type rl_type, u32 bw, u8 layer_num)
{
@@ -3598,6 +3613,57 @@ ice_sched_set_node_bw(struct ice_port_info *pi, struct ice_sched_node *node,
ICE_AQC_RL_PROFILE_TYPE_M, old_id);
}
/**
* ice_sched_set_node_priority - set node's priority
* @pi: port information structure
* @node: tree node
* @priority: number 0-7 representing priority among siblings
*
* This function sets priority of a node among it's siblings.
*/
int
ice_sched_set_node_priority(struct ice_port_info *pi, struct ice_sched_node *node,
u16 priority)
{
struct ice_aqc_txsched_elem_data buf;
struct ice_aqc_txsched_elem *data;
buf = node->info;
data = &buf.data;
data->valid_sections |= ICE_AQC_ELEM_VALID_GENERIC;
data->generic |= FIELD_PREP(ICE_AQC_ELEM_GENERIC_PRIO_M, priority);
return ice_sched_update_elem(pi->hw, node, &buf);
}
/**
* ice_sched_set_node_weight - set node's weight
* @pi: port information structure
* @node: tree node
* @weight: number 1-200 representing weight for WFQ
*
* This function sets weight of the node for WFQ algorithm.
*/
int
ice_sched_set_node_weight(struct ice_port_info *pi, struct ice_sched_node *node, u16 weight)
{
struct ice_aqc_txsched_elem_data buf;
struct ice_aqc_txsched_elem *data;
buf = node->info;
data = &buf.data;
data->valid_sections = ICE_AQC_ELEM_VALID_CIR | ICE_AQC_ELEM_VALID_EIR |
ICE_AQC_ELEM_VALID_GENERIC;
data->cir_bw.bw_alloc = cpu_to_le16(weight);
data->eir_bw.bw_alloc = cpu_to_le16(weight);
data->generic |= FIELD_PREP(ICE_AQC_ELEM_GENERIC_SP_M, 0x0);
return ice_sched_update_elem(pi->hw, node, &buf);
}
/**
* ice_sched_set_node_bw_lmt - set node's BW limit
* @pi: port information structure
@@ -3608,7 +3674,7 @@ ice_sched_set_node_bw(struct ice_port_info *pi, struct ice_sched_node *node,
* It updates node's BW limit parameters like BW RL profile ID of type CIR,
* EIR, or SRL. The caller needs to hold scheduler lock.
*/
static int
int
ice_sched_set_node_bw_lmt(struct ice_port_info *pi, struct ice_sched_node *node,
enum ice_rl_type rl_type, u32 bw)
{

View File

@@ -6,6 +6,8 @@
#include "ice_common.h"
#define SCHED_NODE_NAME_MAX_LEN 32
#define ICE_QGRP_LAYER_OFFSET 2
#define ICE_VSI_LAYER_OFFSET 4
#define ICE_AGG_LAYER_OFFSET 6
@@ -69,6 +71,28 @@ int
ice_aq_query_sched_elems(struct ice_hw *hw, u16 elems_req,
struct ice_aqc_txsched_elem_data *buf, u16 buf_size,
u16 *elems_ret, struct ice_sq_cd *cd);
int
ice_sched_set_node_bw_lmt(struct ice_port_info *pi, struct ice_sched_node *node,
enum ice_rl_type rl_type, u32 bw);
int
ice_sched_set_node_bw(struct ice_port_info *pi, struct ice_sched_node *node,
enum ice_rl_type rl_type, u32 bw, u8 layer_num);
int
ice_sched_add_elems(struct ice_port_info *pi, struct ice_sched_node *tc_node,
struct ice_sched_node *parent, u8 layer, u16 num_nodes,
u16 *num_nodes_added, u32 *first_node_teid);
int
ice_sched_move_nodes(struct ice_port_info *pi, struct ice_sched_node *parent,
u16 num_items, u32 *list);
int ice_sched_set_node_priority(struct ice_port_info *pi, struct ice_sched_node *node,
u16 priority);
int ice_sched_set_node_weight(struct ice_port_info *pi, struct ice_sched_node *node, u16 weight);
int ice_sched_init_port(struct ice_port_info *pi);
int ice_sched_query_res_alloc(struct ice_hw *hw);
void ice_sched_get_psm_clk_freq(struct ice_hw *hw);
@@ -82,6 +106,9 @@ ice_sched_find_node_by_teid(struct ice_sched_node *start_node, u32 teid);
int
ice_sched_add_node(struct ice_port_info *pi, u8 layer,
struct ice_aqc_txsched_elem_data *info);
void
ice_sched_update_parent(struct ice_sched_node *new_parent,
struct ice_sched_node *node);
void ice_free_sched_node(struct ice_port_info *pi, struct ice_sched_node *node);
struct ice_sched_node *ice_sched_get_tc_node(struct ice_port_info *pi, u8 tc);
struct ice_sched_node *

View File

@@ -1636,21 +1636,16 @@ ice_save_vsi_ctx(struct ice_hw *hw, u16 vsi_handle, struct ice_vsi_ctx *vsi)
*/
static void ice_clear_vsi_q_ctx(struct ice_hw *hw, u16 vsi_handle)
{
struct ice_vsi_ctx *vsi;
struct ice_vsi_ctx *vsi = ice_get_vsi_ctx(hw, vsi_handle);
u8 i;
vsi = ice_get_vsi_ctx(hw, vsi_handle);
if (!vsi)
return;
ice_for_each_traffic_class(i) {
if (vsi->lan_q_ctx[i]) {
devm_kfree(ice_hw_to_dev(hw), vsi->lan_q_ctx[i]);
vsi->lan_q_ctx[i] = NULL;
}
if (vsi->rdma_q_ctx[i]) {
devm_kfree(ice_hw_to_dev(hw), vsi->rdma_q_ctx[i]);
vsi->rdma_q_ctx[i] = NULL;
}
devm_kfree(ice_hw_to_dev(hw), vsi->lan_q_ctx[i]);
vsi->lan_q_ctx[i] = NULL;
devm_kfree(ice_hw_to_dev(hw), vsi->rdma_q_ctx[i]);
vsi->rdma_q_ctx[i] = NULL;
}
}
@@ -5525,9 +5520,7 @@ err_unroll:
devm_kfree(ice_hw_to_dev(hw), fvit);
}
if (rm->root_buf)
devm_kfree(ice_hw_to_dev(hw), rm->root_buf);
devm_kfree(ice_hw_to_dev(hw), rm->root_buf);
kfree(rm);
err_free_lkup_exts:

View File

@@ -524,7 +524,14 @@ struct ice_sched_node {
struct ice_sched_node *sibling; /* next sibling in the same layer */
struct ice_sched_node **children;
struct ice_aqc_txsched_elem_data info;
char *name;
struct devlink_rate *rate_node;
u64 tx_max;
u64 tx_share;
u32 agg_id; /* aggregator group ID */
u32 id;
u32 tx_priority;
u32 tx_weight;
u16 vsi_handle;
u8 in_use; /* suspended or in use */
u8 tx_sched_layer; /* Logical Layer (1-9) */
@@ -706,6 +713,7 @@ struct ice_port_info {
/* List contain profile ID(s) and other params per layer */
struct list_head rl_prof_list[ICE_AQC_TOPO_MAX_LEVEL_NUM];
struct ice_qos_cfg qos_cfg;
struct xarray sched_node_ids;
u8 is_vf:1;
};

View File

@@ -281,7 +281,6 @@ static int ice_xsk_pool_disable(struct ice_vsi *vsi, u16 qid)
if (!pool)
return -EINVAL;
clear_bit(qid, vsi->af_xdp_zc_qps);
xsk_pool_dma_unmap(pool, ICE_RX_DMA_ATTR);
return 0;
@@ -312,8 +311,6 @@ ice_xsk_pool_enable(struct ice_vsi *vsi, struct xsk_buff_pool *pool, u16 qid)
if (err)
return err;
set_bit(qid, vsi->af_xdp_zc_qps);
return 0;
}
@@ -361,11 +358,13 @@ ice_realloc_rx_xdp_bufs(struct ice_rx_ring *rx_ring, bool pool_present)
int ice_realloc_zc_buf(struct ice_vsi *vsi, bool zc)
{
struct ice_rx_ring *rx_ring;
unsigned long q;
uint i;
ice_for_each_rxq(vsi, i) {
rx_ring = vsi->rx_rings[i];
if (!rx_ring->xsk_pool)
continue;
for_each_set_bit(q, vsi->af_xdp_zc_qps,
max_t(int, vsi->alloc_txq, vsi->alloc_rxq)) {
rx_ring = vsi->rx_rings[q];
if (ice_realloc_rx_xdp_bufs(rx_ring, zc))
return -ENOMEM;
}

View File

@@ -2506,7 +2506,17 @@ static int npc_mcam_alloc_entries(struct npc_mcam *mcam, u16 pcifunc,
* - when available free entries are less.
* Lower priority ones out of avaialble free entries are always
* chosen when 'high vs low' question arises.
*
* For a VF base MCAM match rule is set by its PF. And all the
* further MCAM rules installed by VF on its own are
* concatenated with the base rule set by its PF. Hence PF entries
* should be at lower priority compared to VF entries. Otherwise
* base rule is hit always and rules installed by VF will be of
* no use. Hence if the request is from PF then allocate low
* priority entries.
*/
if (!(pcifunc & RVU_PFVF_FUNC_MASK))
goto lprio_alloc;
/* Get the search range for priority allocation request */
if (req->priority) {
@@ -2515,17 +2525,6 @@ static int npc_mcam_alloc_entries(struct npc_mcam *mcam, u16 pcifunc,
goto alloc;
}
/* For a VF base MCAM match rule is set by its PF. And all the
* further MCAM rules installed by VF on its own are
* concatenated with the base rule set by its PF. Hence PF entries
* should be at lower priority compared to VF entries. Otherwise
* base rule is hit always and rules installed by VF will be of
* no use. Hence if the request is from PF and NOT a priority
* allocation request then allocate low priority entries.
*/
if (!(pcifunc & RVU_PFVF_FUNC_MASK))
goto lprio_alloc;
/* Find out the search range for non-priority allocation request
*
* Get MCAM free entry count in middle zone.
@@ -2555,6 +2554,18 @@ lprio_alloc:
reverse = true;
start = 0;
end = mcam->bmap_entries;
/* Ensure PF requests are always at bottom and if PF requests
* for higher/lower priority entry wrt reference entry then
* honour that criteria and start search for entries from bottom
* and not in mid zone.
*/
if (!(pcifunc & RVU_PFVF_FUNC_MASK) &&
req->priority == NPC_MCAM_HIGHER_PRIO)
end = req->ref_entry;
if (!(pcifunc & RVU_PFVF_FUNC_MASK) &&
req->priority == NPC_MCAM_LOWER_PRIO)
start = req->ref_entry;
}
alloc:

View File

@@ -4587,7 +4587,7 @@ static netdev_features_t mlx5e_tunnel_features_check(struct mlx5e_priv *priv,
/* Verify if UDP port is being offloaded by HW */
if (mlx5_vxlan_lookup_port(priv->mdev->vxlan, port))
return features;
return vxlan_features_check(skb, features);
#if IS_ENABLED(CONFIG_GENEVE)
/* Support Geneve offload for default UDP port */
@@ -4613,7 +4613,6 @@ netdev_features_t mlx5e_features_check(struct sk_buff *skb,
struct mlx5e_priv *priv = netdev_priv(netdev);
features = vlan_features_check(skb, features);
features = vxlan_features_check(skb, features);
/* Validate if the tunneled packet is being offloaded by HW */
if (skb->encapsulation &&

View File

@@ -379,6 +379,10 @@ int mlx5_cmd_fast_teardown_hca(struct mlx5_core_dev *dev)
do {
if (mlx5_get_nic_state(dev) == MLX5_NIC_IFC_DISABLED)
break;
if (pci_channel_offline(dev->pdev)) {
mlx5_core_err(dev, "PCI channel offline, stop waiting for NIC IFC\n");
return -EACCES;
}
cond_resched();
} while (!time_after(jiffies, end));

View File

@@ -260,6 +260,10 @@ recover_from_sw_reset:
do {
if (mlx5_get_nic_state(dev) == MLX5_NIC_IFC_DISABLED)
break;
if (pci_channel_offline(dev->pdev)) {
mlx5_core_err(dev, "PCI channel offline, stop waiting for NIC IFC\n");
goto unlock;
}
msleep(20);
} while (!time_after(jiffies, end));
@@ -325,6 +329,14 @@ int mlx5_health_wait_pci_up(struct mlx5_core_dev *dev)
while (sensor_pci_not_working(dev)) {
if (time_after(jiffies, end))
return -ETIMEDOUT;
if (test_bit(MLX5_BREAK_FW_WAIT, &dev->intf_state)) {
mlx5_core_warn(dev, "device is being removed, stop waiting for PCI\n");
return -ENODEV;
}
if (pci_channel_offline(dev->pdev)) {
mlx5_core_err(dev, "PCI channel offline, stop waiting for PCI\n");
return -EACCES;
}
msleep(100);
}
return 0;

View File

@@ -88,9 +88,13 @@ static int mlx5_lag_create_port_sel_table(struct mlx5_lag *ldev,
&dest, 1);
if (IS_ERR(lag_definer->rules[idx])) {
err = PTR_ERR(lag_definer->rules[idx]);
while (i--)
while (j--)
do {
while (j--) {
idx = i * ldev->buckets + j;
mlx5_del_flow_rules(lag_definer->rules[idx]);
}
j = ldev->buckets;
} while (i--);
goto destroy_fg;
}
}

View File

@@ -74,6 +74,10 @@ int mlx5_vsc_gw_lock(struct mlx5_core_dev *dev)
ret = -EBUSY;
goto pci_unlock;
}
if (pci_channel_offline(dev->pdev)) {
ret = -EACCES;
goto pci_unlock;
}
/* Check if semaphore is already locked */
ret = vsc_read(dev, VSC_SEMAPHORE_OFFSET, &lock_val);

View File

@@ -1093,7 +1093,7 @@ static void mlx5_cleanup_once(struct mlx5_core_dev *dev)
mlx5_devcom_unregister_device(dev->priv.devcom);
}
static int mlx5_function_setup(struct mlx5_core_dev *dev, bool boot, u64 timeout)
static int mlx5_function_enable(struct mlx5_core_dev *dev, bool boot, u64 timeout)
{
int err;
@@ -1158,39 +1158,6 @@ static int mlx5_function_setup(struct mlx5_core_dev *dev, bool boot, u64 timeout
goto reclaim_boot_pages;
}
err = set_hca_ctrl(dev);
if (err) {
mlx5_core_err(dev, "set_hca_ctrl failed\n");
goto reclaim_boot_pages;
}
err = set_hca_cap(dev);
if (err) {
mlx5_core_err(dev, "set_hca_cap failed\n");
goto reclaim_boot_pages;
}
err = mlx5_satisfy_startup_pages(dev, 0);
if (err) {
mlx5_core_err(dev, "failed to allocate init pages\n");
goto reclaim_boot_pages;
}
err = mlx5_cmd_init_hca(dev, sw_owner_id);
if (err) {
mlx5_core_err(dev, "init hca failed\n");
goto reclaim_boot_pages;
}
mlx5_set_driver_version(dev);
err = mlx5_query_hca_caps(dev);
if (err) {
mlx5_core_err(dev, "query hca failed\n");
goto reclaim_boot_pages;
}
mlx5_start_health_fw_log_up(dev);
return 0;
reclaim_boot_pages:
@@ -1206,7 +1173,55 @@ err_cmd_cleanup:
return err;
}
static int mlx5_function_teardown(struct mlx5_core_dev *dev, bool boot)
static void mlx5_function_disable(struct mlx5_core_dev *dev, bool boot)
{
mlx5_reclaim_startup_pages(dev);
mlx5_core_disable_hca(dev, 0);
mlx5_stop_health_poll(dev, boot);
mlx5_cmd_set_state(dev, MLX5_CMDIF_STATE_DOWN);
mlx5_cmd_cleanup(dev);
}
static int mlx5_function_open(struct mlx5_core_dev *dev)
{
int err;
err = set_hca_ctrl(dev);
if (err) {
mlx5_core_err(dev, "set_hca_ctrl failed\n");
return err;
}
err = set_hca_cap(dev);
if (err) {
mlx5_core_err(dev, "set_hca_cap failed\n");
return err;
}
err = mlx5_satisfy_startup_pages(dev, 0);
if (err) {
mlx5_core_err(dev, "failed to allocate init pages\n");
return err;
}
err = mlx5_cmd_init_hca(dev, sw_owner_id);
if (err) {
mlx5_core_err(dev, "init hca failed\n");
return err;
}
mlx5_set_driver_version(dev);
err = mlx5_query_hca_caps(dev);
if (err) {
mlx5_core_err(dev, "query hca failed\n");
return err;
}
mlx5_start_health_fw_log_up(dev);
return 0;
}
static int mlx5_function_close(struct mlx5_core_dev *dev)
{
int err;
@@ -1215,15 +1230,36 @@ static int mlx5_function_teardown(struct mlx5_core_dev *dev, bool boot)
mlx5_core_err(dev, "tear_down_hca failed, skip cleanup\n");
return err;
}
mlx5_reclaim_startup_pages(dev);
mlx5_core_disable_hca(dev, 0);
mlx5_stop_health_poll(dev, boot);
mlx5_cmd_set_state(dev, MLX5_CMDIF_STATE_DOWN);
mlx5_cmd_cleanup(dev);
return 0;
}
static int mlx5_function_setup(struct mlx5_core_dev *dev, bool boot, u64 timeout)
{
int err;
err = mlx5_function_enable(dev, boot, timeout);
if (err)
return err;
err = mlx5_function_open(dev);
if (err)
mlx5_function_disable(dev, boot);
return err;
}
static int mlx5_function_teardown(struct mlx5_core_dev *dev, bool boot)
{
int err = mlx5_function_close(dev);
if (!err)
mlx5_function_disable(dev, boot);
else
mlx5_stop_health_poll(dev, boot);
return err;
}
static int mlx5_load(struct mlx5_core_dev *dev)
{
int err;

View File

@@ -292,10 +292,8 @@ static int ionic_qcq_enable(struct ionic_qcq *qcq)
if (ret)
return ret;
if (qcq->napi.poll)
napi_enable(&qcq->napi);
if (qcq->flags & IONIC_QCQ_F_INTR) {
napi_enable(&qcq->napi);
irq_set_affinity_hint(qcq->intr.vector,
&qcq->intr.affinity_mask);
ionic_intr_mask(idev->intr_ctrl, qcq->intr.index,

View File

@@ -343,10 +343,11 @@ static int tc_setup_cbs(struct stmmac_priv *priv,
struct tc_cbs_qopt_offload *qopt)
{
u32 tx_queues_count = priv->plat->tx_queues_to_use;
s64 port_transmit_rate_kbps;
u32 queue = qopt->queue;
u32 ptr, speed_div;
u32 mode_to_use;
u64 value;
u32 ptr;
int ret;
/* Queue 0 is not AVB capable */
@@ -355,30 +356,26 @@ static int tc_setup_cbs(struct stmmac_priv *priv,
if (!priv->dma_cap.av)
return -EOPNOTSUPP;
port_transmit_rate_kbps = qopt->idleslope - qopt->sendslope;
/* Port Transmit Rate and Speed Divider */
switch (priv->speed) {
switch (div_s64(port_transmit_rate_kbps, 1000)) {
case SPEED_10000:
ptr = 32;
speed_div = 10000000;
break;
case SPEED_5000:
ptr = 32;
speed_div = 5000000;
break;
case SPEED_2500:
ptr = 8;
speed_div = 2500000;
break;
case SPEED_1000:
ptr = 8;
speed_div = 1000000;
break;
case SPEED_100:
ptr = 4;
speed_div = 100000;
break;
default:
return -EOPNOTSUPP;
netdev_err(priv->dev,
"Invalid portTransmitRate %lld (idleSlope - sendSlope)\n",
port_transmit_rate_kbps);
return -EINVAL;
}
mode_to_use = priv->plat->tx_queues_cfg[queue].mode_to_use;
@@ -398,10 +395,10 @@ static int tc_setup_cbs(struct stmmac_priv *priv,
}
/* Final adjustments for HW */
value = div_s64(qopt->idleslope * 1024ll * ptr, speed_div);
value = div_s64(qopt->idleslope * 1024ll * ptr, port_transmit_rate_kbps);
priv->plat->tx_queues_cfg[queue].idle_slope = value & GENMASK(31, 0);
value = div_s64(-qopt->sendslope * 1024ll * ptr, speed_div);
value = div_s64(-qopt->sendslope * 1024ll * ptr, port_transmit_rate_kbps);
priv->plat->tx_queues_cfg[queue].send_slope = value & GENMASK(31, 0);
value = qopt->hicredit * 1024ll * 8;

View File

@@ -919,6 +919,7 @@ static int geneve_xmit_skb(struct sk_buff *skb, struct net_device *dev,
struct geneve_dev *geneve,
const struct ip_tunnel_info *info)
{
bool inner_proto_inherit = geneve->cfg.inner_proto_inherit;
bool xnet = !net_eq(geneve->net, dev_net(geneve->dev));
struct geneve_sock *gs4 = rcu_dereference(geneve->sock4);
const struct ip_tunnel_key *key = &info->key;
@@ -930,7 +931,7 @@ static int geneve_xmit_skb(struct sk_buff *skb, struct net_device *dev,
__be16 sport;
int err;
if (!skb_vlan_inet_prepare(skb))
if (!skb_vlan_inet_prepare(skb, inner_proto_inherit))
return -EINVAL;
sport = udp_flow_src_port(geneve->net, skb, 1, USHRT_MAX, true);
@@ -1003,7 +1004,7 @@ static int geneve_xmit_skb(struct sk_buff *skb, struct net_device *dev,
}
err = geneve_build_skb(&rt->dst, skb, info, xnet, sizeof(struct iphdr),
geneve->cfg.inner_proto_inherit);
inner_proto_inherit);
if (unlikely(err))
return err;
@@ -1019,6 +1020,7 @@ static int geneve6_xmit_skb(struct sk_buff *skb, struct net_device *dev,
struct geneve_dev *geneve,
const struct ip_tunnel_info *info)
{
bool inner_proto_inherit = geneve->cfg.inner_proto_inherit;
bool xnet = !net_eq(geneve->net, dev_net(geneve->dev));
struct geneve_sock *gs6 = rcu_dereference(geneve->sock6);
const struct ip_tunnel_key *key = &info->key;
@@ -1028,7 +1030,7 @@ static int geneve6_xmit_skb(struct sk_buff *skb, struct net_device *dev,
__be16 sport;
int err;
if (!skb_vlan_inet_prepare(skb))
if (!skb_vlan_inet_prepare(skb, inner_proto_inherit))
return -EINVAL;
sport = udp_flow_src_port(geneve->net, skb, 1, USHRT_MAX, true);
@@ -1083,7 +1085,7 @@ static int geneve6_xmit_skb(struct sk_buff *skb, struct net_device *dev,
ttl = ttl ? : ip6_dst_hoplimit(dst);
}
err = geneve_build_skb(dst, skb, info, xnet, sizeof(struct ipv6hdr),
geneve->cfg.inner_proto_inherit);
inner_proto_inherit);
if (unlikely(err))
return err;

View File

@@ -2150,8 +2150,7 @@ static void sfp_sm_module(struct sfp *sfp, unsigned int event)
/* Handle remove event globally, it resets this state machine */
if (event == SFP_E_REMOVE) {
if (sfp->sm_mod_state > SFP_MOD_PROBE)
sfp_sm_mod_remove(sfp);
sfp_sm_mod_remove(sfp);
sfp_sm_mod_next(sfp, SFP_MOD_EMPTY, 0);
return;
}

View File

@@ -1493,6 +1493,10 @@ static bool vxlan_snoop(struct net_device *dev,
struct vxlan_fdb *f;
u32 ifindex = 0;
/* Ignore packets from invalid src-address */
if (!is_valid_ether_addr(src_mac))
return true;
#if IS_ENABLED(CONFIG_IPV6)
if (src_ip->sa.sa_family == AF_INET6 &&
(ipv6_addr_type(&src_ip->sin6.sin6_addr) & IPV6_ADDR_LINKLOCAL))

View File

@@ -44,6 +44,7 @@ config ATH10K_SNOC
tristate "Qualcomm ath10k SNOC support"
depends on ATH10K
depends on ARCH_QCOM || COMPILE_TEST
depends on QCOM_RPROC_COMMON || QCOM_RPROC_COMMON=n
select QCOM_SCM
select QCOM_QMI_HELPERS
help

View File

@@ -1750,8 +1750,8 @@ struct iwl_drv *iwl_drv_start(struct iwl_trans *trans)
err_fw:
#ifdef CONFIG_IWLWIFI_DEBUGFS
debugfs_remove_recursive(drv->dbgfs_drv);
iwl_dbg_tlv_free(drv->trans);
#endif
iwl_dbg_tlv_free(drv->trans);
kfree(drv);
err:
return ERR_PTR(ret);

View File

@@ -91,20 +91,10 @@ void iwl_mvm_mfu_assert_dump_notif(struct iwl_mvm *mvm,
{
struct iwl_rx_packet *pkt = rxb_addr(rxb);
struct iwl_mfu_assert_dump_notif *mfu_dump_notif = (void *)pkt->data;
__le32 *dump_data = mfu_dump_notif->data;
int n_words = le32_to_cpu(mfu_dump_notif->data_size) / sizeof(__le32);
int i;
if (mfu_dump_notif->index_num == 0)
IWL_INFO(mvm, "MFUART assert id 0x%x occurred\n",
le32_to_cpu(mfu_dump_notif->assert_id));
for (i = 0; i < n_words; i++)
IWL_DEBUG_INFO(mvm,
"MFUART assert dump, dword %u: 0x%08x\n",
le16_to_cpu(mfu_dump_notif->index_num) *
n_words + i,
le32_to_cpu(dump_data[i]));
}
static bool iwl_alive_fn(struct iwl_notif_wait_data *notif_wait,

View File

@@ -123,13 +123,8 @@ enum {
#define LINK_QUAL_AGG_FRAME_LIMIT_DEF (63)
#define LINK_QUAL_AGG_FRAME_LIMIT_MAX (63)
/*
* FIXME - various places in firmware API still use u8,
* e.g. LQ command and SCD config command.
* This should be 256 instead.
*/
#define LINK_QUAL_AGG_FRAME_LIMIT_GEN2_DEF (255)
#define LINK_QUAL_AGG_FRAME_LIMIT_GEN2_MAX (255)
#define LINK_QUAL_AGG_FRAME_LIMIT_GEN2_DEF (64)
#define LINK_QUAL_AGG_FRAME_LIMIT_GEN2_MAX (64)
#define LINK_QUAL_AGG_FRAME_LIMIT_MIN (0)
#define LQ_SIZE 2 /* 2 mode tables: "Active" and "Search" */

Some files were not shown because too many files have changed in this diff Show More