
Changes in 5.10.121 binfmt_flat: do not stop relocating GOT entries prematurely on riscv parisc/stifb: Implement fb_is_primary_device() riscv: Initialize thread pointer before calling C functions riscv: Fix irq_work when SMP is disabled ALSA: hda/realtek: Enable 4-speaker output for Dell XPS 15 9520 laptop ALSA: hda/realtek - Fix microphone noise on ASUS TUF B550M-PLUS ALSA: usb-audio: Cancel pending work at closing a MIDI substream USB: serial: option: add Quectel BG95 modem USB: new quirk for Dell Gen 2 devices usb: dwc3: gadget: Move null pinter check to proper place usb: core: hcd: Add support for deferring roothub registration cifs: when extending a file with falloc we should make files not-sparse xhci: Allow host runtime PM as default for Intel Alder Lake N xHCI Fonts: Make font size unsigned in font_desc parisc/stifb: Keep track of hardware path of graphics card x86/MCE/AMD: Fix memory leak when threshold_create_bank() fails perf/x86/intel: Fix event constraints for ICL ptrace/um: Replace PT_DTRACE with TIF_SINGLESTEP ptrace/xtensa: Replace PT_SINGLESTEP with TIF_SINGLESTEP ptrace: Reimplement PTRACE_KILL by always sending SIGKILL btrfs: add "0x" prefix for unsupported optional features btrfs: repair super block num_devices automatically iommu/vt-d: Add RPLS to quirk list to skip TE disabling drm/virtio: fix NULL pointer dereference in virtio_gpu_conn_get_modes mwifiex: add mutex lock for call in mwifiex_dfs_chan_sw_work_queue b43legacy: Fix assigning negative value to unsigned variable b43: Fix assigning negative value to unsigned variable ipw2x00: Fix potential NULL dereference in libipw_xmit() ipv6: fix locking issues with loops over idev->addr_list fbcon: Consistently protect deferred_takeover with console_lock() x86/platform/uv: Update TSC sync state for UV5 ACPICA: Avoid cache flush inside virtual machines drm/komeda: return early if drm_universal_plane_init() fails. rcu-tasks: Fix race in schedule and flush work rcu: Make TASKS_RUDE_RCU select IRQ_WORK sfc: ef10: Fix assigning negative value to unsigned variable ALSA: jack: Access input_dev under mutex spi: spi-rspi: Remove setting {src,dst}_{addr,addr_width} based on DMA direction tools/power turbostat: fix ICX DRAM power numbers drm/amd/pm: fix double free in si_parse_power_table() ath9k: fix QCA9561 PA bias level media: venus: hfi: avoid null dereference in deinit media: pci: cx23885: Fix the error handling in cx23885_initdev() media: cx25821: Fix the warning when removing the module md/bitmap: don't set sb values if can't pass sanity check mmc: jz4740: Apply DMA engine limits to maximum segment size drivers: mmc: sdhci_am654: Add the quirk to set TESTCD bit scsi: megaraid: Fix error check return value of register_chrdev() scsi: ufs: Use pm_runtime_resume_and_get() instead of pm_runtime_get_sync() scsi: lpfc: Fix resource leak in lpfc_sli4_send_seq_to_ulp() ath11k: disable spectral scan during spectral deinit ASoC: Intel: bytcr_rt5640: Add quirk for the HP Pro Tablet 408 drm/plane: Move range check for format_count earlier drm/amd/pm: fix the compile warning ath10k: skip ath10k_halt during suspend for driver state RESTARTING arm64: compat: Do not treat syscall number as ESR_ELx for a bad syscall drm: msm: fix error check return value of irq_of_parse_and_map() ipv6: Don't send rs packets to the interface of ARPHRD_TUNNEL net/mlx5: fs, delete the FTE when there are no rules attached to it ASoC: dapm: Don't fold register value changes into notifications mlxsw: spectrum_dcb: Do not warn about priority changes mlxsw: Treat LLDP packets as control drm/amdgpu/ucode: Remove firmware load type check in amdgpu_ucode_free_bo HID: bigben: fix slab-out-of-bounds Write in bigben_probe ASoC: tscs454: Add endianness flag in snd_soc_component_driver net: remove two BUG() from skb_checksum_help() s390/preempt: disable __preempt_count_add() optimization for PROFILE_ALL_BRANCHES perf/amd/ibs: Cascade pmu init functions' return value spi: stm32-qspi: Fix wait_cmd timeout in APM mode dma-debug: change allocation mode from GFP_NOWAIT to GFP_ATIOMIC ACPI: PM: Block ASUS B1400CEAE from suspend to idle by default ipmi:ssif: Check for NULL msg when handling events and messages ipmi: Fix pr_fmt to avoid compilation issues rtlwifi: Use pr_warn instead of WARN_ONCE media: rga: fix possible memory leak in rga_probe media: coda: limit frame interval enumeration to supported encoder frame sizes media: imon: reorganize serialization media: cec-adap.c: fix is_configuring state openrisc: start CPU timer early in boot nvme-pci: fix a NULL pointer dereference in nvme_alloc_admin_tags ASoC: rt5645: Fix errorenous cleanup order nbd: Fix hung on disconnect request if socket is closed before net: phy: micrel: Allow probing without .driver_data media: exynos4-is: Fix compile warning ASoC: max98357a: remove dependency on GPIOLIB ASoC: rt1015p: remove dependency on GPIOLIB can: mcp251xfd: silence clang's -Wunaligned-access warning x86/microcode: Add explicit CPU vendor dependency m68k: atari: Make Atari ROM port I/O write macros return void rxrpc: Return an error to sendmsg if call failed rxrpc, afs: Fix selection of abort codes eth: tg3: silence the GCC 12 array-bounds warning selftests/bpf: fix btf_dump/btf_dump due to recent clang change gfs2: use i_lock spin_lock for inode qadata IB/rdmavt: add missing locks in rvt_ruc_loopback ARM: dts: ox820: align interrupt controller node name with dtschema ARM: dts: s5pv210: align DMA channels with dtschema arm64: dts: qcom: msm8994: Fix BLSP[12]_DMA channels count PM / devfreq: rk3399_dmc: Disable edev on remove() crypto: ccree - use fine grained DMA mapping dir soc: ti: ti_sci_pm_domains: Check for null return of devm_kcalloc fs: jfs: fix possible NULL pointer dereference in dbFree() ARM: OMAP1: clock: Fix UART rate reporting algorithm powerpc/fadump: Fix fadump to work with a different endian capture kernel fat: add ratelimit to fat*_ent_bread() pinctrl: renesas: rzn1: Fix possible null-ptr-deref in sh_pfc_map_resources() ARM: versatile: Add missing of_node_put in dcscb_init ARM: dts: exynos: add atmel,24c128 fallback to Samsung EEPROM ARM: hisi: Add missing of_node_put after of_find_compatible_node PCI: Avoid pci_dev_lock() AB/BA deadlock with sriov_numvfs_store() tracing: incorrect isolate_mote_t cast in mm_vmscan_lru_isolate powerpc/powernv/vas: Assign real address to rx_fifo in vas_rx_win_attr powerpc/xics: fix refcount leak in icp_opal_init() powerpc/powernv: fix missing of_node_put in uv_init() macintosh/via-pmu: Fix build failure when CONFIG_INPUT is disabled powerpc/iommu: Add missing of_node_put in iommu_init_early_dart RDMA/hfi1: Prevent panic when SDMA is disabled drm: fix EDID struct for old ARM OABI format dt-bindings: display: sitronix, st7735r: Fix backlight in example ath11k: acquire ab->base_lock in unassign when finding the peer by addr ath9k: fix ar9003_get_eepmisc drm/edid: fix invalid EDID extension block filtering drm/bridge: adv7511: clean up CEC adapter when probe fails spi: qcom-qspi: Add minItems to interconnect-names ASoC: mediatek: Fix error handling in mt8173_max98090_dev_probe ASoC: mediatek: Fix missing of_node_put in mt2701_wm8960_machine_probe x86/delay: Fix the wrong asm constraint in delay_loop() drm/ingenic: Reset pixclock rate when parent clock rate changes drm/mediatek: Fix mtk_cec_mask() drm/vc4: hvs: Reset muxes at probe time drm/vc4: txp: Don't set TXP_VSTART_AT_EOF drm/vc4: txp: Force alpha to be 0xff if it's disabled libbpf: Don't error out on CO-RE relos for overriden weak subprogs bpf: Fix excessive memory allocation in stack_map_alloc() nl80211: show SSID for P2P_GO interfaces drm/komeda: Fix an undefined behavior bug in komeda_plane_add() drm: mali-dp: potential dereference of null pointer spi: spi-ti-qspi: Fix return value handling of wait_for_completion_timeout scftorture: Fix distribution of short handler delays net: dsa: mt7530: 1G can also support 1000BASE-X link mode NFC: NULL out the dev->rfkill to prevent UAF efi: Add missing prototype for efi_capsule_setup_info target: remove an incorrect unmap zeroes data deduction drbd: fix duplicate array initializer EDAC/dmc520: Don't print an error for each unconfigured interrupt line mtd: rawnand: denali: Use managed device resources HID: hid-led: fix maximum brightness for Dream Cheeky HID: elan: Fix potential double free in elan_input_configured drm/bridge: Fix error handling in analogix_dp_probe sched/fair: Fix cfs_rq_clock_pelt() for throttled cfs_rq spi: img-spfi: Fix pm_runtime_get_sync() error checking cpufreq: Fix possible race in cpufreq online error path ath9k_htc: fix potential out of bounds access with invalid rxstatus->rs_keyix media: hantro: Empty encoder capture buffers by default drm/panel: simple: Add missing bus flags for Innolux G070Y2-L01 ALSA: pcm: Check for null pointer of pointer substream before dereferencing it inotify: show inotify mask flags in proc fdinfo fsnotify: fix wrong lockdep annotations of: overlay: do not break notify on NOTIFY_{OK|STOP} drm/msm/dpu: adjust display_v_end for eDP and DP scsi: ufs: qcom: Fix ufs_qcom_resume() scsi: ufs: core: Exclude UECxx from SFR dump list selftests/resctrl: Fix null pointer dereference on open failed libbpf: Fix logic for finding matching program for CO-RE relocation mtd: spi-nor: core: Check written SR value in spi_nor_write_16bit_sr_and_check() x86/pm: Fix false positive kmemleak report in msr_build_context() mtd: rawnand: cadence: fix possible null-ptr-deref in cadence_nand_dt_probe() x86/speculation: Add missing prototype for unpriv_ebpf_notify() ASoC: rk3328: fix disabling mclk on pclk probe failure perf tools: Add missing headers needed by util/data.h drm/msm/disp/dpu1: set vbif hw config to NULL to avoid use after memory free during pm runtime resume drm/msm/dp: stop event kernel thread when DP unbind drm/msm/dp: fix error check return value of irq_of_parse_and_map() drm/msm/dsi: fix error checks and return values for DSI xmit functions drm/msm/hdmi: check return value after calling platform_get_resource_byname() drm/msm/hdmi: fix error check return value of irq_of_parse_and_map() drm/msm: add missing include to msm_drv.c drm/panel: panel-simple: Fix proper bpc for AM-1280800N3TZQW-T00H drm/rockchip: vop: fix possible null-ptr-deref in vop_bind() perf tools: Use Python devtools for version autodetection rather than runtime virtio_blk: fix the discard_granularity and discard_alignment queue limits x86: Fix return value of __setup handlers irqchip/exiu: Fix acknowledgment of edge triggered interrupts irqchip/aspeed-i2c-ic: Fix irq_of_parse_and_map() return value irqchip/aspeed-scu-ic: Fix irq_of_parse_and_map() return value x86/mm: Cleanup the control_va_addr_alignment() __setup handler arm64: fix types in copy_highpage() regulator: core: Fix enable_count imbalance with EXCLUSIVE_GET drm/msm/dp: fix event thread stuck in wait_event after kthread_stop() drm/msm/mdp5: Return error code in mdp5_pipe_release when deadlock is detected drm/msm/mdp5: Return error code in mdp5_mixer_release when deadlock is detected drm/msm: return an error pointer in msm_gem_prime_get_sg_table() media: uvcvideo: Fix missing check to determine if element is found in list iomap: iomap_write_failed fix spi: spi-fsl-qspi: check return value after calling platform_get_resource_byname() Revert "cpufreq: Fix possible race in cpufreq online error path" regulator: qcom_smd: Fix up PM8950 regulator configuration perf/amd/ibs: Use interrupt regs ip for stack unwinding ath11k: Don't check arvif->is_started before sending management frames ASoC: fsl: Fix refcount leak in imx_sgtl5000_probe ASoC: mxs-saif: Fix refcount leak in mxs_saif_probe regulator: pfuze100: Fix refcount leak in pfuze_parse_regulators_dt ASoC: samsung: Use dev_err_probe() helper ASoC: samsung: Fix refcount leak in aries_audio_probe kselftest/cgroup: fix test_stress.sh to use OUTPUT dir scripts/faddr2line: Fix overlapping text section failures media: aspeed: Fix an error handling path in aspeed_video_probe() media: exynos4-is: Fix PM disable depth imbalance in fimc_is_probe media: st-delta: Fix PM disable depth imbalance in delta_probe media: exynos4-is: Change clk_disable to clk_disable_unprepare media: pvrusb2: fix array-index-out-of-bounds in pvr2_i2c_core_init media: vsp1: Fix offset calculation for plane cropping Bluetooth: fix dangling sco_conn and use-after-free in sco_sock_timeout Bluetooth: Interleave with allowlist scan Bluetooth: L2CAP: Rudimentary typo fixes Bluetooth: LL privacy allow RPA Bluetooth: use inclusive language in HCI role comments Bluetooth: use inclusive language when filtering devices Bluetooth: use hdev lock for accept_list and reject_list in conn req nvme: set dma alignment to dword m68k: math-emu: Fix dependencies of math emulation support lsm,selinux: pass flowi_common instead of flowi to the LSM hooks sctp: read sk->sk_bound_dev_if once in sctp_rcv() net: hinic: add missing destroy_workqueue in hinic_pf_to_mgmt_init ASoC: ti: j721e-evm: Fix refcount leak in j721e_soc_probe_* media: ov7670: remove ov7670_power_off from ov7670_remove media: staging: media: rkvdec: Make use of the helper function devm_platform_ioremap_resource() media: rkvdec: h264: Fix dpb_valid implementation media: rkvdec: h264: Fix bit depth wrap in pps packet ext4: reject the 'commit' option on ext2 filesystems drm/msm/a6xx: Fix refcount leak in a6xx_gpu_init drm: msm: fix possible memory leak in mdp5_crtc_cursor_set() x86/sev: Annotate stack change in the #VC handler drm/msm/dpu: handle pm_runtime_get_sync() errors in bind path drm/i915: Fix CFI violation with show_dynamic_id() thermal/drivers/bcm2711: Don't clamp temperature at zero thermal/drivers/broadcom: Fix potential NULL dereference in sr_thermal_probe thermal/drivers/core: Use a char pointer for the cooling device name thermal/core: Fix memory leak in __thermal_cooling_device_register() thermal/drivers/imx_sc_thermal: Fix refcount leak in imx_sc_thermal_probe ASoC: wm2000: fix missing clk_disable_unprepare() on error in wm2000_anc_transition() NFC: hci: fix sleep in atomic context bugs in nfc_hci_hcp_message_tx ASoC: max98090: Move check for invalid values before casting in max98090_put_enab_tlv() net: stmmac: selftests: Use kcalloc() instead of kzalloc() net: stmmac: fix out-of-bounds access in a selftest hv_netvsc: Fix potential dereference of NULL pointer rxrpc: Fix listen() setting the bar too high for the prealloc rings rxrpc: Don't try to resend the request if we're receiving the reply rxrpc: Fix overlapping ACK accounting rxrpc: Don't let ack.previousPacket regress rxrpc: Fix decision on when to generate an IDLE ACK net: huawei: hinic: Use devm_kcalloc() instead of devm_kzalloc() hinic: Avoid some over memory allocation net/smc: postpone sk_refcnt increment in connect() arm64: dts: rockchip: Move drive-impedance-ohm to emmc phy on rk3399 memory: samsung: exynos5422-dmc: Avoid some over memory allocation ARM: dts: suniv: F1C100: fix watchdog compatible soc: qcom: smp2p: Fix missing of_node_put() in smp2p_parse_ipc soc: qcom: smsm: Fix missing of_node_put() in smsm_parse_ipc PCI: cadence: Fix find_first_zero_bit() limit PCI: rockchip: Fix find_first_zero_bit() limit PCI: dwc: Fix setting error return on MSI DMA mapping failure ARM: dts: ci4x10: Adapt to changes in imx6qdl.dtsi regarding fec clocks soc: qcom: llcc: Add MODULE_DEVICE_TABLE() KVM: nVMX: Leave most VM-Exit info fields unmodified on failed VM-Entry KVM: nVMX: Clear IDT vectoring on nested VM-Exit for double/triple fault platform/chrome: cros_ec: fix error handling in cros_ec_register() ARM: dts: imx6dl-colibri: Fix I2C pinmuxing platform/chrome: Re-introduce cros_ec_cmd_xfer and use it for ioctls can: xilinx_can: mark bit timing constants as const ARM: dts: stm32: Fix PHY post-reset delay on Avenger96 ARM: dts: bcm2835-rpi-zero-w: Fix GPIO line name for Wifi/BT ARM: dts: bcm2837-rpi-cm3-io3: Fix GPIO line names for SMPS I2C ARM: dts: bcm2837-rpi-3-b-plus: Fix GPIO line name of power LED ARM: dts: bcm2835-rpi-b: Fix GPIO line names misc: ocxl: fix possible double free in ocxl_file_register_afu crypto: marvell/cesa - ECB does not IV gpiolib: of: Introduce hook for missing gpio-ranges pinctrl: bcm2835: implement hook for missing gpio-ranges arm: mediatek: select arch timer for mt7629 powerpc/fadump: fix PT_LOAD segment for boot memory area mfd: ipaq-micro: Fix error check return value of platform_get_irq() scsi: fcoe: Fix Wstringop-overflow warnings in fcoe_wwn_from_mac() firmware: arm_scmi: Fix list protocols enumeration in the base protocol nvdimm: Fix firmware activation deadlock scenarios nvdimm: Allow overwrite in the presence of disabled dimms pinctrl: mvebu: Fix irq_of_parse_and_map() return value drivers/base/node.c: fix compaction sysfs file leak dax: fix cache flush on PMD-mapped pages drivers/base/memory: fix an unlikely reference counting issue in __add_memory_block() powerpc/8xx: export 'cpm_setbrg' for modules pinctrl: renesas: core: Fix possible null-ptr-deref in sh_pfc_map_resources() powerpc/idle: Fix return value of __setup() handler powerpc/4xx/cpm: Fix return value of __setup() handler ASoC: atmel-pdmic: Remove endianness flag on pdmic component ASoC: atmel-classd: Remove endianness flag on class d component proc: fix dentry/inode overinstantiating under /proc/${pid}/net ipc/mqueue: use get_tree_nodev() in mqueue_get_tree() PCI: imx6: Fix PERST# start-up sequence tty: fix deadlock caused by calling printk() under tty_port->lock crypto: sun8i-ss - rework handling of IV crypto: sun8i-ss - handle zero sized sg crypto: cryptd - Protect per-CPU resource by disabling BH. Input: sparcspkr - fix refcount leak in bbc_beep_probe PCI/AER: Clear MULTI_ERR_COR/UNCOR_RCV bits hwrng: omap3-rom - fix using wrong clk_disable() in omap_rom_rng_runtime_resume() powerpc/64: Only WARN if __pa()/__va() called with bad addresses powerpc/perf: Fix the threshold compare group constraint for power9 macintosh: via-pmu and via-cuda need RTC_LIB powerpc/fsl_rio: Fix refcount leak in fsl_rio_setup mfd: davinci_voicecodec: Fix possible null-ptr-deref davinci_vc_probe() mailbox: forward the hrtimer if not queued and under a lock RDMA/hfi1: Prevent use of lock before it is initialized Input: stmfts - do not leave device disabled in stmfts_input_open OPP: call of_node_put() on error path in _bandwidth_supported() f2fs: fix dereference of stale list iterator after loop body iommu/mediatek: Add list_del in mtk_iommu_remove i2c: at91: use dma safe buffers cpufreq: mediatek: add missing platform_driver_unregister() on error in mtk_cpufreq_driver_init cpufreq: mediatek: Use module_init and add module_exit cpufreq: mediatek: Unregister platform device on exit MIPS: Loongson: Use hwmon_device_register_with_groups() to register hwmon i2c: at91: Initialize dma_buf in at91_twi_xfer() dmaengine: idxd: Fix the error handling path in idxd_cdev_register() NFS: Do not report EINTR/ERESTARTSYS as mapping errors NFS: fsync() should report filesystem errors over EINTR/ERESTARTSYS NFS: Do not report flush errors in nfs_write_end() NFS: Don't report errors from nfs_pageio_complete() more than once NFSv4/pNFS: Do not fail I/O when we fail to allocate the pNFS layout video: fbdev: clcdfb: Fix refcount leak in clcdfb_of_vram_setup dmaengine: stm32-mdma: remove GISR1 register dmaengine: stm32-mdma: rework interrupt handler dmaengine: stm32-mdma: fix chan initialization in stm32_mdma_irq_handler() iommu/amd: Increase timeout waiting for GA log enablement i2c: npcm: Fix timeout calculation i2c: npcm: Correct register access width i2c: npcm: Handle spurious interrupts i2c: rcar: fix PM ref counts in probe error paths perf c2c: Use stdio interface if slang is not supported perf jevents: Fix event syntax error caused by ExtSel f2fs: fix to avoid f2fs_bug_on() in dec_valid_node_count() f2fs: fix to do sanity check on block address in f2fs_do_zero_range() f2fs: fix to clear dirty inode in f2fs_evict_inode() f2fs: fix deadloop in foreground GC f2fs: don't need inode lock for system hidden quota f2fs: fix to do sanity check on total_data_blocks f2fs: fix fallocate to use file_modified to update permissions consistently f2fs: fix to do sanity check for inline inode wifi: mac80211: fix use-after-free in chanctx code iwlwifi: mvm: fix assert 1F04 upon reconfig fs-writeback: writeback_sb_inodes:Recalculate 'wrote' according skipped pages efi: Do not import certificates from UEFI Secure Boot for T2 Macs bfq: Split shared queues on move between cgroups bfq: Update cgroup information before merging bio bfq: Track whether bfq_group is still online ext4: fix use-after-free in ext4_rename_dir_prepare ext4: fix warning in ext4_handle_inode_extension ext4: fix bug_on in ext4_writepages ext4: filter out EXT4_FC_REPLAY from on-disk superblock field s_state ext4: fix bug_on in __es_tree_search ext4: verify dir block before splitting it ext4: avoid cycles in directory h-tree ACPI: property: Release subnode properties with data nodes tracing: Fix potential double free in create_var_ref() PCI/PM: Fix bridge_d3_blacklist[] Elo i2 overwrite of Gigabyte X299 PCI: qcom: Fix runtime PM imbalance on probe errors PCI: qcom: Fix unbalanced PHY init on probe errors mm, compaction: fast_find_migrateblock() should return pfn in the target zone s390/perf: obtain sie_block from the right address dlm: fix plock invalid read dlm: fix missing lkb refcount handling ocfs2: dlmfs: fix error handling of user_dlm_destroy_lock scsi: dc395x: Fix a missing check on list iterator scsi: ufs: qcom: Add a readl() to make sure ref_clk gets enabled drm/amdgpu/cs: make commands with 0 chunks illegal behaviour. drm/etnaviv: check for reaped mapping in etnaviv_iommu_unmap_gem drm/nouveau/clk: Fix an incorrect NULL check on list iterator drm/nouveau/kms/nv50-: atom: fix an incorrect NULL check on list iterator drm/bridge: analogix_dp: Grab runtime PM reference for DP-AUX drm/i915/dsi: fix VBT send packet port selection for ICL+ md: fix an incorrect NULL check in does_sb_need_changing md: fix an incorrect NULL check in md_reload_sb mtd: cfi_cmdset_0002: Move and rename chip_check/chip_ready/chip_good_for_write mtd: cfi_cmdset_0002: Use chip_ready() for write on S29GL064N media: coda: Fix reported H264 profile media: coda: Add more H264 levels for CODA960 ima: remove the IMA_TEMPLATE Kconfig option Kconfig: Add option for asm goto w/ tied outputs to workaround clang-13 bug RDMA/hfi1: Fix potential integer multiplication overflow errors csky: patch_text: Fixup last cpu should be master irqchip/armada-370-xp: Do not touch Performance Counter Overflow on A375, A38x, A39x irqchip: irq-xtensa-mx: fix initial IRQ affinity cfg80211: declare MODULE_FIRMWARE for regulatory.db mac80211: upgrade passive scan to active scan on DFS channels after beacon rx um: chan_user: Fix winch_tramp() return value um: Fix out-of-bounds read in LDT setup kexec_file: drop weak attribute from arch_kexec_apply_relocations[_add] ftrace: Clean up hash direct_functions on register failures iommu/msm: Fix an incorrect NULL check on list iterator nodemask.h: fix compilation error with GCC12 hugetlb: fix huge_pmd_unshare address update xtensa/simdisk: fix proc_read_simdisk() rtl818x: Prevent using not initialized queues ASoC: rt5514: Fix event generation for "DSP Voice Wake Up" control carl9170: tx: fix an incorrect use of list iterator stm: ltdc: fix two incorrect NULL checks on list iterator bcache: improve multithreaded bch_btree_check() bcache: improve multithreaded bch_sectors_dirty_init() bcache: remove incremental dirty sector counting for bch_sectors_dirty_init() bcache: avoid journal no-space deadlock by reserving 1 journal bucket serial: pch: don't overwrite xmit->buf[0] by x_char tilcdc: tilcdc_external: fix an incorrect NULL check on list iterator gma500: fix an incorrect NULL check on list iterator arm64: dts: qcom: ipq8074: fix the sleep clock frequency phy: qcom-qmp: fix struct clk leak on probe errors ARM: dts: s5pv210: Remove spi-cs-high on panel in Aries ARM: pxa: maybe fix gpio lookup tables SMB3: EBADF/EIO errors in rename/open caused by race condition in smb2_compound_op docs/conf.py: Cope with removal of language=None in Sphinx 5.0.0 dt-bindings: gpio: altera: correct interrupt-cells vdpasim: allow to enable a vq repeatedly blk-iolatency: Fix inflight count imbalances and IO hangs on offline coresight: core: Fix coresight device probe failure issue phy: qcom-qmp: fix reset-controller leak on probe errors net: ipa: fix page free in ipa_endpoint_trans_release() net: ipa: fix page free in ipa_endpoint_replenish_one() xfs: set inode size after creating symlink xfs: sync lazy sb accounting on quiesce of read-only mounts xfs: fix chown leaking delalloc quota blocks when fssetxattr fails xfs: fix incorrect root dquot corruption error when switching group/project quota types xfs: restore shutdown check in mapped write fault path xfs: force log and push AIL to clear pinned inodes when aborting mount xfs: consider shutdown in bmapbt cursor delete assert xfs: assert in xfs_btree_del_cursor should take into account error kseltest/cgroup: Make test_stress.sh work if run interactively thermal/core: fix a UAF bug in __thermal_cooling_device_register() thermal/core: Fix memory leak in the error path bfq: Avoid merging queues with different parents bfq: Drop pointless unlock-lock pair bfq: Remove pointless bfq_init_rq() calls bfq: Get rid of __bio_blkcg() usage bfq: Make sure bfqg for which we are queueing requests is online block: fix bio_clone_blkg_association() to associate with proper blkcg_gq Revert "random: use static branch for crng_ready()" RDMA/rxe: Generate a completion for unsupported/invalid opcode MIPS: IP27: Remove incorrect `cpu_has_fpu' override MIPS: IP30: Remove incorrect `cpu_has_fpu' override ext4: only allow test_dummy_encryption when supported md: bcache: check the return value of kzalloc() in detached_dev_do_request() Linux 5.10.121 Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> Change-Id: I52dd11dc43acfa0ebddd2b6e277c823b96b07327
620 lines
16 KiB
C
620 lines
16 KiB
C
// SPDX-License-Identifier: GPL-2.0
|
|
/*
|
|
* Synopsys DesignWare PCIe host controller driver
|
|
*
|
|
* Copyright (C) 2013 Samsung Electronics Co., Ltd.
|
|
* https://www.samsung.com
|
|
*
|
|
* Author: Jingoo Han <jg1.han@samsung.com>
|
|
*/
|
|
|
|
#include <linux/irqchip/chained_irq.h>
|
|
#include <linux/irqdomain.h>
|
|
#include <linux/msi.h>
|
|
#include <linux/of_address.h>
|
|
#include <linux/of_pci.h>
|
|
#include <linux/pci_regs.h>
|
|
#include <linux/platform_device.h>
|
|
|
|
#include "../../pci.h"
|
|
#include "pcie-designware.h"
|
|
|
|
static struct pci_ops dw_pcie_ops;
|
|
static struct pci_ops dw_child_pcie_ops;
|
|
|
|
static void dw_msi_ack_irq(struct irq_data *d)
|
|
{
|
|
irq_chip_ack_parent(d);
|
|
}
|
|
|
|
static void dw_msi_mask_irq(struct irq_data *d)
|
|
{
|
|
pci_msi_mask_irq(d);
|
|
irq_chip_mask_parent(d);
|
|
}
|
|
|
|
static void dw_msi_unmask_irq(struct irq_data *d)
|
|
{
|
|
pci_msi_unmask_irq(d);
|
|
irq_chip_unmask_parent(d);
|
|
}
|
|
|
|
static struct irq_chip dw_pcie_msi_irq_chip = {
|
|
.name = "PCI-MSI",
|
|
.irq_ack = dw_msi_ack_irq,
|
|
.irq_mask = dw_msi_mask_irq,
|
|
.irq_unmask = dw_msi_unmask_irq,
|
|
};
|
|
|
|
static struct msi_domain_info dw_pcie_msi_domain_info = {
|
|
.flags = (MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS |
|
|
MSI_FLAG_PCI_MSIX | MSI_FLAG_MULTI_PCI_MSI),
|
|
.chip = &dw_pcie_msi_irq_chip,
|
|
};
|
|
|
|
/* MSI int handler */
|
|
irqreturn_t dw_handle_msi_irq(struct pcie_port *pp)
|
|
{
|
|
int i, pos, irq;
|
|
unsigned long val;
|
|
u32 status, num_ctrls;
|
|
irqreturn_t ret = IRQ_NONE;
|
|
struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
|
|
|
|
num_ctrls = pp->num_vectors / MAX_MSI_IRQS_PER_CTRL;
|
|
|
|
for (i = 0; i < num_ctrls; i++) {
|
|
status = dw_pcie_readl_dbi(pci, PCIE_MSI_INTR0_STATUS +
|
|
(i * MSI_REG_CTRL_BLOCK_SIZE));
|
|
if (!status)
|
|
continue;
|
|
|
|
ret = IRQ_HANDLED;
|
|
val = status;
|
|
pos = 0;
|
|
while ((pos = find_next_bit(&val, MAX_MSI_IRQS_PER_CTRL,
|
|
pos)) != MAX_MSI_IRQS_PER_CTRL) {
|
|
irq = irq_find_mapping(pp->irq_domain,
|
|
(i * MAX_MSI_IRQS_PER_CTRL) +
|
|
pos);
|
|
generic_handle_irq(irq);
|
|
pos++;
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
EXPORT_SYMBOL_GPL(dw_handle_msi_irq);
|
|
|
|
/* Chained MSI interrupt service routine */
|
|
static void dw_chained_msi_isr(struct irq_desc *desc)
|
|
{
|
|
struct irq_chip *chip = irq_desc_get_chip(desc);
|
|
struct pcie_port *pp;
|
|
|
|
chained_irq_enter(chip, desc);
|
|
|
|
pp = irq_desc_get_handler_data(desc);
|
|
dw_handle_msi_irq(pp);
|
|
|
|
chained_irq_exit(chip, desc);
|
|
}
|
|
|
|
static void dw_pci_setup_msi_msg(struct irq_data *d, struct msi_msg *msg)
|
|
{
|
|
struct pcie_port *pp = irq_data_get_irq_chip_data(d);
|
|
struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
|
|
u64 msi_target;
|
|
|
|
msi_target = (u64)pp->msi_data;
|
|
|
|
msg->address_lo = lower_32_bits(msi_target);
|
|
msg->address_hi = upper_32_bits(msi_target);
|
|
|
|
msg->data = d->hwirq;
|
|
|
|
dev_dbg(pci->dev, "msi#%d address_hi %#x address_lo %#x\n",
|
|
(int)d->hwirq, msg->address_hi, msg->address_lo);
|
|
}
|
|
|
|
static int dw_pci_msi_set_affinity(struct irq_data *d,
|
|
const struct cpumask *mask, bool force)
|
|
{
|
|
return -EINVAL;
|
|
}
|
|
|
|
static void dw_pci_bottom_mask(struct irq_data *d)
|
|
{
|
|
struct pcie_port *pp = irq_data_get_irq_chip_data(d);
|
|
struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
|
|
unsigned int res, bit, ctrl;
|
|
unsigned long flags;
|
|
|
|
raw_spin_lock_irqsave(&pp->lock, flags);
|
|
|
|
ctrl = d->hwirq / MAX_MSI_IRQS_PER_CTRL;
|
|
res = ctrl * MSI_REG_CTRL_BLOCK_SIZE;
|
|
bit = d->hwirq % MAX_MSI_IRQS_PER_CTRL;
|
|
|
|
pp->irq_mask[ctrl] |= BIT(bit);
|
|
dw_pcie_writel_dbi(pci, PCIE_MSI_INTR0_MASK + res, pp->irq_mask[ctrl]);
|
|
|
|
raw_spin_unlock_irqrestore(&pp->lock, flags);
|
|
}
|
|
|
|
static void dw_pci_bottom_unmask(struct irq_data *d)
|
|
{
|
|
struct pcie_port *pp = irq_data_get_irq_chip_data(d);
|
|
struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
|
|
unsigned int res, bit, ctrl;
|
|
unsigned long flags;
|
|
|
|
raw_spin_lock_irqsave(&pp->lock, flags);
|
|
|
|
ctrl = d->hwirq / MAX_MSI_IRQS_PER_CTRL;
|
|
res = ctrl * MSI_REG_CTRL_BLOCK_SIZE;
|
|
bit = d->hwirq % MAX_MSI_IRQS_PER_CTRL;
|
|
|
|
pp->irq_mask[ctrl] &= ~BIT(bit);
|
|
dw_pcie_writel_dbi(pci, PCIE_MSI_INTR0_MASK + res, pp->irq_mask[ctrl]);
|
|
|
|
raw_spin_unlock_irqrestore(&pp->lock, flags);
|
|
}
|
|
|
|
static void dw_pci_bottom_ack(struct irq_data *d)
|
|
{
|
|
struct pcie_port *pp = irq_data_get_irq_chip_data(d);
|
|
struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
|
|
unsigned int res, bit, ctrl;
|
|
|
|
ctrl = d->hwirq / MAX_MSI_IRQS_PER_CTRL;
|
|
res = ctrl * MSI_REG_CTRL_BLOCK_SIZE;
|
|
bit = d->hwirq % MAX_MSI_IRQS_PER_CTRL;
|
|
|
|
dw_pcie_writel_dbi(pci, PCIE_MSI_INTR0_STATUS + res, BIT(bit));
|
|
}
|
|
|
|
static struct irq_chip dw_pci_msi_bottom_irq_chip = {
|
|
.name = "DWPCI-MSI",
|
|
.irq_ack = dw_pci_bottom_ack,
|
|
.irq_compose_msi_msg = dw_pci_setup_msi_msg,
|
|
.irq_set_affinity = dw_pci_msi_set_affinity,
|
|
.irq_mask = dw_pci_bottom_mask,
|
|
.irq_unmask = dw_pci_bottom_unmask,
|
|
};
|
|
|
|
static int dw_pcie_irq_domain_alloc(struct irq_domain *domain,
|
|
unsigned int virq, unsigned int nr_irqs,
|
|
void *args)
|
|
{
|
|
struct pcie_port *pp = domain->host_data;
|
|
unsigned long flags;
|
|
u32 i;
|
|
int bit;
|
|
|
|
raw_spin_lock_irqsave(&pp->lock, flags);
|
|
|
|
bit = bitmap_find_free_region(pp->msi_irq_in_use, pp->num_vectors,
|
|
order_base_2(nr_irqs));
|
|
|
|
raw_spin_unlock_irqrestore(&pp->lock, flags);
|
|
|
|
if (bit < 0)
|
|
return -ENOSPC;
|
|
|
|
for (i = 0; i < nr_irqs; i++)
|
|
irq_domain_set_info(domain, virq + i, bit + i,
|
|
pp->msi_irq_chip,
|
|
pp, handle_edge_irq,
|
|
NULL, NULL);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void dw_pcie_irq_domain_free(struct irq_domain *domain,
|
|
unsigned int virq, unsigned int nr_irqs)
|
|
{
|
|
struct irq_data *d = irq_domain_get_irq_data(domain, virq);
|
|
struct pcie_port *pp = domain->host_data;
|
|
unsigned long flags;
|
|
|
|
raw_spin_lock_irqsave(&pp->lock, flags);
|
|
|
|
bitmap_release_region(pp->msi_irq_in_use, d->hwirq,
|
|
order_base_2(nr_irqs));
|
|
|
|
raw_spin_unlock_irqrestore(&pp->lock, flags);
|
|
}
|
|
|
|
static const struct irq_domain_ops dw_pcie_msi_domain_ops = {
|
|
.alloc = dw_pcie_irq_domain_alloc,
|
|
.free = dw_pcie_irq_domain_free,
|
|
};
|
|
|
|
int dw_pcie_allocate_domains(struct pcie_port *pp)
|
|
{
|
|
struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
|
|
struct fwnode_handle *fwnode = of_node_to_fwnode(pci->dev->of_node);
|
|
|
|
pp->irq_domain = irq_domain_create_linear(fwnode, pp->num_vectors,
|
|
&dw_pcie_msi_domain_ops, pp);
|
|
if (!pp->irq_domain) {
|
|
dev_err(pci->dev, "Failed to create IRQ domain\n");
|
|
return -ENOMEM;
|
|
}
|
|
|
|
irq_domain_update_bus_token(pp->irq_domain, DOMAIN_BUS_NEXUS);
|
|
|
|
pp->msi_domain = pci_msi_create_irq_domain(fwnode,
|
|
&dw_pcie_msi_domain_info,
|
|
pp->irq_domain);
|
|
if (!pp->msi_domain) {
|
|
dev_err(pci->dev, "Failed to create MSI domain\n");
|
|
irq_domain_remove(pp->irq_domain);
|
|
return -ENOMEM;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
void dw_pcie_free_msi(struct pcie_port *pp)
|
|
{
|
|
if (pp->msi_irq) {
|
|
irq_set_chained_handler(pp->msi_irq, NULL);
|
|
irq_set_handler_data(pp->msi_irq, NULL);
|
|
}
|
|
|
|
irq_domain_remove(pp->msi_domain);
|
|
irq_domain_remove(pp->irq_domain);
|
|
|
|
if (pp->msi_data) {
|
|
struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
|
|
struct device *dev = pci->dev;
|
|
|
|
dma_unmap_single_attrs(dev, pp->msi_data, sizeof(pp->msi_msg),
|
|
DMA_FROM_DEVICE, DMA_ATTR_SKIP_CPU_SYNC);
|
|
}
|
|
}
|
|
|
|
void dw_pcie_msi_init(struct pcie_port *pp)
|
|
{
|
|
struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
|
|
u64 msi_target = (u64)pp->msi_data;
|
|
|
|
if (!IS_ENABLED(CONFIG_PCI_MSI))
|
|
return;
|
|
|
|
/* Program the msi_data */
|
|
dw_pcie_writel_dbi(pci, PCIE_MSI_ADDR_LO, lower_32_bits(msi_target));
|
|
dw_pcie_writel_dbi(pci, PCIE_MSI_ADDR_HI, upper_32_bits(msi_target));
|
|
}
|
|
EXPORT_SYMBOL_GPL(dw_pcie_msi_init);
|
|
|
|
int dw_pcie_host_init(struct pcie_port *pp)
|
|
{
|
|
struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
|
|
struct device *dev = pci->dev;
|
|
struct device_node *np = dev->of_node;
|
|
struct platform_device *pdev = to_platform_device(dev);
|
|
struct resource_entry *win;
|
|
struct pci_host_bridge *bridge;
|
|
struct resource *cfg_res;
|
|
int ret;
|
|
|
|
raw_spin_lock_init(&pci->pp.lock);
|
|
|
|
cfg_res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "config");
|
|
if (cfg_res) {
|
|
pp->cfg0_size = resource_size(cfg_res);
|
|
pp->cfg0_base = cfg_res->start;
|
|
} else if (!pp->va_cfg0_base) {
|
|
dev_err(dev, "Missing *config* reg space\n");
|
|
}
|
|
|
|
bridge = devm_pci_alloc_host_bridge(dev, 0);
|
|
if (!bridge)
|
|
return -ENOMEM;
|
|
|
|
pp->bridge = bridge;
|
|
|
|
/* Get the I/O and memory ranges from DT */
|
|
resource_list_for_each_entry(win, &bridge->windows) {
|
|
switch (resource_type(win->res)) {
|
|
case IORESOURCE_IO:
|
|
pp->io_size = resource_size(win->res);
|
|
pp->io_bus_addr = win->res->start - win->offset;
|
|
pp->io_base = pci_pio_to_address(win->res->start);
|
|
break;
|
|
case 0:
|
|
dev_err(dev, "Missing *config* reg space\n");
|
|
pp->cfg0_size = resource_size(win->res);
|
|
pp->cfg0_base = win->res->start;
|
|
if (!pci->dbi_base) {
|
|
pci->dbi_base = devm_pci_remap_cfgspace(dev,
|
|
pp->cfg0_base,
|
|
pp->cfg0_size);
|
|
if (!pci->dbi_base) {
|
|
dev_err(dev, "Error with ioremap\n");
|
|
return -ENOMEM;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!pp->va_cfg0_base) {
|
|
pp->va_cfg0_base = devm_pci_remap_cfgspace(dev,
|
|
pp->cfg0_base, pp->cfg0_size);
|
|
if (!pp->va_cfg0_base) {
|
|
dev_err(dev, "Error with ioremap in function\n");
|
|
return -ENOMEM;
|
|
}
|
|
}
|
|
|
|
ret = of_property_read_u32(np, "num-viewport", &pci->num_viewport);
|
|
if (ret)
|
|
pci->num_viewport = 2;
|
|
|
|
if (pci->link_gen < 1)
|
|
pci->link_gen = of_pci_get_max_link_speed(np);
|
|
|
|
if (pci_msi_enabled()) {
|
|
/*
|
|
* If a specific SoC driver needs to change the
|
|
* default number of vectors, it needs to implement
|
|
* the set_num_vectors callback.
|
|
*/
|
|
if (!pp->ops->set_num_vectors) {
|
|
pp->num_vectors = MSI_DEF_NUM_VECTORS;
|
|
} else {
|
|
pp->ops->set_num_vectors(pp);
|
|
|
|
if (pp->num_vectors > MAX_MSI_IRQS ||
|
|
pp->num_vectors == 0) {
|
|
dev_err(dev,
|
|
"Invalid number of vectors\n");
|
|
return -EINVAL;
|
|
}
|
|
}
|
|
|
|
if (!pp->ops->msi_host_init) {
|
|
pp->msi_irq_chip = &dw_pci_msi_bottom_irq_chip;
|
|
|
|
ret = dw_pcie_allocate_domains(pp);
|
|
if (ret)
|
|
return ret;
|
|
|
|
if (pp->msi_irq)
|
|
irq_set_chained_handler_and_data(pp->msi_irq,
|
|
dw_chained_msi_isr,
|
|
pp);
|
|
|
|
pp->msi_data = dma_map_single_attrs(pci->dev, &pp->msi_msg,
|
|
sizeof(pp->msi_msg),
|
|
DMA_FROM_DEVICE,
|
|
DMA_ATTR_SKIP_CPU_SYNC);
|
|
ret = dma_mapping_error(pci->dev, pp->msi_data);
|
|
if (ret) {
|
|
dev_err(pci->dev, "Failed to map MSI data\n");
|
|
pp->msi_data = 0;
|
|
goto err_free_msi;
|
|
}
|
|
} else {
|
|
ret = pp->ops->msi_host_init(pp);
|
|
if (ret < 0)
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
/* Set default bus ops */
|
|
bridge->ops = &dw_pcie_ops;
|
|
bridge->child_ops = &dw_child_pcie_ops;
|
|
|
|
if (pp->ops->host_init) {
|
|
ret = pp->ops->host_init(pp);
|
|
if (ret)
|
|
goto err_free_msi;
|
|
}
|
|
|
|
bridge->sysdata = pp;
|
|
|
|
ret = pci_host_probe(bridge);
|
|
if (!ret)
|
|
return 0;
|
|
|
|
err_free_msi:
|
|
if (pci_msi_enabled() && !pp->ops->msi_host_init)
|
|
dw_pcie_free_msi(pp);
|
|
return ret;
|
|
}
|
|
EXPORT_SYMBOL_GPL(dw_pcie_host_init);
|
|
|
|
void dw_pcie_host_deinit(struct pcie_port *pp)
|
|
{
|
|
pci_stop_root_bus(pp->bridge->bus);
|
|
pci_remove_root_bus(pp->bridge->bus);
|
|
if (pci_msi_enabled() && !pp->ops->msi_host_init)
|
|
dw_pcie_free_msi(pp);
|
|
}
|
|
EXPORT_SYMBOL_GPL(dw_pcie_host_deinit);
|
|
|
|
static void __iomem *dw_pcie_other_conf_map_bus(struct pci_bus *bus,
|
|
unsigned int devfn, int where)
|
|
{
|
|
int type;
|
|
u32 busdev;
|
|
struct pcie_port *pp = bus->sysdata;
|
|
struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
|
|
|
|
/*
|
|
* Checking whether the link is up here is a last line of defense
|
|
* against platforms that forward errors on the system bus as
|
|
* SError upon PCI configuration transactions issued when the link
|
|
* is down. This check is racy by definition and does not stop
|
|
* the system from triggering an SError if the link goes down
|
|
* after this check is performed.
|
|
*/
|
|
if (!dw_pcie_link_up(pci))
|
|
return NULL;
|
|
|
|
busdev = PCIE_ATU_BUS(bus->number) | PCIE_ATU_DEV(PCI_SLOT(devfn)) |
|
|
PCIE_ATU_FUNC(PCI_FUNC(devfn));
|
|
|
|
if (pci_is_root_bus(bus->parent))
|
|
type = PCIE_ATU_TYPE_CFG0;
|
|
else
|
|
type = PCIE_ATU_TYPE_CFG1;
|
|
|
|
|
|
dw_pcie_prog_outbound_atu(pci, PCIE_ATU_REGION_INDEX1,
|
|
type, pp->cfg0_base,
|
|
busdev, pp->cfg0_size);
|
|
|
|
return pp->va_cfg0_base + where;
|
|
}
|
|
|
|
static int dw_pcie_rd_other_conf(struct pci_bus *bus, unsigned int devfn,
|
|
int where, int size, u32 *val)
|
|
{
|
|
int ret;
|
|
struct pcie_port *pp = bus->sysdata;
|
|
struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
|
|
|
|
ret = pci_generic_config_read(bus, devfn, where, size, val);
|
|
|
|
if (!ret && pci->num_viewport <= 2)
|
|
dw_pcie_prog_outbound_atu(pci, PCIE_ATU_REGION_INDEX1,
|
|
PCIE_ATU_TYPE_IO, pp->io_base,
|
|
pp->io_bus_addr, pp->io_size);
|
|
|
|
return ret;
|
|
}
|
|
|
|
static int dw_pcie_wr_other_conf(struct pci_bus *bus, unsigned int devfn,
|
|
int where, int size, u32 val)
|
|
{
|
|
int ret;
|
|
struct pcie_port *pp = bus->sysdata;
|
|
struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
|
|
|
|
ret = pci_generic_config_write(bus, devfn, where, size, val);
|
|
|
|
if (!ret && pci->num_viewport <= 2)
|
|
dw_pcie_prog_outbound_atu(pci, PCIE_ATU_REGION_INDEX1,
|
|
PCIE_ATU_TYPE_IO, pp->io_base,
|
|
pp->io_bus_addr, pp->io_size);
|
|
|
|
return ret;
|
|
}
|
|
|
|
static struct pci_ops dw_child_pcie_ops = {
|
|
.map_bus = dw_pcie_other_conf_map_bus,
|
|
.read = dw_pcie_rd_other_conf,
|
|
.write = dw_pcie_wr_other_conf,
|
|
};
|
|
|
|
void __iomem *dw_pcie_own_conf_map_bus(struct pci_bus *bus, unsigned int devfn, int where)
|
|
{
|
|
struct pcie_port *pp = bus->sysdata;
|
|
struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
|
|
|
|
if (PCI_SLOT(devfn) > 0)
|
|
return NULL;
|
|
|
|
return pci->dbi_base + where;
|
|
}
|
|
EXPORT_SYMBOL_GPL(dw_pcie_own_conf_map_bus);
|
|
|
|
static struct pci_ops dw_pcie_ops = {
|
|
.map_bus = dw_pcie_own_conf_map_bus,
|
|
.read = pci_generic_config_read,
|
|
.write = pci_generic_config_write,
|
|
};
|
|
|
|
void dw_pcie_setup_rc(struct pcie_port *pp)
|
|
{
|
|
u32 val, ctrl, num_ctrls;
|
|
struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
|
|
|
|
/*
|
|
* Enable DBI read-only registers for writing/updating configuration.
|
|
* Write permission gets disabled towards the end of this function.
|
|
*/
|
|
dw_pcie_dbi_ro_wr_en(pci);
|
|
|
|
dw_pcie_setup(pci);
|
|
|
|
if (pci_msi_enabled() && !pp->ops->msi_host_init) {
|
|
num_ctrls = pp->num_vectors / MAX_MSI_IRQS_PER_CTRL;
|
|
|
|
/* Initialize IRQ Status array */
|
|
for (ctrl = 0; ctrl < num_ctrls; ctrl++) {
|
|
pp->irq_mask[ctrl] = ~0;
|
|
dw_pcie_writel_dbi(pci, PCIE_MSI_INTR0_MASK +
|
|
(ctrl * MSI_REG_CTRL_BLOCK_SIZE),
|
|
pp->irq_mask[ctrl]);
|
|
dw_pcie_writel_dbi(pci, PCIE_MSI_INTR0_ENABLE +
|
|
(ctrl * MSI_REG_CTRL_BLOCK_SIZE),
|
|
~0);
|
|
}
|
|
}
|
|
|
|
/* Setup RC BARs */
|
|
dw_pcie_writel_dbi(pci, PCI_BASE_ADDRESS_0, 0x00000004);
|
|
dw_pcie_writel_dbi(pci, PCI_BASE_ADDRESS_1, 0x00000000);
|
|
|
|
/* Setup interrupt pins */
|
|
val = dw_pcie_readl_dbi(pci, PCI_INTERRUPT_LINE);
|
|
val &= 0xffff00ff;
|
|
val |= 0x00000100;
|
|
dw_pcie_writel_dbi(pci, PCI_INTERRUPT_LINE, val);
|
|
|
|
/* Setup bus numbers */
|
|
val = dw_pcie_readl_dbi(pci, PCI_PRIMARY_BUS);
|
|
val &= 0xff000000;
|
|
val |= 0x00ff0100;
|
|
dw_pcie_writel_dbi(pci, PCI_PRIMARY_BUS, val);
|
|
|
|
/* Setup command register */
|
|
val = dw_pcie_readl_dbi(pci, PCI_COMMAND);
|
|
val &= 0xffff0000;
|
|
val |= PCI_COMMAND_IO | PCI_COMMAND_MEMORY |
|
|
PCI_COMMAND_MASTER | PCI_COMMAND_SERR;
|
|
dw_pcie_writel_dbi(pci, PCI_COMMAND, val);
|
|
|
|
/*
|
|
* If the platform provides its own child bus config accesses, it means
|
|
* the platform uses its own address translation component rather than
|
|
* ATU, so we should not program the ATU here.
|
|
*/
|
|
if (pp->bridge->child_ops == &dw_child_pcie_ops) {
|
|
struct resource_entry *tmp, *entry = NULL;
|
|
|
|
/* Get last memory resource entry */
|
|
resource_list_for_each_entry(tmp, &pp->bridge->windows)
|
|
if (resource_type(tmp->res) == IORESOURCE_MEM)
|
|
entry = tmp;
|
|
|
|
dw_pcie_prog_outbound_atu(pci, PCIE_ATU_REGION_INDEX0,
|
|
PCIE_ATU_TYPE_MEM, entry->res->start,
|
|
entry->res->start - entry->offset,
|
|
resource_size(entry->res));
|
|
if (pci->num_viewport > 2)
|
|
dw_pcie_prog_outbound_atu(pci, PCIE_ATU_REGION_INDEX2,
|
|
PCIE_ATU_TYPE_IO, pp->io_base,
|
|
pp->io_bus_addr, pp->io_size);
|
|
}
|
|
|
|
dw_pcie_writel_dbi(pci, PCI_BASE_ADDRESS_0, 0);
|
|
|
|
/* Program correct class for RC */
|
|
dw_pcie_writew_dbi(pci, PCI_CLASS_DEVICE, PCI_CLASS_BRIDGE_PCI);
|
|
|
|
val = dw_pcie_readl_dbi(pci, PCIE_LINK_WIDTH_SPEED_CONTROL);
|
|
val |= PORT_LOGIC_SPEED_CHANGE;
|
|
dw_pcie_writel_dbi(pci, PCIE_LINK_WIDTH_SPEED_CONTROL, val);
|
|
|
|
dw_pcie_dbi_ro_wr_dis(pci);
|
|
}
|
|
EXPORT_SYMBOL_GPL(dw_pcie_setup_rc);
|