mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-05 10:31:46 +09:00
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:
2
Makefile
2
Makefile
@@ -1,7 +1,7 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
VERSION = 6
|
||||
PATCHLEVEL = 1
|
||||
SUBLEVEL = 94
|
||||
SUBLEVEL = 95
|
||||
EXTRAVERSION =
|
||||
NAME = Curry Ramen
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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>;
|
||||
|
||||
@@ -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( \
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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];
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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) ^
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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 = {
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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 = {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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[] = {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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_ */
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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 *
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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 &&
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user