Kernel
Threads by month
- ----- 2026 -----
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- 34 participants
- 22813 discussions
Backport 5.10.84 LTS patches from upstream.
Aaro Koskinen (1):
i2c: cbus-gpio: set atomic transfer callback
Alain Volmat (3):
i2c: stm32f7: flush TX FIFO upon transfer errors
i2c: stm32f7: recover the bus on access timeout
i2c: stm32f7: stop dma transfer in case of NACK
Alexey Kardashevskiy (1):
powerpc/pseries/ddw: Revert "Extend upper limit for huge DMA window
for persistent memory"
Andreas Gruenbacher (1):
gfs2: Fix length of holes reported at end-of-file
Arnd Bergmann (1):
siphash: use _unaligned version by default
Badhri Jagan Sridharan (1):
usb: typec: tcpm: Wait in SNK_DEBOUNCED until disconnect
Baokun Li (2):
sata_fsl: fix UAF in sata_fsl_port_stop when rmmod sata_fsl
sata_fsl: fix warning in remove_proc_entry when rmmod sata_fsl
Benjamin Coddington (1):
NFSv42: Fix pagecache invalidation after COPY/CLONE
Benjamin Poirier (1):
net: mpls: Fix notifications when deleting a device
Bernard Zhao (1):
drm/amd/amdgpu: fix potential memleak
Bob Peterson (1):
gfs2: release iopen glock early in evict
Catalin Marinas (1):
KVM: arm64: Avoid setting the upper 32 bits of TCR_EL2 and CPTR_EL2 to
1
Christophe JAILLET (1):
net: marvell: mvpp2: Fix the computation of shared CPUs
Dan Carpenter (1):
KVM: VMX: Set failure code in prepare_vmcs02()
Dmitry Bogdanov (2):
atlantic: Increase delay for fw transactions
atlantic: Fix statistics logic for production hardware
Dongliang Mu (1):
dpaa2-eth: destroy workqueue at the end of remove function
Douglas Anderson (1):
drm/msm/a6xx: Allocate enough space for GMU registers
Dust Li (1):
net/smc: fix wrong list_del in smc_lgr_cleanup_early
Eiichi Tsukata (2):
rxrpc: Fix rxrpc_peer leak in rxrpc_look_up_bundle()
rxrpc: Fix rxrpc_local leak in rxrpc_lookup_peer()
Eric Dumazet (2):
net: annotate data-races on txq->xmit_lock_owner
ipv4: convert fib_num_tclassid_users to atomic_t
Feng Tang (2):
x86/tsc: Add a timer to make sure TSC_adjust is always checked
x86/tsc: Disable clocksource watchdog for TSC on qualified platorms
Gustavo A. R. Silva (1):
wireguard: ratelimiter: use kvcalloc() instead of kvzalloc()
Helge Deller (3):
parisc: Fix KBUILD_IMAGE for self-extracting kernel
parisc: Fix "make install" on newer debian releases
parisc: Mark cr16 CPU clocksource unstable on all SMP machines
Ian Rogers (2):
perf hist: Fix memory leak of a perf_hpp_fmt
perf report: Fix memory leaks around perf_tip()
Ioanna Alifieraki (1):
ipmi: Move remove_work to dedicated workqueue
Jason A. Donenfeld (6):
wireguard: selftests: increase default dmesg log size
wireguard: allowedips: add missing __rcu annotation to satisfy sparse
wireguard: selftests: actually test for routing loops
wireguard: device: reset peer src endpoint when netns exits
wireguard: receive: use ring buffer for incoming handshakes
wireguard: receive: drop handshakes if queue lock is contended
Jay Dolan (2):
serial: 8250_pci: Fix ACCES entries in pci_serial_quirks array
serial: 8250_pci: rewrite pericom_do_set_divisor()
Jimmy Wang (1):
platform/x86: thinkpad_acpi: Add support for dual fan control
Joerg Roedel (1):
x86/64/mm: Map all kernel memory into trampoline_pgd
Johan Hovold (1):
serial: core: fix transmit-buffer reset and memleak
Jordy Zomer (1):
ipv6: check return value of ipv6_skip_exthdr
Juergen Gross (1):
x86/pv: Switch SWAPGS to ALTERNATIVE
Julian Braha (1):
drm/sun4i: fix unmet dependency on RESET_CONTROLLER for
PHY_SUN6I_MIPI_DPHY
Lai Jiangshan (4):
KVM: X86: Use vcpu->arch.walk_mmu for kvm_mmu_invlpg()
x86/entry: Use the correct fence macro after swapgs in kernel CR3
x86/xen: Add xenpv_restore_regs_and_return_to_usermode()
x86/entry: Add a fence for kernel entry SWAPGS in paranoid_entry()
Li Zhijian (2):
wireguard: selftests: rename DEBUG_PI_LIST to DEBUG_PLIST
selftests: net: Correct case name
Like Xu (1):
KVM: x86/pmu: Fix reserved bits for AMD PerfEvtSeln register
Lorenzo Bianconi (1):
mt76: mt7915: fix NULL pointer dereference in mt7915_get_phy_mode
Lukas Wunner (1):
serial: 8250: Fix RTS modem control while in rs485 mode
Maciej W. Rozycki (1):
vgacon: Propagate console boot parameters before calling `vc_resize'
Manaf Meethalavalappu Pallikunhi (1):
thermal: core: Reset previous low and high trip during thermal zone
init
Mario Limonciello (2):
ata: ahci: Add Green Sardine vendor ID as board_ahci_mobile
ACPI: Add stubs for wakeup handler functions
Mark Rutland (1):
arm64: ftrace: add missing BTIs
Masami Hiramatsu (1):
kprobes: Limit max data_size of the kretprobe instances
Mathias Nyman (1):
xhci: Fix commad ring abort, write all 64 bits to CRCR register.
Michael Sterritt (1):
x86/sev: Fix SEV-ES INS/OUTS instructions for word, dword, and qword
Mike Christie (1):
scsi: iscsi: Unblock session then wake up error handler
Miklos Szeredi (2):
ovl: simplify file splice
ovl: fix deadlock in splice write
Mordechay Goodstein (1):
iwlwifi: mvm: retry init flow if failed
Nicholas Kazlauskas (1):
drm/amd/display: Allow DSC on supported MST branch devices
Nikita Danilov (2):
atlatnic: enable Nbase-t speeds with base-t
atlantic: Add missing DIDs and fix 115c.
Niklas Schnelle (1):
s390/pci: move pseudo-MMIO to prevent MIO overlap
Ole Ernst (1):
USB: NO_LPM quirk Lenovo Powered USB-C Travel Hub
Paolo Abeni (1):
tcp: fix page frag corruption on page fault
Paolo Bonzini (1):
KVM: x86: Use a stable condition around all VT-d PI paths
Patrik John (1):
serial: tegra: Change lower tolerance baud rate limit for tegra20 and
tegra30
Pierre Gondois (1):
serial: pl011: Add ACPI SBSA UART match id
Pierre-Louis Bossart (1):
ALSA: intel-dsp-config: add quirk for CML devices based on ES8336
codec
Qais Yousef (1):
sched/uclamp: Fix rq->uclamp_max not set on first enqueue
Randy Dunlap (1):
natsemi: xtensa: fix section mismatch warnings
Rob Clark (1):
drm/msm: Do hw_init() before capturing GPU state
Sameer Pujar (9):
ASoC: tegra: Fix wrong value type in ADMAIF
ASoC: tegra: Fix wrong value type in I2S
ASoC: tegra: Fix wrong value type in DMIC
ASoC: tegra: Fix wrong value type in DSPK
ASoC: tegra: Fix kcontrol put callback in ADMAIF
ASoC: tegra: Fix kcontrol put callback in I2S
ASoC: tegra: Fix kcontrol put callback in DMIC
ASoC: tegra: Fix kcontrol put callback in DSPK
ASoC: tegra: Fix kcontrol put callback in AHUB
Sameer Saurabh (3):
atlantic: Fix to display FW bundle version instead of FW mac version.
Remove Half duplex mode speed capabilities.
atlantic: Remove warn trace message.
Sean Christopherson (2):
KVM: Disallow user memslot with size that exceeds "unsigned long"
KVM: nVMX: Flush current VPID (L1 vs. L2) for KVM_REQ_TLB_FLUSH_GUEST
Slark Xiao (1):
platform/x86: thinkpad_acpi: Fix WWAN device disabled issue after S3
deep
Stanislaw Gruszka (1):
rt2x00: do not mark device gone on EPROTO errors during start
Stephen Suryaputra (1):
vrf: Reset IPCB/IP6CB when processing outbound pkts in vrf dev xmit
Steven Rostedt (VMware) (1):
tracing/histograms: String compares should not care about signed
values
Sven Eckelmann (1):
tty: serial: msm_serial: Deactivate RX DMA for polling support
Sven Schuchmann (1):
net: usb: lan78xx: lan78xx_phy_init(): use PHY_POLL instead of "0" if
no IRQ is available
Teng Qi (2):
ethernet: hisilicon: hns: hns_dsaf_misc: fix a possible array overflow
in hns_dsaf_ge_srst_by_port()
net: ethernet: dec: tulip: de4x5: fix possible array overflows in
type3_infoblock()
Tianjia Zhang (1):
net/tls: Fix authentication failure in CCM mode
Tony Lu (1):
net/smc: Keep smc_close_final rc during active close
Vasily Gorbik (1):
s390/setup: avoid using memblock_enforce_memory_limit
Wang Yugui (1):
btrfs: check-integrity: fix a warning on write caching disabled disk
Wei Yongjun (1):
ipmi: msghandler: Make symbol 'remove_work_wq' static
Wen Gu (2):
net/smc: Transfer remaining wait queue entries during fallback
net/smc: Avoid warning of possible recursive locking
William Kucharski (1):
net/rds: correct socket tunable error in rds_tcp_tune()
Xing Song (1):
mac80211: do not access the IV when it was stripped
Zhang Changzhong (1):
can: j1939: j1939_tp_cmd_recv(): check the dst address of TP.CM_BAM
Zhou Qingyang (2):
net: qlogic: qlcnic: Fix a NULL pointer dereference in
qlcnic_83xx_add_rings()
net/mlx4_en: Fix an use-after-free bug in
mlx4_en_try_alloc_resources()
liuguoqiang (1):
net: return correct error code
msizanoen1 (1):
ipv6: fix memory leak in fib6_rule_suppress
shaoyunl (1):
drm/amd/amdkfd: Fix kernel panic when reset failed and been triggered
again
zhangyue (1):
net: tulip: de4x5: fix the problem that the array 'lp->phy[8]' may be
out of bound
arch/arm64/include/asm/kvm_arm.h | 4 +-
arch/arm64/kernel/entry-ftrace.S | 6 +
arch/parisc/Makefile | 5 +
arch/parisc/install.sh | 1 +
arch/parisc/kernel/time.c | 24 +-
arch/powerpc/platforms/pseries/iommu.c | 9 -
arch/s390/include/asm/pci_io.h | 7 +-
arch/s390/kernel/setup.c | 3 -
arch/x86/entry/entry_64.S | 45 ++-
arch/x86/include/asm/irqflags.h | 20 +-
arch/x86/include/asm/paravirt.h | 20 --
arch/x86/include/asm/paravirt_types.h | 2 -
arch/x86/kernel/asm-offsets_64.c | 1 -
arch/x86/kernel/paravirt.c | 1 -
arch/x86/kernel/paravirt_patch.c | 3 -
arch/x86/kernel/sev-es.c | 57 ++--
arch/x86/kernel/tsc.c | 28 +-
arch/x86/kernel/tsc_sync.c | 41 +++
arch/x86/kvm/mmu/mmu.c | 2 +-
arch/x86/kvm/svm/pmu.c | 2 +-
arch/x86/kvm/vmx/nested.c | 4 +-
arch/x86/kvm/vmx/posted_intr.c | 20 +-
arch/x86/kvm/vmx/vmx.c | 23 +-
arch/x86/realmode/init.c | 12 +-
arch/x86/xen/enlighten_pv.c | 3 -
arch/x86/xen/xen-asm.S | 20 ++
drivers/ata/ahci.c | 1 +
drivers/ata/sata_fsl.c | 20 +-
drivers/char/ipmi/ipmi_msghandler.c | 13 +-
drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c | 1 +
.../drm/amd/amdkfd/kfd_device_queue_manager.c | 5 +
.../display/amdgpu_dm/amdgpu_dm_mst_types.c | 20 +-
drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c | 4 +-
drivers/gpu/drm/msm/msm_debugfs.c | 1 +
drivers/gpu/drm/sun4i/Kconfig | 1 +
drivers/i2c/busses/i2c-cbus-gpio.c | 5 +-
drivers/i2c/busses/i2c-stm32f7.c | 31 +-
.../ethernet/aquantia/atlantic/aq_common.h | 27 +-
.../net/ethernet/aquantia/atlantic/aq_hw.h | 2 +
.../net/ethernet/aquantia/atlantic/aq_nic.c | 10 +-
.../ethernet/aquantia/atlantic/aq_pci_func.c | 7 +-
.../net/ethernet/aquantia/atlantic/aq_vec.c | 3 -
.../aquantia/atlantic/hw_atl/hw_atl_utils.c | 15 +-
.../atlantic/hw_atl/hw_atl_utils_fw2x.c | 3 -
.../aquantia/atlantic/hw_atl2/hw_atl2.c | 22 +-
.../aquantia/atlantic/hw_atl2/hw_atl2.h | 2 +
.../aquantia/atlantic/hw_atl2/hw_atl2_utils.h | 38 ++-
.../atlantic/hw_atl2/hw_atl2_utils_fw.c | 110 +++++--
drivers/net/ethernet/dec/tulip/de4x5.c | 34 +-
.../net/ethernet/freescale/dpaa2/dpaa2-eth.c | 2 +
.../ethernet/hisilicon/hns/hns_dsaf_misc.c | 4 +
.../net/ethernet/marvell/mvpp2/mvpp2_main.c | 2 +-
.../net/ethernet/mellanox/mlx4/en_netdev.c | 9 +-
drivers/net/ethernet/natsemi/xtsonic.c | 2 +-
.../ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c | 10 +-
drivers/net/usb/lan78xx.c | 2 +-
drivers/net/vrf.c | 2 +
drivers/net/wireguard/allowedips.c | 2 +-
drivers/net/wireguard/device.c | 39 +--
drivers/net/wireguard/device.h | 9 +-
drivers/net/wireguard/queueing.c | 6 +-
drivers/net/wireguard/queueing.h | 2 +-
drivers/net/wireguard/ratelimiter.c | 4 +-
drivers/net/wireguard/receive.c | 39 ++-
drivers/net/wireguard/socket.c | 2 +-
drivers/net/wireless/intel/iwlwifi/iwl-drv.c | 22 +-
drivers/net/wireless/intel/iwlwifi/iwl-drv.h | 3 +
.../net/wireless/intel/iwlwifi/mvm/mac80211.c | 24 +-
drivers/net/wireless/intel/iwlwifi/mvm/mvm.h | 3 +
drivers/net/wireless/intel/iwlwifi/mvm/ops.c | 3 +
.../net/wireless/mediatek/mt76/mt7915/mcu.c | 4 +-
.../net/wireless/ralink/rt2x00/rt2x00usb.c | 3 +
drivers/platform/x86/thinkpad_acpi.c | 13 +-
drivers/scsi/scsi_transport_iscsi.c | 6 +-
drivers/thermal/thermal_core.c | 2 +
drivers/tty/serial/8250/8250_pci.c | 39 ++-
drivers/tty/serial/8250/8250_port.c | 7 -
drivers/tty/serial/amba-pl011.c | 1 +
drivers/tty/serial/msm_serial.c | 3 +
drivers/tty/serial/serial-tegra.c | 4 +-
drivers/tty/serial/serial_core.c | 18 +-
drivers/usb/core/quirks.c | 3 +
drivers/usb/host/xhci-ring.c | 21 +-
drivers/usb/typec/tcpm/tcpm.c | 4 -
drivers/video/console/vgacon.c | 14 +-
fs/btrfs/disk-io.c | 14 +-
fs/gfs2/bmap.c | 2 +-
fs/gfs2/super.c | 14 +-
fs/nfs/nfs42proc.c | 5 +-
fs/overlayfs/file.c | 59 ++--
include/linux/acpi.h | 9 +
include/linux/kprobes.h | 2 +
include/linux/netdevice.h | 19 +-
include/linux/siphash.h | 14 +-
include/net/dst_cache.h | 11 +
include/net/fib_rules.h | 4 +-
include/net/ip_fib.h | 2 +-
include/net/netns/ipv4.h | 2 +-
include/net/sock.h | 13 +-
kernel/kprobes.c | 3 +
kernel/sched/core.c | 2 +-
kernel/trace/trace_events_hist.c | 2 +-
lib/siphash.c | 12 +-
net/can/j1939/transport.c | 6 +
net/core/dev.c | 5 +-
net/core/dst_cache.c | 19 ++
net/core/fib_rules.c | 2 +-
net/ipv4/devinet.c | 2 +-
net/ipv4/fib_frontend.c | 2 +-
net/ipv4/fib_rules.c | 5 +-
net/ipv4/fib_semantics.c | 4 +-
net/ipv6/esp6.c | 6 +
net/ipv6/fib6_rules.c | 4 +-
net/mac80211/rx.c | 3 +-
net/mpls/af_mpls.c | 68 +++-
net/rds/tcp.c | 2 +-
net/rxrpc/conn_client.c | 14 +-
net/rxrpc/peer_object.c | 14 +-
net/smc/af_smc.c | 14 +
net/smc/smc_close.c | 8 +-
net/smc/smc_core.c | 7 +-
net/tls/tls_sw.c | 4 +-
sound/hda/intel-dsp-config.c | 10 +
sound/soc/tegra/tegra186_dspk.c | 181 +++++++++--
sound/soc/tegra/tegra210_admaif.c | 140 +++++++--
sound/soc/tegra/tegra210_ahub.c | 11 +-
sound/soc/tegra/tegra210_dmic.c | 184 ++++++++---
sound/soc/tegra/tegra210_i2s.c | 296 +++++++++++++-----
tools/perf/builtin-report.c | 15 +-
tools/perf/ui/hist.c | 28 +-
tools/perf/util/hist.h | 1 -
tools/perf/util/util.c | 14 +-
tools/perf/util/util.h | 2 +-
tools/testing/selftests/net/fcnal-test.sh | 4 +-
tools/testing/selftests/wireguard/netns.sh | 30 +-
.../selftests/wireguard/qemu/debug.config | 2 +-
.../selftests/wireguard/qemu/kernel.config | 1 +
virt/kvm/kvm_main.c | 3 +-
138 files changed, 1694 insertions(+), 677 deletions(-)
--
2.20.1
1
121
Backport 5.10.83 LTS patches from upstream.
Adrian Hunter (1):
mmc: sdhci: Fix ADMA for PAGE_SIZE >= 64KiB
Albert Wang (1):
usb: dwc3: gadget: Fix null pointer exception
Alex Deucher (1):
drm/amdgpu/gfx9: switch to golden tsc registers for renoir+
Alexander Aring (1):
net: ieee802154: handle iftypes as u32
Alexander Mikhalitsyn (1):
shm: extend forced shm destroy to support objects from several IPC
nses
Amit Cohen (1):
mlxsw: spectrum: Protect driver from buggy firmware
Arjun Roy (1):
tcp: correctly handle increased zerocopy args struct size
Christophe Leroy (1):
powerpc/32: Fix hardlockup on vmap stack overflow
Dan Carpenter (4):
usb: chipidea: ci_hdrc_imx: fix potential error pointer dereference in
probe
staging: rtl8192e: Fix use after free in _rtl92e_pci_disconnect()
drm/nouveau/acr: fix a couple NULL vs IS_ERR() checks
drm/vc4: fix error code in vc4_create_object()
Daniele Palmas (1):
USB: serial: option: add Telit LE910S1 0x9200 composition
Danielle Ratson (1):
mlxsw: Verify the accessed index doesn't exceed the array length
David Hildenbrand (2):
proc/vmcore: fix clearing user buffer by properly using clear_user()
s390/mm: validate VMA in PGSTE manipulation functions
Davide Caratti (1):
net/sched: sch_ets: don't peek at classes beyond 'nbands'
Diana Wang (1):
nfp: checking parameter process for rx-usecs/tx-usecs is invalid
Dylan Hung (1):
mdio: aspeed: Fix "Link is Down" issue
Eric Dumazet (3):
mptcp: fix delack timer
ipv6: fix typos in __ip6_finish_output()
tcp_cubic: fix spurious Hystart ACK train detections for
not-cwnd-limited flows
Florent Fourcot (2):
netfilter: ctnetlink: fix filtering with CTA_TUPLE_REPLY
netfilter: ctnetlink: do not erase error code with EINVAL
Florian Fainelli (3):
ARM: dts: BCM5301X: Fix I2C controller interrupt
ARM: dts: BCM5301X: Add interrupt properties to GPIO node
ARM: dts: bcm2711: Fix PCIe interrupts
Guo DaXing (1):
net/smc: Fix loop in smc_listen
Hans Verkuil (1):
media: cec: copy sequence field for the reply
Heiner Kallweit (1):
lan743x: fix deadlock in lan743x_phy_link_status_change()
Helge Deller (1):
Revert "parisc: Fix backtrace to always include init funtion names"
Holger Assmann (1):
net: stmmac: retain PTP clock time during SIOCSHWTSTAMP ioctls
Huang Jianan (1):
erofs: fix deadlock when shrink erofs slab
Huang Pei (2):
MIPS: loongson64: fix FTLB configuration
MIPS: use 3-level pgtable for 64KB page size on MIPS_VA_BITS_48
Jakub Kicinski (2):
tls: splice_read: fix record type check
tls: fix replacing proto_ops
Jason Gerecke (1):
HID: wacom: Use "Confidence" flag to prevent reporting invalid
contacts
Jeff Layton (1):
ceph: properly handle statfs on multifs setups
Jesse Brandeburg (1):
igb: fix netpoll exit with traffic
Jiri Olsa (1):
tracing/uprobe: Fix uprobe_perf_open probes iteration
Joakim Zhang (2):
net: stmmac: fix system hang caused by eee_ctrl_timer during
suspend/resume
net: stmmac: platform: fix build warning when with !CONFIG_PM_SLEEP
Joerg Roedel (1):
iommu/amd: Clarify AMD IOMMUv2 initialization messages
Juergen Gross (9):
xen: sync include/xen/interface/io/ring.h with Xen's newest version
xen/blkfront: read response from backend only once
xen/blkfront: don't take local copy of a request from the ring page
xen/blkfront: don't trust the backend response data blindly
xen/netfront: read response from backend only once
xen/netfront: don't read data from request on the ring page
xen/netfront: disentangle tx_skb_freelist
xen/netfront: don't trust the backend response data blindly
tty: hvc: replace BUG_ON() with negative return value
Karsten Graul (1):
net/smc: Fix NULL pointer dereferencing in smc_vlan_by_tcpsk()
Kumar Thangavel (1):
net/ncsi : Add payload to be 32-bit aligned to fix dropped packets
Maciej Fijalkowski (1):
ice: fix vsi->txq_map sizing
Marek Behún (2):
PCI: aardvark: Deduplicate code in advk_pcie_rd_conf()
net: marvell: mvpp2: increase MTU limit when XDP enabled
Mark Rutland (1):
sched/scs: Reset task stack state in bringup_cpu()
Marta Plantykow (1):
ice: avoid bpf_prog refcount underflow
Mathias Nyman (2):
usb: hub: Fix usb enumeration issue due to address0 race
usb: hub: Fix locking issues with address0_mutex
Maurizio Lombardi (1):
nvmet: use IOCB_NOWAIT only if the filesystem supports it
Michael Kelley (1):
firmware: smccc: Fix check for ARCH_SOC_ID not implemented
Mike Christie (1):
scsi: core: sysfs: Fix setting device state to SDEV_RUNNING
Miklos Szeredi (1):
fuse: release pipe buf after last use
Minas Harutyunyan (1):
usb: dwc2: gadget: Fix ISOC flow for elapsed frames
Mingjie Zhang (1):
USB: serial: option: add Fibocom FM101-GL variants
Nathan Chancellor (1):
usb: dwc2: hcd_queue: Fix use of floating point literal
Nicholas Kazlauskas (1):
drm/amd/display: Set plane update flags for all planes in reset
Nicholas Piggin (1):
KVM: PPC: Book3S HV: Prevent POWER7/8 TLB flush flushing SLB
Nikolay Aleksandrov (3):
net: nexthop: fix null pointer dereference when IPv6 is not enabled
net: ipv6: add fib6_nh_release_dsts stub
net: nexthop: release IPv6 per-cpu dsts when replacing a nexthop group
Nitesh B Venkatesh (1):
iavf: Prevent changing static ITR values if adaptive moderation is on
Noralf Trønnes (1):
staging/fbtft: Fix backlight
Ondrej Jirman (1):
usb: typec: fusb302: Fix masking of comparator and bc_lvl interrupts
Pali Rohár (4):
PCI: aardvark: Update comment about disabling link training
PCI: aardvark: Implement re-issuing config requests on CRS response
PCI: aardvark: Simplify initialization of rootcap on virtual bridge
PCI: aardvark: Fix link training
Peng Fan (1):
firmware: arm_scmi: pm: Propagate return value to caller
Pierre-Louis Bossart (1):
ALSA: intel-dsp-config: add quirk for JSL devices based on ES8336
codec
Russell King (Oracle) (2):
net: phylink: Force link down and retrigger resolve on interface
change
net: phylink: Force retrigger in case of latched link-fail indicator
Sakari Ailus (1):
ACPI: Get acpi_device's parent from the parent field
Shin'ichiro Kawasaki (1):
scsi: scsi_debug: Zero clear zones at reset write pointer
Sreekanth Reddy (1):
scsi: mpt3sas: Fix kernel panic during drive powercycle test
Srinivas Kandagatla (3):
ASoC: qdsp6: q6routing: Conditionally reset FrontEnd Mixer
ASoC: qdsp6: q6asm: fix q6asm_dai_prepare error handling
ASoC: codecs: wcd934x: return error code correctly from hw_params
Stefano Garzarella (1):
vhost/vsock: fix incorrect used length reported to the guest
Stefano Stabellini (2):
xen: don't continue xenstore initialization in case of errors
xen: detect uninitialized xenbus in xenbus_init
Steve French (1):
smb3: do not error on fsync when readonly
Steven Rostedt (VMware) (2):
tracing: Fix pid filtering when triggers are attached
tracing: Check pid filtering when creating events
Takashi Iwai (5):
ALSA: ctxfi: Fix out-of-range access
ALSA: hda/realtek: Fix LED on HP ProBook 435 G7
staging: greybus: Add missing rwsem around snd_ctl_remove() calls
ASoC: topology: Add missing rwsem around snd_ctl_remove() calls
ARM: socfpga: Fix crash with CONFIG_FORTIRY_SOURCE
Thinh Nguyen (2):
usb: dwc3: gadget: Ignore NoStream after End Transfer
usb: dwc3: gadget: Check for L1/L2/U3 for Start Transfer
Thomas Zeitlhofer (1):
PM: hibernate: use correct mode for swsusp_close()
Tim Harvey (1):
mmc: sdhci-esdhc-imx: disable CMDQ support
Todd Kjos (1):
binder: fix test regression due to sender_euid change
Tony Lu (2):
net/smc: Ensure the active closing peer first closes clcsock
net/smc: Don't call clcsock shutdown twice when smc shutdown
Trond Myklebust (1):
NFSv42: Don't fail clone() unless the OP_CLONE operation failed
Varun Prakash (1):
nvmet-tcp: fix incomplete data digest send
Vladimir Oltean (2):
net: mscc: ocelot: don't downgrade timestamping RX filters in
SIOCSHWTSTAMP
net: mscc: ocelot: correctly report the timestamping RX filters in
ethtool
Volodymyr Mytnyk (1):
net: marvell: prestera: fix double free issue on err path
Weichao Guo (1):
f2fs: set SBI_NEED_FSCK flag when inconsistent node block found
Werner Sembach (1):
ALSA: hda/realtek: Add quirk for ASRock NUC Box 1100
Will Mortensen (1):
netfilter: flowtable: fix IPv6 tunnel addr match
Ziyang Xuan (1):
net: vlan: fix underflow for the real_dev refcnt
yangxingwu (1):
netfilter: ipvs: Fix reuse connection if RS weight is 0
Documentation/networking/ipvs-sysctl.rst | 3 +-
arch/arm/boot/dts/bcm2711.dtsi | 8 +-
arch/arm/boot/dts/bcm5301x.dtsi | 4 +-
arch/arm/mach-socfpga/core.h | 2 +-
arch/arm/mach-socfpga/platsmp.c | 8 +-
arch/mips/Kconfig | 2 +-
arch/mips/kernel/cpu-probe.c | 4 +-
arch/parisc/kernel/vmlinux.lds.S | 3 +-
arch/powerpc/kernel/head_32.h | 6 +-
arch/powerpc/kvm/book3s_hv_builtin.c | 5 +-
arch/s390/mm/pgtable.c | 13 +
drivers/acpi/property.c | 11 +-
drivers/android/binder.c | 2 +-
drivers/block/xen-blkfront.c | 126 +++++---
drivers/firmware/arm_scmi/scmi_pm_domain.c | 4 +-
drivers/firmware/smccc/soc_id.c | 2 +-
drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c | 46 ++-
.../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 4 +-
.../gpu/drm/nouveau/nvkm/subdev/acr/gm200.c | 6 +-
.../gpu/drm/nouveau/nvkm/subdev/acr/gp102.c | 6 +-
drivers/gpu/drm/vc4/vc4_bo.c | 2 +-
drivers/hid/wacom_wac.c | 8 +-
drivers/hid/wacom_wac.h | 1 +
drivers/iommu/amd/iommu_v2.c | 6 +-
drivers/media/cec/core/cec-adap.c | 1 +
drivers/mmc/host/sdhci-esdhc-imx.c | 2 -
drivers/mmc/host/sdhci.c | 21 +-
drivers/mmc/host/sdhci.h | 4 +-
.../net/ethernet/intel/iavf/iavf_ethtool.c | 30 +-
drivers/net/ethernet/intel/ice/ice_lib.c | 9 +-
drivers/net/ethernet/intel/ice/ice_main.c | 18 +-
drivers/net/ethernet/intel/igb/igb_main.c | 2 +-
.../net/ethernet/marvell/mvpp2/mvpp2_main.c | 14 +-
.../marvell/prestera/prestera_switchdev.c | 6 +-
drivers/net/ethernet/mellanox/mlxsw/minimal.c | 4 +
.../net/ethernet/mellanox/mlxsw/spectrum.c | 5 +
.../ethernet/mellanox/mlxsw/spectrum_ptp.c | 3 +
.../ethernet/mellanox/mlxsw/spectrum_router.c | 3 +
.../mellanox/mlxsw/spectrum_switchdev.c | 4 +
drivers/net/ethernet/microchip/lan743x_main.c | 12 +-
drivers/net/ethernet/mscc/ocelot.c | 11 +-
drivers/net/ethernet/netronome/nfp/nfp_net.h | 3 -
.../ethernet/netronome/nfp/nfp_net_ethtool.c | 2 +-
drivers/net/ethernet/stmicro/stmmac/stmmac.h | 1 +
.../net/ethernet/stmicro/stmmac/stmmac_main.c | 139 +++++----
.../ethernet/stmicro/stmmac/stmmac_platform.c | 44 +++
drivers/net/mdio/mdio-aspeed.c | 7 +
drivers/net/phy/phylink.c | 26 +-
drivers/net/xen-netfront.c | 272 ++++++++++-------
drivers/nvme/target/io-cmd-file.c | 4 +-
drivers/nvme/target/tcp.c | 7 +-
drivers/pci/controller/pci-aardvark.c | 235 +++++++--------
drivers/scsi/mpt3sas/mpt3sas_scsih.c | 2 +-
drivers/scsi/scsi_debug.c | 5 +
drivers/scsi/scsi_sysfs.c | 2 +-
drivers/staging/fbtft/fb_ssd1351.c | 4 -
drivers/staging/fbtft/fbtft-core.c | 9 +-
drivers/staging/greybus/audio_helper.c | 8 +-
drivers/staging/rtl8192e/rtl8192e/rtl_core.c | 3 +-
drivers/tty/hvc/hvc_xen.c | 17 +-
drivers/usb/chipidea/ci_hdrc_imx.c | 18 +-
drivers/usb/core/hub.c | 24 +-
drivers/usb/dwc2/gadget.c | 17 +-
drivers/usb/dwc2/hcd_queue.c | 2 +-
drivers/usb/dwc3/gadget.c | 39 ++-
drivers/usb/serial/option.c | 5 +
drivers/usb/typec/tcpm/fusb302.c | 6 +-
drivers/vhost/vsock.c | 2 +-
drivers/xen/xenbus/xenbus_probe.c | 27 +-
fs/ceph/super.c | 11 +-
fs/cifs/file.c | 35 ++-
fs/erofs/utils.c | 8 +-
fs/f2fs/node.c | 1 +
fs/fuse/dev.c | 10 +-
fs/nfs/nfs42xdr.c | 3 +-
fs/proc/vmcore.c | 16 +-
include/linux/ipc_namespace.h | 15 +
include/linux/sched/task.h | 2 +-
include/net/ip6_fib.h | 1 +
include/net/ipv6_stubs.h | 1 +
include/net/nl802154.h | 7 +-
include/xen/interface/io/ring.h | 278 ++++++++++--------
ipc/shm.c | 189 +++++++++---
kernel/cpu.c | 7 +
kernel/power/hibernate.c | 6 +-
kernel/sched/core.c | 4 -
kernel/trace/trace.h | 24 +-
kernel/trace/trace_events.c | 10 +
kernel/trace/trace_uprobe.c | 1 +
net/8021q/vlan.c | 3 -
net/8021q/vlan_dev.c | 3 +
net/ipv4/nexthop.c | 35 ++-
net/ipv4/tcp.c | 4 +-
net/ipv4/tcp_cubic.c | 5 +-
net/ipv6/af_inet6.c | 1 +
net/ipv6/ip6_output.c | 2 +-
net/ipv6/route.c | 19 ++
net/mptcp/options.c | 3 +-
net/ncsi/ncsi-cmd.c | 24 +-
net/netfilter/ipvs/ip_vs_core.c | 8 +-
net/netfilter/nf_conntrack_netlink.c | 6 +-
net/netfilter/nf_flow_table_offload.c | 4 +-
net/sched/sch_ets.c | 8 +-
net/smc/af_smc.c | 12 +-
net/smc/smc_close.c | 6 +
net/smc/smc_core.c | 35 +--
net/tls/tls_main.c | 47 ++-
net/tls/tls_sw.c | 23 +-
sound/hda/intel-dsp-config.c | 9 +
sound/pci/ctxfi/ctamixer.c | 14 +-
sound/pci/ctxfi/ctdaio.c | 16 +-
sound/pci/ctxfi/ctresource.c | 7 +-
sound/pci/ctxfi/ctresource.h | 4 +-
sound/pci/ctxfi/ctsrc.c | 7 +-
sound/pci/hda/patch_realtek.c | 28 ++
sound/soc/codecs/wcd934x.c | 3 +-
sound/soc/qcom/qdsp6/q6asm-dai.c | 19 +-
sound/soc/qcom/qdsp6/q6routing.c | 6 +-
sound/soc/soc-topology.c | 3 +
119 files changed, 1539 insertions(+), 815 deletions(-)
--
2.20.1
1
119
[PATCH openEuler-5.10 01/16] USB: gadget: detect too-big endpoint 0 requests
by Zheng Zengkai 14 Jan '22
by Zheng Zengkai 14 Jan '22
14 Jan '22
From: Greg Kroah-Hartman <gregkh(a)linuxfoundation.org>
stable inclusion
form stable-v5.10.85
commit 7193ad3e50e596ac2192531c58ba83b9e6d2444b
bugzilla: 185937 https://gitee.com/openeuler/kernel/issues/I4DDEL
CVE: CVE-2021-39685
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id…
--------------------------------
Sometimes USB hosts can ask for buffers that are too large from endpoint
0, which should not be allowed. If this happens for OUT requests, stall
the endpoint, but for IN requests, trim the request size to the endpoint
buffer size.
Co-developed-by: Szymon Heidrich <szymon.heidrich(a)gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh(a)linuxfoundation.org>
Signed-off-by: Chen Jun <chenjun102(a)huawei.com>
Signed-off-by: Zheng Zengkai <zhengzengkai(a)huawei.com>
---
drivers/usb/gadget/composite.c | 12 ++++++++++++
drivers/usb/gadget/legacy/dbgp.c | 13 +++++++++++++
drivers/usb/gadget/legacy/inode.c | 16 +++++++++++++++-
3 files changed, 40 insertions(+), 1 deletion(-)
diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c
index a8704e6498ab..426132988512 100644
--- a/drivers/usb/gadget/composite.c
+++ b/drivers/usb/gadget/composite.c
@@ -1648,6 +1648,18 @@ composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
struct usb_function *f = NULL;
u8 endp;
+ if (w_length > USB_COMP_EP0_BUFSIZ) {
+ if (ctrl->bRequestType == USB_DIR_OUT) {
+ goto done;
+ } else {
+ /* Cast away the const, we are going to overwrite on purpose. */
+ __le16 *temp = (__le16 *)&ctrl->wLength;
+
+ *temp = cpu_to_le16(USB_COMP_EP0_BUFSIZ);
+ w_length = USB_COMP_EP0_BUFSIZ;
+ }
+ }
+
/* partial re-init of the response message; the function or the
* gadget might need to intercept e.g. a control-OUT completion
* when we delegate to it.
diff --git a/drivers/usb/gadget/legacy/dbgp.c b/drivers/usb/gadget/legacy/dbgp.c
index e1d566c9918a..e567afcb2794 100644
--- a/drivers/usb/gadget/legacy/dbgp.c
+++ b/drivers/usb/gadget/legacy/dbgp.c
@@ -345,6 +345,19 @@ static int dbgp_setup(struct usb_gadget *gadget,
void *data = NULL;
u16 len = 0;
+ if (length > DBGP_REQ_LEN) {
+ if (ctrl->bRequestType == USB_DIR_OUT) {
+ return err;
+ } else {
+ /* Cast away the const, we are going to overwrite on purpose. */
+ __le16 *temp = (__le16 *)&ctrl->wLength;
+
+ *temp = cpu_to_le16(DBGP_REQ_LEN);
+ length = DBGP_REQ_LEN;
+ }
+ }
+
+
if (request == USB_REQ_GET_DESCRIPTOR) {
switch (value>>8) {
case USB_DT_DEVICE:
diff --git a/drivers/usb/gadget/legacy/inode.c b/drivers/usb/gadget/legacy/inode.c
index 71e7d10dd76b..04b9c4f5f129 100644
--- a/drivers/usb/gadget/legacy/inode.c
+++ b/drivers/usb/gadget/legacy/inode.c
@@ -110,6 +110,8 @@ enum ep0_state {
/* enough for the whole queue: most events invalidate others */
#define N_EVENT 5
+#define RBUF_SIZE 256
+
struct dev_data {
spinlock_t lock;
refcount_t count;
@@ -144,7 +146,7 @@ struct dev_data {
struct dentry *dentry;
/* except this scratch i/o buffer for ep0 */
- u8 rbuf [256];
+ u8 rbuf[RBUF_SIZE];
};
static inline void get_dev (struct dev_data *data)
@@ -1333,6 +1335,18 @@ gadgetfs_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
u16 w_value = le16_to_cpu(ctrl->wValue);
u16 w_length = le16_to_cpu(ctrl->wLength);
+ if (w_length > RBUF_SIZE) {
+ if (ctrl->bRequestType == USB_DIR_OUT) {
+ return value;
+ } else {
+ /* Cast away the const, we are going to overwrite on purpose. */
+ __le16 *temp = (__le16 *)&ctrl->wLength;
+
+ *temp = cpu_to_le16(RBUF_SIZE);
+ w_length = RBUF_SIZE;
+ }
+ }
+
spin_lock (&dev->lock);
dev->setup_abort = 0;
if (dev->state == STATE_DEV_UNCONNECTED) {
--
2.20.1
1
15
Backport LTS 5.10.82 patches from upstream.
Adrian Hunter (2):
scsi: ufs: core: Fix task management completion
scsi: ufs: core: Fix task management completion timeout race
Alex Elder (1):
net: ipa: disable HOLB drop when updating timer
Alexander Antonov (2):
perf/x86/intel/uncore: Fix filter_tid mask for CHA events on Skylake
Server
perf/x86/intel/uncore: Fix IIO event constraints for Skylake Server
Alexander Mikhalitsyn (1):
ipc: WARN if trying to remove ipc object which is absent
Alistair Delva (1):
block: Check ADMIN before NICE for IOPRIO_CLASS_RT
Alvin Lee (1):
drm/amd/display: Update swizzle mode enums
Amit Kumar Mahapatra (1):
arm64: zynqmp: Do not duplicate flash partition label property
Anatolij Gustschin (1):
powerpc/5200: dts: fix memory node unit name
AngeloGioacchino Del Regno (1):
arm64: dts: qcom: msm8998: Fix CPU/L2 idle state latency and residency
Arjun Roy (3):
net-zerocopy: Copy straggler unaligned data for TCP Rx. zerocopy.
net-zerocopy: Refactor skb frag fast-forward op.
tcp: Fix uninitialized access in skb frags array for Rx 0cp.
Baoquan He (1):
s390/kexec: fix memory leak of ipl report buffer
Bart Van Assche (1):
MIPS: sni: Fix the build
Bjorn Andersson (1):
pinctrl: qcom: sdm845: Enable dual edge errata
Bongsu Jeon (1):
net: nfc: nci: Change the NCI close sequence
Chao Yu (1):
f2fs: fix incorrect return value in f2fs_sanity_check_ckpt()
Chengfeng Ye (1):
ALSA: gus: fix null pointer dereference on pointer block
Christian Lamparter (1):
ARM: BCM53016: Specify switch ports for Meraki MR32
Christophe JAILLET (1):
platform/x86: hp_accel: Fix an error handling path in
'lis3lv02d_probe()'
Christophe Leroy (2):
powerpc/8xx: Fix Oops with STRICT_KERNEL_RWX without DEBUG_RODATA_TEST
powerpc/8xx: Fix pinned TLBs with CONFIG_STRICT_KERNEL_RWX
Colin Ian King (1):
MIPS: generic/yamon-dt: fix uninitialized variable error
David Heidelberg (1):
ARM: dts: qcom: fix memory and mdio nodes naming for RB3011
Dmitry Baryshkov (1):
clk: qcom: gcc-msm8996: Drop (again) gcc_aggre1_pnoc_ahb_clk
Eric Dumazet (1):
net: reduce indentation level in sk_clone_lock()
Eryk Rybak (3):
i40e: Fix correct max_pkt_size on VF RX queue
i40e: Fix changing previously set num_queue_pairs for PFs
i40e: Fix ping is lost after configuring ADq on VF
Ewan D. Milne (1):
scsi: qla2xxx: Fix mailbox direction flags in qla2xxx_get_adapter_id()
Fabio Aiuto (1):
staging: rtl8723bs: remove possible deadlock when disconnect (v2)
Gao Xiang (1):
f2fs: fix up f2fs_lookup tracepoints
Grzegorz Szczurek (2):
iavf: Fix for setting queues to 0
i40e: Fix display error code in dmesg
Guanghui Feng (1):
tty: tty_buffer: Fix the softlockup issue in flush_to_ldisc
Guo Zhi (1):
scsi: advansys: Fix kernel pointer leak
Hans Verkuil (1):
drm/nouveau: hdmigv100.c: fix corrupted HDMI Vendor InfoFrame
Hans de Goede (1):
ASoC: nau8824: Add DMI quirk mechanism for active-high jack-detect
Heiko Carstens (1):
s390/kexec: fix return code handling
Hyeong-Jun Kim (1):
f2fs: compress: disallow disabling compress on non-empty compressed
file
Ian Rogers (1):
perf bpf: Avoid memory leak from perf_env__insert_btf()
Imre Deak (1):
drm/i915/dp: Ensure sink rate values are always valid
Jacob Keller (1):
iavf: prevent accidental free of filter structure
James Clark (1):
perf tests: Remove bash construct from record+zstd_comp_decomp.sh
James Smart (1):
scsi: lpfc: Fix list_add() corruption in lpfc_drain_txq()
Jan Kara (1):
udf: Fix crash after seekdir
Jedrzej Jagielski (1):
i40e: Fix creation of first queue by omitting it if is not power of
two
Jesse Brandeburg (1):
e100: fix device suspend/resume
Joel Stanley (1):
clk/ast2600: Fix soc revision for AHB
Johan Hovold (1):
drm/udl: fix control-message timeout
Jonathan Davies (1):
net: virtio_net_hdr_to_skb: count transport header in UFO
Josef Bacik (2):
fs: export an inode_update_time helper
btrfs: update device path inode time instead of bd_inode
Jérôme Pouiller (1):
staging: wfx: ensure IRQ is ready before enabling it
Karen Sornek (1):
i40e: Fix warning message and call stack during rmmod i40e driver
Keoseong Park (1):
f2fs: fix to use WHINT_MODE
Leon Romanovsky (2):
RDMA/netlink: Add __maybe_unused to static inline in C file
ice: Delete always true check of PF pointer
Li Yang (2):
ARM: dts: ls1021a: move thermal-zones node out of soc/
ARM: dts: ls1021a-tsn: use generic "jedec,spi-nor" compatible for
flash
Like Xu (1):
perf/x86/vlbr: Add c->flags to vlbr event constraints
Lin Ma (3):
NFC: reorganize the functions in nci_request
NFC: reorder the logic in nfc_{un,}register_device
NFC: add NCI_UNREG flag to eliminate the race
Linus Walleij (1):
ARM: dts: ux500: Skomer regulator fixes
Lu Wei (1):
maple: fix wrong return value of maple_bus_init().
Luis Chamberlain (1):
firmware_loader: fix pre-allocated buf built-in firmware use
Maher Sanalla (1):
net/mlx5: Lag, update tracker when state change event received
Masami Hiramatsu (1):
tracing/histogram: Do not copy the fixed-size char array field over
the field size
Mateusz Palczewski (1):
iavf: Fix return of set the new channel count
Matthew Hagan (1):
ARM: dts: NSP: Fix mpcore, mmc node names
Matthias Brugger (1):
arm64: dts: rockchip: Disable CDN DP on Pinebook Pro
Maxim Levitsky (1):
KVM: nVMX: don't use vcpu->arch.efer when checking host state on
nested state load
Maxime Ripard (3):
ARM: dts: sunxi: Fix OPPs node name
arm64: dts: allwinner: h5: Fix GPU thermal zone node name
arm64: dts: allwinner: a100: Fix thermal zone node name
Meng Li (1):
net: stmmac: socfpga: add runtime suspend/resume callback for
stratix10 platform
Michael Ellerman (2):
powerpc/dcr: Use cmplwi instead of 3-argument cmpli
KVM: PPC: Book3S HV: Use GLOBAL_TOC for kvmppc_h_set_dabr/xdabr()
Michael Walle (2):
arm64: dts: hisilicon: fix arm,sp805 compatible string
arm64: dts: freescale: fix arm,sp805 compatible string
Michal Maloszewski (1):
i40e: Fix NULL ptr dereference on VSI filter sync
Michal Simek (1):
arm64: zynqmp: Fix serial compatible string
Mike Christie (3):
scsi: target: Fix ordered tag handling
scsi: target: Fix alua_tg_pt_gps_count tracking
scsi: core: sysfs: Fix hang when device state is set via sysfs
Mitch Williams (1):
iavf: validate pointers
Nathan Chancellor (2):
hexagon: export raw I/O routines for modules
hexagon: clean up timer-regs.h
Nguyen Dinh Phi (1):
cfg80211: call cfg80211_stop_ap when switch from P2P_GO type
Nicholas Nunley (2):
iavf: check for null in iavf_fix_features
iavf: free q_vectors before queues in iavf_disable_vf
Nick Desaulniers (2):
sh: check return code of request_irq
arm64: vdso32: suppress error message for 'make mrproper'
Nicolas Dichtel (1):
tun: fix bonding active backup with arp monitoring
Nikolay Borisov (1):
btrfs: fix memory ordering between normal and ordered work functions
Ondrej Mosnacek (1):
selinux: fix NULL-pointer dereference when hashtab allocation fails
Paul Cercueil (1):
clk: ingenic: Fix bugs with divided dividers
Pavel Skripkin (2):
net: bnx2x: fix variable dereferenced before check
net: dpaa2-eth: fix use-after-free in dpaa2_eth_remove
Pierre-Louis Bossart (4):
ASoC: SOF: Intel: hda-dai: fix potential locking issue
ALSA: intel-dsp-config: add quirk for APL/GLK/TGL devices based on
ES8336 codec
ALSA: hda: hdac_ext_stream: fix potential locking issues
ALSA: hda: hdac_stream: fix potential locking issue in
snd_hdac_stream_assign()
Piotr Marczak (1):
iavf: Fix failure to exit out from last all-multicast mode
Punit Agrawal (1):
net: stmmac: dwmac-rk: Fix ethernet on rk3399 based devices
Raed Salem (1):
net/mlx5: E-Switch, return error if encap isn't supported
Randy Dunlap (8):
ALSA: ISA: not for M68K
sh: fix kconfig unmet dependency warning for FRAME_POINTER
sh: math-emu: drop unused functions
sh: define __BIG_ENDIAN for math-emu
mips: BCM63XX: ensure that CPU_SUPPORTS_32BIT_KERNEL is set
mips: bcm63xx: add support for clk_get_parent()
mips: lantiq: add support for clk_get_parent()
x86/Kconfig: Fix an unused variable error in dell-smm-hwmon
Roger Quadros (1):
ARM: dts: omap: fix gpmc,mux-add-data type
Roi Dayan (1):
net/mlx5: E-Switch, Change mode lock from mutex to rw semaphore
Rustam Kovhaev (1):
mm: kmemleak: slob: respect SLAB_NOLEAKTRACE flag
Sasha Levin (1):
Revert "perf: Rework perf_event_exit_event()"
Sean Christopherson (1):
x86/hyperv: Fix NULL deref in set_hv_tscchange_cb() if Hyper-V setup
fails
Selvin Xavier (1):
RDMA/bnxt_re: Check if the vlan is valid before reporting
Shawn Guo (1):
arm64: dts: qcom: ipq6018: Fix qcom,controlled-remotely property
Sohaib Mohamed (1):
perf bench futex: Fix memory leak of perf_cpu_map__new()
Sriharsha Basavapatna (1):
bnxt_en: reject indirect blk offload when hw-tc-offload is off
Stefan Riedmueller (1):
clk: imx: imx6ul: Move csi_sel mux to correct base register
Steven Rostedt (VMware) (1):
tracing: Add length protection to histogram string copies
Surabhi Boob (1):
iavf: Fix for the false positive ASQ/ARQ errors while issuing VF reset
Sven Peter (1):
usb: typec: tipd: Remove WARN_ON in tps6598x_block_read
Sven Schnelle (1):
parisc/sticon: fix reverse colors
Tadeusz Struk (1):
tipc: check for null after calling kmemdup
Takashi Iwai (1):
ASoC: DAPM: Cover regression by kctl change notification fix
Teng Qi (1):
iio: imu: st_lsm6dsx: Avoid potential array overflow in
st_lsm6dsx_set_odr()
Tetsuo Handa (1):
sock: fix /proc/net/sockstat underflow in sk_clone_lock()
Tony Lindgren (2):
bus: ti-sysc: Add quirk handling for reinit on context lost
bus: ti-sysc: Use context lost quirk for otg
Uwe Kleine-König (1):
usb: max-3421: Use driver data instead of maintaining a list of bound
devices
Valentine Fatiev (1):
net/mlx5e: nullify cq->dbg pointer in mlx5_debug_cq_remove()
Vincent Donnefort (1):
sched/core: Mitigate race cpus_share_cache()/update_top_cache_domain()
Wen Gu (1):
net/smc: Make sure the link_id is unique
Xin Long (2):
tipc: only accept encrypted MSG_CRYPTO msgs
net: sched: act_mirred: drop dst for the direction from egress to
ingress
Yang Yingliang (2):
usb: musb: tusb6010: check return value after calling
platform_get_resource()
usb: host: ohci-tmio: check return value after calling
platform_get_resource()
hongao (1):
drm/amdgpu: fix set scaling mode Full/Full aspect/Center not works on
vga and dvi connectors
arch/arm/boot/dts/bcm-nsp.dtsi | 4 +-
arch/arm/boot/dts/bcm53016-meraki-mr32.dts | 22 ++
arch/arm/boot/dts/ls1021a-tsn.dts | 2 +-
arch/arm/boot/dts/ls1021a.dtsi | 66 +++---
arch/arm/boot/dts/omap-gpmc-smsc9221.dtsi | 2 +-
.../boot/dts/omap3-overo-tobiduo-common.dtsi | 2 +-
arch/arm/boot/dts/qcom-ipq8064-rb3011.dts | 6 +-
.../arm/boot/dts/ste-ux500-samsung-skomer.dts | 8 +-
arch/arm/boot/dts/sun8i-a33.dtsi | 4 +-
arch/arm/boot/dts/sun8i-a83t.dtsi | 4 +-
arch/arm/boot/dts/sun8i-h3.dtsi | 4 +-
.../arm64/boot/dts/allwinner/sun50i-a100.dtsi | 6 +-
.../dts/allwinner/sun50i-a64-cpu-opp.dtsi | 2 +-
.../boot/dts/allwinner/sun50i-h5-cpu-opp.dtsi | 2 +-
arch/arm64/boot/dts/allwinner/sun50i-h5.dtsi | 2 +-
.../boot/dts/allwinner/sun50i-h6-cpu-opp.dtsi | 2 +-
.../arm64/boot/dts/freescale/fsl-ls1088a.dtsi | 16 +-
.../arm64/boot/dts/freescale/fsl-ls208xa.dtsi | 16 +-
arch/arm64/boot/dts/hisilicon/hi3660.dtsi | 4 +-
arch/arm64/boot/dts/hisilicon/hi6220.dtsi | 2 +-
arch/arm64/boot/dts/qcom/ipq6018.dtsi | 2 +-
arch/arm64/boot/dts/qcom/msm8998.dtsi | 20 +-
.../boot/dts/rockchip/rk3399-pinebook-pro.dts | 4 -
.../dts/xilinx/zynqmp-zc1751-xm016-dc2.dts | 4 +-
arch/arm64/boot/dts/xilinx/zynqmp.dtsi | 4 +-
arch/arm64/kernel/vdso32/Makefile | 3 +-
arch/hexagon/include/asm/timer-regs.h | 26 ---
arch/hexagon/include/asm/timex.h | 3 +-
arch/hexagon/kernel/time.c | 12 +-
arch/hexagon/lib/io.c | 4 +
arch/mips/Kconfig | 3 +
arch/mips/bcm63xx/clk.c | 6 +
arch/mips/generic/yamon-dt.c | 2 +-
arch/mips/lantiq/clk.c | 6 +
arch/mips/sni/time.c | 4 +-
arch/powerpc/boot/dts/charon.dts | 2 +-
arch/powerpc/boot/dts/digsy_mtc.dts | 2 +-
arch/powerpc/boot/dts/lite5200.dts | 2 +-
arch/powerpc/boot/dts/lite5200b.dts | 2 +-
arch/powerpc/boot/dts/media5200.dts | 2 +-
arch/powerpc/boot/dts/mpc5200b.dtsi | 2 +-
arch/powerpc/boot/dts/o2d.dts | 2 +-
arch/powerpc/boot/dts/o2d.dtsi | 2 +-
arch/powerpc/boot/dts/o2dnt2.dts | 2 +-
arch/powerpc/boot/dts/o3dnt.dts | 2 +-
arch/powerpc/boot/dts/pcm032.dts | 2 +-
arch/powerpc/boot/dts/tqm5200.dts | 2 +-
arch/powerpc/kernel/head_8xx.S | 13 +-
arch/powerpc/kvm/book3s_hv_rmhandlers.S | 4 +-
arch/powerpc/sysdev/dcr-low.S | 2 +-
arch/s390/include/asm/kexec.h | 6 +
arch/s390/kernel/ipl.c | 3 +-
arch/s390/kernel/machine_kexec_file.c | 18 +-
arch/sh/Kconfig.debug | 1 +
arch/sh/include/asm/sfp-machine.h | 8 +
arch/sh/kernel/cpu/sh4a/smp-shx3.c | 5 +-
arch/sh/math-emu/math.c | 103 ----------
arch/x86/Kconfig | 3 +-
arch/x86/events/intel/core.c | 4 +-
arch/x86/events/intel/uncore_snbep.c | 4 +
arch/x86/hyperv/hv_init.c | 3 +
arch/x86/kvm/vmx/nested.c | 22 +-
block/ioprio.c | 9 +-
drivers/base/firmware_loader/main.c | 13 +-
drivers/bus/ti-sysc.c | 110 +++++++++-
drivers/clk/clk-ast2600.c | 12 +-
drivers/clk/imx/clk-imx6ul.c | 2 +-
drivers/clk/ingenic/cgu.c | 6 +-
drivers/clk/qcom/gcc-msm8996.c | 15 --
.../gpu/drm/amd/amdgpu/amdgpu_connectors.c | 1 +
.../drm/amd/display/dc/dcn20/dcn20_resource.c | 4 +-
.../amd/display/dc/dml/display_mode_enums.h | 4 +-
drivers/gpu/drm/i915/display/intel_dp.c | 11 +
.../drm/nouveau/nvkm/engine/disp/hdmigv100.c | 1 -
drivers/gpu/drm/udl/udl_connector.c | 2 +-
drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c | 6 +-
drivers/infiniband/hw/bnxt_re/ib_verbs.c | 12 +-
.../ethernet/broadcom/bnx2x/bnx2x_init_ops.h | 4 +-
drivers/net/ethernet/broadcom/bnxt/bnxt_tc.c | 2 +-
.../net/ethernet/freescale/dpaa2/dpaa2-eth.c | 4 +-
drivers/net/ethernet/intel/e100.c | 18 +-
drivers/net/ethernet/intel/i40e/i40e.h | 2 +
drivers/net/ethernet/intel/i40e/i40e_main.c | 160 +++++++++------
.../ethernet/intel/i40e/i40e_virtchnl_pf.c | 121 ++++-------
.../net/ethernet/intel/iavf/iavf_ethtool.c | 30 ++-
drivers/net/ethernet/intel/iavf/iavf_main.c | 14 +-
drivers/net/ethernet/intel/ice/ice_main.c | 3 -
drivers/net/ethernet/mellanox/mlx5/core/cq.c | 5 +-
.../net/ethernet/mellanox/mlx5/core/debugfs.c | 4 +-
.../net/ethernet/mellanox/mlx5/core/eswitch.c | 11 +-
.../net/ethernet/mellanox/mlx5/core/eswitch.h | 2 +-
.../mellanox/mlx5/core/eswitch_offloads.c | 28 +--
drivers/net/ethernet/mellanox/mlx5/core/lag.c | 28 ++-
.../net/ethernet/stmicro/stmmac/dwmac-rk.c | 5 +
.../ethernet/stmicro/stmmac/dwmac-socfpga.c | 24 ++-
drivers/net/ipa/ipa_endpoint.c | 2 +
drivers/net/tun.c | 5 +
drivers/pinctrl/qcom/pinctrl-sdm845.c | 1 +
drivers/platform/x86/hp_accel.c | 2 +
drivers/scsi/advansys.c | 4 +-
drivers/scsi/lpfc/lpfc_sli.c | 1 +
drivers/scsi/qla2xxx/qla_mbx.c | 6 +-
drivers/scsi/scsi_sysfs.c | 30 ++-
drivers/scsi/ufs/ufshcd.c | 57 +++---
drivers/scsi/ufs/ufshcd.h | 1 +
drivers/sh/maple/maple.c | 5 +-
drivers/staging/rtl8723bs/core/rtw_mlme_ext.c | 7 +-
drivers/staging/rtl8723bs/core/rtw_recv.c | 10 +-
drivers/staging/rtl8723bs/core/rtw_sta_mgt.c | 22 +-
drivers/staging/rtl8723bs/core/rtw_xmit.c | 16 +-
.../staging/rtl8723bs/hal/rtl8723bs_xmit.c | 2 -
drivers/staging/wfx/bus_sdio.c | 17 +-
drivers/target/target_core_alua.c | 1 -
drivers/target/target_core_device.c | 2 +
drivers/target/target_core_internal.h | 1 +
drivers/target/target_core_transport.c | 76 +++++--
drivers/tty/tty_buffer.c | 3 +
drivers/usb/host/max3421-hcd.c | 25 +--
drivers/usb/host/ohci-tmio.c | 2 +-
drivers/usb/musb/tusb6010.c | 5 +
drivers/usb/typec/tps6598x.c | 2 +-
drivers/video/console/sticon.c | 12 +-
fs/btrfs/async-thread.c | 14 ++
fs/btrfs/volumes.c | 21 +-
fs/f2fs/f2fs.h | 3 +-
fs/f2fs/super.c | 4 +-
fs/inode.c | 7 +-
fs/udf/dir.c | 32 ++-
fs/udf/namei.c | 3 +
fs/udf/super.c | 2 +
include/linux/fs.h | 2 +
include/linux/perf_event.h | 1 -
include/linux/platform_data/ti-sysc.h | 1 +
include/linux/trace_events.h | 2 +-
include/linux/virtio_net.h | 7 +-
include/net/nfc/nci_core.h | 1 +
include/rdma/rdma_netlink.h | 2 +-
include/sound/hdaudio_ext.h | 2 +
include/target/target_core_base.h | 6 +-
include/trace/events/f2fs.h | 12 +-
include/uapi/linux/tcp.h | 2 +
ipc/util.c | 6 +-
kernel/events/core.c | 142 ++++++-------
kernel/sched/core.c | 3 +
kernel/trace/trace_events_hist.c | 14 +-
mm/slab.h | 2 +-
net/core/sock.c | 189 +++++++++---------
net/ipv4/tcp.c | 122 ++++++++---
net/nfc/core.c | 32 +--
net/nfc/nci/core.c | 34 +++-
net/sched/act_mirred.c | 11 +-
net/smc/smc_core.c | 3 +-
net/tipc/crypto.c | 4 +
net/tipc/link.c | 7 +-
net/wireless/util.c | 1 +
security/selinux/ss/hashtab.c | 17 +-
sound/core/Makefile | 2 +
sound/hda/ext/hdac_ext_stream.c | 46 +++--
sound/hda/hdac_stream.c | 4 +-
sound/hda/intel-dsp-config.c | 22 +-
sound/isa/Kconfig | 2 +-
sound/isa/gus/gus_dma.c | 2 +
sound/pci/Kconfig | 1 +
sound/soc/codecs/nau8824.c | 40 ++++
sound/soc/soc-dapm.c | 29 ++-
sound/soc/sof/intel/hda-dai.c | 7 +-
tools/perf/bench/futex-lock-pi.c | 1 +
tools/perf/bench/futex-requeue.c | 1 +
tools/perf/bench/futex-wake-parallel.c | 1 +
tools/perf/bench/futex-wake.c | 1 +
.../tests/shell/record+zstd_comp_decomp.sh | 2 +-
tools/perf/util/bpf-event.c | 6 +-
tools/perf/util/env.c | 5 +-
tools/perf/util/env.h | 2 +-
174 files changed, 1413 insertions(+), 964 deletions(-)
delete mode 100644 arch/hexagon/include/asm/timer-regs.h
--
2.20.1
1
146
[PATCH openEuler-5.10 01/16] drm/i915/guc: Update to use firmware v49.0.1
by Zheng Zengkai 14 Jan '22
by Zheng Zengkai 14 Jan '22
14 Jan '22
From: John Harrison <John.C.Harrison(a)Intel.com>
mainline inclusion
from mainline-5.11-rc1
commit c784e5249e773689e38d2bc1749f08b986621a26
bugzilla: 185850 https://gitee.com/openeuler/kernel/issues/I4DDEL
CVE: CVE-2020-12363, CVE-2020-12364
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?…
--------------------------------
The latest GuC firmware includes a number of interface changes that
require driver updates to match.
* Starting from Gen11, the ID to be provided to GuC needs to contain
the engine class in bits [0..2] and the instance in bits [3..6].
NOTE: this patch breaks pointer dereferences in some existing GuC
functions that use the guc_id to dereference arrays but these functions
are not used for now as we have GuC submission disabled and we will
update these functions in follow up patch which requires new IDs.
* The new GuC requires the additional data structure (ADS) and associated
'private_data' pointer to be setup. This is basically a scratch area
of memory that the GuC owns. The size is read from the CSS header.
* There is now a physical to logical engine mapping table in the ADS
which needs to be configured in order for the firmware to load. For
now, the table is initialised with a 1 to 1 mapping.
* GUC_CTL_CTXINFO has been removed from the initialization params.
* reg_state_buffer is maintained internally by the GuC as part of
the private data.
* The ADS layout has changed significantly. This patch updates the
shared structure and also adds better documentation of the layout.
* While i915 does not use GuC doorbells, the firmware now requires
that some initialisation is done.
* The number of engine classes and instances supported in the ADS has
been increased.
Signed-off-by: John Harrison <John.C.Harrison(a)Intel.com>
Signed-off-by: Matthew Brost <matthew.brost(a)intel.com>
Signed-off-by: Daniele Ceraolo Spurio <daniele.ceraolospurio(a)intel.com>
Signed-off-by: Oscar Mateo <oscar.mateo(a)intel.com>
Signed-off-by: Michel Thierry <michel.thierry(a)intel.com>
Signed-off-by: Rodrigo Vivi <rodrigo.vivi(a)intel.com>
Signed-off-by: Michal Wajdeczko <michal.wajdeczko(a)intel.com>
Cc: Michal Winiarski <michal.winiarski(a)intel.com>
Cc: Tomasz Lis <tomasz.lis(a)intel.com>
Cc: Joonas Lahtinen <joonas.lahtinen(a)linux.intel.com>
Reviewed-by: Daniele Ceraolo Spurio <daniele.ceraolospurio(a)intel.com>
Signed-off-by: Joonas Lahtinen <joonas.lahtinen(a)linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20201028145826.2949180-2-John…
Signed-off-by: Chen Jun <chenjun102(a)huawei.com>
Reviewed-by: Xiu Jianfeng <xiujianfeng(a)huawei.com>
Reviewed-by: Jason Yan <yanaijie(a)huawei.com>
Signed-off-by: Chen Jun <chenjun102(a)huawei.com>
Signed-off-by: Zheng Zengkai <zhengzengkai(a)huawei.com>
---
drivers/gpu/drm/i915/gt/intel_engine_cs.c | 3 +-
drivers/gpu/drm/i915/gt/uc/intel_guc.c | 18 ---
drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c | 131 +++++++++++++++----
drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h | 80 +++++------
drivers/gpu/drm/i915/gt/uc/intel_guc_reg.h | 5 +
drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c | 27 ++--
drivers/gpu/drm/i915/gt/uc/intel_uc_fw.h | 2 +
drivers/gpu/drm/i915/gt/uc/intel_uc_fw_abi.h | 6 +-
8 files changed, 176 insertions(+), 96 deletions(-)
diff --git a/drivers/gpu/drm/i915/gt/intel_engine_cs.c b/drivers/gpu/drm/i915/gt/intel_engine_cs.c
index a19537706ed1..c940ac3aae2f 100644
--- a/drivers/gpu/drm/i915/gt/intel_engine_cs.c
+++ b/drivers/gpu/drm/i915/gt/intel_engine_cs.c
@@ -305,8 +305,9 @@ static int intel_engine_setup(struct intel_gt *gt, enum intel_engine_id id)
engine->i915 = i915;
engine->gt = gt;
engine->uncore = gt->uncore;
- engine->hw_id = engine->guc_id = info->hw_id;
engine->mmio_base = __engine_mmio_base(i915, info->mmio_bases);
+ engine->hw_id = info->hw_id;
+ engine->guc_id = MAKE_GUC_ID(info->class, info->instance);
engine->class = info->class;
engine->instance = info->instance;
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.c b/drivers/gpu/drm/i915/gt/uc/intel_guc.c
index 942c7c187adb..6909da1e1a73 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_guc.c
+++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.c
@@ -213,23 +213,6 @@ static u32 guc_ctl_feature_flags(struct intel_guc *guc)
return flags;
}
-static u32 guc_ctl_ctxinfo_flags(struct intel_guc *guc)
-{
- u32 flags = 0;
-
- if (intel_guc_submission_is_used(guc)) {
- u32 ctxnum, base;
-
- base = intel_guc_ggtt_offset(guc, guc->stage_desc_pool);
- ctxnum = GUC_MAX_STAGE_DESCRIPTORS / 16;
-
- base >>= PAGE_SHIFT;
- flags |= (base << GUC_CTL_BASE_ADDR_SHIFT) |
- (ctxnum << GUC_CTL_CTXNUM_IN16_SHIFT);
- }
- return flags;
-}
-
static u32 guc_ctl_log_params_flags(struct intel_guc *guc)
{
u32 offset = intel_guc_ggtt_offset(guc, guc->log.vma) >> PAGE_SHIFT;
@@ -291,7 +274,6 @@ static void guc_init_params(struct intel_guc *guc)
BUILD_BUG_ON(sizeof(guc->params) != GUC_CTL_MAX_DWORDS * sizeof(u32));
- params[GUC_CTL_CTXINFO] = guc_ctl_ctxinfo_flags(guc);
params[GUC_CTL_LOG_PARAMS] = guc_ctl_log_params_flags(guc);
params[GUC_CTL_FEATURE] = guc_ctl_feature_flags(guc);
params[GUC_CTL_DEBUG] = guc_ctl_debug_flags(guc);
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c
index d44061033f23..7950d28beb8c 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c
+++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c
@@ -10,11 +10,52 @@
/*
* The Additional Data Struct (ADS) has pointers for different buffers used by
- * the GuC. One single gem object contains the ADS struct itself (guc_ads), the
- * scheduling policies (guc_policies), a structure describing a collection of
- * register sets (guc_mmio_reg_state) and some extra pages for the GuC to save
- * its internal state for sleep.
+ * the GuC. One single gem object contains the ADS struct itself (guc_ads) and
+ * all the extra buffers indirectly linked via the ADS struct's entries.
+ *
+ * Layout of the ADS blob allocated for the GuC:
+ *
+ * +---------------------------------------+ <== base
+ * | guc_ads |
+ * +---------------------------------------+
+ * | guc_policies |
+ * +---------------------------------------+
+ * | guc_gt_system_info |
+ * +---------------------------------------+
+ * | guc_clients_info |
+ * +---------------------------------------+
+ * | guc_ct_pool_entry[size] |
+ * +---------------------------------------+
+ * | padding |
+ * +---------------------------------------+ <== 4K aligned
+ * | private data |
+ * +---------------------------------------+
+ * | padding |
+ * +---------------------------------------+ <== 4K aligned
*/
+struct __guc_ads_blob {
+ struct guc_ads ads;
+ struct guc_policies policies;
+ struct guc_gt_system_info system_info;
+ struct guc_clients_info clients_info;
+ struct guc_ct_pool_entry ct_pool[GUC_CT_POOL_SIZE];
+} __packed;
+
+static u32 guc_ads_private_data_size(struct intel_guc *guc)
+{
+ return PAGE_ALIGN(guc->fw.private_data_size);
+}
+
+static u32 guc_ads_private_data_offset(struct intel_guc *guc)
+{
+ return PAGE_ALIGN(sizeof(struct __guc_ads_blob));
+}
+
+static u32 guc_ads_blob_size(struct intel_guc *guc)
+{
+ return guc_ads_private_data_offset(guc) +
+ guc_ads_private_data_size(guc);
+}
static void guc_policy_init(struct guc_policy *policy)
{
@@ -48,26 +89,37 @@ static void guc_ct_pool_entries_init(struct guc_ct_pool_entry *pool, u32 num)
memset(pool, 0, num * sizeof(*pool));
}
+static void guc_mapping_table_init(struct intel_gt *gt,
+ struct guc_gt_system_info *system_info)
+{
+ unsigned int i, j;
+ struct intel_engine_cs *engine;
+ enum intel_engine_id id;
+
+ /* Table must be set to invalid values for entries not used */
+ for (i = 0; i < GUC_MAX_ENGINE_CLASSES; ++i)
+ for (j = 0; j < GUC_MAX_INSTANCES_PER_CLASS; ++j)
+ system_info->mapping_table[i][j] =
+ GUC_MAX_INSTANCES_PER_CLASS;
+
+ for_each_engine(engine, gt, id) {
+ u8 guc_class = engine->class;
+
+ system_info->mapping_table[guc_class][engine->instance] =
+ engine->instance;
+ }
+}
+
/*
* The first 80 dwords of the register state context, containing the
* execlists and ppgtt registers.
*/
#define LR_HW_CONTEXT_SIZE (80 * sizeof(u32))
-/* The ads obj includes the struct itself and buffers passed to GuC */
-struct __guc_ads_blob {
- struct guc_ads ads;
- struct guc_policies policies;
- struct guc_mmio_reg_state reg_state;
- struct guc_gt_system_info system_info;
- struct guc_clients_info clients_info;
- struct guc_ct_pool_entry ct_pool[GUC_CT_POOL_SIZE];
- u8 reg_state_buffer[GUC_S3_SAVE_SPACE_PAGES * PAGE_SIZE];
-} __packed;
-
static void __guc_ads_init(struct intel_guc *guc)
{
struct intel_gt *gt = guc_to_gt(guc);
+ struct drm_i915_private *i915 = gt->i915;
struct __guc_ads_blob *blob = guc->ads_blob;
const u32 skipped_size = LRC_PPHWSP_SZ * PAGE_SIZE + LR_HW_CONTEXT_SIZE;
u32 base;
@@ -99,13 +151,25 @@ static void __guc_ads_init(struct intel_guc *guc)
}
/* System info */
- blob->system_info.slice_enabled = hweight8(gt->info.sseu.slice_mask);
- blob->system_info.rcs_enabled = 1;
- blob->system_info.bcs_enabled = 1;
+ blob->system_info.engine_enabled_masks[RENDER_CLASS] = 1;
+ blob->system_info.engine_enabled_masks[COPY_ENGINE_CLASS] = 1;
+ blob->system_info.engine_enabled_masks[VIDEO_DECODE_CLASS] = VDBOX_MASK(gt);
+ blob->system_info.engine_enabled_masks[VIDEO_ENHANCEMENT_CLASS] = VEBOX_MASK(gt);
+
+ blob->system_info.generic_gt_sysinfo[GUC_GENERIC_GT_SYSINFO_SLICE_ENABLED] =
+ hweight8(gt->info.sseu.slice_mask);
+ blob->system_info.generic_gt_sysinfo[GUC_GENERIC_GT_SYSINFO_VDBOX_SFC_SUPPORT_MASK] =
+ gt->info.vdbox_sfc_access;
+
+ if (INTEL_GEN(i915) >= 12 && !IS_DGFX(i915)) {
+ u32 distdbreg = intel_uncore_read(gt->uncore,
+ GEN12_DIST_DBS_POPULATED);
+ blob->system_info.generic_gt_sysinfo[GUC_GENERIC_GT_SYSINFO_DOORBELL_COUNT_PER_SQIDI] =
+ ((distdbreg >> GEN12_DOORBELLS_PER_SQIDI_SHIFT) &
+ GEN12_DOORBELLS_PER_SQIDI) + 1;
+ }
- blob->system_info.vdbox_enable_mask = VDBOX_MASK(gt);
- blob->system_info.vebox_enable_mask = VEBOX_MASK(gt);
- blob->system_info.vdbox_sfc_support_mask = gt->info.vdbox_sfc_access;
+ guc_mapping_table_init(guc_to_gt(guc), &blob->system_info);
base = intel_guc_ggtt_offset(guc, guc->ads_vma);
@@ -118,11 +182,12 @@ static void __guc_ads_init(struct intel_guc *guc)
/* ADS */
blob->ads.scheduler_policies = base + ptr_offset(blob, policies);
- blob->ads.reg_state_buffer = base + ptr_offset(blob, reg_state_buffer);
- blob->ads.reg_state_addr = base + ptr_offset(blob, reg_state);
blob->ads.gt_system_info = base + ptr_offset(blob, system_info);
blob->ads.clients_info = base + ptr_offset(blob, clients_info);
+ /* Private Data */
+ blob->ads.private_data = base + guc_ads_private_data_offset(guc);
+
i915_gem_object_flush_map(guc->ads_vma->obj);
}
@@ -135,14 +200,15 @@ static void __guc_ads_init(struct intel_guc *guc)
*/
int intel_guc_ads_create(struct intel_guc *guc)
{
- const u32 size = PAGE_ALIGN(sizeof(struct __guc_ads_blob));
+ u32 size;
int ret;
GEM_BUG_ON(guc->ads_vma);
+ size = guc_ads_blob_size(guc);
+
ret = intel_guc_allocate_and_map_vma(guc, size, &guc->ads_vma,
(void **)&guc->ads_blob);
-
if (ret)
return ret;
@@ -156,6 +222,18 @@ void intel_guc_ads_destroy(struct intel_guc *guc)
i915_vma_unpin_and_release(&guc->ads_vma, I915_VMA_RELEASE_MAP);
}
+static void guc_ads_private_data_reset(struct intel_guc *guc)
+{
+ u32 size;
+
+ size = guc_ads_private_data_size(guc);
+ if (!size)
+ return;
+
+ memset((void *)guc->ads_blob + guc_ads_private_data_offset(guc), 0,
+ size);
+}
+
/**
* intel_guc_ads_reset() - prepares GuC Additional Data Struct for reuse
* @guc: intel_guc struct
@@ -168,5 +246,8 @@ void intel_guc_ads_reset(struct intel_guc *guc)
{
if (!guc->ads_vma)
return;
+
__guc_ads_init(guc);
+
+ guc_ads_private_data_reset(guc);
}
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h b/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h
index a6b733c146c9..79c560d9c0b6 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h
+++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h
@@ -26,8 +26,8 @@
#define GUC_VIDEO_ENGINE2 4
#define GUC_MAX_ENGINES_NUM (GUC_VIDEO_ENGINE2 + 1)
-#define GUC_MAX_ENGINE_CLASSES 5
-#define GUC_MAX_INSTANCES_PER_CLASS 16
+#define GUC_MAX_ENGINE_CLASSES 16
+#define GUC_MAX_INSTANCES_PER_CLASS 32
#define GUC_DOORBELL_INVALID 256
@@ -62,12 +62,7 @@
#define GUC_STAGE_DESC_ATTR_PCH BIT(6)
#define GUC_STAGE_DESC_ATTR_TERMINATED BIT(7)
-/* New GuC control data */
-#define GUC_CTL_CTXINFO 0
-#define GUC_CTL_CTXNUM_IN16_SHIFT 0
-#define GUC_CTL_BASE_ADDR_SHIFT 12
-
-#define GUC_CTL_LOG_PARAMS 1
+#define GUC_CTL_LOG_PARAMS 0
#define GUC_LOG_VALID (1 << 0)
#define GUC_LOG_NOTIFY_ON_HALF_FULL (1 << 1)
#define GUC_LOG_ALLOC_IN_MEGABYTE (1 << 3)
@@ -79,11 +74,11 @@
#define GUC_LOG_ISR_MASK (0x7 << GUC_LOG_ISR_SHIFT)
#define GUC_LOG_BUF_ADDR_SHIFT 12
-#define GUC_CTL_WA 2
-#define GUC_CTL_FEATURE 3
+#define GUC_CTL_WA 1
+#define GUC_CTL_FEATURE 2
#define GUC_CTL_DISABLE_SCHEDULER (1 << 14)
-#define GUC_CTL_DEBUG 4
+#define GUC_CTL_DEBUG 3
#define GUC_LOG_VERBOSITY_SHIFT 0
#define GUC_LOG_VERBOSITY_LOW (0 << GUC_LOG_VERBOSITY_SHIFT)
#define GUC_LOG_VERBOSITY_MED (1 << GUC_LOG_VERBOSITY_SHIFT)
@@ -97,12 +92,37 @@
#define GUC_LOG_DISABLED (1 << 6)
#define GUC_PROFILE_ENABLED (1 << 7)
-#define GUC_CTL_ADS 5
+#define GUC_CTL_ADS 4
#define GUC_ADS_ADDR_SHIFT 1
#define GUC_ADS_ADDR_MASK (0xFFFFF << GUC_ADS_ADDR_SHIFT)
#define GUC_CTL_MAX_DWORDS (SOFT_SCRATCH_COUNT - 2) /* [1..14] */
+/* Generic GT SysInfo data types */
+#define GUC_GENERIC_GT_SYSINFO_SLICE_ENABLED 0
+#define GUC_GENERIC_GT_SYSINFO_VDBOX_SFC_SUPPORT_MASK 1
+#define GUC_GENERIC_GT_SYSINFO_DOORBELL_COUNT_PER_SQIDI 2
+#define GUC_GENERIC_GT_SYSINFO_MAX 16
+
+/*
+ * The class goes in bits [0..2] of the GuC ID, the instance in bits [3..6].
+ * Bit 7 can be used for operations that apply to all engine classes&instances.
+ */
+#define GUC_ENGINE_CLASS_SHIFT 0
+#define GUC_ENGINE_CLASS_MASK (0x7 << GUC_ENGINE_CLASS_SHIFT)
+#define GUC_ENGINE_INSTANCE_SHIFT 3
+#define GUC_ENGINE_INSTANCE_MASK (0xf << GUC_ENGINE_INSTANCE_SHIFT)
+#define GUC_ENGINE_ALL_INSTANCES BIT(7)
+
+#define MAKE_GUC_ID(class, instance) \
+ (((class) << GUC_ENGINE_CLASS_SHIFT) | \
+ ((instance) << GUC_ENGINE_INSTANCE_SHIFT))
+
+#define GUC_ID_TO_ENGINE_CLASS(guc_id) \
+ (((guc_id) & GUC_ENGINE_CLASS_MASK) >> GUC_ENGINE_CLASS_SHIFT)
+#define GUC_ID_TO_ENGINE_INSTANCE(guc_id) \
+ (((guc_id) & GUC_ENGINE_INSTANCE_MASK) >> GUC_ENGINE_INSTANCE_SHIFT)
+
/* Work item for submitting workloads into work queue of GuC. */
struct guc_wq_item {
u32 header;
@@ -336,11 +356,6 @@ struct guc_policies {
} __packed;
/* GuC MMIO reg state struct */
-
-
-#define GUC_REGSET_MAX_REGISTERS 64
-#define GUC_S3_SAVE_SPACE_PAGES 10
-
struct guc_mmio_reg {
u32 offset;
u32 value;
@@ -348,28 +363,18 @@ struct guc_mmio_reg {
#define GUC_REGSET_MASKED (1 << 0)
} __packed;
-struct guc_mmio_regset {
- struct guc_mmio_reg registers[GUC_REGSET_MAX_REGISTERS];
- u32 values_valid;
- u32 number_of_registers;
-} __packed;
-
/* GuC register sets */
-struct guc_mmio_reg_state {
- struct guc_mmio_regset engine_reg[GUC_MAX_ENGINE_CLASSES][GUC_MAX_INSTANCES_PER_CLASS];
- u32 reserved[98];
+struct guc_mmio_reg_set {
+ u32 address;
+ u16 count;
+ u16 reserved;
} __packed;
/* HW info */
struct guc_gt_system_info {
- u32 slice_enabled;
- u32 rcs_enabled;
- u32 reserved0;
- u32 bcs_enabled;
- u32 vdbox_enable_mask;
- u32 vdbox_sfc_support_mask;
- u32 vebox_enable_mask;
- u32 reserved[9];
+ u8 mapping_table[GUC_MAX_ENGINE_CLASSES][GUC_MAX_INSTANCES_PER_CLASS];
+ u32 engine_enabled_masks[GUC_MAX_ENGINE_CLASSES];
+ u32 generic_gt_sysinfo[GUC_GENERIC_GT_SYSINFO_MAX];
} __packed;
/* Clients info */
@@ -390,15 +395,16 @@ struct guc_clients_info {
/* GuC Additional Data Struct */
struct guc_ads {
- u32 reg_state_addr;
- u32 reg_state_buffer;
+ struct guc_mmio_reg_set reg_state_list[GUC_MAX_ENGINE_CLASSES][GUC_MAX_INSTANCES_PER_CLASS];
+ u32 reserved0;
u32 scheduler_policies;
u32 gt_system_info;
u32 clients_info;
u32 control_data;
u32 golden_context_lrca[GUC_MAX_ENGINE_CLASSES];
u32 eng_state_size[GUC_MAX_ENGINE_CLASSES];
- u32 reserved[16];
+ u32 private_data;
+ u32 reserved[15];
} __packed;
/* GuC logging structures */
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_reg.h b/drivers/gpu/drm/i915/gt/uc/intel_guc_reg.h
index 1949346e714e..b37fc2ffaef2 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_guc_reg.h
+++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_reg.h
@@ -118,6 +118,11 @@ struct guc_doorbell_info {
#define GEN8_DRB_VALID (1<<0)
#define GEN8_DRBREGU(x) _MMIO(0x1000 + (x) * 8 + 4)
+#define GEN12_DIST_DBS_POPULATED _MMIO(0xd08)
+#define GEN12_DOORBELLS_PER_SQIDI_SHIFT 16
+#define GEN12_DOORBELLS_PER_SQIDI (0xff)
+#define GEN12_SQIDIS_DOORBELL_EXIST (0xffff)
+
#define DE_GUCRMR _MMIO(0x44054)
#define GUC_BCS_RCS_IER _MMIO(0xC550)
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c b/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c
index 80e8b6c3bc8c..ee4ac3922277 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c
+++ b/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c
@@ -44,23 +44,19 @@ void intel_uc_fw_change_status(struct intel_uc_fw *uc_fw,
* List of required GuC and HuC binaries per-platform.
* Must be ordered based on platform + revid, from newer to older.
*
- * TGL 35.2 is interface-compatible with 33.0 for previous Gens. The deltas
- * between 33.0 and 35.2 are only related to new additions to support new Gen12
- * features.
- *
* Note that RKL uses the same firmware as TGL.
*/
#define INTEL_UC_FIRMWARE_DEFS(fw_def, guc_def, huc_def) \
- fw_def(ROCKETLAKE, 0, guc_def(tgl, 35, 2, 0), huc_def(tgl, 7, 5, 0)) \
- fw_def(TIGERLAKE, 0, guc_def(tgl, 35, 2, 0), huc_def(tgl, 7, 5, 0)) \
- fw_def(ELKHARTLAKE, 0, guc_def(ehl, 33, 0, 4), huc_def(ehl, 9, 0, 0)) \
- fw_def(ICELAKE, 0, guc_def(icl, 33, 0, 0), huc_def(icl, 9, 0, 0)) \
- fw_def(COMETLAKE, 5, guc_def(cml, 33, 0, 0), huc_def(cml, 4, 0, 0)) \
- fw_def(COFFEELAKE, 0, guc_def(kbl, 33, 0, 0), huc_def(kbl, 4, 0, 0)) \
- fw_def(GEMINILAKE, 0, guc_def(glk, 33, 0, 0), huc_def(glk, 4, 0, 0)) \
- fw_def(KABYLAKE, 0, guc_def(kbl, 33, 0, 0), huc_def(kbl, 4, 0, 0)) \
- fw_def(BROXTON, 0, guc_def(bxt, 33, 0, 0), huc_def(bxt, 2, 0, 0)) \
- fw_def(SKYLAKE, 0, guc_def(skl, 33, 0, 0), huc_def(skl, 2, 0, 0))
+ fw_def(ROCKETLAKE, 0, guc_def(tgl, 49, 0, 1), huc_def(tgl, 7, 5, 0)) \
+ fw_def(TIGERLAKE, 0, guc_def(tgl, 49, 0, 1), huc_def(tgl, 7, 5, 0)) \
+ fw_def(ELKHARTLAKE, 0, guc_def(ehl, 49, 0, 1), huc_def(ehl, 9, 0, 0)) \
+ fw_def(ICELAKE, 0, guc_def(icl, 49, 0, 1), huc_def(icl, 9, 0, 0)) \
+ fw_def(COMETLAKE, 5, guc_def(cml, 49, 0, 1), huc_def(cml, 4, 0, 0)) \
+ fw_def(COFFEELAKE, 0, guc_def(kbl, 49, 0, 1), huc_def(kbl, 4, 0, 0)) \
+ fw_def(GEMINILAKE, 0, guc_def(glk, 49, 0, 1), huc_def(glk, 4, 0, 0)) \
+ fw_def(KABYLAKE, 0, guc_def(kbl, 49, 0, 1), huc_def(kbl, 4, 0, 0)) \
+ fw_def(BROXTON, 0, guc_def(bxt, 49, 0, 1), huc_def(bxt, 2, 0, 0)) \
+ fw_def(SKYLAKE, 0, guc_def(skl, 49, 0, 1), huc_def(skl, 2, 0, 0))
#define __MAKE_UC_FW_PATH(prefix_, name_, major_, minor_, patch_) \
"i915/" \
@@ -371,6 +367,9 @@ int intel_uc_fw_fetch(struct intel_uc_fw *uc_fw)
}
}
+ if (uc_fw->type == INTEL_UC_FW_TYPE_GUC)
+ uc_fw->private_data_size = css->private_data_size;
+
obj = i915_gem_object_create_shmem_from_data(i915, fw->data, fw->size);
if (IS_ERR(obj)) {
err = PTR_ERR(obj);
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.h b/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.h
index 23d3a423ac0f..99bb1fe1af66 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.h
+++ b/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.h
@@ -88,6 +88,8 @@ struct intel_uc_fw {
u32 rsa_size;
u32 ucode_size;
+
+ u32 private_data_size;
};
#ifdef CONFIG_DRM_I915_DEBUG_GUC
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_uc_fw_abi.h b/drivers/gpu/drm/i915/gt/uc/intel_uc_fw_abi.h
index 029214cdedd5..e41ffc7a7fbc 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_uc_fw_abi.h
+++ b/drivers/gpu/drm/i915/gt/uc/intel_uc_fw_abi.h
@@ -69,7 +69,11 @@ struct uc_css_header {
#define CSS_SW_VERSION_UC_MAJOR (0xFF << 16)
#define CSS_SW_VERSION_UC_MINOR (0xFF << 8)
#define CSS_SW_VERSION_UC_PATCH (0xFF << 0)
- u32 reserved[14];
+ u32 reserved0[13];
+ union {
+ u32 private_data_size; /* only applies to GuC */
+ u32 reserved1;
+ };
u32 header_info;
} __packed;
static_assert(sizeof(struct uc_css_header) == 128);
--
2.20.1
1
15
[PATCH OLK-5.10] x86/tsc: Make cur->adjusted values in package#1 to be the same
by LeoLiuoc 14 Jan '22
by LeoLiuoc 14 Jan '22
14 Jan '22
When resume from S4 on Zhaoxin 2 packages platform that support
X86_FEATURE_TSC_ADJUST,
the following warning messages appear:
[ 327.445302] [Firmware Bug]: TSC ADJUST differs: CPU15 45960750 -->
78394770. Restoring
[ 329.209120] [Firmware Bug]: TSC ADJUST differs: CPU14 45960750 -->
78394770. Restoring
[ 329.209128] [Firmware Bug]: TSC ADJUST differs: CPU13 45960750 -->
78394770. Restoring
[ 329.209138] [Firmware Bug]: TSC ADJUST differs: CPU12 45960750 -->
78394770. Restoring
[ 329.209151] [Firmware Bug]: TSC ADJUST differs: CPU11 45960750 -->
78394770. Restoring
[ 329.209160] [Firmware Bug]: TSC ADJUST differs: CPU10 45960750 -->
78394770. Restoring
[ 329.209169] [Firmware Bug]: TSC ADJUST differs: CPU9 45960750 -->
78394770. Restoring
The reason is:
Step 1: Bring up.
TSC is sync after bring up with following settings:
MSR 0x3b cur->adjusted
Package#0 CPU 0-7 0 0
Package#1 first CPU value1 value1
Package#1 non-first CPU value1 value1
Step 2: Suspend to S4.
Settings in Step 1 are not changed in this Step.
Step 3: Bring up caused by S4 wake up event.
TSC is sync when bring up with following settings:
MSR 0x3b cur->adjusted
Package#0 CPU 0-7 0 0
Package#1 first CPU value2 value2
Package#1 non-first CPU value2 value2
Step 4: Resume from S4.
When resuming from S4, Current TSC synchronous mechanism
cause following settings:
MSR 0x3b cur->adjusted
Package#0 CPU 0-7 0 0
Package#1 first CPU value2 value2
Package#1 non-first CPU value2 value1
In these Steps, value1 != 0 and value2 != value1.
In Step4, as function tsc_store_and_check_tsc_adjust() do, when the value
of MSR 0x3b on the non-first online CPU in package#1 is equal to the value
of cur->adjusted on the first online CPU in the same package,
the cur->adjusted value on this non-first online CPU will hold the old
value1.
This cause function tsc_verify_tsc_adjust() set the value of MSR 0x3b on the
non-first online CPUs in the package#1 to the old value1 and print the
beginning warning messages.
Fix it by setting cur->adjusted value on the non-first online CPU in a
package
to the value of MSR 0x3b on the same CPU when they are not equal.
Signed-off-by: LeoLiu-oc <LeoLiu-oc(a)zhaoxin.com>
---
arch/x86/kernel/tsc_sync.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/arch/x86/kernel/tsc_sync.c b/arch/x86/kernel/tsc_sync.c
index 3d3c761eb..19a0bed9b 100644
--- a/arch/x86/kernel/tsc_sync.c
+++ b/arch/x86/kernel/tsc_sync.c
@@ -190,6 +190,8 @@ bool tsc_store_and_check_tsc_adjust(bool bootcpu)
if (bootval != ref->adjusted) {
cur->adjusted = ref->adjusted;
wrmsrl(MSR_IA32_TSC_ADJUST, ref->adjusted);
+ } else if (cur->adjusted != bootval) {
+ cur->adjusted = bootval;
}
/*
* We have the TSCs forced to be in sync on this package. Skip sync
--
2.20.1
1
0
[PATCH OLK-5.10] Add support for PxSCT.LPM set based on actual LPM circumstances
by LeoLiuoc 14 Jan '22
by LeoLiuoc 14 Jan '22
14 Jan '22
AHCI Spec shows that the PxSCTL.IPM field in each port must be programmed
to disallow device initiated LPM requests when HBA can not support
transitions to the LPM state. The current LPM driver has no restrictions
on LPM transitions when enabling device initiated LPM.
Signed-off-by: LeoLiu-oc <LeoLiu-oc(a)zhaoxin.com>
---
drivers/ata/libata-sata.c | 11 ++++++++++-
1 file changed, 10 insertions(+), 1 deletion(-)
diff --git a/drivers/ata/libata-sata.c b/drivers/ata/libata-sata.c
index c16423e44..7e1296b55 100644
--- a/drivers/ata/libata-sata.c
+++ b/drivers/ata/libata-sata.c
@@ -394,9 +394,18 @@ int sata_link_scr_lpm(struct ata_link *link, enum
ata_lpm_policy policy,
case ATA_LPM_MED_POWER_WITH_DIPM:
case ATA_LPM_MIN_POWER_WITH_PARTIAL:
case ATA_LPM_MIN_POWER:
- if (ata_link_nr_enabled(link) > 0)
+ if (ata_link_nr_enabled(link) > 0) {
/* no restrictions on LPM transitions */
scontrol &= ~(0x7 << 8);
+ /* if Host does not support partial, then disallows it,
+ * the same for slumber
+ */
+ if (!(link->ap->host->flags & ATA_HOST_PART))
+ scontrol |= (0x1 << 8);
+
+ if (!(link->ap->host->flags & ATA_HOST_SSC))
+ scontrol |= (0x2 << 8);
+ }
else {
/* empty port, power off */
scontrol &= ~0xf;
--
2.20.1
1
0
[PATCH OLK-5.10] Add support for PxSCT.LPM setting based on actual LPM circumstances
by LeoLiuoc 14 Jan '22
by LeoLiuoc 14 Jan '22
14 Jan '22
In AHCI spec, PhyRdy Change Interrupt cannot coexist with
Link Power Management (LPM). While LPM driver would disable
PhyRdy Change interrupt without checking whether HBA supports
LPM or not before enabling it. Therefore, if enabling LPM from
LPM driver by default, we can not disable it from BIOS without
influence Hotplug out capability.
Signed-off-by: LeoLiu-oc <LeoLiu-oc(a)zhaoxin.com>
---
drivers/ata/ahci.c | 9 +++++++++
drivers/ata/libata-eh.c | 4 ++++
include/linux/libata.h | 4 ++++
3 files changed, 17 insertions(+)
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
index f8059eed3..2d1ac1b5b 100644
--- a/drivers/ata/ahci.c
+++ b/drivers/ata/ahci.c
@@ -1883,6 +1883,15 @@ static int ahci_init_one(struct pci_dev *pdev,
const struct pci_device_id *ent)
else
dev_info(&pdev->dev, "SSS flag set, parallel bus scan
disabled\n");
+ if (hpriv->cap & HOST_CAP_PART)
+ host->flags |= ATA_HOST_PART;
+
+ if (hpriv->cap & HOST_CAP_SSC)
+ host->flags |= ATA_HOST_SSC;
+
+ if (hpriv->cap2 & HOST_CAP2_SDS)
+ host->flags |= ATA_HOST_DEVSLP;
+
if (pi.flags & ATA_FLAG_EM)
ahci_reset_em(host);
diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c
index b6f92050e..ff6e660d6 100644
--- a/drivers/ata/libata-eh.c
+++ b/drivers/ata/libata-eh.c
@@ -3237,6 +3237,10 @@ static int ata_eh_set_lpm(struct ata_link *link,
enum ata_lpm_policy policy,
unsigned int err_mask;
int rc;
+ /* if Host does not support lpm, then sets no LPM flags*/
+ if (!(ap->host->flags & (ATA_HOST_PART | ATA_HOST_SSC |
ATA_HOST_DEVSLP)))
+ link->flags |= ATA_LFLAG_NO_LPM;
+
/* if the link or host doesn't do LPM, noop */
if (!IS_ENABLED(CONFIG_SATA_HOST) ||
(link->flags & ATA_LFLAG_NO_LPM) || (ap && !ap->ops->set_lpm))
diff --git a/include/linux/libata.h b/include/linux/libata.h
index 5f550eb27..81124ddc2 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -260,6 +260,10 @@ enum {
ATA_HOST_PARALLEL_SCAN = (1 << 2), /* Ports on this host can
be scanned in parallel */
ATA_HOST_IGNORE_ATA = (1 << 3), /* Ignore ATA devices on
this host. */
+ ATA_HOST_PART = (1 << 4), /* Host support partial.*/
+ ATA_HOST_SSC = (1 << 5), /* Host support slumber.*/
+ ATA_HOST_DEVSLP = (1 << 6), /* Host support devslp.*/
+
/* bits 24:31 of host->flags are reserved for LLD specific flags */
/* various lengths of time */
--
2.20.1
1
0
[PATCH OLK-5.10] Fix some bugs like plugin support and sata link stability when user enable ahci RTD3
by LeoLiuoc 14 Jan '22
by LeoLiuoc 14 Jan '22
14 Jan '22
The kernel driver now will disable interrupt when port is suspended,
causing plugin not work. It is useful to make plugin work,when the
plugin interrupt is enabled with power management status.
Adding pm_request_resume() is to reume port for plugin or PME signal
waking up controller which in D3.
with the AHCI controller frequently enters into D3 and leaves from D3,
the identify cmd may be timeout when controller resumes and establishes
a connect with the device.it is effective to delay 10ms between
controller resume and port resume,with link’s smooth transition.
with non power management request and power management competing with
each other in queue, it is often found that block IO hang 120s when
system disk is suspending or resuming.it is now guaranteed that PM
requests will enter the queue no matter other non-PM requests are
waiting. Increase the pm_only counter before checking whether any
non-PM blk_queue_enter() calls are in progress.
Meanwhile, the new blk_pm_request_resume() call is necessary to occur
during request assigned to a queue when device is suspended.
Signed-off-by: LeoLiu-oc <LeoLiu-oc(a)zhaoxin.com>
---
drivers/ata/ahci.c | 13 +++++++++++++
drivers/ata/libahci.c | 14 ++++++++++++++
2 files changed, 27 insertions(+)
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
index 33192a8f6..617cfcb2b 100644
--- a/drivers/ata/ahci.c
+++ b/drivers/ata/ahci.c
@@ -868,6 +868,19 @@ static int ahci_pci_device_runtime_resume(struct
device *dev)
if (rc)
return rc;
ahci_pci_init_controller(host);
+
+ /* controller delay for 10ms when being reusmed &&
+ * port resume for Zx platform
+ */
+ if (pdev->vendor == PCI_VENDOR_ID_ZHAOXIN) {
+ ata_msleep(NULL, 10);
+ for (rc = 0; rc < host->n_ports; rc++) {
+ struct ata_port *ap = host->ports[rc];
+
+ pm_request_resume(&ap->tdev);
+ }
+ }
+
return 0;
}
diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c
index fec2e9754..a37eac335 100644
--- a/drivers/ata/libahci.c
+++ b/drivers/ata/libahci.c
@@ -826,6 +826,12 @@ static void ahci_power_down(struct ata_port *ap)
void __iomem *port_mmio = ahci_port_base(ap);
u32 cmd, scontrol;
+ /* port suspended enable Plugin intr for Zx platform */
+ struct pci_dev *pdev = to_pci_dev(ap->host->dev);
+
+ if ((pdev->vendor == PCI_VENDOR_ID_ZHAOXIN) &&
(!ap->link.device->sdev))
+ writel(PORT_IRQ_CONNECT, port_mmio + PORT_IRQ_MASK);
+
if (!(hpriv->cap & HOST_CAP_SSS))
return;
@@ -1703,6 +1709,7 @@ static void ahci_error_intr(struct ata_port *ap,
u32 irq_stat)
struct ata_eh_info *active_ehi;
bool fbs_need_dec = false;
u32 serror;
+ struct pci_dev *pdev;
/* determine active link with error */
if (pp->fbs_enabled) {
@@ -1791,6 +1798,13 @@ static void ahci_error_intr(struct ata_port *ap,
u32 irq_stat)
ata_ehi_push_desc(host_ehi, "%s",
irq_stat & PORT_IRQ_CONNECT ?
"connection status changed" : "PHY RDY changed");
+ /* when plugin intr happen,now resume suspended port for Zx
platform */
+ pdev = to_pci_dev(ap->host->dev);
+ if ((pdev->vendor == PCI_VENDOR_ID_ZHAOXIN) &&
+ (ap->pflags & ATA_PFLAG_SUSPENDED)) {
+ pm_request_resume(&ap->tdev);
+ return;
+ }
}
/* okay, let's hand over to EH */
--
2.20.1
1
0
[PATCH OLK-5.10] EHCI:Clear wakeup signal locked in S0 state when device plug in
by LeoLiuoc 14 Jan '22
by LeoLiuoc 14 Jan '22
14 Jan '22
If we plug in a LS/FS device on USB2 port of EHCI, it will latch a wakeup
signal in EHCI internal. This is a bug of EHCI for Some project of
ZhaoXin. If enable EHCI runtime suspend and no device attach.
PM core will let EHCI go to D3 to save power. However, once EHCI go to D3,
it will release wakeup signal that latched on device connect to port
during S0. Which will generate a SCI interrupt and bring EHCI to D0.
But without device connect, EHCI will go to D3 again.
So, there is suspend-resume loop and generate SCI interrupt Continuously.
In order to fix this issues, we need to clear the wakeup signal latched
in EHCI when EHCI suspend function is called.
Signed-off-by: LeoLiu-oc <LeoLiu-oc(a)zhaoxin.com>
---
drivers/pci/pci-driver.c | 6 +++++-
drivers/usb/host/ehci-hcd.c | 21 +++++++++++++++++++++
drivers/usb/host/ehci-pci.c | 4 ++++
drivers/usb/host/ehci.h | 1 +
4 files changed, 31 insertions(+), 1 deletion(-)
diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c
index 8b587fc97..c33d7e0a6 100644
--- a/drivers/pci/pci-driver.c
+++ b/drivers/pci/pci-driver.c
@@ -518,7 +518,11 @@ static int pci_restore_standard_config(struct
pci_dev *pci_dev)
}
pci_restore_state(pci_dev);
- pci_pme_restore(pci_dev);
+ if (!((pci_dev->vendor == PCI_VENDOR_ID_ZHAOXIN) &&
+ (pci_dev->device == 0x3104) &&
+ ((pci_dev->revision & 0xf0) == 0x90)) ||
+ !(pci_dev->class == PCI_CLASS_SERIAL_USB_EHCI))
+ pci_pme_restore(pci_dev);
return 0;
}
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index 8aff19ff8..586e2735d 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -1142,6 +1142,27 @@ int ehci_suspend(struct usb_hcd *hcd, bool do_wakeup)
return -EBUSY;
}
+ /*clear wakeup signal locked in S0 state when device plug in*/
+ if (ehci->zx_wakeup_clear == 1) {
+ u32 __iomem *reg = &ehci->regs->port_status[4];
+ u32 t1 = ehci_readl(ehci, reg);
+
+ t1 &= (u32)~0xf0000;
+ t1 |= PORT_TEST_FORCE;
+ ehci_writel(ehci, t1, reg);
+ t1 = ehci_readl(ehci, reg);
+ usleep_range(1000, 2000);
+ t1 &= (u32)~0xf0000;
+ ehci_writel(ehci, t1, reg);
+ usleep_range(1000, 2000);
+ t1 = ehci_readl(ehci, reg);
+ ehci_writel(ehci, t1 | PORT_CSC, reg);
+ udelay(500);
+ t1 = ehci_readl(ehci, &ehci->regs->status);
+ ehci_writel(ehci, t1 & STS_PCD, &ehci->regs->status);
+ ehci_readl(ehci, &ehci->regs->status);
+ }
+
return 0;
}
EXPORT_SYMBOL_GPL(ehci_suspend);
diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c
index e87cf3a00..a5e27deda 100644
--- a/drivers/usb/host/ehci-pci.c
+++ b/drivers/usb/host/ehci-pci.c
@@ -222,6 +222,10 @@ static int ehci_pci_setup(struct usb_hcd *hcd)
ehci->has_synopsys_hc_bug = 1;
}
break;
+ case PCI_VENDOR_ID_ZHAOXIN:
+ if (pdev->device == 0x3104 && (pdev->revision & 0xf0) == 0x90)
+ ehci->zx_wakeup_clear = 1;
+ break;
}
/* optional debug port, normally in the first BAR */
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
index 59fd523c5..8da080a54 100644
--- a/drivers/usb/host/ehci.h
+++ b/drivers/usb/host/ehci.h
@@ -219,6 +219,7 @@ struct ehci_hcd { /* one per controller */
unsigned need_oc_pp_cycle:1; /* MPC834X port power */
unsigned imx28_write_fix:1; /* For Freescale i.MX28 */
unsigned is_aspeed:1;
+ unsigned zx_wakeup_clear:1;
/* required for usb32 quirk */
#define OHCI_CTRL_HCFS (3 << 6)
--
2.25.1
1
0
[PATCH OLK-5.10] XHCI:Fix some device identify fail when enable xHCI runtime suspend
by LeoLiuoc 14 Jan '22
by LeoLiuoc 14 Jan '22
14 Jan '22
If plug out device form xhci with runtime suspend enabled.
On the one hand, driver will disconnect this device and send disabled
slot command to xhci.
On the other hand, without no device connect to xhci, PM core will
call xhci suspend function to let xhci go to D3 to save power.
However there is a temporal competition to get xhci lock between
disable slot command interrupt and xhci suspend.
If xhci suspend function get xhci lock first, then this function will
clear xhci command ring. It will get error command trb when driver to
handle disable slot command interrupt. This is a serious error for
driver and driver will cleanup xhci. So,any device connect to this
xhci port again will not be recognized.
In order to fix this issues, we let disable slot command interrupt ISR
to get xhci lock first. So, add a delay in xhci suspend function before
to get xhci lock.
Signed-off-by: LeoLiu-oc <LeoLiu-oc(a)zhaoxin.com>
---
drivers/usb/host/xhci-pci.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c
index 583a8e895..83aa8e179 100644
--- a/drivers/usb/host/xhci-pci.c
+++ b/drivers/usb/host/xhci-pci.c
@@ -272,6 +272,8 @@ static void xhci_pci_quirks(struct device *dev,
struct xhci_hcd *xhci)
xhci->quirks |= XHCI_LPM_SUPPORT;
xhci->quirks |= XHCI_ZHAOXIN_HOST;
}
+ if (pdev->vendor == PCI_VENDOR_ID_ZHAOXIN)
+ xhci->quirks |= XHCI_SUSPEND_DELAY;
/* See https://bugzilla.kernel.org/show_bug.cgi?id=79511 */
if (pdev->vendor == PCI_VENDOR_ID_VIA &&
--
2.20.1
1
0
14 Jan '22
When the RTC divider is changed from reset to an operating time base,
the first update cycle should be 500ms later. But on some Zhaoxin SOCs,
this first update cycle is one second later.
So set RTC time on these Zhaoxin SOCs will causing 500ms delay.
Skip setup RTC divider on these SOCs in mc146818_set_time to fix it.
Signed-off-by: LeoLiu-oc <LeoLiu-oc(a)zhaoxin.com>
---
drivers/rtc/rtc-mc146818-lib.c | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
diff --git a/drivers/rtc/rtc-mc146818-lib.c b/drivers/rtc/rtc-mc146818-lib.c
index 2ecd8752b..96d9d0219 100644
--- a/drivers/rtc/rtc-mc146818-lib.c
+++ b/drivers/rtc/rtc-mc146818-lib.c
@@ -171,8 +171,17 @@ int mc146818_set_time(struct rtc_time *time)
save_control = CMOS_READ(RTC_CONTROL);
CMOS_WRITE((save_control|RTC_SET), RTC_CONTROL);
+#ifdef CONFIG_X86
+ if (!((boot_cpu_data.x86_vendor == X86_VENDOR_CENTAUR ||
+ boot_cpu_data.x86_vendor == X86_VENDOR_ZHAOXIN) &&
+ (boot_cpu_data.x86 <= 7 && boot_cpu_data.x86_model <= 59))) {
+ save_freq_select = CMOS_READ(RTC_FREQ_SELECT);
+ CMOS_WRITE((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT);
+ }
+#else
save_freq_select = CMOS_READ(RTC_FREQ_SELECT);
CMOS_WRITE((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT);
+#endif
#ifdef CONFIG_MACH_DECSTATION
CMOS_WRITE(real_yrs, RTC_DEC_YEAR);
@@ -190,7 +199,14 @@ int mc146818_set_time(struct rtc_time *time)
#endif
CMOS_WRITE(save_control, RTC_CONTROL);
+#ifdef CONFIG_X86
+ if (!((boot_cpu_data.x86_vendor == X86_VENDOR_CENTAUR ||
+ boot_cpu_data.x86_vendor == X86_VENDOR_ZHAOXIN) &&
+ (boot_cpu_data.x86 <= 7 && boot_cpu_data.x86_model <= 59)))
+ CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT);
+#else
CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT);
+#endif
spin_unlock_irqrestore(&rtc_lock, flags);
--
2.20.1
1
0
hulk inclusion
category: feature
bugzilla: https://gitee.com/openeuler/kernel/issues/I4O31I?from=project-issue
CVE: NA
Add "!" in memmap parameter, use memmap(memmap=nn[KMG]!ss[KMG]) reserve memory
for pmem which register persistent memory in arm64.
Signed-off-by: Zhuling <zhuling8(a)huawei.com>
---
Documentation/admin-guide/kernel-parameters.txt | 9 +++++++--
arch/arm64/mm/init.c | 6 ++++++
2 files changed, 13 insertions(+), 2 deletions(-)
diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
index 64be32b..ab42db4 100644
--- a/Documentation/admin-guide/kernel-parameters.txt
+++ b/Documentation/admin-guide/kernel-parameters.txt
@@ -2829,10 +2829,15 @@
will be eaten.
memmap=nn[KMG]!ss[KMG]
- [KNL,X86] Mark specific memory as protected.
+ [KNL,X86,ARM64] Mark specific memory as protected.
Region of memory to be used, from ss to ss+nn.
- The memory region may be marked as e820 type 12 (0xc)
+ [X86]The memory region may be marked as e820 type 12 (0xc)
and is NVDIMM or ADR memory.
+ [ARM64]Reserve memory for persistent storage when the kernel
+ restart or update. the data in PMEM will not be lost and can
+ be loaded faster
+ Example:
+ memmap=100K!0x1a0000000
memmap=<size>%<offset>-<oldtype>+<newtype>
[KNL,ACPI] Convert memory within the specified region
diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c
index 6ebfabd..b6512dc 100644
--- a/arch/arm64/mm/init.c
+++ b/arch/arm64/mm/init.c
@@ -56,6 +56,8 @@
s64 memstart_addr __ro_after_init = -1;
EXPORT_SYMBOL(memstart_addr);
+phys_addr_t start_at, mem_size;
+
#ifdef CONFIG_PIN_MEMORY
struct resource pin_memory_resource = {
.name = "Pin memory",
@@ -442,6 +444,10 @@ static int __init parse_memmap_one(char *p)
start_at = memparse(p + 1, &p);
memblock_reserve(start_at, mem_size);
memblock_mark_memmap(start_at, mem_size);
+ } else if (*p == '!') {
+ start_at = memparse(p+1, &p);
+ pmem_start = start_at;
+ pmem_size = mem_size;
} else
pr_info("Unrecognized memmap option, please check the parameter.\n");
--
2.9.5
1
2
您好!
Kernel SIG 邀请您参加 2021-12-31 14:00 召开的ZOOM会议(自动录制)
会议主题:openEuler kernel技术分享第十七期 & 双周例会
会议内容:
14:10-15:30 openEuler kernel 技术分享第17期 - cgroup介绍
会议链接:https://us06web.zoom.us/j/83118407147?pwd=elVzMVhGc2YzaDQ1TGorN2tPa1NhZz09
温馨提醒:建议接入会议后修改参会人的姓名,也可以使用您在gitee.com的ID
更多资讯尽在:https://openeuler.org/zh/
Hello!
openEuler Kernel SIG invites you to attend the ZOOM conference(auto recording) will be held at 2021-12-31 14:00,
The subject of the conference is openEuler kernel技术分享第十七期 & 双周例会,
Summary:
14:10-15:30 openEuler kernel 技术分享第17期 - cgroup介绍
You can join the meeting at https://us06web.zoom.us/j/83118407147?pwd=elVzMVhGc2YzaDQ1TGorN2tPa1NhZz09.
Note: You are advised to change the participant name after joining the conference or use your ID at gitee.com.
More information: https://openeuler.org/en/
3
2
您好!
Kernel SIG 邀请您参加 2022-01-14 14:00 召开的ZOOM会议(自动录制)
会议主题:openEuler kernel SIG 双周例会
会议内容:
议题:ebpf增加机制以支持非主线helper从而保证一定的兼容性
会议链接:https://us06web.zoom.us/j/86252266487?pwd=VjRNTVJzdkVwaXl6K2V1VUcxTWpEQT09
温馨提醒:建议接入会议后修改参会人的姓名,也可以使用您在gitee.com的ID
更多资讯尽在:https://openeuler.org/zh/
Hello!
openEuler Kernel SIG invites you to attend the ZOOM conference(auto recording) will be held at 2022-01-14 14:00,
The subject of the conference is openEuler kernel SIG 双周例会,
Summary:
议题:ebpf增加机制以支持非主线helper从而保证一定的兼容性
You can join the meeting at https://us06web.zoom.us/j/86252266487?pwd=VjRNTVJzdkVwaXl6K2V1VUcxTWpEQT09.
Note: You are advised to change the participant name after joining the conference or use your ID at gitee.com.
More information: https://openeuler.org/en/
2
1
From: Hannes Reinecke <hare(a)suse.de>
mainline inclusion
from mainline-5.14-rc1
commit ced202f7bd78eb6a79c441a8b217e0f3d38bccfc
category: bugfix
bugzilla: 185813
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?…
---------------------------
Return the actual error code in __scsi_execute() (which, according to the
documentation, should have happened anyway). And audit all callers to cope
with negative return values from __scsi_execute() and friends.
[mkp: resolve conflict and return bool]
Link: https://lore.kernel.org/r/20210427083046.31620-7-hare@suse.de
Reviewed-by: Bart Van Assche <bvanassche(a)acm.org>
Reviewed-by: Christoph Hellwig <hch(a)lst.de>
Signed-off-by: Hannes Reinecke <hare(a)suse.de>
Signed-off-by: Martin K. Petersen <martin.petersen(a)oracle.com>
Signed-off-by: Zhang Yi <yi.zhang(a)huawei.com>
---
drivers/ata/libata-scsi.c | 8 ++++++++
drivers/scsi/ch.c | 3 ++-
drivers/scsi/cxlflash/superpipe.c | 2 +-
drivers/scsi/scsi.c | 2 ++
drivers/scsi/scsi_ioctl.c | 4 +++-
drivers/scsi/scsi_lib.c | 15 +++++++++------
drivers/scsi/scsi_scan.c | 4 ++--
drivers/scsi/scsi_transport_spi.c | 2 +-
drivers/scsi/sd.c | 15 +++++++++------
drivers/scsi/sd_zbc.c | 2 +-
drivers/scsi/sr_ioctl.c | 4 ++++
drivers/scsi/ufs/ufshcd.c | 2 +-
drivers/scsi/virtio_scsi.c | 2 +-
include/scsi/scsi.h | 7 +++++--
14 files changed, 49 insertions(+), 23 deletions(-)
diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
index 48b8934970f3..c5129b9e3afd 100644
--- a/drivers/ata/libata-scsi.c
+++ b/drivers/ata/libata-scsi.c
@@ -409,6 +409,10 @@ int ata_cmd_ioctl(struct scsi_device *scsidev, void __user *arg)
cmd_result = scsi_execute(scsidev, scsi_cmd, data_dir, argbuf, argsize,
sensebuf, &sshdr, (10*HZ), 5, 0, 0, NULL);
+ if (cmd_result < 0) {
+ rc = cmd_result;
+ goto error;
+ }
if (driver_byte(cmd_result) == DRIVER_SENSE) {/* sense data available */
u8 *desc = sensebuf + 8;
cmd_result &= ~(0xFF<<24); /* DRIVER_SENSE is not an error */
@@ -490,6 +494,10 @@ int ata_task_ioctl(struct scsi_device *scsidev, void __user *arg)
cmd_result = scsi_execute(scsidev, scsi_cmd, DMA_NONE, NULL, 0,
sensebuf, &sshdr, (10*HZ), 5, 0, 0, NULL);
+ if (cmd_result < 0) {
+ rc = cmd_result;
+ goto error;
+ }
if (driver_byte(cmd_result) == DRIVER_SENSE) {/* sense data available */
u8 *desc = sensebuf + 8;
cmd_result &= ~(0xFF<<24); /* DRIVER_SENSE is not an error */
diff --git a/drivers/scsi/ch.c b/drivers/scsi/ch.c
index cb74ab1ae5a4..0e7d1214c3d8 100644
--- a/drivers/scsi/ch.c
+++ b/drivers/scsi/ch.c
@@ -198,7 +198,8 @@ ch_do_scsi(scsi_changer *ch, unsigned char *cmd, int cmd_len,
result = scsi_execute_req(ch->device, cmd, direction, buffer,
buflength, &sshdr, timeout * HZ,
MAX_RETRIES, NULL);
-
+ if (result < 0)
+ return result;
if (driver_byte(result) == DRIVER_SENSE) {
if (debug)
scsi_print_sense_hdr(ch->device, ch->name, &sshdr);
diff --git a/drivers/scsi/cxlflash/superpipe.c b/drivers/scsi/cxlflash/superpipe.c
index 5dddf67dfa24..3ebb7ac86a64 100644
--- a/drivers/scsi/cxlflash/superpipe.c
+++ b/drivers/scsi/cxlflash/superpipe.c
@@ -369,7 +369,7 @@ static int read_cap16(struct scsi_device *sdev, struct llun_info *lli)
goto out;
}
- if (driver_byte(result) == DRIVER_SENSE) {
+ if (result > 0 && driver_byte(result) == DRIVER_SENSE) {
result &= ~(0xFF<<24); /* DRIVER_SENSE is not an error */
if (result & SAM_STAT_CHECK_CONDITION) {
switch (sshdr.sense_key) {
diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c
index 6ad834d61d4c..f561caabc771 100644
--- a/drivers/scsi/scsi.c
+++ b/drivers/scsi/scsi.c
@@ -495,6 +495,8 @@ int scsi_report_opcode(struct scsi_device *sdev, unsigned char *buffer,
result = scsi_execute_req(sdev, cmd, DMA_FROM_DEVICE, buffer, len,
&sshdr, 30 * HZ, 3, NULL);
+ if (result < 0)
+ return result;
if (result && scsi_sense_valid(&sshdr) &&
sshdr.sense_key == ILLEGAL_REQUEST &&
(sshdr.asc == 0x20 || sshdr.asc == 0x24) && sshdr.ascq == 0x00)
diff --git a/drivers/scsi/scsi_ioctl.c b/drivers/scsi/scsi_ioctl.c
index 14872c9dc78c..d34e1b41dc71 100644
--- a/drivers/scsi/scsi_ioctl.c
+++ b/drivers/scsi/scsi_ioctl.c
@@ -101,6 +101,8 @@ static int ioctl_internal_command(struct scsi_device *sdev, char *cmd,
SCSI_LOG_IOCTL(2, sdev_printk(KERN_INFO, sdev,
"Ioctl returned 0x%x\n", result));
+ if (result < 0)
+ goto out;
if (driver_byte(result) == DRIVER_SENSE &&
scsi_sense_valid(&sshdr)) {
switch (sshdr.sense_key) {
@@ -133,7 +135,7 @@ static int ioctl_internal_command(struct scsi_device *sdev, char *cmd,
break;
}
}
-
+out:
SCSI_LOG_IOCTL(2, sdev_printk(KERN_INFO, sdev,
"IOCTL Releasing command\n"));
return result;
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index 0a265a3e3dc6..9352a309fe55 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -245,20 +245,23 @@ int __scsi_execute(struct scsi_device *sdev, const unsigned char *cmd,
{
struct request *req;
struct scsi_request *rq;
- int ret = DRIVER_ERROR << 24;
+ int ret;
req = blk_get_request(sdev->request_queue,
data_direction == DMA_TO_DEVICE ?
REQ_OP_SCSI_OUT : REQ_OP_SCSI_IN,
rq_flags & RQF_PM ? BLK_MQ_REQ_PM : 0);
if (IS_ERR(req))
- return ret;
- rq = scsi_req(req);
+ return PTR_ERR(req);
- if (bufflen && blk_rq_map_kern(sdev->request_queue, req,
- buffer, bufflen, GFP_NOIO))
- goto out;
+ rq = scsi_req(req);
+ if (bufflen) {
+ ret = blk_rq_map_kern(sdev->request_queue, req,
+ buffer, bufflen, GFP_NOIO);
+ if (ret)
+ goto out;
+ }
rq->cmd_len = COMMAND_SIZE(cmd[0]);
memcpy(rq->cmd, cmd, rq->cmd_len);
rq->retries = retries;
diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
index 8e474b145249..57002529174f 100644
--- a/drivers/scsi/scsi_scan.c
+++ b/drivers/scsi/scsi_scan.c
@@ -599,7 +599,7 @@ static int scsi_probe_lun(struct scsi_device *sdev, unsigned char *inq_result,
"scsi scan: INQUIRY %s with code 0x%x\n",
result ? "failed" : "successful", result));
- if (result) {
+ if (result > 0) {
/*
* not-ready to ready transition [asc/ascq=0x28/0x0]
* or power-on, reset [asc/ascq=0x29/0x0], continue.
@@ -614,7 +614,7 @@ static int scsi_probe_lun(struct scsi_device *sdev, unsigned char *inq_result,
(sshdr.ascq == 0))
continue;
}
- } else {
+ } else if (result == 0) {
/*
* if nothing was transferred, we try
* again. It's a workaround for some USB
diff --git a/drivers/scsi/scsi_transport_spi.c b/drivers/scsi/scsi_transport_spi.c
index c37dd15d16d2..a9bb7ae2fafd 100644
--- a/drivers/scsi/scsi_transport_spi.c
+++ b/drivers/scsi/scsi_transport_spi.c
@@ -127,7 +127,7 @@ static int spi_execute(struct scsi_device *sdev, const void *cmd,
REQ_FAILFAST_TRANSPORT |
REQ_FAILFAST_DRIVER,
RQF_PM, NULL);
- if (driver_byte(result) != DRIVER_SENSE ||
+ if (result < 0 || driver_byte(result) != DRIVER_SENSE ||
sshdr->sense_key != UNIT_ATTENTION)
break;
}
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index 97713f595a29..3fc184e9702f 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -1673,7 +1673,7 @@ static unsigned int sd_check_events(struct gendisk *disk, unsigned int clearing)
&sshdr);
/* failed to execute TUR, assume media not present */
- if (host_byte(retval)) {
+ if (retval < 0 || host_byte(retval)) {
set_media_not_present(sdkp);
goto out;
}
@@ -1734,6 +1734,9 @@ static int sd_sync_cache(struct scsi_disk *sdkp, struct scsi_sense_hdr *sshdr)
if (res) {
sd_print_result(sdkp, "Synchronize Cache(10) failed", res);
+ if (res < 0)
+ return res;
+
if (driver_byte(res) == DRIVER_SENSE)
sd_print_sense_hdr(sdkp, sshdr);
@@ -1842,7 +1845,7 @@ static int sd_pr_command(struct block_device *bdev, u8 sa,
result = scsi_execute_req(sdev, cmd, DMA_TO_DEVICE, &data, sizeof(data),
&sshdr, SD_TIMEOUT, sdkp->max_retries, NULL);
- if (driver_byte(result) == DRIVER_SENSE &&
+ if (result > 0 && driver_byte(result) == DRIVER_SENSE &&
scsi_sense_valid(&sshdr)) {
sdev_printk(KERN_INFO, sdev, "PR command failed: %d\n", result);
scsi_print_sense_hdr(sdev, NULL, &sshdr);
@@ -2194,7 +2197,7 @@ sd_spinup_disk(struct scsi_disk *sdkp)
((driver_byte(the_result) == DRIVER_SENSE) &&
sense_valid && sshdr.sense_key == UNIT_ATTENTION)));
- if (driver_byte(the_result) != DRIVER_SENSE) {
+ if (the_result < 0 || driver_byte(the_result) != DRIVER_SENSE) {
/* no sense, TUR either succeeded or failed
* with a status error */
if(!spintime && !scsi_status_is_good(the_result)) {
@@ -2379,7 +2382,7 @@ static int read_capacity_16(struct scsi_disk *sdkp, struct scsi_device *sdp,
if (media_not_present(sdkp, &sshdr))
return -ENODEV;
- if (the_result) {
+ if (the_result > 0) {
sense_valid = scsi_sense_valid(&sshdr);
if (sense_valid &&
sshdr.sense_key == ILLEGAL_REQUEST &&
@@ -2464,7 +2467,7 @@ static int read_capacity_10(struct scsi_disk *sdkp, struct scsi_device *sdp,
if (media_not_present(sdkp, &sshdr))
return -ENODEV;
- if (the_result) {
+ if (the_result > 0) {
sense_valid = scsi_sense_valid(&sshdr);
if (sense_valid &&
sshdr.sense_key == UNIT_ATTENTION &&
@@ -3614,7 +3617,7 @@ static int sd_start_stop_device(struct scsi_disk *sdkp, int start)
SD_TIMEOUT, sdkp->max_retries, 0, RQF_PM, NULL);
if (res) {
sd_print_result(sdkp, "Start/Stop Unit failed", res);
- if (driver_byte(res) == DRIVER_SENSE)
+ if (res > 0 && driver_byte(res) == DRIVER_SENSE)
sd_print_sense_hdr(sdkp, &sshdr);
if (scsi_sense_valid(&sshdr) &&
/* 0x3a is medium not present */
diff --git a/drivers/scsi/sd_zbc.c b/drivers/scsi/sd_zbc.c
index 01088f333dbc..6834e029906a 100644
--- a/drivers/scsi/sd_zbc.c
+++ b/drivers/scsi/sd_zbc.c
@@ -116,7 +116,7 @@ static int sd_zbc_do_report_zones(struct scsi_disk *sdkp, unsigned char *buf,
sd_printk(KERN_ERR, sdkp,
"REPORT ZONES start lba %llu failed\n", lba);
sd_print_result(sdkp, "REPORT ZONES", result);
- if (driver_byte(result) == DRIVER_SENSE &&
+ if (result > 0 && driver_byte(result) == DRIVER_SENSE &&
scsi_sense_valid(&sshdr))
sd_print_sense_hdr(sdkp, &sshdr);
return -EIO;
diff --git a/drivers/scsi/sr_ioctl.c b/drivers/scsi/sr_ioctl.c
index ffcf902da390..4c1de11e69fb 100644
--- a/drivers/scsi/sr_ioctl.c
+++ b/drivers/scsi/sr_ioctl.c
@@ -205,6 +205,10 @@ int sr_do_ioctl(Scsi_CD *cd, struct packet_command *cgc)
cgc->timeout, IOCTL_RETRIES, 0, 0, NULL);
/* Minimal error checking. Ignore cases we know about, and report the rest. */
+ if (result < 0) {
+ err = result;
+ goto out;
+ }
if (driver_byte(result) != 0) {
switch (sshdr->sense_key) {
case UNIT_ATTENTION:
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 930f35863cbb..b8462f54cb72 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -8354,7 +8354,7 @@ static int ufshcd_set_dev_pwr_mode(struct ufs_hba *hba,
sdev_printk(KERN_WARNING, sdp,
"START_STOP failed for power mode: %d, result %x\n",
pwr_mode, ret);
- if (driver_byte(ret) == DRIVER_SENSE)
+ if (ret > 0 && driver_byte(ret) == DRIVER_SENSE)
scsi_print_sense_hdr(sdp, NULL, &sshdr);
}
diff --git a/drivers/scsi/virtio_scsi.c b/drivers/scsi/virtio_scsi.c
index 6dac58ae6120..fabbad5cda60 100644
--- a/drivers/scsi/virtio_scsi.c
+++ b/drivers/scsi/virtio_scsi.c
@@ -355,7 +355,7 @@ static void virtscsi_rescan_hotunplug(struct virtio_scsi *vscsi)
if (result == 0 && inq_result[0] >> 5) {
/* PQ indicates the LUN is not attached */
scsi_remove_device(sdev);
- } else if (host_byte(result) == DID_BAD_TARGET) {
+ } else if (result > 0 && host_byte(result) == DID_BAD_TARGET) {
/*
* If all LUNs of a virtio-scsi device are unplugged
* it will respond with BAD TARGET on any INQUIRY
diff --git a/include/scsi/scsi.h b/include/scsi/scsi.h
index 7ac50dbee475..6f227b610681 100644
--- a/include/scsi/scsi.h
+++ b/include/scsi/scsi.h
@@ -256,10 +256,13 @@ static inline int scsi_is_wlun(u64 lun)
* This returns true for known good conditions that may be treated as
* command completed normally
*/
-static inline int scsi_status_is_good(int status)
+static inline bool scsi_status_is_good(int status)
{
+ if (status < 0)
+ return false;
+
if (host_byte(status) == DID_NO_CONNECT)
- return 0;
+ return false;
/*
* FIXME: bit0 is listed as reserved in SCSI-2, but is
--
2.31.1
1
0
Ramaxel inclusion
category: feature
bugzilla: https://gitee.com/openeuler/kernel/issues/I4QLBP
CVE: NA
Changes:
1. Read lb mode from chip
2. Disable fake vf function
3. Remove unnecessary code
Signed-off-by: Yanling Song <songyl(a)ramaxel.com>
Reviewed-by: Yun Xu <xuyun(a)ramaxel.com>
---
.../ethernet/ramaxel/spnic/hw/sphw_cfg_cmd.h | 3 +-
.../ethernet/ramaxel/spnic/hw/sphw_hw_cfg.c | 3 +
.../ethernet/ramaxel/spnic/hw/sphw_hw_cfg.h | 3 +
drivers/scsi/spfc/hw/spfc_cqm_bat_cla.c | 43 +--
drivers/scsi/spfc/hw/spfc_cqm_bitmap_table.c | 10 +-
drivers/scsi/spfc/hw/spfc_cqm_main.c | 299 +-----------------
drivers/scsi/spfc/hw/spfc_cqm_main.h | 3 -
drivers/scsi/spfc/hw/spfc_cqm_object.c | 21 --
8 files changed, 29 insertions(+), 356 deletions(-)
diff --git a/drivers/net/ethernet/ramaxel/spnic/hw/sphw_cfg_cmd.h b/drivers/net/ethernet/ramaxel/spnic/hw/sphw_cfg_cmd.h
index 23644958e33a..63b89e71c552 100644
--- a/drivers/net/ethernet/ramaxel/spnic/hw/sphw_cfg_cmd.h
+++ b/drivers/net/ethernet/ramaxel/spnic/hw/sphw_cfg_cmd.h
@@ -40,7 +40,8 @@ struct cfg_cmd_dev_cap {
u8 sf_svc_attr;
u8 func_sf_en;
- u16 rsvd_sf;
+ u8 lb_mode;
+ u8 smf_pg;
u32 max_conn_num;
u16 max_stick2cache_num;
diff --git a/drivers/net/ethernet/ramaxel/spnic/hw/sphw_hw_cfg.c b/drivers/net/ethernet/ramaxel/spnic/hw/sphw_hw_cfg.c
index 5d6a53307f0a..4b2674ec66f0 100644
--- a/drivers/net/ethernet/ramaxel/spnic/hw/sphw_hw_cfg.c
+++ b/drivers/net/ethernet/ramaxel/spnic/hw/sphw_hw_cfg.c
@@ -112,6 +112,9 @@ static void parse_pub_res_cap(struct sphw_hwdev *hwdev,
else
cap->sf_en = false;
+ cap->lb_mode = dev_cap->lb_mode;
+ cap->smf_pg = dev_cap->smf_pg;
+
cap->timer_en = (u8)timer_enable; /* timer enable */
cap->host_oq_id_mask_val = dev_cap->host_oq_id_mask_val;
cap->max_connect_num = dev_cap->max_conn_num;
diff --git a/drivers/net/ethernet/ramaxel/spnic/hw/sphw_hw_cfg.h b/drivers/net/ethernet/ramaxel/spnic/hw/sphw_hw_cfg.h
index 1147beeb76ad..1b48e0991563 100644
--- a/drivers/net/ethernet/ramaxel/spnic/hw/sphw_hw_cfg.h
+++ b/drivers/net/ethernet/ramaxel/spnic/hw/sphw_hw_cfg.h
@@ -201,6 +201,9 @@ struct service_cap {
u8 timer_en; /* 0:disable, 1:enable */
u8 bloomfilter_en; /* 0:disable, 1:enable*/
+ u8 lb_mode;
+ u8 smf_pg;
+
/* For test */
u32 test_mode;
u32 test_qpc_num;
diff --git a/drivers/scsi/spfc/hw/spfc_cqm_bat_cla.c b/drivers/scsi/spfc/hw/spfc_cqm_bat_cla.c
index 30fb56a9bfed..0c1d97d9e3e6 100644
--- a/drivers/scsi/spfc/hw/spfc_cqm_bat_cla.c
+++ b/drivers/scsi/spfc/hw/spfc_cqm_bat_cla.c
@@ -53,17 +53,6 @@ cqm_bat_fill_cla_common_gpa(struct cqm_handle *cqm_handle,
gpa.acs_spu_en = 0;
}
- /* In fake mode, fake_vf_en in the GPA address of the BAT
- * must be set to 1.
- */
- if (cqm_handle->func_capability.fake_func_type == CQM_FAKE_FUNC_CHILD) {
- gpa.fake_vf_en = 1;
- func_attr = &cqm_handle->parent_cqm_handle->func_attribute;
- gpa.pf_id = func_attr->func_global_idx;
- } else {
- gpa.fake_vf_en = 0;
- }
-
memcpy(&cla_gpa_h, &gpa, sizeof(u32));
bat_entry_standerd->cla_gpa_h = cla_gpa_h;
@@ -379,13 +368,8 @@ s32 cqm_bat_update(struct cqm_handle *cqm_handle)
CQM_PTR_CHECK_RET(buf_in, CQM_FAIL, CQM_ALLOC_FAIL(buf_in));
buf_in->size = sizeof(struct cqm_cmdq_bat_update);
- /* In non-fake mode, func_id is set to 0xffff, indicating the current func.
- * In fake mode, the value of func_id is specified. This is a fake func_id.
- */
- if (cqm_handle->func_capability.fake_func_type == CQM_FAKE_FUNC_CHILD)
- func_id = cqm_handle->func_attribute.func_global_idx;
- else
- func_id = 0xffff;
+ /* In non-fake mode, func_id is set to 0xffff */
+ func_id = 0xffff;
/* The LB scenario is supported.
* The normal mode is the traditional mode and is configured on SMF0.
@@ -545,19 +529,6 @@ s32 cqm_cla_fill_buf(struct cqm_handle *cqm_handle, struct cqm_buf *cla_base_buf
spu_en = 0;
}
- /* fake enable */
- if (cqm_handle->func_capability.fake_func_type ==
- CQM_FAKE_FUNC_CHILD) {
- fake_en = 1ULL << 62;
- func_attr =
- &cqm_handle->parent_cqm_handle->func_attribute;
- pf_id = func_attr->func_global_idx;
- pf_id = (pf_id & 0x1f) << 57;
- } else {
- fake_en = 0;
- pf_id = 0;
- }
-
*base = (((((cla_sub_buf->buf_list[i].pa & CQM_CHIP_GPA_MASK) |
spu_en) |
fake_en) |
@@ -1248,14 +1219,8 @@ s32 cqm_cla_update(struct cqm_handle *cqm_handle, struct cqm_buf_list *buf_node_
}
}
- /* In non-fake mode, set func_id to 0xffff.
- * Indicates the current func fake mode, set func_id to the
- * specified value, This is a fake func_id.
- */
- if (cqm_handle->func_capability.fake_func_type == CQM_FAKE_FUNC_CHILD)
- cmd.func_id = cqm_handle->func_attribute.func_global_idx;
- else
- cmd.func_id = 0xffff;
+ /* In non-fake mode, set func_id to 0xffff. */
+ cmd.func_id = 0xffff;
/* Mode 0 is hashed to 4 SMF engines (excluding PPF) by func ID. */
if (cqm_handle->func_capability.lb_mode == CQM_LB_MODE_NORMAL ||
diff --git a/drivers/scsi/spfc/hw/spfc_cqm_bitmap_table.c b/drivers/scsi/spfc/hw/spfc_cqm_bitmap_table.c
index 4e482776a14f..21100e8db8f4 100644
--- a/drivers/scsi/spfc/hw/spfc_cqm_bitmap_table.c
+++ b/drivers/scsi/spfc/hw/spfc_cqm_bitmap_table.c
@@ -405,14 +405,8 @@ s32 cqm_cla_cache_invalid(struct cqm_handle *cqm_handle, dma_addr_t gpa, u32 cac
cmd.gpa_h = CQM_ADDR_HI(gpa);
cmd.gpa_l = CQM_ADDR_LW(gpa);
- /* In non-fake mode, set func_id to 0xffff.
- * Indicate the current func fake mode.
- * The value of func_id is a fake func ID.
- */
- if (cqm_handle->func_capability.fake_func_type == CQM_FAKE_FUNC_CHILD)
- cmd.func_id = cqm_handle->func_attribute.func_global_idx;
- else
- cmd.func_id = 0xffff;
+ /* In non-fake mode, set func_id to 0xffff. */
+ cmd.func_id = 0xffff;
/* Mode 0 is hashed to 4 SMF engines (excluding PPF) by func ID. */
if (cqm_handle->func_capability.lb_mode == CQM_LB_MODE_NORMAL ||
diff --git a/drivers/scsi/spfc/hw/spfc_cqm_main.c b/drivers/scsi/spfc/hw/spfc_cqm_main.c
index a4c8e60971b1..52cc2c7838e9 100644
--- a/drivers/scsi/spfc/hw/spfc_cqm_main.c
+++ b/drivers/scsi/spfc/hw/spfc_cqm_main.c
@@ -11,21 +11,8 @@
#include "sphw_crm.h"
#include "sphw_hw.h"
#include "sphw_hw_cfg.h"
-
#include "spfc_cqm_main.h"
-static unsigned char cqm_lb_mode = CQM_LB_MODE_NORMAL;
-module_param(cqm_lb_mode, byte, 0644);
-MODULE_PARM_DESC(cqm_lb_mode, "for cqm lb mode (default=0xff)");
-
-static unsigned char cqm_fake_mode = CQM_FAKE_MODE_DISABLE;
-module_param(cqm_fake_mode, byte, 0644);
-MODULE_PARM_DESC(cqm_fake_mode, "for cqm fake mode (default=0 disable)");
-
-static unsigned char cqm_platform_mode = CQM_FPGA_MODE;
-module_param(cqm_platform_mode, byte, 0644);
-MODULE_PARM_DESC(cqm_platform_mode, "for cqm platform mode (default=0 FPGA)");
-
s32 cqm3_init(void *ex_handle)
{
struct sphw_hwdev *handle = (struct sphw_hwdev *)ex_handle;
@@ -63,19 +50,6 @@ s32 cqm3_init(void *ex_handle)
goto err1;
}
- /* In FAKE mode, only the bitmap of the timer of the function is
- * enabled, and resources are not initialized. Otherwise, the
- * configuration of the fake function is overwritten.
- */
- if (cqm_handle->func_capability.fake_func_type == CQM_FAKE_FUNC_CHILD_CONFLICT) {
- if (sphw_func_tmr_bitmap_set(ex_handle, true) != CQM_SUCCESS)
- cqm_err(handle->dev_hdl, "Timer start: enable timer bitmap failed\n");
-
- handle->cqm_hdl = NULL;
- kfree(cqm_handle);
- return CQM_SUCCESS;
- }
-
/* Initialize memory entries such as BAT, CLA, and bitmap. */
if (cqm_mem_init(ex_handle) != CQM_SUCCESS) {
cqm_err(handle->dev_hdl, CQM_FUNCTION_FAIL(cqm_mem_init));
@@ -287,64 +261,6 @@ void cqm_service_capability_init(struct cqm_handle *cqm_handle,
cqm_service_capability_init_fc(cqm_handle, (void *)service_capability);
}
-s32 cqm_get_fake_func_type(struct cqm_handle *cqm_handle)
-{
- struct cqm_func_capability *func_cap = &cqm_handle->func_capability;
- u32 parent_func, child_func_start, child_func_number, i;
- u32 idx = cqm_handle->func_attribute.func_global_idx;
-
- /* Currently, only one set of fake configurations is implemented.
- * fake_cfg_number = 1
- */
- for (i = 0; i < func_cap->fake_cfg_number; i++) {
- parent_func = func_cap->fake_cfg[i].parent_func;
- child_func_start = func_cap->fake_cfg[i].child_func_start;
- child_func_number = func_cap->fake_cfg[i].child_func_number;
-
- if (idx == parent_func) {
- return CQM_FAKE_FUNC_PARENT;
- } else if ((idx >= child_func_start) &&
- (idx < (child_func_start + child_func_number))) {
- return CQM_FAKE_FUNC_CHILD_CONFLICT;
- }
- }
-
- return CQM_FAKE_FUNC_NORMAL;
-}
-
-s32 cqm_get_child_func_start(struct cqm_handle *cqm_handle)
-{
- struct cqm_func_capability *func_cap = &cqm_handle->func_capability;
- struct sphw_func_attr *func_attr = &cqm_handle->func_attribute;
- u32 i;
-
- /* Currently, only one set of fake configurations is implemented.
- * fake_cfg_number = 1
- */
- for (i = 0; i < func_cap->fake_cfg_number; i++) {
- if (func_attr->func_global_idx ==
- func_cap->fake_cfg[i].parent_func)
- return (s32)(func_cap->fake_cfg[i].child_func_start);
- }
-
- return CQM_FAIL;
-}
-
-s32 cqm_get_child_func_number(struct cqm_handle *cqm_handle)
-{
- struct cqm_func_capability *func_cap = &cqm_handle->func_capability;
- struct sphw_func_attr *func_attr = &cqm_handle->func_attribute;
- u32 i;
-
- for (i = 0; i < func_cap->fake_cfg_number; i++) {
- if (func_attr->func_global_idx ==
- func_cap->fake_cfg[i].parent_func)
- return (s32)(func_cap->fake_cfg[i].child_func_number);
- }
-
- return CQM_FAIL;
-}
-
/* Set func_type in fake_cqm_handle to ppf, pf, or vf. */
void cqm_set_func_type(struct cqm_handle *cqm_handle)
{
@@ -358,41 +274,20 @@ void cqm_set_func_type(struct cqm_handle *cqm_handle)
cqm_handle->func_attribute.func_type = CQM_VF;
}
-void cqm_lb_fake_mode_init(struct cqm_handle *cqm_handle)
+void cqm_lb_fake_mode_init(struct cqm_handle *cqm_handle, struct service_cap *svc_cap)
{
struct cqm_func_capability *func_cap = &cqm_handle->func_capability;
- struct cqm_fake_cfg *cfg = func_cap->fake_cfg;
- func_cap->lb_mode = cqm_lb_mode;
- func_cap->fake_mode = cqm_fake_mode;
+ func_cap->lb_mode = svc_cap->lb_mode;
/* Initializing the LB Mode */
- if (func_cap->lb_mode == CQM_LB_MODE_NORMAL) {
+ if (func_cap->lb_mode == CQM_LB_MODE_NORMAL)
func_cap->smf_pg = 0;
- } else {
- /* The LB mode is tailored on the FPGA.
- * Only SMF0 and SMF2 are instantiated.
- */
- if (cqm_platform_mode == CQM_FPGA_MODE)
- func_cap->smf_pg = 0x5;
- else
- func_cap->smf_pg = 0xF;
- }
+ else
+ func_cap->smf_pg = svc_cap->smf_pg;
- /* Initializing the FAKE Mode */
- if (func_cap->fake_mode == CQM_FAKE_MODE_DISABLE) {
- func_cap->fake_cfg_number = 0;
- func_cap->fake_func_type = CQM_FAKE_FUNC_NORMAL;
- } else {
- func_cap->fake_cfg_number = 1;
-
- /* When configuring fake mode, ensure that the parent function
- * cannot be contained in the child function; otherwise, the
- * system will be initialized repeatedly.
- */
- cfg[0].child_func_start = CQM_FAKE_CFUNC_START;
- func_cap->fake_func_type = cqm_get_fake_func_type(cqm_handle);
- }
+ func_cap->fake_cfg_number = 0;
+ func_cap->fake_func_type = CQM_FAKE_FUNC_NORMAL;
}
s32 cqm_capability_init(void *ex_handle)
@@ -465,10 +360,9 @@ s32 cqm_capability_init(void *ex_handle)
func_cap->gpa_check_enable = true;
- cqm_lb_fake_mode_init(cqm_handle);
+ cqm_lb_fake_mode_init(cqm_handle, service_capability);
cqm_info(handle->dev_hdl, "Cap init: lb_mode=%u\n", func_cap->lb_mode);
cqm_info(handle->dev_hdl, "Cap init: smf_pg=%u\n", func_cap->smf_pg);
- cqm_info(handle->dev_hdl, "Cap init: fake_mode=%u\n", func_cap->fake_mode);
cqm_info(handle->dev_hdl, "Cap init: fake_func_type=%u\n", func_cap->fake_func_type);
cqm_info(handle->dev_hdl, "Cap init: fake_cfg_number=%u\n", func_cap->fake_cfg_number);
@@ -517,153 +411,6 @@ s32 cqm_capability_init(void *ex_handle)
return err;
}
-void cqm_fake_uninit(struct cqm_handle *cqm_handle)
-{
- u32 i;
-
- if (cqm_handle->func_capability.fake_func_type !=
- CQM_FAKE_FUNC_PARENT)
- return;
-
- for (i = 0; i < CQM_FAKE_FUNC_MAX; i++) {
- kfree(cqm_handle->fake_cqm_handle[i]);
- cqm_handle->fake_cqm_handle[i] = NULL;
- }
-}
-
-s32 cqm_fake_init(struct cqm_handle *cqm_handle)
-{
- struct sphw_hwdev *handle = cqm_handle->ex_handle;
- struct cqm_func_capability *func_cap = NULL;
- struct cqm_handle *fake_cqm_handle = NULL;
- struct sphw_func_attr *func_attr = NULL;
- s32 child_func_start, child_func_number;
- u32 i;
-
- func_cap = &cqm_handle->func_capability;
- if (func_cap->fake_func_type != CQM_FAKE_FUNC_PARENT)
- return CQM_SUCCESS;
-
- child_func_start = cqm_get_child_func_start(cqm_handle);
- if (child_func_start == CQM_FAIL) {
- cqm_err(handle->dev_hdl, CQM_WRONG_VALUE(child_func_start));
- return CQM_FAIL;
- }
-
- child_func_number = cqm_get_child_func_number(cqm_handle);
- if (child_func_number == CQM_FAIL) {
- cqm_err(handle->dev_hdl, CQM_WRONG_VALUE(child_func_number));
- return CQM_FAIL;
- }
-
- for (i = 0; i < (u32)child_func_number; i++) {
- fake_cqm_handle = kmalloc(sizeof(*fake_cqm_handle), GFP_KERNEL | __GFP_ZERO);
- if (!fake_cqm_handle) {
- cqm_err(handle->dev_hdl,
- CQM_ALLOC_FAIL(fake_cqm_handle));
- goto err;
- }
-
- /* Copy the attributes of the parent CQM handle to the child CQM
- * handle and modify the values of function.
- */
- memcpy(fake_cqm_handle, cqm_handle, sizeof(struct cqm_handle));
- func_attr = &fake_cqm_handle->func_attribute;
- func_cap = &fake_cqm_handle->func_capability;
- func_attr->func_global_idx = (u16)(child_func_start + i);
- cqm_set_func_type(fake_cqm_handle);
- func_cap->fake_func_type = CQM_FAKE_FUNC_CHILD;
- cqm_info(handle->dev_hdl, "Fake func init: function[%u] type %d(0:PF,1:VF,2:PPF)\n",
- func_attr->func_global_idx, func_attr->func_type);
-
- fake_cqm_handle->parent_cqm_handle = cqm_handle;
- cqm_handle->fake_cqm_handle[i] = fake_cqm_handle;
- }
-
- return CQM_SUCCESS;
-
-err:
- cqm_fake_uninit(cqm_handle);
- return CQM_FAIL;
-}
-
-void cqm_fake_mem_uninit(struct cqm_handle *cqm_handle)
-{
- struct sphw_hwdev *handle = cqm_handle->ex_handle;
- struct cqm_handle *fake_cqm_handle = NULL;
- s32 child_func_number;
- u32 i;
-
- if (cqm_handle->func_capability.fake_func_type != CQM_FAKE_FUNC_PARENT)
- return;
-
- child_func_number = cqm_get_child_func_number(cqm_handle);
- if (child_func_number == CQM_FAIL) {
- cqm_err(handle->dev_hdl, CQM_WRONG_VALUE(child_func_number));
- return;
- }
-
- for (i = 0; i < (u32)child_func_number; i++) {
- fake_cqm_handle = cqm_handle->fake_cqm_handle[i];
- cqm_object_table_uninit(fake_cqm_handle);
- cqm_bitmap_uninit(fake_cqm_handle);
- cqm_cla_uninit(fake_cqm_handle, CQM_BAT_ENTRY_MAX);
- cqm_bat_uninit(fake_cqm_handle);
- }
-}
-
-s32 cqm_fake_mem_init(struct cqm_handle *cqm_handle)
-{
- struct sphw_hwdev *handle = cqm_handle->ex_handle;
- struct cqm_handle *fake_cqm_handle = NULL;
- s32 child_func_number;
- u32 i;
-
- if (cqm_handle->func_capability.fake_func_type !=
- CQM_FAKE_FUNC_PARENT)
- return CQM_SUCCESS;
-
- child_func_number = cqm_get_child_func_number(cqm_handle);
- if (child_func_number == CQM_FAIL) {
- cqm_err(handle->dev_hdl, CQM_WRONG_VALUE(child_func_number));
- return CQM_FAIL;
- }
-
- for (i = 0; i < (u32)child_func_number; i++) {
- fake_cqm_handle = cqm_handle->fake_cqm_handle[i];
-
- if (cqm_bat_init(fake_cqm_handle) != CQM_SUCCESS) {
- cqm_err(handle->dev_hdl,
- CQM_FUNCTION_FAIL(cqm_bat_init));
- goto err;
- }
-
- if (cqm_cla_init(fake_cqm_handle) != CQM_SUCCESS) {
- cqm_err(handle->dev_hdl,
- CQM_FUNCTION_FAIL(cqm_cla_init));
- goto err;
- }
-
- if (cqm_bitmap_init(fake_cqm_handle) != CQM_SUCCESS) {
- cqm_err(handle->dev_hdl,
- CQM_FUNCTION_FAIL(cqm_bitmap_init));
- goto err;
- }
-
- if (cqm_object_table_init(fake_cqm_handle) != CQM_SUCCESS) {
- cqm_err(handle->dev_hdl,
- CQM_FUNCTION_FAIL(cqm_object_table_init));
- goto err;
- }
- }
-
- return CQM_SUCCESS;
-
-err:
- cqm_fake_mem_uninit(cqm_handle);
- return CQM_FAIL;
-}
-
s32 cqm_mem_init(void *ex_handle)
{
struct sphw_hwdev *handle = (struct sphw_hwdev *)ex_handle;
@@ -671,49 +418,35 @@ s32 cqm_mem_init(void *ex_handle)
cqm_handle = (struct cqm_handle *)(handle->cqm_hdl);
- if (cqm_fake_init(cqm_handle) != CQM_SUCCESS) {
- cqm_err(handle->dev_hdl, CQM_FUNCTION_FAIL(cqm_fake_init));
- return CQM_FAIL;
- }
-
- if (cqm_fake_mem_init(cqm_handle) != CQM_SUCCESS) {
- cqm_err(handle->dev_hdl, CQM_FUNCTION_FAIL(cqm_fake_mem_init));
- goto err1;
- }
-
if (cqm_bat_init(cqm_handle) != CQM_SUCCESS) {
cqm_err(handle->dev_hdl, CQM_FUNCTION_FAIL(cqm_bat_init));
- goto err2;
+ return CQM_FAIL;
}
if (cqm_cla_init(cqm_handle) != CQM_SUCCESS) {
cqm_err(handle->dev_hdl, CQM_FUNCTION_FAIL(cqm_cla_init));
- goto err3;
+ goto err1;
}
if (cqm_bitmap_init(cqm_handle) != CQM_SUCCESS) {
cqm_err(handle->dev_hdl, CQM_FUNCTION_FAIL(cqm_bitmap_init));
- goto err4;
+ goto err2;
}
if (cqm_object_table_init(cqm_handle) != CQM_SUCCESS) {
cqm_err(handle->dev_hdl,
CQM_FUNCTION_FAIL(cqm_object_table_init));
- goto err5;
+ goto err3;
}
return CQM_SUCCESS;
-err5:
- cqm_bitmap_uninit(cqm_handle);
-err4:
- cqm_cla_uninit(cqm_handle, CQM_BAT_ENTRY_MAX);
err3:
- cqm_bat_uninit(cqm_handle);
+ cqm_bitmap_uninit(cqm_handle);
err2:
- cqm_fake_mem_uninit(cqm_handle);
+ cqm_cla_uninit(cqm_handle, CQM_BAT_ENTRY_MAX);
err1:
- cqm_fake_uninit(cqm_handle);
+ cqm_bat_uninit(cqm_handle);
return CQM_FAIL;
}
@@ -728,8 +461,6 @@ void cqm_mem_uninit(void *ex_handle)
cqm_bitmap_uninit(cqm_handle);
cqm_cla_uninit(cqm_handle, CQM_BAT_ENTRY_MAX);
cqm_bat_uninit(cqm_handle);
- cqm_fake_mem_uninit(cqm_handle);
- cqm_fake_uninit(cqm_handle);
}
s32 cqm_event_init(void *ex_handle)
diff --git a/drivers/scsi/spfc/hw/spfc_cqm_main.h b/drivers/scsi/spfc/hw/spfc_cqm_main.h
index 1b8cf8bdb3b7..cf10d7f5c339 100644
--- a/drivers/scsi/spfc/hw/spfc_cqm_main.h
+++ b/drivers/scsi/spfc/hw/spfc_cqm_main.h
@@ -328,9 +328,6 @@ void cqm_mem_uninit(void *ex_handle);
s32 cqm_event_init(void *ex_handle);
void cqm_event_uninit(void *ex_handle);
u8 cqm_aeq_callback(void *ex_handle, u8 event, u8 *data);
-s32 cqm_get_fake_func_type(struct cqm_handle *cqm_handle);
-s32 cqm_get_child_func_start(struct cqm_handle *cqm_handle);
-s32 cqm_get_child_func_number(struct cqm_handle *cqm_handle);
s32 cqm3_init(void *ex_handle);
void cqm3_uninit(void *ex_handle);
diff --git a/drivers/scsi/spfc/hw/spfc_cqm_object.c b/drivers/scsi/spfc/hw/spfc_cqm_object.c
index b895d37aebae..165794e9c7e5 100644
--- a/drivers/scsi/spfc/hw/spfc_cqm_object.c
+++ b/drivers/scsi/spfc/hw/spfc_cqm_object.c
@@ -155,8 +155,6 @@ struct cqm_qpc_mpt *cqm3_object_qpc_mpt_create(void *ex_handle, u32 service_type
struct cqm_qpc_mpt_info *qpc_mpt_info = NULL;
struct cqm_handle *cqm_handle = NULL;
s32 ret = CQM_FAIL;
- u32 relative_index;
- u32 fake_func_id;
CQM_PTR_CHECK_RET(ex_handle, NULL, CQM_PTR_NULL(ex_handle));
@@ -180,25 +178,6 @@ struct cqm_qpc_mpt *cqm3_object_qpc_mpt_create(void *ex_handle, u32 service_type
return NULL;
}
- /* fake vf adaption, switch to corresponding VF. */
- if (cqm_handle->func_capability.fake_func_type ==
- CQM_FAKE_FUNC_PARENT) {
- fake_func_id = index / cqm_handle->func_capability.qpc_number;
- relative_index = index % cqm_handle->func_capability.qpc_number;
-
- cqm_info(handle->dev_hdl, "qpc create: fake_func_id=%u, relative_index=%u\n",
- fake_func_id, relative_index);
-
- if ((s32)fake_func_id >=
- cqm_get_child_func_number(cqm_handle)) {
- cqm_err(handle->dev_hdl, CQM_WRONG_VALUE(fake_func_id));
- return NULL;
- }
-
- index = relative_index;
- cqm_handle = cqm_handle->fake_cqm_handle[fake_func_id];
- }
-
qpc_mpt_info = kmalloc(sizeof(*qpc_mpt_info), GFP_ATOMIC | __GFP_ZERO);
CQM_PTR_CHECK_RET(qpc_mpt_info, NULL, CQM_ALLOC_FAIL(qpc_mpt_info));
--
2.32.0
1
0
1.Remove unused functions about ceq
2.Remove unused clp hardware channels
3.Remove the code of polling mode
4.Remove the code about little endian and big endian conversion
Yanling Song (4):
net/spnic:Remove unused functions about ceq
net/spnic:Remove unused clp hardware channels
net/spnic:Remove the code of polling mode
net/spnic:Remove the code about little endian and big endian conversion
.../net/ethernet/ramaxel/spnic/hw/sphw_cmdq.c | 58 +--
.../ethernet/ramaxel/spnic/hw/sphw_common.h | 12 -
.../net/ethernet/ramaxel/spnic/hw/sphw_crm.h | 2 -
.../net/ethernet/ramaxel/spnic/hw/sphw_csr.h | 13 -
.../net/ethernet/ramaxel/spnic/hw/sphw_eqs.c | 104 +---
.../net/ethernet/ramaxel/spnic/hw/sphw_hw.h | 2 -
.../ethernet/ramaxel/spnic/hw/sphw_hwdev.c | 31 --
.../ethernet/ramaxel/spnic/hw/sphw_hwdev.h | 2 -
.../net/ethernet/ramaxel/spnic/hw/sphw_hwif.c | 27 +-
.../net/ethernet/ramaxel/spnic/hw/sphw_mbox.c | 20 +-
.../net/ethernet/ramaxel/spnic/hw/sphw_mbox.h | 2 -
.../net/ethernet/ramaxel/spnic/hw/sphw_mgmt.c | 487 ------------------
.../net/ethernet/ramaxel/spnic/hw/sphw_mgmt.h | 50 --
.../net/ethernet/ramaxel/spnic/hw/sphw_mt.h | 1 -
.../net/ethernet/ramaxel/spnic/spnic_nic_io.h | 6 +-
.../net/ethernet/ramaxel/spnic/spnic_nic_qp.h | 7 +-
drivers/net/ethernet/ramaxel/spnic/spnic_rx.c | 39 +-
drivers/net/ethernet/ramaxel/spnic/spnic_tx.c | 20 +-
18 files changed, 41 insertions(+), 842 deletions(-)
--
2.23.0
1
4
[PATCH openEuler-1.0-LTS] ext4: Fix BUG_ON in ext4_bread when write quota data
by Yang Yingliang 13 Jan '22
by Yang Yingliang 13 Jan '22
13 Jan '22
From: Ye Bin <yebin10(a)huawei.com>
mainline inclusion
from mainline-v5.17
commit ce85548ab4295234b4f8e63a0eea0c157d2f6b25
category: bugfix
bugzilla: 185930
CVE: NA
-----------------------------------------------
We got issue as follows when run syzkaller:
[ 167.936972] EXT4-fs error (device loop0): __ext4_remount:6314: comm rep: Abort forced by user
[ 167.938306] EXT4-fs (loop0): Remounting filesystem read-only
[ 167.981637] Assertion failure in ext4_getblk() at fs/ext4/inode.c:847: '(EXT4_SB(inode->i_sb)->s_mount_state & EXT4_FC_REPLAY) || handle != NULL || create == 0'
[ 167.983601] ------------[ cut here ]------------
[ 167.984245] kernel BUG at fs/ext4/inode.c:847!
[ 167.984882] invalid opcode: 0000 [#1] PREEMPT SMP KASAN PTI
[ 167.985624] CPU: 7 PID: 2290 Comm: rep Tainted: G B 5.16.0-rc5-next-20211217+ #123
[ 167.986823] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS ?-20190727_073836-buildvm-ppc64le-16.ppc.fedoraproject.org-3.fc31 04/01/2014
[ 167.988590] RIP: 0010:ext4_getblk+0x17e/0x504
[ 167.989189] Code: c6 01 74 28 49 c7 c0 a0 a3 5c 9b b9 4f 03 00 00 48 c7 c2 80 9c 5c 9b 48 c7 c6 40 b6 5c 9b 48 c7 c7 20 a4 5c 9b e8 77 e3 fd ff <0f> 0b 8b 04 244
[ 167.991679] RSP: 0018:ffff8881736f7398 EFLAGS: 00010282
[ 167.992385] RAX: 0000000000000094 RBX: 1ffff1102e6dee75 RCX: 0000000000000000
[ 167.993337] RDX: 0000000000000001 RSI: ffffffff9b6e29e0 RDI: ffffed102e6dee66
[ 167.994292] RBP: ffff88816a076210 R08: 0000000000000094 R09: ffffed107363fa09
[ 167.995252] R10: ffff88839b1fd047 R11: ffffed107363fa08 R12: ffff88816a0761e8
[ 167.996205] R13: 0000000000000000 R14: 0000000000000021 R15: 0000000000000001
[ 167.997158] FS: 00007f6a1428c740(0000) GS:ffff88839b000000(0000) knlGS:0000000000000000
[ 167.998238] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 167.999025] CR2: 00007f6a140716c8 CR3: 0000000133216000 CR4: 00000000000006e0
[ 167.999987] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
[ 168.000944] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
[ 168.001899] Call Trace:
[ 168.002235] <TASK>
[ 168.007167] ext4_bread+0xd/0x53
[ 168.007612] ext4_quota_write+0x20c/0x5c0
[ 168.010457] write_blk+0x100/0x220
[ 168.010944] remove_free_dqentry+0x1c6/0x440
[ 168.011525] free_dqentry.isra.0+0x565/0x830
[ 168.012133] remove_tree+0x318/0x6d0
[ 168.014744] remove_tree+0x1eb/0x6d0
[ 168.017346] remove_tree+0x1eb/0x6d0
[ 168.019969] remove_tree+0x1eb/0x6d0
[ 168.022128] qtree_release_dquot+0x291/0x340
[ 168.023297] v2_release_dquot+0xce/0x120
[ 168.023847] dquot_release+0x197/0x3e0
[ 168.024358] ext4_release_dquot+0x22a/0x2d0
[ 168.024932] dqput.part.0+0x1c9/0x900
[ 168.025430] __dquot_drop+0x120/0x190
[ 168.025942] ext4_clear_inode+0x86/0x220
[ 168.026472] ext4_evict_inode+0x9e8/0xa22
[ 168.028200] evict+0x29e/0x4f0
[ 168.028625] dispose_list+0x102/0x1f0
[ 168.029148] evict_inodes+0x2c1/0x3e0
[ 168.030188] generic_shutdown_super+0xa4/0x3b0
[ 168.030817] kill_block_super+0x95/0xd0
[ 168.031360] deactivate_locked_super+0x85/0xd0
[ 168.031977] cleanup_mnt+0x2bc/0x480
[ 168.033062] task_work_run+0xd1/0x170
[ 168.033565] do_exit+0xa4f/0x2b50
[ 168.037155] do_group_exit+0xef/0x2d0
[ 168.037666] __x64_sys_exit_group+0x3a/0x50
[ 168.038237] do_syscall_64+0x3b/0x90
[ 168.038751] entry_SYSCALL_64_after_hwframe+0x44/0xae
In order to reproduce this problem, the following conditions need to be met:
1. Ext4 filesystem with no journal;
2. Filesystem image with incorrect quota data;
3. Abort filesystem forced by user;
4. umount filesystem;
As in ext4_quota_write:
...
if (EXT4_SB(sb)->s_journal && !handle) {
ext4_msg(sb, KERN_WARNING, "Quota write (off=%llu, len=%llu)"
" cancelled because transaction is not started",
(unsigned long long)off, (unsigned long long)len);
return -EIO;
}
...
We only check handle if NULL when filesystem has journal. There is need
check handle if NULL even when filesystem has no journal.
Signed-off-by: Ye Bin <yebin10(a)huawei.com>
Reviewed-by: Jan Kara <jack(a)suse.cz>
Link: https://lore.kernel.org/r/20211223015506.297766-1-yebin10@huawei.com
Signed-off-by: Theodore Ts'o <tytso(a)mit.edu>
Cc: stable(a)kernel.org
Signed-off-by: Ye Bin <yebin10(a)huawei.com>
Reviewed-by: Zhang Yi <yi.zhang(a)huawei.com>
Signed-off-by: Yang Yingliang <yangyingliang(a)huawei.com>
---
fs/ext4/super.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index 587817ac60990..b89f431ec78d3 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -6245,7 +6245,7 @@ static ssize_t ext4_quota_write(struct super_block *sb, int type,
struct buffer_head *bh;
handle_t *handle = journal_current_handle();
- if (EXT4_SB(sb)->s_journal && !handle) {
+ if (!handle) {
ext4_msg(sb, KERN_WARNING, "Quota write (off=%llu, len=%llu)"
" cancelled because transaction is not started",
(unsigned long long)off, (unsigned long long)len);
--
2.25.1
1
0
[PATCH openEuler-1.0-LTS] PM: hibernate: use correct mode for swsusp_close()
by Yang Yingliang 13 Jan '22
by Yang Yingliang 13 Jan '22
13 Jan '22
From: Thomas Zeitlhofer <thomas.zeitlhofer+lkml(a)ze-it.at>
stable inclusion
from linux-v4.19.219
commit 68945e943519df1532e598fafab16ac54488933f
---------------------------------------------------
[ Upstream commit cefcf24b4d351daf70ecd945324e200d3736821e ]
Commit 39fbef4b0f77 ("PM: hibernate: Get block device exclusively in
swsusp_check()") changed the opening mode of the block device to
(FMODE_READ | FMODE_EXCL).
In the corresponding calls to swsusp_close(), the mode is still just
FMODE_READ which triggers the warning in blkdev_flush_mapping() on
resume from hibernate.
So, use the mode (FMODE_READ | FMODE_EXCL) also when closing the
device.
Fixes: 39fbef4b0f77 ("PM: hibernate: Get block device exclusively in swsusp_check()")
Signed-off-by: Thomas Zeitlhofer <thomas.zeitlhofer+lkml(a)ze-it.at>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki(a)intel.com>
Signed-off-by: Sasha Levin <sashal(a)kernel.org>
Signed-off-by: Ye Bin <yebin10(a)huawei.com>
Reviewed-by: Zhang Yi <yi.zhang(a)huawei.com>
Signed-off-by: Yang Yingliang <yangyingliang(a)huawei.com>
---
kernel/power/hibernate.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/kernel/power/hibernate.c b/kernel/power/hibernate.c
index 72ef9df2a29cd..fc6466351e62f 100644
--- a/kernel/power/hibernate.c
+++ b/kernel/power/hibernate.c
@@ -686,7 +686,7 @@ static int load_image_and_restore(void)
goto Unlock;
error = swsusp_read(&flags);
- swsusp_close(FMODE_READ);
+ swsusp_close(FMODE_READ | FMODE_EXCL);
if (!error)
hibernation_restore(flags & SF_PLATFORM_MODE);
@@ -896,7 +896,7 @@ static int software_resume(void)
/* The snapshot device should not be opened while we're running */
if (!atomic_add_unless(&snapshot_device_available, -1, 0)) {
error = -EBUSY;
- swsusp_close(FMODE_READ);
+ swsusp_close(FMODE_READ | FMODE_EXCL);
goto Unlock;
}
@@ -925,7 +925,7 @@ static int software_resume(void)
pm_pr_dbg("Hibernation image not present or could not be loaded.\n");
return error;
Close_Finish:
- swsusp_close(FMODE_READ);
+ swsusp_close(FMODE_READ | FMODE_EXCL);
goto Finish;
}
--
2.25.1
1
0
[PATCH openEuler-1.0-LTS] Revert "watchdog: Fix check_preemption_disabled() error"
by Yang Yingliang 13 Jan '22
by Yang Yingliang 13 Jan '22
13 Jan '22
hulk inclusion
category: bugfix
bugzilla: 173968, https://gitee.com/openeuler/kernel/issues/I3J87Y
CVE: NA
---------------------------
This reverts commit b2e484e966ac2f211f8f8cf56083e9bc4d5d3c6a.
When CONFIG_LOCKDEP and CONFIG_DEBUG_LOCKDEP are enabled, it detects the following error:
[ 10.145007] BUG: sleeping function called from invalid context at mm/slab.h:418
[ 10.145394] in_atomic(): 1, irqs_disabled(): 0, pid: 1, name: swapper/0
[ 10.145765] Preemption disabled at:
[ 10.145978] [<ffff000008f8e7b4>] hardlockup_detector_perf_init+0x20/0x100
[ 10.146770] CPU: 6 PID: 1 Comm: swapper/0 Not tainted 4.19.90+ #3
[ 10.148242] Hardware name: linux,dummy-virt (DT)
[ 10.148572] Call trace:
[ 10.148667] dump_backtrace+0x0/0x190
[ 10.148765] show_stack+0x24/0x30
[ 10.148875] dump_stack+0xa4/0xf8
[ 10.148964] ___might_sleep+0x150/0x180
[ 10.149065] __might_sleep+0x58/0x90
[ 10.149199] kmem_cache_alloc_trace+0x244/0x2b0
[ 10.149308] perf_event_alloc+0x74/0x680
[ 10.149402] perf_event_create_kernel_counter+0x2c/0x190
[ 10.149516] arch_probe_cpu_freq+0x84/0x1ac
[ 10.149611] hw_nmi_get_sample_period+0xb8/0x180
[ 10.149713] hardlockup_detector_event_create+0x28/0xfc
[ 10.149827] hardlockup_detector_perf_init+0x24/0x100
[ 10.149943] watchdog_nmi_probe+0x14/0x1c
[ 10.150037] lockup_detector_init+0x58/0x98
[ 10.150173] kernel_init_freeable+0x10c/0x1c4
[ 10.150298] kernel_init+0x18/0x110
[ 10.150422] ret_from_fork+0x10/0x18
In 'b2e484e966ac ("watchdog: Fix check_preemption_disabled() error")', we
tried to fix check_preemption_disabled() error by disabling preemption in
hardlockup_detector_perf_init(), but missed that function
perf_event_create_kernel_counter() may sleep.
The preemption is always disabled, the problem that wanted be fixed is not
existed, so just revert this commit.
Fixes: b2e484e966ac ("watchdog: Fix check_preemption_disabled() error")
Signed-off-by: Yang Yingliang <yangyingliang(a)huawei.com>
Reviewed-by: Xiongfeng Wang <wangxiongfeng2(a)huawei.com>
Signed-off-by: Yang Yingliang <yangyingliang(a)huawei.com>
---
kernel/watchdog_hld.c | 5 +----
1 file changed, 1 insertion(+), 4 deletions(-)
diff --git a/kernel/watchdog_hld.c b/kernel/watchdog_hld.c
index a5aff8ffa48ce..43832b1023693 100644
--- a/kernel/watchdog_hld.c
+++ b/kernel/watchdog_hld.c
@@ -508,17 +508,14 @@ void __init hardlockup_detector_perf_restart(void)
*/
int __init hardlockup_detector_perf_init(void)
{
- int ret;
+ int ret = hardlockup_detector_event_create();
- preempt_disable();
- ret = hardlockup_detector_event_create();
if (ret) {
pr_info("Perf NMI watchdog permanently disabled\n");
} else {
perf_event_release_kernel(this_cpu_read(watchdog_ev));
this_cpu_write(watchdog_ev, NULL);
}
- preempt_enable();
return ret;
}
#endif /* CONFIG_HARDLOCKUP_DETECTOR_PERF */
--
2.25.1
1
0
Ramaxel inclusion
category: feature
bugzilla: https://gitee.com/openeuler/kernel/issues/I4QLBP
CVE: NA
Changes:
1. Read lb mode from chip
2. Disable fake vf function
3. Remove unnecessary code
Signed-off-by: Yanling Song <songyl(a)ramaxel.com>
Reviewed-by: Yun Xu <xuyun(a)ramaxel.com>
---
.../ethernet/ramaxel/spnic/hw/sphw_cfg_cmd.h | 3 +-
.../ethernet/ramaxel/spnic/hw/sphw_hw_cfg.c | 3 +
.../ethernet/ramaxel/spnic/hw/sphw_hw_cfg.h | 3 +
drivers/scsi/spfc/hw/spfc_cqm_bat_cla.c | 43 +--
drivers/scsi/spfc/hw/spfc_cqm_bitmap_table.c | 10 +-
drivers/scsi/spfc/hw/spfc_cqm_main.c | 299 +-----------------
drivers/scsi/spfc/hw/spfc_cqm_main.h | 3 -
drivers/scsi/spfc/hw/spfc_cqm_object.c | 21 --
8 files changed, 29 insertions(+), 356 deletions(-)
diff --git a/drivers/net/ethernet/ramaxel/spnic/hw/sphw_cfg_cmd.h b/drivers/net/ethernet/ramaxel/spnic/hw/sphw_cfg_cmd.h
index 23644958e33a..63b89e71c552 100644
--- a/drivers/net/ethernet/ramaxel/spnic/hw/sphw_cfg_cmd.h
+++ b/drivers/net/ethernet/ramaxel/spnic/hw/sphw_cfg_cmd.h
@@ -40,7 +40,8 @@ struct cfg_cmd_dev_cap {
u8 sf_svc_attr;
u8 func_sf_en;
- u16 rsvd_sf;
+ u8 lb_mode;
+ u8 smf_pg;
u32 max_conn_num;
u16 max_stick2cache_num;
diff --git a/drivers/net/ethernet/ramaxel/spnic/hw/sphw_hw_cfg.c b/drivers/net/ethernet/ramaxel/spnic/hw/sphw_hw_cfg.c
index 5d6a53307f0a..4b2674ec66f0 100644
--- a/drivers/net/ethernet/ramaxel/spnic/hw/sphw_hw_cfg.c
+++ b/drivers/net/ethernet/ramaxel/spnic/hw/sphw_hw_cfg.c
@@ -112,6 +112,9 @@ static void parse_pub_res_cap(struct sphw_hwdev *hwdev,
else
cap->sf_en = false;
+ cap->lb_mode = dev_cap->lb_mode;
+ cap->smf_pg = dev_cap->smf_pg;
+
cap->timer_en = (u8)timer_enable; /* timer enable */
cap->host_oq_id_mask_val = dev_cap->host_oq_id_mask_val;
cap->max_connect_num = dev_cap->max_conn_num;
diff --git a/drivers/net/ethernet/ramaxel/spnic/hw/sphw_hw_cfg.h b/drivers/net/ethernet/ramaxel/spnic/hw/sphw_hw_cfg.h
index 1147beeb76ad..1b48e0991563 100644
--- a/drivers/net/ethernet/ramaxel/spnic/hw/sphw_hw_cfg.h
+++ b/drivers/net/ethernet/ramaxel/spnic/hw/sphw_hw_cfg.h
@@ -201,6 +201,9 @@ struct service_cap {
u8 timer_en; /* 0:disable, 1:enable */
u8 bloomfilter_en; /* 0:disable, 1:enable*/
+ u8 lb_mode;
+ u8 smf_pg;
+
/* For test */
u32 test_mode;
u32 test_qpc_num;
diff --git a/drivers/scsi/spfc/hw/spfc_cqm_bat_cla.c b/drivers/scsi/spfc/hw/spfc_cqm_bat_cla.c
index 30fb56a9bfed..0c1d97d9e3e6 100644
--- a/drivers/scsi/spfc/hw/spfc_cqm_bat_cla.c
+++ b/drivers/scsi/spfc/hw/spfc_cqm_bat_cla.c
@@ -53,17 +53,6 @@ cqm_bat_fill_cla_common_gpa(struct cqm_handle *cqm_handle,
gpa.acs_spu_en = 0;
}
- /* In fake mode, fake_vf_en in the GPA address of the BAT
- * must be set to 1.
- */
- if (cqm_handle->func_capability.fake_func_type == CQM_FAKE_FUNC_CHILD) {
- gpa.fake_vf_en = 1;
- func_attr = &cqm_handle->parent_cqm_handle->func_attribute;
- gpa.pf_id = func_attr->func_global_idx;
- } else {
- gpa.fake_vf_en = 0;
- }
-
memcpy(&cla_gpa_h, &gpa, sizeof(u32));
bat_entry_standerd->cla_gpa_h = cla_gpa_h;
@@ -379,13 +368,8 @@ s32 cqm_bat_update(struct cqm_handle *cqm_handle)
CQM_PTR_CHECK_RET(buf_in, CQM_FAIL, CQM_ALLOC_FAIL(buf_in));
buf_in->size = sizeof(struct cqm_cmdq_bat_update);
- /* In non-fake mode, func_id is set to 0xffff, indicating the current func.
- * In fake mode, the value of func_id is specified. This is a fake func_id.
- */
- if (cqm_handle->func_capability.fake_func_type == CQM_FAKE_FUNC_CHILD)
- func_id = cqm_handle->func_attribute.func_global_idx;
- else
- func_id = 0xffff;
+ /* In non-fake mode, func_id is set to 0xffff */
+ func_id = 0xffff;
/* The LB scenario is supported.
* The normal mode is the traditional mode and is configured on SMF0.
@@ -545,19 +529,6 @@ s32 cqm_cla_fill_buf(struct cqm_handle *cqm_handle, struct cqm_buf *cla_base_buf
spu_en = 0;
}
- /* fake enable */
- if (cqm_handle->func_capability.fake_func_type ==
- CQM_FAKE_FUNC_CHILD) {
- fake_en = 1ULL << 62;
- func_attr =
- &cqm_handle->parent_cqm_handle->func_attribute;
- pf_id = func_attr->func_global_idx;
- pf_id = (pf_id & 0x1f) << 57;
- } else {
- fake_en = 0;
- pf_id = 0;
- }
-
*base = (((((cla_sub_buf->buf_list[i].pa & CQM_CHIP_GPA_MASK) |
spu_en) |
fake_en) |
@@ -1248,14 +1219,8 @@ s32 cqm_cla_update(struct cqm_handle *cqm_handle, struct cqm_buf_list *buf_node_
}
}
- /* In non-fake mode, set func_id to 0xffff.
- * Indicates the current func fake mode, set func_id to the
- * specified value, This is a fake func_id.
- */
- if (cqm_handle->func_capability.fake_func_type == CQM_FAKE_FUNC_CHILD)
- cmd.func_id = cqm_handle->func_attribute.func_global_idx;
- else
- cmd.func_id = 0xffff;
+ /* In non-fake mode, set func_id to 0xffff. */
+ cmd.func_id = 0xffff;
/* Mode 0 is hashed to 4 SMF engines (excluding PPF) by func ID. */
if (cqm_handle->func_capability.lb_mode == CQM_LB_MODE_NORMAL ||
diff --git a/drivers/scsi/spfc/hw/spfc_cqm_bitmap_table.c b/drivers/scsi/spfc/hw/spfc_cqm_bitmap_table.c
index 4e482776a14f..21100e8db8f4 100644
--- a/drivers/scsi/spfc/hw/spfc_cqm_bitmap_table.c
+++ b/drivers/scsi/spfc/hw/spfc_cqm_bitmap_table.c
@@ -405,14 +405,8 @@ s32 cqm_cla_cache_invalid(struct cqm_handle *cqm_handle, dma_addr_t gpa, u32 cac
cmd.gpa_h = CQM_ADDR_HI(gpa);
cmd.gpa_l = CQM_ADDR_LW(gpa);
- /* In non-fake mode, set func_id to 0xffff.
- * Indicate the current func fake mode.
- * The value of func_id is a fake func ID.
- */
- if (cqm_handle->func_capability.fake_func_type == CQM_FAKE_FUNC_CHILD)
- cmd.func_id = cqm_handle->func_attribute.func_global_idx;
- else
- cmd.func_id = 0xffff;
+ /* In non-fake mode, set func_id to 0xffff. */
+ cmd.func_id = 0xffff;
/* Mode 0 is hashed to 4 SMF engines (excluding PPF) by func ID. */
if (cqm_handle->func_capability.lb_mode == CQM_LB_MODE_NORMAL ||
diff --git a/drivers/scsi/spfc/hw/spfc_cqm_main.c b/drivers/scsi/spfc/hw/spfc_cqm_main.c
index a4c8e60971b1..52cc2c7838e9 100644
--- a/drivers/scsi/spfc/hw/spfc_cqm_main.c
+++ b/drivers/scsi/spfc/hw/spfc_cqm_main.c
@@ -11,21 +11,8 @@
#include "sphw_crm.h"
#include "sphw_hw.h"
#include "sphw_hw_cfg.h"
-
#include "spfc_cqm_main.h"
-static unsigned char cqm_lb_mode = CQM_LB_MODE_NORMAL;
-module_param(cqm_lb_mode, byte, 0644);
-MODULE_PARM_DESC(cqm_lb_mode, "for cqm lb mode (default=0xff)");
-
-static unsigned char cqm_fake_mode = CQM_FAKE_MODE_DISABLE;
-module_param(cqm_fake_mode, byte, 0644);
-MODULE_PARM_DESC(cqm_fake_mode, "for cqm fake mode (default=0 disable)");
-
-static unsigned char cqm_platform_mode = CQM_FPGA_MODE;
-module_param(cqm_platform_mode, byte, 0644);
-MODULE_PARM_DESC(cqm_platform_mode, "for cqm platform mode (default=0 FPGA)");
-
s32 cqm3_init(void *ex_handle)
{
struct sphw_hwdev *handle = (struct sphw_hwdev *)ex_handle;
@@ -63,19 +50,6 @@ s32 cqm3_init(void *ex_handle)
goto err1;
}
- /* In FAKE mode, only the bitmap of the timer of the function is
- * enabled, and resources are not initialized. Otherwise, the
- * configuration of the fake function is overwritten.
- */
- if (cqm_handle->func_capability.fake_func_type == CQM_FAKE_FUNC_CHILD_CONFLICT) {
- if (sphw_func_tmr_bitmap_set(ex_handle, true) != CQM_SUCCESS)
- cqm_err(handle->dev_hdl, "Timer start: enable timer bitmap failed\n");
-
- handle->cqm_hdl = NULL;
- kfree(cqm_handle);
- return CQM_SUCCESS;
- }
-
/* Initialize memory entries such as BAT, CLA, and bitmap. */
if (cqm_mem_init(ex_handle) != CQM_SUCCESS) {
cqm_err(handle->dev_hdl, CQM_FUNCTION_FAIL(cqm_mem_init));
@@ -287,64 +261,6 @@ void cqm_service_capability_init(struct cqm_handle *cqm_handle,
cqm_service_capability_init_fc(cqm_handle, (void *)service_capability);
}
-s32 cqm_get_fake_func_type(struct cqm_handle *cqm_handle)
-{
- struct cqm_func_capability *func_cap = &cqm_handle->func_capability;
- u32 parent_func, child_func_start, child_func_number, i;
- u32 idx = cqm_handle->func_attribute.func_global_idx;
-
- /* Currently, only one set of fake configurations is implemented.
- * fake_cfg_number = 1
- */
- for (i = 0; i < func_cap->fake_cfg_number; i++) {
- parent_func = func_cap->fake_cfg[i].parent_func;
- child_func_start = func_cap->fake_cfg[i].child_func_start;
- child_func_number = func_cap->fake_cfg[i].child_func_number;
-
- if (idx == parent_func) {
- return CQM_FAKE_FUNC_PARENT;
- } else if ((idx >= child_func_start) &&
- (idx < (child_func_start + child_func_number))) {
- return CQM_FAKE_FUNC_CHILD_CONFLICT;
- }
- }
-
- return CQM_FAKE_FUNC_NORMAL;
-}
-
-s32 cqm_get_child_func_start(struct cqm_handle *cqm_handle)
-{
- struct cqm_func_capability *func_cap = &cqm_handle->func_capability;
- struct sphw_func_attr *func_attr = &cqm_handle->func_attribute;
- u32 i;
-
- /* Currently, only one set of fake configurations is implemented.
- * fake_cfg_number = 1
- */
- for (i = 0; i < func_cap->fake_cfg_number; i++) {
- if (func_attr->func_global_idx ==
- func_cap->fake_cfg[i].parent_func)
- return (s32)(func_cap->fake_cfg[i].child_func_start);
- }
-
- return CQM_FAIL;
-}
-
-s32 cqm_get_child_func_number(struct cqm_handle *cqm_handle)
-{
- struct cqm_func_capability *func_cap = &cqm_handle->func_capability;
- struct sphw_func_attr *func_attr = &cqm_handle->func_attribute;
- u32 i;
-
- for (i = 0; i < func_cap->fake_cfg_number; i++) {
- if (func_attr->func_global_idx ==
- func_cap->fake_cfg[i].parent_func)
- return (s32)(func_cap->fake_cfg[i].child_func_number);
- }
-
- return CQM_FAIL;
-}
-
/* Set func_type in fake_cqm_handle to ppf, pf, or vf. */
void cqm_set_func_type(struct cqm_handle *cqm_handle)
{
@@ -358,41 +274,20 @@ void cqm_set_func_type(struct cqm_handle *cqm_handle)
cqm_handle->func_attribute.func_type = CQM_VF;
}
-void cqm_lb_fake_mode_init(struct cqm_handle *cqm_handle)
+void cqm_lb_fake_mode_init(struct cqm_handle *cqm_handle, struct service_cap *svc_cap)
{
struct cqm_func_capability *func_cap = &cqm_handle->func_capability;
- struct cqm_fake_cfg *cfg = func_cap->fake_cfg;
- func_cap->lb_mode = cqm_lb_mode;
- func_cap->fake_mode = cqm_fake_mode;
+ func_cap->lb_mode = svc_cap->lb_mode;
/* Initializing the LB Mode */
- if (func_cap->lb_mode == CQM_LB_MODE_NORMAL) {
+ if (func_cap->lb_mode == CQM_LB_MODE_NORMAL)
func_cap->smf_pg = 0;
- } else {
- /* The LB mode is tailored on the FPGA.
- * Only SMF0 and SMF2 are instantiated.
- */
- if (cqm_platform_mode == CQM_FPGA_MODE)
- func_cap->smf_pg = 0x5;
- else
- func_cap->smf_pg = 0xF;
- }
+ else
+ func_cap->smf_pg = svc_cap->smf_pg;
- /* Initializing the FAKE Mode */
- if (func_cap->fake_mode == CQM_FAKE_MODE_DISABLE) {
- func_cap->fake_cfg_number = 0;
- func_cap->fake_func_type = CQM_FAKE_FUNC_NORMAL;
- } else {
- func_cap->fake_cfg_number = 1;
-
- /* When configuring fake mode, ensure that the parent function
- * cannot be contained in the child function; otherwise, the
- * system will be initialized repeatedly.
- */
- cfg[0].child_func_start = CQM_FAKE_CFUNC_START;
- func_cap->fake_func_type = cqm_get_fake_func_type(cqm_handle);
- }
+ func_cap->fake_cfg_number = 0;
+ func_cap->fake_func_type = CQM_FAKE_FUNC_NORMAL;
}
s32 cqm_capability_init(void *ex_handle)
@@ -465,10 +360,9 @@ s32 cqm_capability_init(void *ex_handle)
func_cap->gpa_check_enable = true;
- cqm_lb_fake_mode_init(cqm_handle);
+ cqm_lb_fake_mode_init(cqm_handle, service_capability);
cqm_info(handle->dev_hdl, "Cap init: lb_mode=%u\n", func_cap->lb_mode);
cqm_info(handle->dev_hdl, "Cap init: smf_pg=%u\n", func_cap->smf_pg);
- cqm_info(handle->dev_hdl, "Cap init: fake_mode=%u\n", func_cap->fake_mode);
cqm_info(handle->dev_hdl, "Cap init: fake_func_type=%u\n", func_cap->fake_func_type);
cqm_info(handle->dev_hdl, "Cap init: fake_cfg_number=%u\n", func_cap->fake_cfg_number);
@@ -517,153 +411,6 @@ s32 cqm_capability_init(void *ex_handle)
return err;
}
-void cqm_fake_uninit(struct cqm_handle *cqm_handle)
-{
- u32 i;
-
- if (cqm_handle->func_capability.fake_func_type !=
- CQM_FAKE_FUNC_PARENT)
- return;
-
- for (i = 0; i < CQM_FAKE_FUNC_MAX; i++) {
- kfree(cqm_handle->fake_cqm_handle[i]);
- cqm_handle->fake_cqm_handle[i] = NULL;
- }
-}
-
-s32 cqm_fake_init(struct cqm_handle *cqm_handle)
-{
- struct sphw_hwdev *handle = cqm_handle->ex_handle;
- struct cqm_func_capability *func_cap = NULL;
- struct cqm_handle *fake_cqm_handle = NULL;
- struct sphw_func_attr *func_attr = NULL;
- s32 child_func_start, child_func_number;
- u32 i;
-
- func_cap = &cqm_handle->func_capability;
- if (func_cap->fake_func_type != CQM_FAKE_FUNC_PARENT)
- return CQM_SUCCESS;
-
- child_func_start = cqm_get_child_func_start(cqm_handle);
- if (child_func_start == CQM_FAIL) {
- cqm_err(handle->dev_hdl, CQM_WRONG_VALUE(child_func_start));
- return CQM_FAIL;
- }
-
- child_func_number = cqm_get_child_func_number(cqm_handle);
- if (child_func_number == CQM_FAIL) {
- cqm_err(handle->dev_hdl, CQM_WRONG_VALUE(child_func_number));
- return CQM_FAIL;
- }
-
- for (i = 0; i < (u32)child_func_number; i++) {
- fake_cqm_handle = kmalloc(sizeof(*fake_cqm_handle), GFP_KERNEL | __GFP_ZERO);
- if (!fake_cqm_handle) {
- cqm_err(handle->dev_hdl,
- CQM_ALLOC_FAIL(fake_cqm_handle));
- goto err;
- }
-
- /* Copy the attributes of the parent CQM handle to the child CQM
- * handle and modify the values of function.
- */
- memcpy(fake_cqm_handle, cqm_handle, sizeof(struct cqm_handle));
- func_attr = &fake_cqm_handle->func_attribute;
- func_cap = &fake_cqm_handle->func_capability;
- func_attr->func_global_idx = (u16)(child_func_start + i);
- cqm_set_func_type(fake_cqm_handle);
- func_cap->fake_func_type = CQM_FAKE_FUNC_CHILD;
- cqm_info(handle->dev_hdl, "Fake func init: function[%u] type %d(0:PF,1:VF,2:PPF)\n",
- func_attr->func_global_idx, func_attr->func_type);
-
- fake_cqm_handle->parent_cqm_handle = cqm_handle;
- cqm_handle->fake_cqm_handle[i] = fake_cqm_handle;
- }
-
- return CQM_SUCCESS;
-
-err:
- cqm_fake_uninit(cqm_handle);
- return CQM_FAIL;
-}
-
-void cqm_fake_mem_uninit(struct cqm_handle *cqm_handle)
-{
- struct sphw_hwdev *handle = cqm_handle->ex_handle;
- struct cqm_handle *fake_cqm_handle = NULL;
- s32 child_func_number;
- u32 i;
-
- if (cqm_handle->func_capability.fake_func_type != CQM_FAKE_FUNC_PARENT)
- return;
-
- child_func_number = cqm_get_child_func_number(cqm_handle);
- if (child_func_number == CQM_FAIL) {
- cqm_err(handle->dev_hdl, CQM_WRONG_VALUE(child_func_number));
- return;
- }
-
- for (i = 0; i < (u32)child_func_number; i++) {
- fake_cqm_handle = cqm_handle->fake_cqm_handle[i];
- cqm_object_table_uninit(fake_cqm_handle);
- cqm_bitmap_uninit(fake_cqm_handle);
- cqm_cla_uninit(fake_cqm_handle, CQM_BAT_ENTRY_MAX);
- cqm_bat_uninit(fake_cqm_handle);
- }
-}
-
-s32 cqm_fake_mem_init(struct cqm_handle *cqm_handle)
-{
- struct sphw_hwdev *handle = cqm_handle->ex_handle;
- struct cqm_handle *fake_cqm_handle = NULL;
- s32 child_func_number;
- u32 i;
-
- if (cqm_handle->func_capability.fake_func_type !=
- CQM_FAKE_FUNC_PARENT)
- return CQM_SUCCESS;
-
- child_func_number = cqm_get_child_func_number(cqm_handle);
- if (child_func_number == CQM_FAIL) {
- cqm_err(handle->dev_hdl, CQM_WRONG_VALUE(child_func_number));
- return CQM_FAIL;
- }
-
- for (i = 0; i < (u32)child_func_number; i++) {
- fake_cqm_handle = cqm_handle->fake_cqm_handle[i];
-
- if (cqm_bat_init(fake_cqm_handle) != CQM_SUCCESS) {
- cqm_err(handle->dev_hdl,
- CQM_FUNCTION_FAIL(cqm_bat_init));
- goto err;
- }
-
- if (cqm_cla_init(fake_cqm_handle) != CQM_SUCCESS) {
- cqm_err(handle->dev_hdl,
- CQM_FUNCTION_FAIL(cqm_cla_init));
- goto err;
- }
-
- if (cqm_bitmap_init(fake_cqm_handle) != CQM_SUCCESS) {
- cqm_err(handle->dev_hdl,
- CQM_FUNCTION_FAIL(cqm_bitmap_init));
- goto err;
- }
-
- if (cqm_object_table_init(fake_cqm_handle) != CQM_SUCCESS) {
- cqm_err(handle->dev_hdl,
- CQM_FUNCTION_FAIL(cqm_object_table_init));
- goto err;
- }
- }
-
- return CQM_SUCCESS;
-
-err:
- cqm_fake_mem_uninit(cqm_handle);
- return CQM_FAIL;
-}
-
s32 cqm_mem_init(void *ex_handle)
{
struct sphw_hwdev *handle = (struct sphw_hwdev *)ex_handle;
@@ -671,49 +418,35 @@ s32 cqm_mem_init(void *ex_handle)
cqm_handle = (struct cqm_handle *)(handle->cqm_hdl);
- if (cqm_fake_init(cqm_handle) != CQM_SUCCESS) {
- cqm_err(handle->dev_hdl, CQM_FUNCTION_FAIL(cqm_fake_init));
- return CQM_FAIL;
- }
-
- if (cqm_fake_mem_init(cqm_handle) != CQM_SUCCESS) {
- cqm_err(handle->dev_hdl, CQM_FUNCTION_FAIL(cqm_fake_mem_init));
- goto err1;
- }
-
if (cqm_bat_init(cqm_handle) != CQM_SUCCESS) {
cqm_err(handle->dev_hdl, CQM_FUNCTION_FAIL(cqm_bat_init));
- goto err2;
+ return CQM_FAIL;
}
if (cqm_cla_init(cqm_handle) != CQM_SUCCESS) {
cqm_err(handle->dev_hdl, CQM_FUNCTION_FAIL(cqm_cla_init));
- goto err3;
+ goto err1;
}
if (cqm_bitmap_init(cqm_handle) != CQM_SUCCESS) {
cqm_err(handle->dev_hdl, CQM_FUNCTION_FAIL(cqm_bitmap_init));
- goto err4;
+ goto err2;
}
if (cqm_object_table_init(cqm_handle) != CQM_SUCCESS) {
cqm_err(handle->dev_hdl,
CQM_FUNCTION_FAIL(cqm_object_table_init));
- goto err5;
+ goto err3;
}
return CQM_SUCCESS;
-err5:
- cqm_bitmap_uninit(cqm_handle);
-err4:
- cqm_cla_uninit(cqm_handle, CQM_BAT_ENTRY_MAX);
err3:
- cqm_bat_uninit(cqm_handle);
+ cqm_bitmap_uninit(cqm_handle);
err2:
- cqm_fake_mem_uninit(cqm_handle);
+ cqm_cla_uninit(cqm_handle, CQM_BAT_ENTRY_MAX);
err1:
- cqm_fake_uninit(cqm_handle);
+ cqm_bat_uninit(cqm_handle);
return CQM_FAIL;
}
@@ -728,8 +461,6 @@ void cqm_mem_uninit(void *ex_handle)
cqm_bitmap_uninit(cqm_handle);
cqm_cla_uninit(cqm_handle, CQM_BAT_ENTRY_MAX);
cqm_bat_uninit(cqm_handle);
- cqm_fake_mem_uninit(cqm_handle);
- cqm_fake_uninit(cqm_handle);
}
s32 cqm_event_init(void *ex_handle)
diff --git a/drivers/scsi/spfc/hw/spfc_cqm_main.h b/drivers/scsi/spfc/hw/spfc_cqm_main.h
index 1b8cf8bdb3b7..cf10d7f5c339 100644
--- a/drivers/scsi/spfc/hw/spfc_cqm_main.h
+++ b/drivers/scsi/spfc/hw/spfc_cqm_main.h
@@ -328,9 +328,6 @@ void cqm_mem_uninit(void *ex_handle);
s32 cqm_event_init(void *ex_handle);
void cqm_event_uninit(void *ex_handle);
u8 cqm_aeq_callback(void *ex_handle, u8 event, u8 *data);
-s32 cqm_get_fake_func_type(struct cqm_handle *cqm_handle);
-s32 cqm_get_child_func_start(struct cqm_handle *cqm_handle);
-s32 cqm_get_child_func_number(struct cqm_handle *cqm_handle);
s32 cqm3_init(void *ex_handle);
void cqm3_uninit(void *ex_handle);
diff --git a/drivers/scsi/spfc/hw/spfc_cqm_object.c b/drivers/scsi/spfc/hw/spfc_cqm_object.c
index b895d37aebae..165794e9c7e5 100644
--- a/drivers/scsi/spfc/hw/spfc_cqm_object.c
+++ b/drivers/scsi/spfc/hw/spfc_cqm_object.c
@@ -155,8 +155,6 @@ struct cqm_qpc_mpt *cqm3_object_qpc_mpt_create(void *ex_handle, u32 service_type
struct cqm_qpc_mpt_info *qpc_mpt_info = NULL;
struct cqm_handle *cqm_handle = NULL;
s32 ret = CQM_FAIL;
- u32 relative_index;
- u32 fake_func_id;
CQM_PTR_CHECK_RET(ex_handle, NULL, CQM_PTR_NULL(ex_handle));
@@ -180,25 +178,6 @@ struct cqm_qpc_mpt *cqm3_object_qpc_mpt_create(void *ex_handle, u32 service_type
return NULL;
}
- /* fake vf adaption, switch to corresponding VF. */
- if (cqm_handle->func_capability.fake_func_type ==
- CQM_FAKE_FUNC_PARENT) {
- fake_func_id = index / cqm_handle->func_capability.qpc_number;
- relative_index = index % cqm_handle->func_capability.qpc_number;
-
- cqm_info(handle->dev_hdl, "qpc create: fake_func_id=%u, relative_index=%u\n",
- fake_func_id, relative_index);
-
- if ((s32)fake_func_id >=
- cqm_get_child_func_number(cqm_handle)) {
- cqm_err(handle->dev_hdl, CQM_WRONG_VALUE(fake_func_id));
- return NULL;
- }
-
- index = relative_index;
- cqm_handle = cqm_handle->fake_cqm_handle[fake_func_id];
- }
-
qpc_mpt_info = kmalloc(sizeof(*qpc_mpt_info), GFP_ATOMIC | __GFP_ZERO);
CQM_PTR_CHECK_RET(qpc_mpt_info, NULL, CQM_ALLOC_FAIL(qpc_mpt_info));
--
2.32.0
1
0
[PATCH openEuler-5.10 01/30] net: hns3: refactor hns3 makefile to support hns3_common module
by Zheng Zengkai 12 Jan '22
by Zheng Zengkai 12 Jan '22
12 Jan '22
From: Jie Wang <wangjie125(a)huawei.com>
mainline inclusion
from mainline-br26_refactor2
commit 5f20be4e90e6
category: feature
bugzilla: https://gitee.com/openeuler/kernel/issues/I4Q02P
CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?…
----------------------------------------------------------------------
Currently we plan to refactor PF and VF cmdq module. A new file folder
hns3_common will be created to store new common APIs used by PF and VF
cmdq module. Thus the PF and VF compilation process will both depends on
the hns3_common. This may cause parallel building problems if we add a new
makefile building unit.
So this patch combined the PF and VF makefile scripts to the top level
makefile to support the new hns3_common which will be created in the next
patch.
Signed-off-by: Jie Wang <wangjie125(a)huawei.com>
Signed-off-by: Guangbin Huang <huangguangbin2(a)huawei.com>
Signed-off-by: David S. Miller <davem(a)davemloft.net>
Reviewed-by: Jian Shen <shenjian15(a)huawei.com>
Reviewed-by: Yue Haibing <yuehaibing(a)huawei.com>
Signed-off-by: Zheng Zengkai <zhengzengkai(a)huawei.com>
---
drivers/net/ethernet/hisilicon/hns3/Makefile | 14 +++++++++++---
.../net/ethernet/hisilicon/hns3/hns3pf/Makefile | 12 ------------
.../net/ethernet/hisilicon/hns3/hns3vf/Makefile | 10 ----------
3 files changed, 11 insertions(+), 25 deletions(-)
delete mode 100644 drivers/net/ethernet/hisilicon/hns3/hns3pf/Makefile
delete mode 100644 drivers/net/ethernet/hisilicon/hns3/hns3vf/Makefile
diff --git a/drivers/net/ethernet/hisilicon/hns3/Makefile b/drivers/net/ethernet/hisilicon/hns3/Makefile
index 7aa2fac76c5e..32e24e0945f5 100644
--- a/drivers/net/ethernet/hisilicon/hns3/Makefile
+++ b/drivers/net/ethernet/hisilicon/hns3/Makefile
@@ -4,9 +4,8 @@
#
ccflags-y += -I$(srctree)/$(src)
-
-obj-$(CONFIG_HNS3) += hns3pf/
-obj-$(CONFIG_HNS3) += hns3vf/
+ccflags-y += -I$(srctree)/drivers/net/ethernet/hisilicon/hns3/hns3pf
+ccflags-y += -I$(srctree)/drivers/net/ethernet/hisilicon/hns3/hns3vf
obj-$(CONFIG_HNS3) += hnae3.o
@@ -14,3 +13,12 @@ obj-$(CONFIG_HNS3_ENET) += hns3.o
hns3-objs = hns3_enet.o hns3_ethtool.o hns3_debugfs.o
hns3-$(CONFIG_HNS3_DCB) += hns3_dcbnl.o
+
+obj-$(CONFIG_HNS3_HCLGEVF) += hclgevf.o
+hclgevf-objs = hns3vf/hclgevf_main.o hns3vf/hclgevf_cmd.o hns3vf/hclgevf_mbx.o hns3vf/hclgevf_devlink.o
+
+obj-$(CONFIG_HNS3_HCLGE) += hclge.o
+hclge-objs = hns3pf/hclge_main.o hns3pf/hclge_cmd.o hns3pf/hclge_mdio.o hns3pf/hclge_tm.o \
+ hns3pf/hclge_mbx.o hns3pf/hclge_err.o hns3pf/hclge_debugfs.o hns3pf/hclge_ptp.o hns3pf/hclge_devlink.o
+
+hclge-$(CONFIG_HNS3_DCB) += hns3pf/hclge_dcb.o
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/Makefile b/drivers/net/ethernet/hisilicon/hns3/hns3pf/Makefile
deleted file mode 100644
index d1bf5c4c0abb..000000000000
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/Makefile
+++ /dev/null
@@ -1,12 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0+
-#
-# Makefile for the HISILICON network device drivers.
-#
-
-ccflags-y := -I $(srctree)/drivers/net/ethernet/hisilicon/hns3
-ccflags-y += -I $(srctree)/$(src)
-
-obj-$(CONFIG_HNS3_HCLGE) += hclge.o
-hclge-objs = hclge_main.o hclge_cmd.o hclge_mdio.o hclge_tm.o hclge_mbx.o hclge_err.o hclge_debugfs.o hclge_ptp.o hclge_devlink.o
-
-hclge-$(CONFIG_HNS3_DCB) += hclge_dcb.o
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/Makefile b/drivers/net/ethernet/hisilicon/hns3/hns3vf/Makefile
deleted file mode 100644
index 51ff7d86ee90..000000000000
--- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/Makefile
+++ /dev/null
@@ -1,10 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0+
-#
-# Makefile for the HISILICON network device drivers.
-#
-
-ccflags-y := -I $(srctree)/drivers/net/ethernet/hisilicon/hns3
-ccflags-y += -I $(srctree)/$(src)
-
-obj-$(CONFIG_HNS3_HCLGEVF) += hclgevf.o
-hclgevf-objs = hclgevf_main.o hclgevf_cmd.o hclgevf_mbx.o hclgevf_devlink.o
--
2.20.1
1
29
This patch set introduce many conflicts while backporting mainline bcache
patches, revert it temporarily.
Zheng Zengkai (8):
Revert "bcache: always record start time of a sample"
Revert "bcache: do not collect data insert info created by
write_moving"
Revert "bcache: Rewrite patch to delay to invalidate cache data"
Revert "bcache: Add a sample of userspace prefetch client"
Revert "bcache: Delay to invalidate cache data in writearound write"
Revert "bcache: inflight prefetch requests block overlapped normal
requests"
Revert "bcache: provide a switch to bypass all IO requests"
Revert "bcache: add a framework to perform prefetch"
Documentation/admin-guide/bcache.rst | 4 -
drivers/md/bcache/Makefile | 2 +-
drivers/md/bcache/acache.c | 586 ---------------------------
drivers/md/bcache/acache.h | 79 ----
drivers/md/bcache/bcache.h | 3 -
drivers/md/bcache/btree.c | 4 +-
drivers/md/bcache/request.c | 161 +++-----
drivers/md/bcache/request.h | 45 --
drivers/md/bcache/stats.c | 13 -
drivers/md/bcache/stats.h | 3 -
drivers/md/bcache/super.c | 6 -
drivers/md/bcache/sysfs.c | 12 -
include/trace/events/bcache.h | 22 -
samples/acache_client/Makefile | 13 -
samples/acache_client/connect.c | 144 -------
samples/acache_client/connect.h | 74 ----
samples/acache_client/main.c | 133 ------
17 files changed, 59 insertions(+), 1245 deletions(-)
delete mode 100644 drivers/md/bcache/acache.c
delete mode 100644 drivers/md/bcache/acache.h
delete mode 100644 samples/acache_client/Makefile
delete mode 100644 samples/acache_client/connect.c
delete mode 100644 samples/acache_client/connect.h
delete mode 100644 samples/acache_client/main.c
--
2.20.1
2
9
[PATCH openEuler-5.10 01/17] tcp: Add some stub info for KABI consistency
by Zheng Zengkai 11 Jan '22
by Zheng Zengkai 11 Jan '22
11 Jan '22
From: Baisong Zhong <zhongbaisong(a)huawei.com>
hulk inclusion
category: feature
bugzilla: https://gitee.com/openeuler/kernel/issues/I4PY1Q
CVE: NA
--------------------------------
We add stub info in some structures to maintain the consistency of KABI
Signed-off-by: Baisong Zhong <zhongbaisong(a)huawei.com>
Reviewed-by: Wei Yongjun <weiyongjun1(a)huawei.com>
Reviewed-by: Yue Haibing <yuehaibing(a)huawei.com>
Signed-off-by: Zheng Zengkai <zhengzengkai(a)huawei.com>
---
include/linux/skbuff.h | 2 ++
include/net/ipv6.h | 2 +-
include/net/sock.h | 3 +++
3 files changed, 6 insertions(+), 1 deletion(-)
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index 9e3a454d2377..d485f17ff33a 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -36,6 +36,7 @@
#include <linux/splice.h>
#include <linux/in6.h>
#include <linux/if_packet.h>
+#include <linux/llist.h>
#include <net/flow.h>
#include <net/page_pool.h>
#include <linux/kabi.h>
@@ -732,6 +733,7 @@ struct sk_buff {
};
struct rb_node rbnode; /* used in netem, ip4 defrag, and tcp stack */
struct list_head list;
+ struct llist_node ll_node;
};
union {
diff --git a/include/net/ipv6.h b/include/net/ipv6.h
index bd1f396cc9c7..c0273ae50296 100644
--- a/include/net/ipv6.h
+++ b/include/net/ipv6.h
@@ -344,9 +344,9 @@ struct ipcm6_cookie {
struct sockcm_cookie sockc;
__s16 hlimit;
__s16 tclass;
+ __u16 gso_size;
__s8 dontfrag;
struct ipv6_txoptions *opt;
- __u16 gso_size;
};
static inline void ipcm6_init(struct ipcm6_cookie *ipc6)
diff --git a/include/net/sock.h b/include/net/sock.h
index 712bb7b09f96..b3d451878640 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -63,6 +63,7 @@
#include <linux/atomic.h>
#include <linux/refcount.h>
+#include <linux/llist.h>
#include <net/dst.h>
#include <net/checksum.h>
#include <net/tcp_states.h>
@@ -405,6 +406,8 @@ struct sock {
struct sk_buff *head;
struct sk_buff *tail;
} sk_backlog;
+ struct llist_head defer_list;
+
#define sk_rmem_alloc sk_backlog.rmem_alloc
int sk_forward_alloc;
--
2.20.1
2
17
hulk inclusion
category: feature
bugzilla: https://gitee.com/openeuler/kernel/issues/I4O31I?from=project-issue
CVE: NA
------------------------------
Register pmem in arm64:
Use memmap(memmap=nn[KMG]!ss[KMG]) reserve memory and
e820(driver/nvdimm/e820.c) function to register persistent
memory in arm64. when the kernel restart or update, the data
in PMEM will not be lost and can be loaded faster. this is a
general features.
driver/nvdimm/e820.c:
The function of this file is scan "iomem_resource" and take
advantage of nvdimm resource discovery mechanism by registering
a resource named "Persistent Memory (legacy)", this function
doesn't depend on architecture.
We will push the feature to linux kernel community and discuss to
modify the file name. because people have a mistaken notion that
the e820.c is depend on x86.
If you want use this features, you need do as follows:
1.Reserve memory: add memmap to reserve memory in grub.cfg
memmap=nn[KMG]!ss[KMG] exp:memmap=100K!0x1a0000000.
2.Insmod nd_e820.ko: modprobe nd_e820.
3.Check pmem device in /dev exp: /dev/pmem0
Signed-off-by: Zhuling <zhuling8(a)huawei.com>
---
arch/arm64/Kconfig | 22 ++++++++++++++++
arch/arm64/kernel/Makefile | 1 +
arch/arm64/kernel/pmem.c | 36 ++++++++++++++++++++++++++
arch/arm64/kernel/setup.c | 11 ++++++++
arch/arm64/mm/init.c | 63 ++++++++++++++++++++++++++++++++++++++++++++++
drivers/nvdimm/Kconfig | 6 +++++
drivers/nvdimm/Makefile | 1 +
7 files changed, 140 insertions(+)
create mode 100644 arch/arm64/kernel/pmem.c
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 405e5ce..2231eac 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -1322,6 +1322,28 @@ config RODATA_FULL_DEFAULT_ENABLED
This requires the linear region to be mapped down to pages,
which may adversely affect performance in some cases.
+config ARM64_PMEM_RESERVE
+ bool "Reserve memory for persistent storage"
+ default n
+ help
+ Use memmap=nn[KMG]!ss[KMG](memmap=100K!0x1a0000000) reserve
+ memory for persistent storage.
+
+ Say y here to enable this feature.
+
+config ARM64_PMEM_LEGACY_DEVICE
+ bool "Create persistent storage"
+ depends on BLK_DEV
+ depends on LIBNVDIMM
+ select ARM64_PMEM_RESERVE
+ help
+ Use reserved memory for persistent storage when the kernel
+ restart or update. the data in PMEM will not be lost and
+ can be loaded faster.
+
+ Say y if unsure.
+
+
config ARM64_SW_TTBR0_PAN
bool "Emulate Privileged Access Never using TTBR0_EL1 switching"
help
diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
index 169d90f..f615325 100644
--- a/arch/arm64/kernel/Makefile
+++ b/arch/arm64/kernel/Makefile
@@ -68,6 +68,7 @@ obj-$(CONFIG_ARM64_PTR_AUTH) += pointer_auth.o
obj-$(CONFIG_SHADOW_CALL_STACK) += scs.o
obj-$(CONFIG_ARM64_MTE) += mte.o
obj-$(CONFIG_MPAM) += mpam/
+obj-$(CONFIG_ARM64_PMEM_LEGACY_DEVICE) += pmem.o
obj-y += vdso/ probes/
obj-$(CONFIG_COMPAT_VDSO) += vdso32/
diff --git a/arch/arm64/kernel/pmem.c b/arch/arm64/kernel/pmem.c
new file mode 100644
index 0000000..d1efdc8
--- /dev/null
+++ b/arch/arm64/kernel/pmem.c
@@ -0,0 +1,36 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright(c) 2021 Huawei Technologies Co., Ltd
+ *
+ * Derived from x86 and arm64 implement PMEM.
+ */
+#include <linux/platform_device.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/module.h>
+
+static int found(struct resource *res, void *data)
+{
+ return 1;
+}
+
+static int __init register_e820_pmem(void)
+{
+ struct platform_device *pdev;
+ int rc;
+
+ rc = walk_iomem_res_desc(IORES_DESC_PERSISTENT_MEMORY_LEGACY,
+ IORESOURCE_MEM, 0, -1, NULL, found);
+ if (rc <= 0)
+ return 0;
+
+ /*
+ * See drivers/nvdimm/e820.c for the implementation, this is
+ * simply here to trigger the module to load on demand.
+ */
+ pdev = platform_device_alloc("e820_pmem", -1);
+
+ return platform_device_add(pdev);
+}
+device_initcall(register_e820_pmem);
+
diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c
index 92d75e3..1a8a4d2 100644
--- a/arch/arm64/kernel/setup.c
+++ b/arch/arm64/kernel/setup.c
@@ -70,6 +70,11 @@ static int __init arm64_enable_cpu0_hotplug(char *str)
__setup("arm64_cpu0_hotplug", arm64_enable_cpu0_hotplug);
#endif
+#ifdef CONFIG_ARM64_PMEM_RESERVE
+extern struct resource pmem_res;
+#endif
+
+
phys_addr_t __fdt_pointer __initdata;
/*
@@ -305,6 +310,12 @@ static void __init request_standard_resources(void)
}
}
+#ifdef CONFIG_ARM64_PMEM_RESERVE
+ if (pmem_res.end && pmem_res.start)
+ request_resource(&iomem_resource, &pmem_res);
+#endif
+
+
static int __init reserve_memblock_reserved_regions(void)
{
u64 i, j;
diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c
index 6ebfabd..3b6907f 100644
--- a/arch/arm64/mm/init.c
+++ b/arch/arm64/mm/init.c
@@ -56,6 +56,8 @@
s64 memstart_addr __ro_after_init = -1;
EXPORT_SYMBOL(memstart_addr);
+phys_addr_t start_at, mem_size;
+
#ifdef CONFIG_PIN_MEMORY
struct resource pin_memory_resource = {
.name = "Pin memory",
@@ -111,6 +113,18 @@ static void __init reserve_pin_memory_res(void)
*/
phys_addr_t arm64_dma_phys_limit __ro_after_init;
+static unsigned long long pmem_size, pmem_start;
+
+#ifdef CONFIG_ARM64_PMEM_RESERVE
+struct resource pmem_res = {
+ .name = "Persistent Memory (legacy)",
+ .start = 0,
+ .end = 0,
+ .flags = IORESOURCE_MEM,
+ .desc = IORES_DESC_PERSISTENT_MEMORY_LEGACY
+};
+#endif
+
#ifndef CONFIG_KEXEC_CORE
static void __init reserve_crashkernel(void)
{
@@ -403,6 +417,26 @@ static int __init reserve_park_mem(void)
return -EINVAL;
}
#endif
+static bool __init is_mem_valid(unsigned long long mem_size, unsigned long long mem_start)
+{
+ if (!memblock_is_region_memory(mem_start, mem_size)) {
+ pr_warn("cannot reserve mem: region is not memory!\n");
+ return false;
+ }
+
+ if (memblock_is_region_reserved(mem_start, mem_size)) {
+ pr_warn("cannot reserve mem: region overlaps reserved memory!\n");
+ return false;
+ }
+
+ if (!IS_ALIGNED(mem_start, SZ_2M)) {
+ pr_warn("cannot reserve mem: base address is not 2MB aligned!\n");
+ return false;
+ }
+
+ return true;
+}
+
static int need_remove_real_memblock __initdata;
@@ -442,7 +476,17 @@ static int __init parse_memmap_one(char *p)
start_at = memparse(p + 1, &p);
memblock_reserve(start_at, mem_size);
memblock_mark_memmap(start_at, mem_size);
+<<<<<<< HEAD
+ } else if (*p == '!') {
+ start_at = memparse(p+1, &p);
+
+ pmem_start = start_at;
+ pmem_size = mem_size;
+
+ }else
+=======
} else
+>>>>>>> 374db2be8805428b4f54b5ef793b0d3f5069c5f9
pr_info("Unrecognized memmap option, please check the parameter.\n");
return *p == '\0' ? 0 : -EINVAL;
@@ -464,6 +508,20 @@ static int __init parse_memmap_opt(char *str)
}
early_param("memmap", parse_memmap_opt);
+#ifdef CONFIG_ARM64_PMEM_RESERVE
+static void __init reserve_pmem(void)
+{
+ if (!is_mem_valid(mem_size, start_at))
+ return;
+
+ memblock_remove(pmem_start, pmem_size);
+ pr_info("pmem reserved: 0x%016llx - 0x%016llx (%lld MB)\n",
+ pmem_start, pmem_start + pmem_size, pmem_size >> 20);
+ pmem_res.start = pmem_start;
+ pmem_res.end = pmem_start + pmem_size - 1;
+}
+#endif
+
void __init arm64_memblock_init(void)
{
const s64 linear_region_size = BIT(vabits_actual - 1);
@@ -638,6 +696,11 @@ void __init bootmem_init(void)
reserve_quick_kexec();
#endif
+#ifdef CONFIG_ARM64_PMEM_RESERVE
+ reserve_pmem();
+#endif
+
+
reserve_pin_memory_res();
memblock_dump_all();
diff --git a/drivers/nvdimm/Kconfig b/drivers/nvdimm/Kconfig
index b7d1eb3..9567cca 100644
--- a/drivers/nvdimm/Kconfig
+++ b/drivers/nvdimm/Kconfig
@@ -132,3 +132,9 @@ config NVDIMM_TEST_BUILD
infrastructure.
endif
+
+config PMEM_LEGACY
+ tristate "Pmem_legacy"
+ select X86_PMEM_LEGACY if X86
+ select ARM64_PMEM_LEGACY_DEVICE if ARM64
+
diff --git a/drivers/nvdimm/Makefile b/drivers/nvdimm/Makefile
index 0407753..6f8dc92 100644
--- a/drivers/nvdimm/Makefile
+++ b/drivers/nvdimm/Makefile
@@ -3,6 +3,7 @@ obj-$(CONFIG_LIBNVDIMM) += libnvdimm.o
obj-$(CONFIG_BLK_DEV_PMEM) += nd_pmem.o
obj-$(CONFIG_ND_BTT) += nd_btt.o
obj-$(CONFIG_ND_BLK) += nd_blk.o
+obj-$(CONFIG_PMEM_LEGACY) += nd_e820.o
obj-$(CONFIG_OF_PMEM) += of_pmem.o
obj-$(CONFIG_VIRTIO_PMEM) += virtio_pmem.o nd_virtio.o
--
2.9.5
3
3
[PATCH openEuler-5.10] BMA: Fix format string compile warning in arm32 builds
by Zheng Zengkai 10 Jan '22
by Zheng Zengkai 10 Jan '22
10 Jan '22
driver inclusion
category: feature
bugzilla: https://gitee.com/openeuler/kernel/issues/I4ETXO
CVE: NA
-----------------------------------------
Fix following build warnings in arm32 builds:
drivers/net/ethernet/huawei/bma/edma_drv/bma_devintf.c: In function ‘bma_cdev_add_msg’:
drivers/net/ethernet/huawei/bma/edma_drv/bma_pci.h:92:20: warning: format ‘%ld’ expects argument of type ‘long int’, but argument 5 has type ‘size_t {aka unsigned int}’ [-Wformat=]
drivers/net/ethernet/huawei/bma/veth_drv/veth_hb.c: In function ‘veth_recv_pkt’:
drivers/net/ethernet/huawei/bma/veth_drv/veth_hb.c:74:37: warning: format ‘%llx’ expects argument of type ‘long long unsigned int’, but argument 7 has type ‘dma_addr_t {aka unsigned int}’ [-Wformat=]
Signed-off-by: Zheng Zengkai <zhengzengkai(a)huawei.com>
Reviewed-by: Kefeng Wang <wangkefeng.wang(a)huawei.com>
Signed-off-by: Zheng Zengkai <zhengzengkai(a)huawei.com>
---
.../bma/cdev_veth_drv/virtual_cdev_eth_net.c | 14 +++++++-------
.../net/ethernet/huawei/bma/edma_drv/bma_devintf.c | 2 +-
.../net/ethernet/huawei/bma/edma_drv/edma_host.c | 2 +-
drivers/net/ethernet/huawei/bma/veth_drv/veth_hb.c | 4 ++--
4 files changed, 11 insertions(+), 11 deletions(-)
diff --git a/drivers/net/ethernet/huawei/bma/cdev_veth_drv/virtual_cdev_eth_net.c b/drivers/net/ethernet/huawei/bma/cdev_veth_drv/virtual_cdev_eth_net.c
index 04ea55f4e0a2..d8c3ab655566 100644
--- a/drivers/net/ethernet/huawei/bma/cdev_veth_drv/virtual_cdev_eth_net.c
+++ b/drivers/net/ethernet/huawei/bma/cdev_veth_drv/virtual_cdev_eth_net.c
@@ -605,7 +605,7 @@ static int edma_veth_cut_tx_packet_send(struct edma_eth_dev_s *eth_dev,
do_queue_rate_limit(eth_dev->ptx_queue);
while (length > 0) {
- LOG(DLOG_DEBUG, "length: %u/%lu", length, len);
+ LOG(DLOG_DEBUG, "length: %u/%zu", length, len);
if (length > BSPPACKET_MTU_MAX) {
/* fragment. */
@@ -1689,7 +1689,7 @@ static ssize_t cdev_copy_packet_to_user(struct edma_eth_dev_s *dev,
start = dev->rx_packet[dev->rx_packet_head].packet + g_read_pos;
LOG(DLOG_DEBUG,
- "User needs %ld bytes, pos: %u, total len: %u, left: %ld.",
+ "User needs %zu bytes, pos: %u, total len: %u, left: %zd.",
count, g_read_pos, dev->rx_packet[dev->rx_packet_head].len, left);
if (left <= 0) {
/* No more data in this message, retry. */
@@ -1721,7 +1721,7 @@ static ssize_t cdev_copy_packet_to_user(struct edma_eth_dev_s *dev,
}
LOG(DLOG_DEBUG,
- "Copied bytes: %ld, pos: %d, buf len: %lu, free_packet: %d.",
+ "Copied bytes: %zd, pos: %d, buf len: %zu, free_packet: %d.",
length, g_read_pos, count, free_packet);
if (packet) {
@@ -1807,11 +1807,11 @@ ssize_t cdev_read(struct file *filp, char __user *data,
if (!data || count >= MAX_PACKET_LEN)
return -EFAULT;
- LOG(DLOG_DEBUG, "read begin, count: %ld, pos: %u.", count, g_read_pos);
+ LOG(DLOG_DEBUG, "read begin, count: %zu, pos: %u.", count, g_read_pos);
length = cdev_copy_packet_to_user(dev, data, count);
- LOG(DLOG_DEBUG, "read done, length: %ld, pos: %u.", length, g_read_pos);
+ LOG(DLOG_DEBUG, "read done, length: %zd, pos: %u.", length, g_read_pos);
return length;
}
@@ -1837,7 +1837,7 @@ ssize_t cdev_write(struct file *filp, const char __user *data,
g_peer_not_ready = 0;
}
- LOG(DLOG_DEBUG, "data length is %lu, pos: %u (%u/%u)",
+ LOG(DLOG_DEBUG, "data length is %zu, pos: %u (%u/%u)",
count, g_read_pos,
pdev->ptx_queue->pshmqhd_v->count,
pdev->ptx_queue->pshmqhd_v->total);
@@ -1859,4 +1859,4 @@ MODULE_DESCRIPTION("HUAWEI CDEV DRIVER");
MODULE_LICENSE("GPL");
module_init(edma_cdev_init);
-module_exit(edma_cdev_exit);
\ No newline at end of file
+module_exit(edma_cdev_exit);
diff --git a/drivers/net/ethernet/huawei/bma/edma_drv/bma_devintf.c b/drivers/net/ethernet/huawei/bma/edma_drv/bma_devintf.c
index 7817f58f8635..acf6bbfc50ff 100644
--- a/drivers/net/ethernet/huawei/bma/edma_drv/bma_devintf.c
+++ b/drivers/net/ethernet/huawei/bma/edma_drv/bma_devintf.c
@@ -497,7 +497,7 @@ int bma_cdev_add_msg(void *handle, const char __user *msg, size_t msg_len)
hdr->sub_type = priv->user.sub_type;
hdr->user_id = priv->user.user_id;
hdr->datalen = msg_len;
- BMA_LOG(DLOG_DEBUG, "msg_len is %ld\n", msg_len);
+ BMA_LOG(DLOG_DEBUG, "msg_len is %zu\n", msg_len);
if (copy_from_user(hdr->data, msg, msg_len)) {
BMA_LOG(DLOG_ERROR, "copy_from_user error\n");
diff --git a/drivers/net/ethernet/huawei/bma/edma_drv/edma_host.c b/drivers/net/ethernet/huawei/bma/edma_drv/edma_host.c
index 2d5f4ffd79d9..3525d41c865f 100644
--- a/drivers/net/ethernet/huawei/bma/edma_drv/edma_host.c
+++ b/drivers/net/ethernet/huawei/bma/edma_drv/edma_host.c
@@ -789,7 +789,7 @@ static int edma_host_send_msg(struct edma_host_s *edma_host)
if (edma_host->msg_send_write >
HOST_MAX_SEND_MBX_LEN - SIZE_OF_MBX_HDR) {
BMA_LOG(DLOG_ERROR,
- "Length of send message %u is larger than %lu\n",
+ "Length of send message %u is larger than %zu\n",
edma_host->msg_send_write,
HOST_MAX_SEND_MBX_LEN - SIZE_OF_MBX_HDR);
edma_host->msg_send_write = 0;
diff --git a/drivers/net/ethernet/huawei/bma/veth_drv/veth_hb.c b/drivers/net/ethernet/huawei/bma/veth_drv/veth_hb.c
index 9681ce3bfc7b..240db31d7178 100644
--- a/drivers/net/ethernet/huawei/bma/veth_drv/veth_hb.c
+++ b/drivers/net/ethernet/huawei/bma/veth_drv/veth_hb.c
@@ -1488,8 +1488,8 @@ s32 veth_recv_pkt(struct bspveth_rxtx_q *prx_queue, int queue)
skb->len, skb->protocol);
VETH_LOG(DLOG_DEBUG,
- "dma_p=0x%llx,dma_map=0x%llx,",
- pbd_v->dma_p, dma_map);
+ "dma_p=0x%llx,dma_map=%pad,",
+ pbd_v->dma_p, &dma_map);
VETH_LOG(DLOG_DEBUG,
"skb=%p,skb->data=%p,skb->len=%d,tail=%d,shm_off=%d\n",
--
2.20.1
1
0
08 Jan '22
From: Yixing Liu <liuyixing1(a)huawei.com>
mainline inclusion
from mainline-v5.15-rc1
commit 260f64a40198
category: feature
bugzilla: https://gitee.com/openeuler/kernel/issues/I4O23M
CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?…
----------------------------------------------------------------------------
The stash feature is enabled by default on HIP09.
Fixes: f93c39bc9547 ("RDMA/hns: Add support for QP stash")
Fixes: bfefae9f108d ("RDMA/hns: Add support for CQ stash")
Link: https://lore.kernel.org/r/1629539607-33217-3-git-send-email-liangwenpeng@hu…
Signed-off-by: Yixing Liu <liuyixing1(a)huawei.com>
Signed-off-by: Wenpeng Liang <liangwenpeng(a)huawei.com>
Signed-off-by: Jason Gunthorpe <jgg(a)nvidia.com>
sigend-off-by: Guofeng Yue <yueguofeng(a)hisilicon.com>
Reviewed-by: Yangyang Li <liyangyang20(a)huawei.com>
Acked-by: Xie XiuQi <xiexiuqi(a)huawei.com>
Signed-off-by: Zheng Zengkai <zhengzengkai(a)huawei.com>
---
drivers/infiniband/hw/hns/hns_roce_hw_v2.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c b/drivers/infiniband/hw/hns/hns_roce_hw_v2.c
index aea6a6a7b238..4f8738bda0a2 100644
--- a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c
+++ b/drivers/infiniband/hw/hns/hns_roce_hw_v2.c
@@ -2004,6 +2004,7 @@ static void set_default_caps(struct hns_roce_dev *hr_dev)
caps->gid_table_len[0] = HNS_ROCE_V2_GID_INDEX_NUM;
if (hr_dev->pci_dev->revision >= PCI_REVISION_ID_HIP09) {
+ caps->flags |= HNS_ROCE_CAP_FLAG_STASH;
caps->max_sq_inline = HNS_ROCE_V3_MAX_SQ_INLINE;
} else {
caps->max_sq_inline = HNS_ROCE_V2_MAX_SQ_INLINE;
--
2.20.1
1
20
08 Jan '22
driver inclusion
category: feature
bugzilla: https://gitee.com/openeuler/kernel/issues/I4ETXO
CVE: NA
-----------------------------------------
Fix following build warnings in arm32 builds:
drivers/net/ethernet/huawei/bma/edma_drv/bma_devintf.c: In function ‘bma_cdev_add_msg’:
drivers/net/ethernet/huawei/bma/edma_drv/bma_pci.h:92:20: warning: format ‘%ld’ expects argument of type ‘long int’, but argument 5 has type ‘size_t {aka unsigned int}’ [-Wformat=]
Signed-off-by: Zheng Zengkai <zhengzengkai(a)huawei.com>
---
.../bma/cdev_veth_drv/virtual_cdev_eth_net.c | 14 +++++++-------
.../net/ethernet/huawei/bma/edma_drv/bma_devintf.c | 2 +-
.../net/ethernet/huawei/bma/edma_drv/edma_host.c | 2 +-
drivers/net/ethernet/huawei/bma/veth_drv/veth_hb.c | 2 +-
4 files changed, 10 insertions(+), 10 deletions(-)
diff --git a/drivers/net/ethernet/huawei/bma/cdev_veth_drv/virtual_cdev_eth_net.c b/drivers/net/ethernet/huawei/bma/cdev_veth_drv/virtual_cdev_eth_net.c
index 04ea55f4e0a2..99466848c034 100644
--- a/drivers/net/ethernet/huawei/bma/cdev_veth_drv/virtual_cdev_eth_net.c
+++ b/drivers/net/ethernet/huawei/bma/cdev_veth_drv/virtual_cdev_eth_net.c
@@ -605,7 +605,7 @@ static int edma_veth_cut_tx_packet_send(struct edma_eth_dev_s *eth_dev,
do_queue_rate_limit(eth_dev->ptx_queue);
while (length > 0) {
- LOG(DLOG_DEBUG, "length: %u/%lu", length, len);
+ LOG(DLOG_DEBUG, "length: %u/%u", length, len);
if (length > BSPPACKET_MTU_MAX) {
/* fragment. */
@@ -1689,7 +1689,7 @@ static ssize_t cdev_copy_packet_to_user(struct edma_eth_dev_s *dev,
start = dev->rx_packet[dev->rx_packet_head].packet + g_read_pos;
LOG(DLOG_DEBUG,
- "User needs %ld bytes, pos: %u, total len: %u, left: %ld.",
+ "User needs %d bytes, pos: %u, total len: %u, left: %d.",
count, g_read_pos, dev->rx_packet[dev->rx_packet_head].len, left);
if (left <= 0) {
/* No more data in this message, retry. */
@@ -1721,7 +1721,7 @@ static ssize_t cdev_copy_packet_to_user(struct edma_eth_dev_s *dev,
}
LOG(DLOG_DEBUG,
- "Copied bytes: %ld, pos: %d, buf len: %lu, free_packet: %d.",
+ "Copied bytes: %d, pos: %d, buf len: %u, free_packet: %d.",
length, g_read_pos, count, free_packet);
if (packet) {
@@ -1807,11 +1807,11 @@ ssize_t cdev_read(struct file *filp, char __user *data,
if (!data || count >= MAX_PACKET_LEN)
return -EFAULT;
- LOG(DLOG_DEBUG, "read begin, count: %ld, pos: %u.", count, g_read_pos);
+ LOG(DLOG_DEBUG, "read begin, count: %d, pos: %u.", count, g_read_pos);
length = cdev_copy_packet_to_user(dev, data, count);
- LOG(DLOG_DEBUG, "read done, length: %ld, pos: %u.", length, g_read_pos);
+ LOG(DLOG_DEBUG, "read done, length: %d, pos: %u.", length, g_read_pos);
return length;
}
@@ -1837,7 +1837,7 @@ ssize_t cdev_write(struct file *filp, const char __user *data,
g_peer_not_ready = 0;
}
- LOG(DLOG_DEBUG, "data length is %lu, pos: %u (%u/%u)",
+ LOG(DLOG_DEBUG, "data length is %u, pos: %u (%u/%u)",
count, g_read_pos,
pdev->ptx_queue->pshmqhd_v->count,
pdev->ptx_queue->pshmqhd_v->total);
@@ -1859,4 +1859,4 @@ MODULE_DESCRIPTION("HUAWEI CDEV DRIVER");
MODULE_LICENSE("GPL");
module_init(edma_cdev_init);
-module_exit(edma_cdev_exit);
\ No newline at end of file
+module_exit(edma_cdev_exit);
diff --git a/drivers/net/ethernet/huawei/bma/edma_drv/bma_devintf.c b/drivers/net/ethernet/huawei/bma/edma_drv/bma_devintf.c
index 7817f58f8635..2d63e44f0ed2 100644
--- a/drivers/net/ethernet/huawei/bma/edma_drv/bma_devintf.c
+++ b/drivers/net/ethernet/huawei/bma/edma_drv/bma_devintf.c
@@ -497,7 +497,7 @@ int bma_cdev_add_msg(void *handle, const char __user *msg, size_t msg_len)
hdr->sub_type = priv->user.sub_type;
hdr->user_id = priv->user.user_id;
hdr->datalen = msg_len;
- BMA_LOG(DLOG_DEBUG, "msg_len is %ld\n", msg_len);
+ BMA_LOG(DLOG_DEBUG, "msg_len is %d\n", msg_len);
if (copy_from_user(hdr->data, msg, msg_len)) {
BMA_LOG(DLOG_ERROR, "copy_from_user error\n");
diff --git a/drivers/net/ethernet/huawei/bma/edma_drv/edma_host.c b/drivers/net/ethernet/huawei/bma/edma_drv/edma_host.c
index 2d5f4ffd79d9..a89a4160dedd 100644
--- a/drivers/net/ethernet/huawei/bma/edma_drv/edma_host.c
+++ b/drivers/net/ethernet/huawei/bma/edma_drv/edma_host.c
@@ -789,7 +789,7 @@ static int edma_host_send_msg(struct edma_host_s *edma_host)
if (edma_host->msg_send_write >
HOST_MAX_SEND_MBX_LEN - SIZE_OF_MBX_HDR) {
BMA_LOG(DLOG_ERROR,
- "Length of send message %u is larger than %lu\n",
+ "Length of send message %u is larger than %u\n",
edma_host->msg_send_write,
HOST_MAX_SEND_MBX_LEN - SIZE_OF_MBX_HDR);
edma_host->msg_send_write = 0;
diff --git a/drivers/net/ethernet/huawei/bma/veth_drv/veth_hb.c b/drivers/net/ethernet/huawei/bma/veth_drv/veth_hb.c
index 9681ce3bfc7b..7b511c05c2e9 100644
--- a/drivers/net/ethernet/huawei/bma/veth_drv/veth_hb.c
+++ b/drivers/net/ethernet/huawei/bma/veth_drv/veth_hb.c
@@ -1488,7 +1488,7 @@ s32 veth_recv_pkt(struct bspveth_rxtx_q *prx_queue, int queue)
skb->len, skb->protocol);
VETH_LOG(DLOG_DEBUG,
- "dma_p=0x%llx,dma_map=0x%llx,",
+ "dma_p=0x%llx,dma_map=0x%x,",
pbd_v->dma_p, dma_map);
VETH_LOG(DLOG_DEBUG,
--
2.20.1
2
1
[PATCH openEuler-5.10 001/125] kabi: Generalize naming of kabi helper macros
by Zheng Zengkai 07 Jan '22
by Zheng Zengkai 07 Jan '22
07 Jan '22
hulk inclusion
category: feature
bugzilla: https://gitee.com/openeuler/kernel/issues/I4K3S5
--------------------------
Generalize naming of some kabi helper macros.
Signed-off-by: Zheng Zengkai <zhengzengkai(a)huawei.com>
Reviewed-by: Xie XiuQi <xiexiuqi(a)huawei.com>
Signed-off-by: Zheng Zengkai <zhengzengkai(a)huawei.com>
---
include/linux/kabi.h | 38 +++++++++++++++++++-------------------
1 file changed, 19 insertions(+), 19 deletions(-)
diff --git a/include/linux/kabi.h b/include/linux/kabi.h
index 713f63cf56cb..0bc7ca2483f4 100644
--- a/include/linux/kabi.h
+++ b/include/linux/kabi.h
@@ -151,7 +151,7 @@
* approaches can (and often are) combined.
*
* To use this for 'struct foo' (the "base structure"), define a new
- * structure called 'struct foo_rh'; this new struct is called "auxiliary
+ * structure called 'struct foo_resvd'; this new struct is called "auxiliary
* structure". Then add KABI_AUX_EMBED or KABI_AUX_PTR to the end
* of the base structure. The argument is the name of the base structure,
* without the 'struct' keyword.
@@ -174,7 +174,7 @@
* end. Note the auxiliary structure cannot be shrunk in size later (i.e.,
* fields cannot be removed, only deprecated). Any code accessing fields
* from the aux struct must guard the access using the KABI_AUX macro.
- * The access itself is then done via a '_rh' field in the base struct.
+ * The access itself is then done via a '_resvd' field in the base struct.
*
* The auxiliary structure is not guaranteed for access by modules unless
* explicitly commented as such in the declaration of the aux struct
@@ -182,7 +182,7 @@
*
* Example:
*
- * struct foo_rh {
+ * struct foo_resvd {
* int newly_added;
* };
*
@@ -194,20 +194,20 @@
* void use(struct foo *f)
* {
* if (KABI_AUX(f, foo, newly_added))
- * f->_rh->newly_added = 123;
+ * f->_resvd->newly_added = 123;
* else
* // the field 'newly_added' is not present in the passed
* // struct, fall back to old behavior
* f->big_hammer = true;
* }
*
- * static struct foo_rh my_foo_rh {
+ * static struct foo_resvd my_foo_resvd {
* .newly_added = 0;
* }
*
* static struct foo my_foo = {
* .big_hammer = false,
- * ._rh = &my_foo_rh,
+ * ._resvd = &my_foo_resvd,
* KABI_AUX_INIT_SIZE(foo)
* };
*
@@ -218,7 +218,7 @@
*
* Example:
*
- * struct foo_rh {
+ * struct foo_resvd {
* };
*
* struct foo {
@@ -385,7 +385,7 @@
_Static_assert(__alignof__(struct{_new;}) <= __alignof__(struct{_orig;}), \
__FILE__ ":" __stringify(__LINE__) ": " __stringify(_orig) " is not aligned the same as " __stringify(_new) KABI_ALIGN_WARNING); \
}
-# define __ABI_CHECK_SIZE(_item, _size) \
+# define __KABI_CHECK_SIZE(_item, _size) \
_Static_assert(sizeof(struct{_item;}) <= _size, \
__FILE__ ":" __stringify(__LINE__) ": " __stringify(_item) " is larger than the reserved size (" __stringify(_size) " bytes)" KABI_ALIGN_WARNING)
#else
@@ -451,14 +451,14 @@
})
#define _KABI_AUX_PTR(_struct) \
- size_t _struct##_size_rh; \
- _KABI_EXCLUDE(struct _struct##_rh *_rh)
+ size_t _struct##_size_resvd; \
+ _KABI_EXCLUDE(struct _struct##_resvd *_resvd)
#define KABI_AUX_PTR(_struct) \
_KABI_AUX_PTR(_struct);
#define _KABI_AUX_EMBED(_struct) \
- size_t _struct##_size_rh; \
- _KABI_EXCLUDE(struct _struct##_rh _rh)
+ size_t _struct##_size_resvd; \
+ _KABI_EXCLUDE(struct _struct##_resvd _resvd)
#define KABI_AUX_EMBED(_struct) \
_KABI_AUX_EMBED(_struct);
@@ -468,7 +468,7 @@
/*
* KABI_AUX_SET_SIZE calculates and sets the size of the extended struct and
- * stores it in the size_rh field for structs that are dynamically allocated.
+ * stores it in the size_resvd field for structs that are dynamically allocated.
* This macro MUST be called when expanding a base struct with
* KABI_SIZE_AND_EXTEND, and it MUST be called from the allocation site
* regardless of being allocated in the kernel or a module.
@@ -476,28 +476,28 @@
* a semicolon is necessary at the end of the line where it is invoked.
*/
#define KABI_AUX_SET_SIZE(_name, _struct) ({ \
- (_name)->_struct##_size_rh = sizeof(struct _struct##_rh); \
+ (_name)->_struct##_size_resvd = sizeof(struct _struct##_resvd); \
})
/*
* KABI_AUX_INIT_SIZE calculates and sets the size of the extended struct and
- * stores it in the size_rh field for structs that are statically allocated.
+ * stores it in the size_resvd field for structs that are statically allocated.
* This macro MUST be called when expanding a base struct with
* KABI_SIZE_AND_EXTEND, and it MUST be called from the declaration site
* regardless of being allocated in the kernel or a module.
*/
#define KABI_AUX_INIT_SIZE(_struct) \
- ._struct##_size_rh = sizeof(struct _struct##_rh),
+ ._struct##_size_resvd = sizeof(struct _struct##_resvd),
/*
* KABI_AUX verifies allocated memory exists. This MUST be called to
- * verify that memory in the _rh struct is valid, and can be called
+ * verify that memory in the _resvd struct is valid, and can be called
* regardless if KABI_SIZE_AND_EXTEND or KABI_SIZE_AND_EXTEND_PTR is
* used.
*/
#define KABI_AUX(_ptr, _struct, _field) ({ \
- size_t __off = offsetof(struct _struct##_rh, _field); \
- (_ptr)->_struct##_size_rh > __off ? true : false; \
+ size_t __off = offsetof(struct _struct##_resvd, _field); \
+ (_ptr)->_struct##_size_resvd > __off ? true : false; \
})
#endif /* _LINUX_KABI_H */
--
2.20.1
1
124
Subscribe
<https://aka.ms/AAb9ysg>
1
0
[PATCH openEuler-5.10 1/2] arm64: Add support for memmap kernel parameters
by Zheng Zengkai 07 Jan '22
by Zheng Zengkai 07 Jan '22
07 Jan '22
From: Peng Liu <liupeng256(a)huawei.com>
hulk inclusion
category: feature
bugzilla: https://gitee.com/openeuler/kernel/issues/I4NYPZ
CVE: NA
-------------------------------------------------
Add support for memmap kernel parameters for ARM64. The three below
modes are supported:
memmap=exactmap
Enable setting of an exact memory map, as specified by the user.
memmap=nn[KMG]@ss[KMG]
Force usage of a specific region of memory.
memmap=nn[KMG]$ss[KMG]
Region of memory to be reserved is from ss to ss+nn, the region must
be in the range of existed memory, otherwise will be ignored.
If users set memmap=exactmap before memmap=nn[KMG]@ss[KMG], they will
get the exact memory specified by memmap=nn[KMG]@ss[KMG]. For example,
on one machine with 4GB memory, "memmap=exactmap memmap=1G@1G" will
make kernel use the memory from 1GB to 2GB only.
Signed-off-by: Peng Liu <liupeng256(a)huawei.com>
Reviewed-by: Kefeng Wang <wangkefeng.wang(a)huawei.com>
Signed-off-by: Zheng Zengkai <zhengzengkai(a)huawei.com>
---
.../admin-guide/kernel-parameters.txt | 9 ++-
arch/arm64/mm/init.c | 59 +++++++++++++++++++
2 files changed, 65 insertions(+), 3 deletions(-)
diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
index de8f7d447295..64be32ba4373 100644
--- a/Documentation/admin-guide/kernel-parameters.txt
+++ b/Documentation/admin-guide/kernel-parameters.txt
@@ -2794,8 +2794,8 @@
option.
See Documentation/admin-guide/mm/memory-hotplug.rst.
- memmap=exactmap [KNL,X86] Enable setting of an exact
- E820 memory map, as specified by the user.
+ memmap=exactmap [KNL,X86,ARM64] Enable setting of an exact
+ E820 and ARM64 memory map, as specified by the user.
Such memmap=exactmap lines can be constructed based on
BIOS output or other requirements. See the memmap=nn@ss
option description.
@@ -2806,7 +2806,8 @@
If @ss[KMG] is omitted, it is equivalent to mem=nn[KMG],
which limits max address to nn[KMG].
Multiple different regions can be specified,
- comma delimited.
+ comma delimited, example as follows is not supported to
+ ARM64.
Example:
memmap=100M@2G,100M#3G,1G!1024G
@@ -2817,6 +2818,8 @@
memmap=nn[KMG]$ss[KMG]
[KNL,ACPI] Mark specific memory as reserved.
Region of memory to be reserved is from ss to ss+nn.
+ For ARM64, reserved memory must be in the range of
+ existed memory.
Example: Exclude memory from 0x18690000-0x1869ffff
memmap=64K$0x18690000
or
diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c
index e8d446164c76..f59546d3b0de 100644
--- a/arch/arm64/mm/init.c
+++ b/arch/arm64/mm/init.c
@@ -404,6 +404,65 @@ static int __init reserve_park_mem(void)
}
#endif
+static int need_remove_real_memblock __initdata;
+
+static int __init parse_memmap_one(char *p)
+{
+ char *oldp;
+ u64 start_at, mem_size;
+
+ if (!p)
+ return -EINVAL;
+
+ if (!strncmp(p, "exactmap", 8)) {
+ need_remove_real_memblock = 1;
+ return -EINVAL;
+ }
+
+ oldp = p;
+ mem_size = memparse(p, &p);
+ if (p == oldp)
+ return -EINVAL;
+
+ if (!mem_size)
+ return -EINVAL;
+
+ if (*p == '@') {
+ start_at = memparse(p + 1, &p);
+ /*
+ * use the exactmap defined by nn[KMG]@ss[KMG], remove
+ * memblock populated by DT etc.
+ */
+ if (need_remove_real_memblock) {
+ need_remove_real_memblock = 0;
+ memblock_remove(0, ULLONG_MAX);
+ }
+ memblock_add(start_at, mem_size);
+ } else if (*p == '$') {
+ start_at = memparse(p + 1, &p);
+ memblock_reserve(start_at, mem_size);
+ } else
+ pr_info("Unrecognized memmap option, please check the parameter.\n");
+
+ return *p == '\0' ? 0 : -EINVAL;
+}
+
+static int __init parse_memmap_opt(char *str)
+{
+ while (str) {
+ char *k = strchr(str, ',');
+
+ if (k)
+ *k++ = 0;
+
+ parse_memmap_one(str);
+ str = k;
+ }
+
+ return 0;
+}
+early_param("memmap", parse_memmap_opt);
+
void __init arm64_memblock_init(void)
{
const s64 linear_region_size = BIT(vabits_actual - 1);
--
2.20.1
1
1
Ramaxel inclusion
category: features
bugzilla: https://gitee.com/openeuler/kernel/issues/I4ON8F
CVE: NA
Changes:
1. Split scmd_tmout_nonpt into two parameters:
scmd_tmout_vd/scmd_tmout_rawdisk
2. Return -ETIME instead of -EINVAL when command is timeout.
3. Add one module parameters: max_io_force.
Signed-off-by: Yanling Song <songyl(a)ramaxel.com>
Reviewed-by: Jiang Yu<yujiang(a)ramaxel.com>
---
drivers/scsi/spraid/spraid_main.c | 96 +++++++++++++++----------------
1 file changed, 45 insertions(+), 51 deletions(-)
diff --git a/drivers/scsi/spraid/spraid_main.c b/drivers/scsi/spraid/spraid_main.c
index 519b39f44e91..7069582d741a 100644
--- a/drivers/scsi/spraid/spraid_main.c
+++ b/drivers/scsi/spraid/spraid_main.c
@@ -42,10 +42,17 @@ static u32 admin_tmout = 60;
module_param(admin_tmout, uint, 0644);
MODULE_PARM_DESC(admin_tmout, "admin commands timeout (seconds)");
-static u32 scmd_tmout_nonpt = 180;
-module_param(scmd_tmout_nonpt, uint, 0644);
-MODULE_PARM_DESC(scmd_tmout_nonpt,
- "scsi commands timeout for rawdisk&raid(seconds)");
+static u32 scmd_tmout_rawdisk = 180;
+module_param(scmd_tmout_rawdisk, uint, 0644);
+MODULE_PARM_DESC(scmd_tmout_rawdisk, "scsi commands timeout for rawdisk(seconds)");
+
+static u32 scmd_tmout_vd = 180;
+module_param(scmd_tmout_vd, uint, 0644);
+MODULE_PARM_DESC(scmd_tmout_vd, "scsi commands timeout for vd(seconds)");
+
+static bool max_io_force;
+module_param(max_io_force, bool, 0644);
+MODULE_PARM_DESC(max_io_force, "force max_hw_sectors_kb = 1024, default false(performance first)");
static int ioq_depth_set(const char *val, const struct kernel_param *kp);
static const struct kernel_param_ops ioq_depth_ops = {
@@ -78,7 +85,7 @@ static unsigned char log_debug_switch;
module_param_cb(log_debug_switch, &log_debug_switch_ops,
&log_debug_switch, 0644);
MODULE_PARM_DESC(log_debug_switch,
- "set log state, default non-zero for switch on");
+ "set log state, default zero for switch off");
static int small_pool_num_set(const char *val, const struct kernel_param *kp)
{
@@ -132,7 +139,6 @@ static struct workqueue_struct *spraid_wq;
#define SPRAID_DRV_VERSION "1.0.0.0"
#define ADMIN_TIMEOUT (admin_tmout * HZ)
-#define ADMIN_ERR_TIMEOUT 32757
#define SPRAID_WAIT_ABNL_CMD_TIMEOUT (3 * 2)
@@ -242,13 +248,6 @@ static int spraid_pci_enable(struct spraid_dev *hdev)
goto disable;
}
- ret = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_ALL_TYPES);
- if (ret < 0) {
- dev_err(hdev->dev,
- "Allocate one IRQ for setup admin channel failed\n");
- goto disable;
- }
-
hdev->cap = lo_hi_readq(hdev->bar + SPRAID_REG_CAP);
hdev->ioq_depth = min_t(u32, SPRAID_CAP_MQES(hdev->cap) + 1,
io_queue_depth);
@@ -261,13 +260,21 @@ static int spraid_pci_enable(struct spraid_dev *hdev)
maskbit);
maskbit = SPRAID_DMA_MSK_BIT_MAX;
}
- if (dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(maskbit))) {
+ if (dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(maskbit)) &&
+ dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32))) {
dev_err(hdev->dev, "set dma mask and coherent failed\n");
goto disable;
}
dev_info(hdev->dev, "set dma mask[%llu] success\n", maskbit);
+ ret = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_ALL_TYPES);
+
+ if (ret < 0) {
+ dev_err(hdev->dev, "Allocate one IRQ for setup admin channel failed\n");
+ goto disable;
+ }
+
pci_enable_pcie_error_reporting(pdev);
pci_save_state(pdev);
@@ -840,6 +847,9 @@ static void spraid_map_status(struct spraid_iod *iod, struct scsi_cmnd *scmd,
break;
default:
set_host_byte(scmd, DID_BAD_TARGET);
+ dev_warn(iod->spraidq->hdev->dev, "[%s] cid[%d] qid[%d];"
+ "bad status[0x%x]\n", __func__, cqe->cmd_id,
+ le16_to_cpu(cqe->sq_id), le16_to_cpu(cqe->status));
break;
}
}
@@ -981,32 +991,17 @@ static void spraid_slave_destroy(struct scsi_device *sdev)
static int spraid_slave_configure(struct scsi_device *sdev)
{
- u16 idx;
- unsigned int timeout = scmd_tmout_nonpt * HZ;
+ unsigned int timeout = scmd_tmout_rawdisk * HZ;
struct spraid_dev *hdev = shost_priv(sdev->host);
struct spraid_sdev_hostdata *hostdata = sdev->hostdata;
u32 max_sec = sdev->host->max_sectors;
if (hostdata) {
- idx = hostdata->hdid - 1;
- if (sdev->channel == hdev->devices[idx].channel &&
- sdev->id == le16_to_cpu(hdev->devices[idx].target) &&
- sdev->lun < hdev->devices[idx].lun) {
- if (SPRAID_DEV_INFO_ATTR_PT(hdev->devices[idx].attr))
- timeout = 30 * HZ;
- else
- timeout = scmd_tmout_nonpt * HZ;
- max_sec = le16_to_cpu(hdev->devices[idx].max_io_kb)
- << 1;
- } else {
- dev_err(hdev->dev,
- "[%s] err, sdev->channel:id:lun[%d:%d:%lld];"
- "devices[%d], channel:target:lun[%d:%d:%d]\n",
- __func__, sdev->channel, sdev->id, sdev->lun,
- idx, hdev->devices[idx].channel,
- hdev->devices[idx].target,
- hdev->devices[idx].lun);
- }
+ if (SPRAID_DEV_INFO_ATTR_VD(hostdata->attr))
+ timeout = scmd_tmout_vd * HZ;
+ else if (SPRAID_DEV_INFO_ATTR_RAWDISK(hostdata->attr))
+ timeout = scmd_tmout_rawdisk * HZ;
+ max_sec = hostdata->max_io_kb << 1;
} else {
dev_err(hdev->dev, "[%s] err, sdev->hostdata is null\n",
__func__);
@@ -1018,11 +1013,12 @@ static int spraid_slave_configure(struct scsi_device *sdev)
if ((max_sec == 0) || (max_sec > sdev->host->max_sectors))
max_sec = sdev->host->max_sectors;
- dev_info(hdev->dev,
- "[%s] sdev->channel:id:lun[%d:%d:%lld];"
- " scmd_timeout[%d]s, maxsec[%d]\n",
- __func__, sdev->channel, sdev->id,
- sdev->lun, timeout / HZ, max_sec);
+ if (!max_io_force)
+ blk_queue_max_hw_sectors(sdev->request_queue, max_sec);
+
+ dev_info(hdev->dev, "[%s] sdev->channel:id:lun[%d:%d:%lld];"
+ "scmd_timeout[%d]s, maxsec[%d]\n", __func__, sdev->channel,
+ sdev->id, sdev->lun, timeout / HZ, max_sec);
return 0;
}
@@ -1677,7 +1673,7 @@ static int spraid_submit_admin_sync_cmd(struct spraid_dev *hdev,
cmd->usr_cmd.opcode, cmd->usr_cmd.info_0.subopcode);
WRITE_ONCE(adm_cmd->state, SPRAID_CMD_TIMEOUT);
spraid_put_cmd(hdev, adm_cmd, SPRAID_CMD_ADM);
- return -EINVAL;
+ return -ETIME;
}
if (result0)
@@ -2630,9 +2626,6 @@ static int spraid_user_admin_cmd(struct spraid_dev *hdev, struct bsg_job *job)
return -EBUSY;
}
- dev_info(hdev->dev, "[%s] opcode[0x%x] subopcode[0x%x] init\n",
- __func__, cmd->opcode, cmd->info_0.subopcode);
-
memset(&admin_cmd, 0, sizeof(admin_cmd));
admin_cmd.common.opcode = cmd->opcode;
admin_cmd.common.flags = cmd->flags;
@@ -2659,10 +2652,11 @@ static int spraid_user_admin_cmd(struct spraid_dev *hdev, struct bsg_job *job)
memcpy(job->reply, result, sizeof(result));
}
- dev_info(hdev->dev, "[%s] opcode[0x%x] subopcode[0x%x];"
- " status[0x%x] result0[0x%x] result1[0x%x]\n",
- __func__, cmd->opcode, cmd->info_0.subopcode,
- status, result[0], result[1]);
+ if (status)
+ dev_info(hdev->dev, "[%s] opcode[0x%x] subopcode[0x%x];"
+ " status[0x%x] result0[0x%x] result1[0x%x]\n",
+ __func__, cmd->opcode, cmd->info_0.subopcode,
+ status, result[0], result[1]);
spraid_bsg_unmap_data(hdev, job);
@@ -2742,7 +2736,7 @@ static int spraid_submit_ioq_sync_cmd(struct spraid_dev *hdev,
(le32_to_cpu(cmd->common.cdw3[0]) & 0xffff));
WRITE_ONCE(pt_cmd->state, SPRAID_CMD_TIMEOUT);
spraid_put_cmd(hdev, pt_cmd, SPRAID_CMD_IOPT);
- return -EINVAL;
+ return -ETIME;
}
if (result && reslen) {
@@ -3140,7 +3134,7 @@ static int spraid_abort_handler(struct scsi_cmnd *scmd)
dev_warn(hdev->dev, "cid[%d] qid[%d] timeout, aborting\n", cid, hwq);
ret = spraid_send_abort_cmd(hdev, hostdata->hdid, hwq, cid);
- if (ret != ADMIN_ERR_TIMEOUT) {
+ if (ret != -ETIME) {
ret = spraid_wait_abnl_cmd_done(iod);
if (ret) {
dev_warn(hdev->dev, "cid[%d] qid[%d] abort failed;"
@@ -3623,7 +3617,7 @@ static int spraid_bsg_host_dispatch(struct bsg_job *job)
struct spraid_bsg_request *bsg_req = job->request;
int ret = 0;
- dev_info(hdev->dev, "[%s] msgcode[%d], msglen[%d], timeout[%d];"
+ dev_log_dbg(hdev->dev, "[%s] msgcode[%d], msglen[%d], timeout[%d];"
" req_nsge[%d], req_len[%d]\n",
__func__, bsg_req->msgcode, job->request_len,
rq->timeout, job->request_payload.sg_cnt,
--
2.27.0
1
0
[PATCH openEuler-1.0-LTS 1/2] arm64/mpam: fix mpam probe error for wrong init order
by Yang Yingliang 06 Jan '22
by Yang Yingliang 06 Jan '22
06 Jan '22
From: Xingang Wang <wangxingang5(a)huawei.com>
ascend inclusion
category: bugfix
bugzilla: https://gitee.com/openeuler/kernel/issues/I49RB2
CVE: NA
---------------------------------------------------
The mpam init procedure failed when probe with ACPI:
[ 1.148657 ] ACPI MPAM: No CPU has cache with PPTT reference 0x72
[ 1.148658 ] ACPI MPAM: All CPUs must be online to probe mpam.
[ 1.148660 ] ACPI MPAM: discovery failed: -19
This is because mpam need to be probed after all cpus be online, the
arm_mpam_driver_init must be called after cacheinfo_sysfs_init, so the
device_initcall should be replaced with device_initcall_sync.
Fixes: b45bdb5a8604 ("arm64/mpam: add device tree support for mpam initialization")
Signed-off-by: Xingang Wang <wangxingang5(a)huawei.com>
Reviewed-by: Wang ShaoBo <bobo.shaobowang(a)huawei.com>
Reviewed-by: Cheng Jian <cj.chengjian(a)huawei.com>
Signed-off-by: Yang Yingliang <yangyingliang(a)huawei.com>
---
arch/arm64/kernel/mpam/mpam_device.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/arm64/kernel/mpam/mpam_device.c b/arch/arm64/kernel/mpam/mpam_device.c
index 4910e99348798..c7b5c50d431bd 100644
--- a/arch/arm64/kernel/mpam/mpam_device.c
+++ b/arch/arm64/kernel/mpam/mpam_device.c
@@ -1876,4 +1876,4 @@ static int __init arm_mpam_driver_init(void)
* We want to run after cacheinfo_sysfs_init() has caused the cacheinfo
* structures to be populated. That runs as a device_initcall.
*/
-device_initcall(arm_mpam_driver_init);
+device_initcall_sync(arm_mpam_driver_init);
--
2.25.1
1
1
06 Jan '22
Add CONFIG_KABI_RESERVE to control KABI padding reserve and enable it by
default.
Zheng Zengkai (2):
KABI: Add CONFIG_KABI_RESERVE to control KABI padding reserve
openeuler_defconfig: Enable CONFIG_KABI_RESERVE for x86 and arm64
Kconfig | 8 ++++++++
arch/arm64/configs/openeuler_defconfig | 1 +
arch/x86/configs/openeuler_defconfig | 1 +
include/linux/kabi.h | 6 +++++-
4 files changed, 15 insertions(+), 1 deletion(-)
--
2.20.1
1
2
hulk inclusion
bugzilla: https://gitee.com/openeuler/kernel/issues/I4MZU1
CVE: NA
---------------------------
For x86 platform, make allmodconfig & make -j64, following two
build errors are reported.
First error:
- build failed:
- In file included from <command-line>:32:0:
./usr/include/asm/bootparam.h:45:10: fatal error: linux/kabi.h: No such file or directory
#include <linux/kabi.h>
^~~~~~~~~~~~~~
compilation terminated.
make[2]: *** [usr/include/asm/bootparam.hdrtest] Error 1
Second error:
./arch/x86/include/asm/paravirt_types.h:198:2: error: expected specifier-qualifier-list before ‘KABI_RESERVE’
KABI_RESERVE(1)
^~~~~~~~~~~~
./arch/x86/include/asm/paravirt_types.h:286:2: error: expected specifier-qualifier-list before ‘KABI_RESERVE’
KABI_RESERVE(1)
^~~~~~~~~~~~
./arch/x86/include/asm/paravirt_types.h:309:2: error: expected specifier-qualifier-list before ‘KABI_RESERVE’
KABI_RESERVE(1)
^~~~~~~~~~~~
make[1]: *** [scripts/Makefile.build:117: arch/x86/kernel/asm-offsets.s] Error 1
To fix first error, reverts commit 3ba63bacfc bootparam: Add kabi_reserve in bootparam.
To fix second error, add include file kabi.h to arch/x86/include/asm/paravirt_types.h.
Signed-off-by: Zheng Zengkai <zhengzengkai(a)huawei.com>
---
arch/x86/include/asm/paravirt_types.h | 2 ++
arch/x86/include/uapi/asm/bootparam.h | 2 --
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/arch/x86/include/asm/paravirt_types.h b/arch/x86/include/asm/paravirt_types.h
index 98eb135b1888..17a2308ef3af 100644
--- a/arch/x86/include/asm/paravirt_types.h
+++ b/arch/x86/include/asm/paravirt_types.h
@@ -2,6 +2,8 @@
#ifndef _ASM_X86_PARAVIRT_TYPES_H
#define _ASM_X86_PARAVIRT_TYPES_H
+#include <linux/kabi.h>
+
/* Bitmask of what can be clobbered: usually at least eax. */
#define CLBR_NONE 0
#define CLBR_EAX (1 << 0)
diff --git a/arch/x86/include/uapi/asm/bootparam.h b/arch/x86/include/uapi/asm/bootparam.h
index b1dce768d073..600a141c8805 100644
--- a/arch/x86/include/uapi/asm/bootparam.h
+++ b/arch/x86/include/uapi/asm/bootparam.h
@@ -42,7 +42,6 @@
#include <linux/types.h>
#include <linux/screen_info.h>
#include <linux/apm_bios.h>
-#include <linux/kabi.h>
#include <linux/edd.h>
#include <asm/ist.h>
#include <video/edid.h>
@@ -103,7 +102,6 @@ struct setup_header {
__u32 init_size;
__u32 handover_offset;
__u32 kernel_info_offset;
- KABI_RESERVE(1)
} __attribute__((packed));
struct sys_desc_table {
--
2.20.1
1
0
[PATCH openEuler-1.0-LTS 1/3] bpf: Use dedicated bpf_trace_printk event instead of trace_printk()
by Liu Xinpeng 06 Jan '22
by Liu Xinpeng 06 Jan '22
06 Jan '22
From: Alan Maguire <alan.maguire(a)oracle.com>
mainline inclusion
from mainline-v5.10.78
commit ac5a72ea5c8989871e61f6bb0852e0f91de51ebe
category: bugfix
bugzilla: https://gitee.com/openeuler/kernel/issues/I4PKDW
CVE: NA
--------------------------------
The bpf helper bpf_trace_printk() uses trace_printk() under the hood.
This leads to an alarming warning message originating from trace
buffer allocation which occurs the first time a program using
bpf_trace_printk() is loaded.
We can instead create a trace event for bpf_trace_printk() and enable
it in-kernel when/if we encounter a program using the
bpf_trace_printk() helper. With this approach, trace_printk()
is not used directly and no warning message appears.
This work was started by Steven (see Link) and finished by Alan; added
Steven's Signed-off-by with his permission.
Signed-off-by: Steven Rostedt (VMware) <rostedt(a)goodmis.org>
Signed-off-by: Alan Maguire <alan.maguire(a)oracle.com>
Signed-off-by: Alexei Starovoitov <ast(a)kernel.org>
Acked-by: Andrii Nakryiko <andriin(a)fb.com>
Link: https://lore.kernel.org/r/20200628194334.6238b933@oasis.local.home
Link: https://lore.kernel.org/bpf/1594641154-18897-2-git-send-email-alan.maguire@…
Signed-off-by: Liu Xinpeng <liuxp11(a)chinatelecom.cn> # openEuler_contributor
Signed-off-by: Ctyun Kernel <ctyuncommiter01(a)chinatelecom.cn> # openEuler_contributor
---
kernel/trace/Makefile | 2 ++
kernel/trace/bpf_trace.c | 42 +++++++++++++++++++++++++++++++++++++-----
kernel/trace/bpf_trace.h | 34 ++++++++++++++++++++++++++++++++++
3 files changed, 73 insertions(+), 5 deletions(-)
create mode 100644 kernel/trace/bpf_trace.h
diff --git a/kernel/trace/Makefile b/kernel/trace/Makefile
index f81dadbc7..846b6b0 100644
--- a/kernel/trace/Makefile
+++ b/kernel/trace/Makefile
@@ -28,6 +28,8 @@ ifdef CONFIG_GCOV_PROFILE_FTRACE
GCOV_PROFILE := y
endif
+CFLAGS_bpf_trace.o := -I$(src)
+
CFLAGS_trace_benchmark.o := -I$(src)
CFLAGS_trace_events_filter.o := -I$(src)
diff --git a/kernel/trace/bpf_trace.c b/kernel/trace/bpf_trace.c
index e0b0e92..f359f79 100644
--- a/kernel/trace/bpf_trace.c
+++ b/kernel/trace/bpf_trace.c
@@ -11,12 +11,16 @@
#include <linux/uaccess.h>
#include <linux/ctype.h>
#include <linux/kprobes.h>
+#include <linux/spinlock.h>
#include <linux/syscalls.h>
#include <linux/error-injection.h>
#include "trace_probe.h"
#include "trace.h"
+#define CREATE_TRACE_POINTS
+#include "bpf_trace.h"
+
#ifdef CONFIG_MODULES
struct bpf_trace_module {
struct module *module;
@@ -318,6 +322,30 @@ static const struct bpf_func_proto *bpf_get_probe_write_proto(void)
return &bpf_probe_write_user_proto;
}
+static DEFINE_RAW_SPINLOCK(trace_printk_lock);
+
+#define BPF_TRACE_PRINTK_SIZE 1024
+
+static inline __printf(1, 0) int bpf_do_trace_printk(const char *fmt, ...)
+{
+ static char buf[BPF_TRACE_PRINTK_SIZE];
+ unsigned long flags;
+ va_list ap;
+ int ret;
+
+ raw_spin_lock_irqsave(&trace_printk_lock, flags);
+ va_start(ap, fmt);
+ ret = vsnprintf(buf, sizeof(buf), fmt, ap);
+ va_end(ap);
+ /* vsnprintf() will not append null for zero-length strings */
+ if (ret == 0)
+ buf[0] = '\0';
+ trace_bpf_trace_printk(buf);
+ raw_spin_unlock_irqrestore(&trace_printk_lock, flags);
+
+ return ret;
+}
+
/*
* Only limited trace_printk() conversion specifiers allowed:
* %d %i %u %x %ld %li %lu %lx %lld %lli %llu %llx %p %s
@@ -408,8 +436,7 @@ static const struct bpf_func_proto *bpf_get_probe_write_proto(void)
*/
#define __BPF_TP_EMIT() __BPF_ARG3_TP()
#define __BPF_TP(...) \
- __trace_printk(0 /* Fake ip */, \
- fmt, ##__VA_ARGS__)
+ bpf_do_trace_printk(fmt, ##__VA_ARGS__)
#define __BPF_ARG1_TP(...) \
((mod[0] == 2 || (mod[0] == 1 && __BITS_PER_LONG == 64)) \
@@ -446,10 +473,15 @@ static const struct bpf_func_proto *bpf_get_probe_write_proto(void)
const struct bpf_func_proto *bpf_get_trace_printk_proto(void)
{
/*
- * this program might be calling bpf_trace_printk,
- * so allocate per-cpu printk buffers
+ * This program might be calling bpf_trace_printk,
+ * so enable the associated bpf_trace/bpf_trace_printk event.
+ * Repeat this each time as it is possible a user has
+ * disabled bpf_trace_printk events. By loading a program
+ * calling bpf_trace_printk() however the user has expressed
+ * the intent to see such events.
*/
- trace_printk_init_buffers();
+ if (trace_set_clr_event("bpf_trace", "bpf_trace_printk", 1))
+ pr_warn_ratelimited("could not enable bpf_trace_printk events");
return &bpf_trace_printk_proto;
}
diff --git a/kernel/trace/bpf_trace.h b/kernel/trace/bpf_trace.h
new file mode 100644
index 00000000..9acbc11
--- /dev/null
+++ b/kernel/trace/bpf_trace.h
@@ -0,0 +1,34 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM bpf_trace
+
+#if !defined(_TRACE_BPF_TRACE_H) || defined(TRACE_HEADER_MULTI_READ)
+
+#define _TRACE_BPF_TRACE_H
+
+#include <linux/tracepoint.h>
+
+TRACE_EVENT(bpf_trace_printk,
+
+ TP_PROTO(const char *bpf_string),
+
+ TP_ARGS(bpf_string),
+
+ TP_STRUCT__entry(
+ __string(bpf_string, bpf_string)
+ ),
+
+ TP_fast_assign(
+ __assign_str(bpf_string, bpf_string);
+ ),
+
+ TP_printk("%s", __get_str(bpf_string))
+);
+
+#endif /* _TRACE_BPF_TRACE_H */
+
+#undef TRACE_INCLUDE_PATH
+#define TRACE_INCLUDE_PATH .
+#define TRACE_INCLUDE_FILE bpf_trace
+
+#include <trace/define_trace.h>
--
1.8.3.1
1
2
06 Jan '22
Ramaxel inclusion
category: features
bugzilla: https://gitee.com/openeuler/kernel/issues/I4JXCG
CVE: NA
Changes:
1. Use bsg module to replace with ioctrl
2. Split scmd_tmout_nonpt into two parameters:
scmd_tmout_vd/scmd_tmout_rawdisk
3. Return -ETIME instead of -EINVAL when command is timeout.
4. Add one module parameters: max_io_force.
5. Remove some unnecessary module parameters.
6. Report disks by the order of channel/target id.
7. Add host_reset handler.
8. Use get_unaligned_be24.
Signed-off-by: Yanling Song <songyl(a)ramaxel.com>
Reviewed-by: Jiang Yu<yujiang(a)ramaxel.com>
---
drivers/scsi/spraid/Kconfig | 6 +-
drivers/scsi/spraid/spraid.h | 142 ++-
drivers/scsi/spraid/spraid_main.c | 1633 +++++++++++++++--------------
3 files changed, 968 insertions(+), 813 deletions(-)
diff --git a/drivers/scsi/spraid/Kconfig b/drivers/scsi/spraid/Kconfig
index 83962efaab07..bfbba3db8db0 100644
--- a/drivers/scsi/spraid/Kconfig
+++ b/drivers/scsi/spraid/Kconfig
@@ -5,7 +5,9 @@
config RAMAXEL_SPRAID
tristate "Ramaxel spraid Adapter"
depends on PCI && SCSI
+ select BLK_DEV_BSGLIB
depends on ARM64 || X86_64
- default m
help
- This driver supports Ramaxel spraid driver.
+ This driver supports Ramaxel SPRxxx serial
+ raid controller, which has PCIE Gen4 interface
+ with host and supports SAS/SATA Hdd/ssd.
diff --git a/drivers/scsi/spraid/spraid.h b/drivers/scsi/spraid/spraid.h
index da46d8e1b4b6..983d7af2faa8 100644
--- a/drivers/scsi/spraid/spraid.h
+++ b/drivers/scsi/spraid/spraid.h
@@ -1,4 +1,5 @@
/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */
#ifndef __SPRAID_H_
#define __SPRAID_H_
@@ -24,7 +25,7 @@
#define SENSE_SIZE(depth) ((depth) * SCSI_SENSE_BUFFERSIZE)
#define SPRAID_AQ_DEPTH 128
-#define SPRAID_NR_AEN_COMMANDS 1
+#define SPRAID_NR_AEN_COMMANDS 16
#define SPRAID_AQ_BLK_MQ_DEPTH (SPRAID_AQ_DEPTH - SPRAID_NR_AEN_COMMANDS)
#define SPRAID_AQ_MQ_TAG_DEPTH (SPRAID_AQ_BLK_MQ_DEPTH - 1)
@@ -44,7 +45,7 @@
#define SMALL_POOL_SIZE 256
#define MAX_SMALL_POOL_NUM 16
-#define MAX_CMD_PER_DEV 32
+#define MAX_CMD_PER_DEV 64
#define MAX_CDB_LEN 32
#define SPRAID_UP_TO_MULTY4(x) (((x) + 4) & (~0x03))
@@ -53,7 +54,7 @@
#define PCI_VENDOR_ID_RAMAXEL_LOGIC 0x1E81
-#define SPRAID_SERVER_DEVICE_HAB_DID 0x2100
+#define SPRAID_SERVER_DEVICE_HBA_DID 0x2100
#define SPRAID_SERVER_DEVICE_RAID_DID 0x2200
#define IO_6_DEFAULT_TX_LEN 256
@@ -142,11 +143,15 @@ enum {
enum {
SPRAID_AEN_DEV_CHANGED = 0x00,
+ SPRAID_AEN_FW_ACT_START = 0x01,
SPRAID_AEN_HOST_PROBING = 0x10,
};
enum {
- SPRAID_AEN_TIMESYN = 0x07
+ SPRAID_AEN_TIMESYN = 0x00,
+ SPRAID_AEN_FW_ACT_FINISH = 0x02,
+ SPRAID_AEN_EVENT_MIN = 0x80,
+ SPRAID_AEN_EVENT_MAX = 0xff,
};
enum {
@@ -175,6 +180,16 @@ enum spraid_state {
SPRAID_DEAD,
};
+enum {
+ SPRAID_CARD_HBA,
+ SPRAID_CARD_RAID,
+};
+
+enum spraid_cmd_type {
+ SPRAID_CMD_ADM,
+ SPRAID_CMD_IOPT,
+};
+
struct spraid_completion {
__le32 result;
union {
@@ -217,8 +232,6 @@ struct spraid_dev {
struct dma_pool *prp_page_pool;
struct dma_pool *prp_small_pool[MAX_SMALL_POOL_NUM];
mempool_t *iod_mempool;
- struct blk_mq_tag_set admin_tagset;
- struct request_queue *admin_q;
void __iomem *bar;
u32 max_qid;
u32 num_vecs;
@@ -232,23 +245,27 @@ struct spraid_dev {
u32 ctrl_config;
u32 online_queues;
u64 cap;
- struct device ctrl_device;
- struct cdev cdev;
int instance;
struct spraid_ctrl_info *ctrl_info;
struct spraid_dev_info *devices;
- struct spraid_ioq_ptcmd *ioq_ptcmds;
+ struct spraid_cmd *adm_cmds;
+ struct list_head adm_cmd_list;
+ spinlock_t adm_cmd_lock;
+
+ struct spraid_cmd *ioq_ptcmds;
struct list_head ioq_pt_list;
spinlock_t ioq_pt_lock;
- struct work_struct aen_work;
struct work_struct scan_work;
struct work_struct timesyn_work;
struct work_struct reset_work;
+ struct work_struct fw_act_work;
enum spraid_state state;
spinlock_t state_lock;
+
+ struct request_queue *bsg_queue;
};
struct spraid_sgl_desc {
@@ -347,6 +364,35 @@ struct spraid_get_info {
__u32 rsvd12[4];
};
+struct spraid_usr_cmd {
+ __u8 opcode;
+ __u8 flags;
+ __u16 command_id;
+ __le32 hdid;
+ union {
+ struct {
+ __le16 subopcode;
+ __le16 rsvd1;
+ } info_0;
+ __le32 cdw2;
+ };
+ union {
+ struct {
+ __le16 data_len;
+ __le16 param_len;
+ } info_1;
+ __le32 cdw3;
+ };
+ __u64 metadata;
+ union spraid_data_ptr dptr;
+ __le32 cdw10;
+ __le32 cdw11;
+ __le32 cdw12;
+ __le32 cdw13;
+ __le32 cdw14;
+ __le32 cdw15;
+};
+
enum {
SPRAID_CMD_FLAG_SGL_METABUF = (1 << 6),
SPRAID_CMD_FLAG_SGL_METASEG = (1 << 7),
@@ -393,6 +439,7 @@ struct spraid_admin_command {
struct spraid_get_info get_info;
struct spraid_abort_cmd abort;
struct spraid_reset_cmd reset;
+ struct spraid_usr_cmd usr_cmd;
};
};
@@ -456,9 +503,6 @@ struct spraid_ioq_command {
};
};
-#define SPRAID_IOCTL_RESET_CMD _IOWR('N', 0x80, struct spraid_passthru_common_cmd)
-#define SPRAID_IOCTL_ADMIN_CMD _IOWR('N', 0x41, struct spraid_passthru_common_cmd)
-
struct spraid_passthru_common_cmd {
__u8 opcode;
__u8 flags;
@@ -494,8 +538,6 @@ struct spraid_passthru_common_cmd {
__u32 result1;
};
-#define SPRAID_IOCTL_IOQ_CMD _IOWR('N', 0x42, struct spraid_ioq_passthru_cmd)
-
struct spraid_ioq_passthru_cmd {
__u8 opcode;
__u8 flags;
@@ -560,7 +602,21 @@ struct spraid_ioq_passthru_cmd {
__u32 result1;
};
-struct spraid_ioq_ptcmd {
+struct spraid_bsg_request {
+ u32 msgcode;
+ u32 control;
+ union {
+ struct spraid_passthru_common_cmd admcmd;
+ struct spraid_ioq_passthru_cmd ioqcmd;
+ };
+};
+
+enum {
+ SPRAID_BSG_ADM,
+ SPRAID_BSG_IOQ,
+};
+
+struct spraid_cmd {
int qid;
int cid;
u32 result0;
@@ -572,14 +628,6 @@ struct spraid_ioq_ptcmd {
struct list_head list;
};
-struct spraid_admin_request {
- struct spraid_admin_command *cmd;
- u32 result0;
- u32 result1;
- u16 flags;
- u16 status;
-};
-
struct spraid_queue {
struct spraid_dev *hdev;
spinlock_t sq_lock; /* spinlock for lock handling */
@@ -607,7 +655,6 @@ struct spraid_queue {
};
struct spraid_iod {
- struct spraid_admin_request req;
struct spraid_queue *spraidq;
enum spraid_cmd_state state;
int npages;
@@ -623,13 +670,51 @@ struct spraid_iod {
};
#define SPRAID_DEV_INFO_ATTR_BOOT(attr) ((attr) & 0x01)
-#define SPRAID_DEV_INFO_ATTR_HDD(attr) ((attr) & 0x02)
+#define SPRAID_DEV_INFO_ATTR_VD(attr) (((attr) & 0x02) == 0x0)
#define SPRAID_DEV_INFO_ATTR_PT(attr) (((attr) & 0x22) == 0x02)
#define SPRAID_DEV_INFO_ATTR_RAWDISK(attr) ((attr) & 0x20)
#define SPRAID_DEV_INFO_FLAG_VALID(flag) ((flag) & 0x01)
#define SPRAID_DEV_INFO_FLAG_CHANGE(flag) ((flag) & 0x02)
+#define BGTASK_TYPE_REBUILD 4
+#define USR_CMD_READ 0xc2
+#define USR_CMD_RDLEN 0x1000
+#define USR_CMD_VDINFO 0x704
+#define USR_CMD_BGTASK 0x504
+#define VDINFO_PARAM_LEN 0x04
+
+struct spraid_vd_info {
+ __u8 name[32];
+ __le16 id;
+ __u8 rg_id;
+ __u8 rg_level;
+ __u8 sg_num;
+ __u8 sg_disk_num;
+ __u8 vd_status;
+ __u8 vd_type;
+ __u8 rsvd1[4056];
+};
+
+#define MAX_REALTIME_BGTASK_NUM 32
+
+struct bgtask_info {
+ __u8 type;
+ __u8 progress;
+ __u8 rate;
+ __u8 rsvd0;
+ __le16 vd_id;
+ __le16 time_left;
+ __u8 rsvd1[4];
+};
+
+struct spraid_bgtask {
+ __u8 sw;
+ __u8 task_num;
+ __u8 rsvd[6];
+ struct bgtask_info bgtask[MAX_REALTIME_BGTASK_NUM];
+};
+
struct spraid_dev_info {
__le32 hdid;
__le16 target;
@@ -649,6 +734,11 @@ struct spraid_dev_list {
struct spraid_sdev_hostdata {
u32 hdid;
+ u16 max_io_kb;
+ u8 attr;
+ u8 flag;
+ u8 rg_id;
+ u8 rsvd[3];
};
#endif
diff --git a/drivers/scsi/spraid/spraid_main.c b/drivers/scsi/spraid/spraid_main.c
index a0a75ecb0027..c6d2a0b8e35e 100644
--- a/drivers/scsi/spraid/spraid_main.c
+++ b/drivers/scsi/spraid/spraid_main.c
@@ -1,8 +1,8 @@
// SPDX-License-Identifier: GPL-2.0
-/*
- * Linux spraid device driver
- * Copyright(c) 2021 Ramaxel Memory Technology, Ltd
- */
+/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */
+
+/* Ramaxel Raid SPXXX Series Linux Driver */
+
#define pr_fmt(fmt) "spraid: " fmt
#include <linux/sched/signal.h>
@@ -23,6 +23,9 @@
#include <linux/debugfs.h>
#include <linux/io-64-nonatomic-lo-hi.h>
#include <linux/blkdev.h>
+#include <linux/bsg-lib.h>
+#include <asm/unaligned.h>
+#include <linux/sort.h>
#include <scsi/scsi.h>
#include <scsi/scsi_cmnd.h>
@@ -31,27 +34,24 @@
#include <scsi/scsi_transport.h>
#include <scsi/scsi_dbg.h>
+
#include "spraid.h"
static u32 admin_tmout = 60;
module_param(admin_tmout, uint, 0644);
MODULE_PARM_DESC(admin_tmout, "admin commands timeout (seconds)");
-static u32 scmd_tmout_pt = 30;
-module_param(scmd_tmout_pt, uint, 0644);
-MODULE_PARM_DESC(scmd_tmout_pt, "scsi commands timeout for passthrough(seconds)");
+static u32 scmd_tmout_rawdisk = 180;
+module_param(scmd_tmout_rawdisk, uint, 0644);
+MODULE_PARM_DESC(scmd_tmout_rawdisk, "scsi commands timeout for rawdisk(seconds)");
-static u32 scmd_tmout_nonpt = 180;
-module_param(scmd_tmout_nonpt, uint, 0644);
-MODULE_PARM_DESC(scmd_tmout_nonpt, "scsi commands timeout for rawdisk&raid(seconds)");
+static u32 scmd_tmout_vd = 180;
+module_param(scmd_tmout_vd, uint, 0644);
+MODULE_PARM_DESC(scmd_tmout_vd, "scsi commands timeout for vd(seconds)");
-static u32 wait_abl_tmout = 3;
-module_param(wait_abl_tmout, uint, 0644);
-MODULE_PARM_DESC(wait_abl_tmout, "wait abnormal io timeout(seconds)");
-
-static bool use_sgl_force;
-module_param(use_sgl_force, bool, 0644);
-MODULE_PARM_DESC(use_sgl_force, "force IO use sgl format, default false");
+static bool max_io_force;
+module_param(max_io_force, bool, 0644);
+MODULE_PARM_DESC(max_io_force, "force max_hw_sectors_kb = 1024, default false(performance first)");
static int ioq_depth_set(const char *val, const struct kernel_param *kp);
static const struct kernel_param_ops ioq_depth_ops = {
@@ -106,16 +106,20 @@ static const struct kernel_param_ops small_pool_num_ops = {
.get = param_get_byte,
};
+/* It was found that the spindlock of a single pool conflicts
+ * a lot with multiple CPUs.So multiple pools are introduced
+ * to reduce the conflictions.
+ */
static unsigned char small_pool_num = 4;
module_param_cb(small_pool_num, &small_pool_num_ops, &small_pool_num, 0644);
MODULE_PARM_DESC(small_pool_num, "set prp small pool num, default 4, MAX 16");
static void spraid_free_queue(struct spraid_queue *spraidq);
static void spraid_handle_aen_notice(struct spraid_dev *hdev, u32 result);
-static void spraid_handle_aen_vs(struct spraid_dev *hdev, u32 result);
+static void spraid_handle_aen_vs(struct spraid_dev *hdev, u32 result, u32 result1);
static DEFINE_IDA(spraid_instance_ida);
-static dev_t spraid_chr_devt;
+
static struct class *spraid_class;
#define SPRAID_CAP_TIMEOUT_UNIT_MS (HZ / 2)
@@ -131,9 +135,8 @@ static struct workqueue_struct *spraid_wq;
#define SPRAID_DRV_VERSION "1.0.0.0"
#define ADMIN_TIMEOUT (admin_tmout * HZ)
-#define ADMIN_ERR_TIMEOUT 32757
-#define SPRAID_WAIT_ABNL_CMD_TIMEOUT (wait_abl_tmout * 2)
+#define SPRAID_WAIT_ABNL_CMD_TIMEOUT (3 * 2)
#define SPRAID_DMA_MSK_BIT_MAX 64
@@ -147,6 +150,13 @@ enum FW_STAT_CODE {
FW_STAT_NEED_RETRY
};
+static const char * const raid_levels[] = {"0", "1", "5", "6", "10", "50", "60", "NA"};
+
+static const char * const raid_states[] = {
+ "NA", "NORMAL", "FAULT", "DEGRADE", "NOT_FORMATTED", "FORMATTING", "SANITIZING",
+ "INITIALIZING", "INITIALIZE_FAIL", "DELETING", "DELETE_FAIL", "WRITE_PROTECT"
+};
+
static int ioq_depth_set(const char *val, const struct kernel_param *kp)
{
int n = 0;
@@ -231,12 +241,6 @@ static int spraid_pci_enable(struct spraid_dev *hdev)
goto disable;
}
- ret = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_ALL_TYPES);
- if (ret < 0) {
- dev_err(hdev->dev, "Allocate one IRQ for setup admin channel failed\n");
- goto disable;
- }
-
hdev->cap = lo_hi_readq(hdev->bar + SPRAID_REG_CAP);
hdev->ioq_depth = min_t(u32, SPRAID_CAP_MQES(hdev->cap) + 1, io_queue_depth);
hdev->db_stride = 1 << SPRAID_CAP_STRIDE(hdev->cap);
@@ -246,13 +250,20 @@ static int spraid_pci_enable(struct spraid_dev *hdev)
dev_err(hdev->dev, "err, dma mask invalid[%llu], set to default\n", maskbit);
maskbit = SPRAID_DMA_MSK_BIT_MAX;
}
- if (dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(maskbit))) {
+ if (dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(maskbit)) &&
+ dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32))) {
dev_err(hdev->dev, "set dma mask and coherent failed\n");
goto disable;
}
dev_info(hdev->dev, "set dma mask[%llu] success\n", maskbit);
+ ret = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_ALL_TYPES);
+ if (ret < 0) {
+ dev_err(hdev->dev, "Allocate one IRQ for setup admin channel failed\n");
+ goto disable;
+ }
+
pci_enable_pcie_error_reporting(pdev);
pci_save_state(pdev);
@@ -263,12 +274,6 @@ static int spraid_pci_enable(struct spraid_dev *hdev)
return ret;
}
-static inline
-struct spraid_admin_request *spraid_admin_req(struct request *req)
-{
- return blk_mq_rq_to_pdu(req);
-}
-
static int spraid_npages_prp(u32 size, struct spraid_dev *hdev)
{
u32 nprps = DIV_ROUND_UP(size + hdev->page_size, hdev->page_size);
@@ -419,7 +424,7 @@ static void spraid_submit_cmd(struct spraid_queue *spraidq, const void *cmd)
writel(spraidq->sq_tail, spraidq->q_db);
spin_unlock_irqrestore(&spraidq->sq_lock, flags);
- dev_log_dbg(spraidq->hdev->dev, "cid[%d], qid[%d], opcode[0x%x], flags[0x%x], hdid[%u]\n",
+ dev_log_dbg(spraidq->hdev->dev, "cid[%d] qid[%d], opcode[0x%x], flags[0x%x], hdid[%u]\n",
acd->command_id, spraidq->qid, acd->opcode, acd->flags, le32_to_cpu(acd->hdid));
}
@@ -605,18 +610,15 @@ static void spraid_setup_rw_cmd(struct spraid_dev *hdev,
if (scmd->cmd_len == 6) {
datalength = (u32)(scmd->cmnd[4] == 0 ?
IO_6_DEFAULT_TX_LEN : scmd->cmnd[4]);
- start_lba_lo = ((u32)scmd->cmnd[1] << 16) |
- ((u32)scmd->cmnd[2] << 8) | (u32)scmd->cmnd[3];
+ start_lba_lo = (u32)get_unaligned_be24(&scmd->cmnd[1]);
start_lba_lo &= 0x1FFFFF;
}
/* 10-byte READ(0x28) or WRITE(0x2A) cdb */
else if (scmd->cmd_len == 10) {
- datalength = (u32)scmd->cmnd[8] | ((u32)scmd->cmnd[7] << 8);
- start_lba_lo = ((u32)scmd->cmnd[2] << 24) |
- ((u32)scmd->cmnd[3] << 16) |
- ((u32)scmd->cmnd[4] << 8) | (u32)scmd->cmnd[5];
+ datalength = (u32)get_unaligned_be16(&scmd->cmnd[7]);
+ start_lba_lo = get_unaligned_be32(&scmd->cmnd[2]);
if (scmd->cmnd[1] & FUA_MASK)
control |= SPRAID_RW_FUA;
@@ -624,42 +626,26 @@ static void spraid_setup_rw_cmd(struct spraid_dev *hdev,
/* 12-byte READ(0xA8) or WRITE(0xAA) cdb */
else if (scmd->cmd_len == 12) {
- datalength = ((u32)scmd->cmnd[6] << 24) |
- ((u32)scmd->cmnd[7] << 16) |
- ((u32)scmd->cmnd[8] << 8) | (u32)scmd->cmnd[9];
- start_lba_lo = ((u32)scmd->cmnd[2] << 24) |
- ((u32)scmd->cmnd[3] << 16) |
- ((u32)scmd->cmnd[4] << 8) | (u32)scmd->cmnd[5];
+ datalength = get_unaligned_be32(&scmd->cmnd[6]);
+ start_lba_lo = get_unaligned_be32(&scmd->cmnd[2]);
if (scmd->cmnd[1] & FUA_MASK)
control |= SPRAID_RW_FUA;
}
/* 16-byte READ(0x88) or WRITE(0x8A) cdb */
else if (scmd->cmd_len == 16) {
- datalength = ((u32)scmd->cmnd[10] << 24) |
- ((u32)scmd->cmnd[11] << 16) |
- ((u32)scmd->cmnd[12] << 8) | (u32)scmd->cmnd[13];
- start_lba_lo = ((u32)scmd->cmnd[6] << 24) |
- ((u32)scmd->cmnd[7] << 16) |
- ((u32)scmd->cmnd[8] << 8) | (u32)scmd->cmnd[9];
- start_lba_hi = ((u32)scmd->cmnd[2] << 24) |
- ((u32)scmd->cmnd[3] << 16) |
- ((u32)scmd->cmnd[4] << 8) | (u32)scmd->cmnd[5];
+ datalength = get_unaligned_be32(&scmd->cmnd[10]);
+ start_lba_lo = get_unaligned_be32(&scmd->cmnd[6]);
+ start_lba_hi = get_unaligned_be32(&scmd->cmnd[2]);
if (scmd->cmnd[1] & FUA_MASK)
control |= SPRAID_RW_FUA;
}
/* 32-byte READ(0x88) or WRITE(0x8A) cdb */
else if (scmd->cmd_len == 32) {
- datalength = ((u32)scmd->cmnd[28] << 24) |
- ((u32)scmd->cmnd[29] << 16) |
- ((u32)scmd->cmnd[30] << 8) | (u32)scmd->cmnd[31];
- start_lba_lo = ((u32)scmd->cmnd[16] << 24) |
- ((u32)scmd->cmnd[17] << 16) |
- ((u32)scmd->cmnd[18] << 8) | (u32)scmd->cmnd[19];
- start_lba_hi = ((u32)scmd->cmnd[12] << 24) |
- ((u32)scmd->cmnd[13] << 16) |
- ((u32)scmd->cmnd[14] << 8) | (u32)scmd->cmnd[15];
+ datalength = get_unaligned_be32(&scmd->cmnd[28]);
+ start_lba_lo = get_unaligned_be32(&scmd->cmnd[16]);
+ start_lba_hi = get_unaligned_be32(&scmd->cmnd[12]);
if (scmd->cmnd[10] & FUA_MASK)
control |= SPRAID_RW_FUA;
@@ -814,7 +800,7 @@ static void spraid_map_status(struct spraid_iod *iod, struct scsi_cmnd *scmd,
if (scmd->result & SAM_STAT_CHECK_CONDITION) {
memset(scmd->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE);
memcpy(scmd->sense_buffer, iod->sense, SCSI_SENSE_BUFFERSIZE);
- set_driver_byte(scmd, DRIVER_SENSE);
+ scmd->result = (scmd->result & 0x00ffffff) | (DRIVER_SENSE << 24);
}
break;
case FW_STAT_ABORTED:
@@ -825,6 +811,8 @@ static void spraid_map_status(struct spraid_iod *iod, struct scsi_cmnd *scmd,
break;
default:
set_host_byte(scmd, DID_BAD_TARGET);
+ dev_warn(iod->spraidq->hdev->dev, "[%s] cid[%d] qid[%d] bad status[0x%x]\n",
+ __func__, cqe->cmd_id, le16_to_cpu(cqe->sq_id), le16_to_cpu(cqe->status));
break;
}
}
@@ -850,14 +838,13 @@ static int spraid_queue_command(struct Scsi_Host *shost, struct scsi_cmnd *scmd)
int ret;
if (unlikely(!scmd)) {
- dev_err(hdev->dev, "err, scmd is null, return 0\n");
+ dev_err(hdev->dev, "err, scmd is null\n");
return 0;
}
if (unlikely(hdev->state != SPRAID_LIVE)) {
set_host_byte(scmd, DID_NO_CONNECT);
scmd->scsi_done(scmd);
- dev_err(hdev->dev, "[%s] err, hdev state is not live\n", __func__);
return 0;
}
@@ -894,7 +881,7 @@ static int spraid_queue_command(struct Scsi_Host *shost, struct scsi_cmnd *scmd)
WRITE_ONCE(iod->state, SPRAID_CMD_IN_FLIGHT);
spraid_submit_cmd(ioq, &ioq_cmd);
elapsed = jiffies - scmd->jiffies_at_alloc;
- dev_log_dbg(hdev->dev, "cid[%d], qid[%d] submit IO cost %3ld.%3ld seconds\n",
+ dev_log_dbg(hdev->dev, "cid[%d] qid[%d] submit IO cost %3ld.%3ld seconds\n",
cid, hwq, elapsed / HZ, elapsed % HZ);
return 0;
@@ -945,6 +932,10 @@ static int spraid_slave_alloc(struct scsi_device *sdev)
scan_host:
hostdata->hdid = le32_to_cpu(hdev->devices[idx].hdid);
+ hostdata->max_io_kb = le16_to_cpu(hdev->devices[idx].max_io_kb);
+ hostdata->attr = hdev->devices[idx].attr;
+ hostdata->flag = hdev->devices[idx].flag;
+ hostdata->rg_id = 0xff;
sdev->hostdata = hostdata;
up_read(&hdev->devices_rwsem);
return 0;
@@ -958,30 +949,17 @@ static void spraid_slave_destroy(struct scsi_device *sdev)
static int spraid_slave_configure(struct scsi_device *sdev)
{
- u16 idx;
- unsigned int timeout = scmd_tmout_nonpt * HZ;
+ unsigned int timeout = scmd_tmout_rawdisk * HZ;
struct spraid_dev *hdev = shost_priv(sdev->host);
struct spraid_sdev_hostdata *hostdata = sdev->hostdata;
u32 max_sec = sdev->host->max_sectors;
- if (!hostdata) {
- idx = hostdata->hdid - 1;
- if (sdev->channel == hdev->devices[idx].channel &&
- sdev->id == le16_to_cpu(hdev->devices[idx].target) &&
- sdev->lun < hdev->devices[idx].lun) {
- if (SPRAID_DEV_INFO_ATTR_PT(hdev->devices[idx].attr))
- timeout = scmd_tmout_pt * HZ;
- else
- timeout = scmd_tmout_nonpt * HZ;
- max_sec = le16_to_cpu(hdev->devices[idx].max_io_kb) << 1;
- } else {
- dev_err(hdev->dev, "[%s] err, sdev->channel:id:lun[%d:%d:%lld];"
- "devices[%d], channel:target:lun[%d:%d:%d]\n",
- __func__, sdev->channel, sdev->id, sdev->lun,
- idx, hdev->devices[idx].channel,
- hdev->devices[idx].target,
- hdev->devices[idx].lun);
- }
+ if (hostdata) {
+ if (SPRAID_DEV_INFO_ATTR_VD(hostdata->attr))
+ timeout = scmd_tmout_vd * HZ;
+ else if (SPRAID_DEV_INFO_ATTR_RAWDISK(hostdata->attr))
+ timeout = scmd_tmout_rawdisk * HZ;
+ max_sec = hostdata->max_io_kb << 1;
} else {
dev_err(hdev->dev, "[%s] err, sdev->hostdata is null\n", __func__);
}
@@ -991,7 +969,9 @@ static int spraid_slave_configure(struct scsi_device *sdev)
if ((max_sec == 0) || (max_sec > sdev->host->max_sectors))
max_sec = sdev->host->max_sectors;
- blk_queue_max_hw_sectors(sdev->request_queue, max_sec);
+
+ if (!max_io_force)
+ blk_queue_max_hw_sectors(sdev->request_queue, max_sec);
dev_info(hdev->dev, "[%s] sdev->channel:id:lun[%d:%d:%lld], scmd_timeout[%d]s, maxsec[%d]\n",
__func__, sdev->channel, sdev->id, sdev->lun, timeout / HZ, max_sec);
@@ -1176,6 +1156,75 @@ static inline bool spraid_cqe_pending(struct spraid_queue *spraidq)
spraidq->cq_phase;
}
+static void spraid_sata_report_zone_handle(struct scsi_cmnd *scmd, struct spraid_iod *iod)
+{
+ int i = 0;
+ unsigned int bytes = 0;
+ struct scatterlist *sg = scsi_sglist(scmd);
+
+ scsi_for_each_sg(scmd, sg, iod->nsge, i) {
+ unsigned int offset = 0;
+
+ if (bytes == 0) {
+ char *hdr;
+ u32 list_length;
+ u64 max_lba, opt_lba;
+ u16 same;
+
+ hdr = sg_virt(sg);
+
+ list_length = get_unaligned_le32(&hdr[0]);
+ same = get_unaligned_le16(&hdr[4]);
+ max_lba = get_unaligned_le64(&hdr[8]);
+ opt_lba = get_unaligned_le64(&hdr[16]);
+ put_unaligned_be32(list_length, &hdr[0]);
+ hdr[4] = same & 0xf;
+ put_unaligned_be64(max_lba, &hdr[8]);
+ put_unaligned_be64(opt_lba, &hdr[16]);
+ offset += 64;
+ bytes += 64;
+ }
+ while (offset < sg_dma_len(sg)) {
+ char *rec;
+ u8 cond, type, non_seq, reset;
+ u64 size, start, wp;
+
+ rec = sg_virt(sg) + offset;
+ type = rec[0] & 0xf;
+ cond = (rec[1] >> 4) & 0xf;
+ non_seq = (rec[1] & 2);
+ reset = (rec[1] & 1);
+ size = get_unaligned_le64(&rec[8]);
+ start = get_unaligned_le64(&rec[16]);
+ wp = get_unaligned_le64(&rec[24]);
+ rec[0] = type;
+ rec[1] = (cond << 4) | non_seq | reset;
+ put_unaligned_be64(size, &rec[8]);
+ put_unaligned_be64(start, &rec[16]);
+ put_unaligned_be64(wp, &rec[24]);
+ WARN_ON(offset + 64 > sg_dma_len(sg));
+ offset += 64;
+ bytes += 64;
+ }
+ }
+}
+
+static inline void spraid_handle_ata_cmd(struct spraid_dev *hdev, struct scsi_cmnd *scmd,
+ struct spraid_iod *iod)
+{
+ if (hdev->ctrl_info->card_type != SPRAID_CARD_HBA)
+ return;
+
+ switch (scmd->cmnd[0]) {
+ case ZBC_IN:
+ dev_info(hdev->dev, "[%s] process report zone\n", __func__);
+ spraid_sata_report_zone_handle(scmd, iod);
+ break;
+ default:
+ break;
+ }
+}
+
static void spraid_complete_ioq_cmnd(struct spraid_queue *ioq, struct spraid_completion *cqe)
{
struct spraid_dev *hdev = ioq->hdev;
@@ -1197,12 +1246,12 @@ static void spraid_complete_ioq_cmnd(struct spraid_queue *ioq, struct spraid_com
iod = scsi_cmd_priv(scmd);
elapsed = jiffies - scmd->jiffies_at_alloc;
- dev_log_dbg(hdev->dev, "cid[%d], qid[%d] finish IO cost %3ld.%3ld seconds\n",
+ dev_log_dbg(hdev->dev, "cid[%d] qid[%d] finish IO cost %3ld.%3ld seconds\n",
cqe->cmd_id, ioq->qid, elapsed / HZ, elapsed % HZ);
if (cmpxchg(&iod->state, SPRAID_CMD_IN_FLIGHT, SPRAID_CMD_COMPLETE) !=
SPRAID_CMD_IN_FLIGHT) {
- dev_warn(hdev->dev, "cid[%d], qid[%d] enters abnormal handler, cost %3ld.%3ld seconds\n",
+ dev_warn(hdev->dev, "cid[%d] qid[%d] enters abnormal handler, cost %3ld.%3ld seconds\n",
cqe->cmd_id, ioq->qid, elapsed / HZ, elapsed % HZ);
WRITE_ONCE(iod->state, SPRAID_CMD_TMO_COMPLETE);
@@ -1215,6 +1264,8 @@ static void spraid_complete_ioq_cmnd(struct spraid_queue *ioq, struct spraid_com
return;
}
+ spraid_handle_ata_cmd(hdev, scmd, iod);
+
spraid_map_status(iod, scmd, cqe);
if (iod->nsge) {
iod->nsge = 0;
@@ -1224,38 +1275,36 @@ static void spraid_complete_ioq_cmnd(struct spraid_queue *ioq, struct spraid_com
scmd->scsi_done(scmd);
}
-static inline void spraid_end_admin_request(struct request *req, __le16 status,
- __le32 result0, __le32 result1)
-{
- struct spraid_admin_request *rq = spraid_admin_req(req);
-
- rq->status = le16_to_cpu(status) >> 1;
- rq->result0 = le32_to_cpu(result0);
- rq->result1 = le32_to_cpu(result1);
- blk_mq_complete_request(req);
-}
-
static void spraid_complete_adminq_cmnd(struct spraid_queue *adminq, struct spraid_completion *cqe)
{
- struct blk_mq_tags *tags = adminq->hdev->admin_tagset.tags[0];
- struct request *req;
+ struct spraid_dev *hdev = adminq->hdev;
+ struct spraid_cmd *adm_cmd;
- req = blk_mq_tag_to_rq(tags, cqe->cmd_id);
- if (unlikely(!req)) {
+ adm_cmd = hdev->adm_cmds + cqe->cmd_id;
+ if (unlikely(adm_cmd->state == SPRAID_CMD_IDLE)) {
dev_warn(adminq->hdev->dev, "Invalid id %d completed on queue %d\n",
cqe->cmd_id, le16_to_cpu(cqe->sq_id));
return;
}
- spraid_end_admin_request(req, cqe->status, cqe->result, cqe->result1);
+
+ adm_cmd->status = le16_to_cpu(cqe->status) >> 1;
+ adm_cmd->result0 = le32_to_cpu(cqe->result);
+ adm_cmd->result1 = le32_to_cpu(cqe->result1);
+
+ complete(&adm_cmd->cmd_done);
}
+static void spraid_send_aen(struct spraid_dev *hdev, u16 cid);
+
static void spraid_complete_aen(struct spraid_queue *spraidq, struct spraid_completion *cqe)
{
struct spraid_dev *hdev = spraidq->hdev;
u32 result = le32_to_cpu(cqe->result);
- dev_info(hdev->dev, "rcv aen, status[%x], result[%x]\n",
- le16_to_cpu(cqe->status) >> 1, result);
+ dev_info(hdev->dev, "rcv aen, cid[%d], status[0x%x], result[0x%x]\n",
+ cqe->cmd_id, le16_to_cpu(cqe->status) >> 1, result);
+
+ spraid_send_aen(hdev, cqe->cmd_id);
if ((le16_to_cpu(cqe->status) >> 1) != SPRAID_SC_SUCCESS)
return;
@@ -1264,22 +1313,19 @@ static void spraid_complete_aen(struct spraid_queue *spraidq, struct spraid_comp
spraid_handle_aen_notice(hdev, result);
break;
case SPRAID_AEN_VS:
- spraid_handle_aen_vs(hdev, result);
+ spraid_handle_aen_vs(hdev, result, le32_to_cpu(cqe->result1));
break;
default:
dev_warn(hdev->dev, "Unsupported async event type: %u\n",
result & 0x7);
break;
}
- queue_work(spraid_wq, &hdev->aen_work);
}
-static void spraid_put_ioq_ptcmd(struct spraid_dev *hdev, struct spraid_ioq_ptcmd *cmd);
-
static void spraid_complete_ioq_sync_cmnd(struct spraid_queue *ioq, struct spraid_completion *cqe)
{
struct spraid_dev *hdev = ioq->hdev;
- struct spraid_ioq_ptcmd *ptcmd;
+ struct spraid_cmd *ptcmd;
ptcmd = hdev->ioq_ptcmds + (ioq->qid - 1) * SPRAID_PTCMDS_PERQ +
cqe->cmd_id - SPRAID_IO_BLK_MQ_DEPTH;
@@ -1289,8 +1335,6 @@ static void spraid_complete_ioq_sync_cmnd(struct spraid_queue *ioq, struct sprai
ptcmd->result1 = le32_to_cpu(cqe->result1);
complete(&ptcmd->cmd_done);
-
- spraid_put_ioq_ptcmd(hdev, ptcmd);
}
static inline void spraid_handle_cqe(struct spraid_queue *spraidq, u16 idx)
@@ -1304,7 +1348,7 @@ static inline void spraid_handle_cqe(struct spraid_queue *spraidq, u16 idx)
return;
}
- dev_log_dbg(hdev->dev, "cid[%d], qid[%d], result[0x%x], sq_id[%d], status[0x%x]\n",
+ dev_log_dbg(hdev->dev, "cid[%d] qid[%d], result[0x%x], sq_id[%d], status[0x%x]\n",
cqe->cmd_id, spraidq->qid, le32_to_cpu(cqe->result),
le16_to_cpu(cqe->sq_id), le16_to_cpu(cqe->status));
@@ -1452,62 +1496,119 @@ static u32 spraid_bar_size(struct spraid_dev *hdev, u32 nr_ioqs)
return (SPRAID_REG_DBS + ((nr_ioqs + 1) * 8 * hdev->db_stride));
}
-static inline void spraid_clear_spraid_request(struct request *req)
+static int spraid_alloc_admin_cmds(struct spraid_dev *hdev)
{
- if (!(req->rq_flags & RQF_DONTPREP)) {
- spraid_admin_req(req)->flags = 0;
- req->rq_flags |= RQF_DONTPREP;
+ int i;
+
+ INIT_LIST_HEAD(&hdev->adm_cmd_list);
+ spin_lock_init(&hdev->adm_cmd_lock);
+
+ hdev->adm_cmds = kcalloc_node(SPRAID_AQ_BLK_MQ_DEPTH, sizeof(struct spraid_cmd),
+ GFP_KERNEL, hdev->numa_node);
+
+ if (!hdev->adm_cmds) {
+ dev_err(hdev->dev, "Alloc admin cmds failed\n");
+ return -ENOMEM;
+ }
+
+ for (i = 0; i < SPRAID_AQ_BLK_MQ_DEPTH; i++) {
+ hdev->adm_cmds[i].qid = 0;
+ hdev->adm_cmds[i].cid = i;
+ list_add_tail(&(hdev->adm_cmds[i].list), &hdev->adm_cmd_list);
}
+
+ dev_info(hdev->dev, "Alloc admin cmds success, num[%d]\n", SPRAID_AQ_BLK_MQ_DEPTH);
+
+ return 0;
}
-static struct request *spraid_alloc_admin_request(struct request_queue *q,
- struct spraid_admin_command *cmd,
- blk_mq_req_flags_t flags)
+static void spraid_free_admin_cmds(struct spraid_dev *hdev)
{
- u32 op = COMMAND_IS_WRITE(cmd) ? REQ_OP_DRV_OUT : REQ_OP_DRV_IN;
- struct request *req;
+ kfree(hdev->adm_cmds);
+ hdev->adm_cmds = NULL;
+ INIT_LIST_HEAD(&hdev->adm_cmd_list);
+}
+
+static struct spraid_cmd *spraid_get_cmd(struct spraid_dev *hdev, enum spraid_cmd_type type)
+{
+ struct spraid_cmd *cmd = NULL;
+ unsigned long flags;
+ struct list_head *head = &hdev->adm_cmd_list;
+ spinlock_t *slock = &hdev->adm_cmd_lock;
+
+ if (type == SPRAID_CMD_IOPT) {
+ head = &hdev->ioq_pt_list;
+ slock = &hdev->ioq_pt_lock;
+ }
+
+ spin_lock_irqsave(slock, flags);
+ if (list_empty(head)) {
+ spin_unlock_irqrestore(slock, flags);
+ dev_err(hdev->dev, "err, cmd[%d] list empty\n", type);
+ return NULL;
+ }
+ cmd = list_entry(head->next, struct spraid_cmd, list);
+ list_del_init(&cmd->list);
+ spin_unlock_irqrestore(slock, flags);
- req = blk_mq_alloc_request(q, op, flags);
- if (IS_ERR(req))
- return req;
- req->cmd_flags |= REQ_FAILFAST_DRIVER;
- spraid_clear_spraid_request(req);
- spraid_admin_req(req)->cmd = cmd;
+ WRITE_ONCE(cmd->state, SPRAID_CMD_IN_FLIGHT);
- return req;
+ return cmd;
}
-static int spraid_submit_admin_sync_cmd(struct request_queue *q,
- struct spraid_admin_command *cmd,
- u32 *result, void *buffer,
- u32 bufflen, u32 timeout, int at_head, blk_mq_req_flags_t flags)
+static void spraid_put_cmd(struct spraid_dev *hdev, struct spraid_cmd *cmd,
+ enum spraid_cmd_type type)
{
- struct request *req;
- int ret;
+ unsigned long flags;
+ struct list_head *head = &hdev->adm_cmd_list;
+ spinlock_t *slock = &hdev->adm_cmd_lock;
- req = spraid_alloc_admin_request(q, cmd, flags);
- if (IS_ERR(req))
- return PTR_ERR(req);
+ if (type == SPRAID_CMD_IOPT) {
+ head = &hdev->ioq_pt_list;
+ slock = &hdev->ioq_pt_lock;
+ }
- req->timeout = timeout ? timeout : ADMIN_TIMEOUT;
- if (buffer && bufflen) {
- ret = blk_rq_map_kern(q, req, buffer, bufflen, GFP_KERNEL);
- if (ret)
- goto out;
+ spin_lock_irqsave(slock, flags);
+ WRITE_ONCE(cmd->state, SPRAID_CMD_IDLE);
+ list_add_tail(&cmd->list, head);
+ spin_unlock_irqrestore(slock, flags);
+}
+
+
+static int spraid_submit_admin_sync_cmd(struct spraid_dev *hdev, struct spraid_admin_command *cmd,
+ u32 *result0, u32 *result1, u32 timeout)
+{
+ struct spraid_cmd *adm_cmd = spraid_get_cmd(hdev, SPRAID_CMD_ADM);
+
+ if (!adm_cmd) {
+ dev_err(hdev->dev, "err, get admin cmd failed\n");
+ return -EFAULT;
}
- blk_execute_rq(req->q, NULL, req, at_head);
- if (result)
- *result = spraid_admin_req(req)->result0;
+ timeout = timeout ? timeout : ADMIN_TIMEOUT;
- if (spraid_admin_req(req)->flags & SPRAID_REQ_CANCELLED)
- ret = -EINTR;
- else
- ret = spraid_admin_req(req)->status;
+ init_completion(&adm_cmd->cmd_done);
-out:
- blk_mq_free_request(req);
- return ret;
+ cmd->common.command_id = adm_cmd->cid;
+ spraid_submit_cmd(&hdev->queues[0], cmd);
+
+ if (!wait_for_completion_timeout(&adm_cmd->cmd_done, timeout)) {
+ dev_err(hdev->dev, "[%s] cid[%d] qid[%d] timeout, opcode[0x%x] subopcode[0x%x]\n",
+ __func__, adm_cmd->cid, adm_cmd->qid, cmd->usr_cmd.opcode,
+ cmd->usr_cmd.info_0.subopcode);
+ WRITE_ONCE(adm_cmd->state, SPRAID_CMD_TIMEOUT);
+ spraid_put_cmd(hdev, adm_cmd, SPRAID_CMD_ADM);
+ return -ETIME;
+ }
+
+ if (result0)
+ *result0 = adm_cmd->result0;
+ if (result1)
+ *result1 = adm_cmd->result1;
+
+ spraid_put_cmd(hdev, adm_cmd, SPRAID_CMD_ADM);
+
+ return adm_cmd->status;
}
static int spraid_create_cq(struct spraid_dev *hdev, u16 qid,
@@ -1524,8 +1625,7 @@ static int spraid_create_cq(struct spraid_dev *hdev, u16 qid,
admin_cmd.create_cq.cq_flags = cpu_to_le16(flags);
admin_cmd.create_cq.irq_vector = cpu_to_le16(cq_vector);
- return spraid_submit_admin_sync_cmd(hdev->admin_q, &admin_cmd, NULL,
- NULL, 0, 0, 0, 0);
+ return spraid_submit_admin_sync_cmd(hdev, &admin_cmd, NULL, NULL, 0);
}
static int spraid_create_sq(struct spraid_dev *hdev, u16 qid,
@@ -1542,8 +1642,7 @@ static int spraid_create_sq(struct spraid_dev *hdev, u16 qid,
admin_cmd.create_sq.sq_flags = cpu_to_le16(flags);
admin_cmd.create_sq.cqid = cpu_to_le16(qid);
- return spraid_submit_admin_sync_cmd(hdev->admin_q, &admin_cmd, NULL,
- NULL, 0, 0, 0, 0);
+ return spraid_submit_admin_sync_cmd(hdev, &admin_cmd, NULL, NULL, 0);
}
static void spraid_free_queue(struct spraid_queue *spraidq)
@@ -1581,8 +1680,7 @@ static int spraid_delete_queue(struct spraid_dev *hdev, u8 op, u16 id)
admin_cmd.delete_queue.opcode = op;
admin_cmd.delete_queue.qid = cpu_to_le16(id);
- ret = spraid_submit_admin_sync_cmd(hdev->admin_q, &admin_cmd, NULL,
- NULL, 0, 0, 0, 0);
+ ret = spraid_submit_admin_sync_cmd(hdev, &admin_cmd, NULL, NULL, 0);
if (ret)
dev_err(hdev->dev, "Delete %s:[%d] failed\n",
@@ -1663,19 +1761,28 @@ static int spraid_set_features(struct spraid_dev *hdev, u32 fid, u32 dword11, vo
size_t buflen, u32 *result)
{
struct spraid_admin_command admin_cmd;
- u32 res;
int ret;
+ u8 *data_ptr = NULL;
+ dma_addr_t data_dma = 0;
+
+ if (buffer && buflen) {
+ data_ptr = dma_alloc_coherent(hdev->dev, buflen, &data_dma, GFP_KERNEL);
+ if (!data_ptr)
+ return -ENOMEM;
+
+ memcpy(data_ptr, buffer, buflen);
+ }
memset(&admin_cmd, 0, sizeof(admin_cmd));
admin_cmd.features.opcode = SPRAID_ADMIN_SET_FEATURES;
admin_cmd.features.fid = cpu_to_le32(fid);
admin_cmd.features.dword11 = cpu_to_le32(dword11);
+ admin_cmd.common.dptr.prp1 = cpu_to_le64(data_dma);
- ret = spraid_submit_admin_sync_cmd(hdev->admin_q, &admin_cmd, &res,
- buffer, buflen, 0, 0, 0);
+ ret = spraid_submit_admin_sync_cmd(hdev, &admin_cmd, result, NULL, 0);
- if (!ret && result)
- *result = res;
+ if (data_ptr)
+ dma_free_coherent(hdev->dev, buflen, data_ptr, data_dma);
return ret;
}
@@ -1764,8 +1871,7 @@ static int spraid_setup_io_queues(struct spraid_dev *hdev)
break;
}
dev_info(hdev->dev, "[%s] max_qid: %d, queue_count: %d, online_queue: %d, ioq_depth: %d\n",
- __func__, hdev->max_qid, hdev->queue_count,
- hdev->online_queues, hdev->ioq_depth);
+ __func__, hdev->max_qid, hdev->queue_count, hdev->online_queues, hdev->ioq_depth);
return spraid_create_io_queues(hdev);
}
@@ -1889,10 +1995,11 @@ static int spraid_get_dev_list(struct spraid_dev *hdev, struct spraid_dev_info *
u32 nd = le32_to_cpu(hdev->ctrl_info->nd);
struct spraid_admin_command admin_cmd;
struct spraid_dev_list *list_buf;
+ dma_addr_t data_dma = 0;
u32 i, idx, hdid, ndev;
int ret = 0;
- list_buf = kmalloc(sizeof(*list_buf), GFP_KERNEL);
+ list_buf = dma_alloc_coherent(hdev->dev, PAGE_SIZE, &data_dma, GFP_KERNEL);
if (!list_buf)
return -ENOMEM;
@@ -1901,9 +2008,9 @@ static int spraid_get_dev_list(struct spraid_dev *hdev, struct spraid_dev_info *
admin_cmd.get_info.opcode = SPRAID_ADMIN_GET_INFO;
admin_cmd.get_info.type = SPRAID_GET_INFO_DEV_LIST;
admin_cmd.get_info.cdw11 = cpu_to_le32(idx);
+ admin_cmd.common.dptr.prp1 = cpu_to_le64(data_dma);
- ret = spraid_submit_admin_sync_cmd(hdev->admin_q, &admin_cmd, NULL, list_buf,
- sizeof(*list_buf), 0, 0, 0);
+ ret = spraid_submit_admin_sync_cmd(hdev, &admin_cmd, NULL, NULL, 0);
if (ret) {
dev_err(hdev->dev, "Get device list failed, nd: %u, idx: %u, ret: %d\n",
@@ -1916,12 +2023,11 @@ static int spraid_get_dev_list(struct spraid_dev *hdev, struct spraid_dev_info *
for (i = 0; i < ndev; i++) {
hdid = le32_to_cpu(list_buf->devices[i].hdid);
- dev_info(hdev->dev, "list_buf->devices[%d], hdid: %u target: %d, channel: %d, lun: %d, attr[%x]\n",
- i, hdid,
- le16_to_cpu(list_buf->devices[i].target),
- list_buf->devices[i].channel,
- list_buf->devices[i].lun,
- list_buf->devices[i].attr);
+ dev_info(hdev->dev, "list_buf->devices[%d], hdid: %u target: %d, channel: %d, lun: %d, attr[0x%x]\n",
+ i, hdid, le16_to_cpu(list_buf->devices[i].target),
+ list_buf->devices[i].channel,
+ list_buf->devices[i].lun,
+ list_buf->devices[i].attr);
if (hdid > nd || hdid == 0) {
dev_err(hdev->dev, "err, hdid[%d] invalid\n", hdid);
continue;
@@ -1936,21 +2042,29 @@ static int spraid_get_dev_list(struct spraid_dev *hdev, struct spraid_dev_info *
}
out:
- kfree(list_buf);
+ dma_free_coherent(hdev->dev, PAGE_SIZE, list_buf, data_dma);
return ret;
}
-static void spraid_send_aen(struct spraid_dev *hdev)
+static void spraid_send_aen(struct spraid_dev *hdev, u16 cid)
{
struct spraid_queue *adminq = &hdev->queues[0];
struct spraid_admin_command admin_cmd;
memset(&admin_cmd, 0, sizeof(admin_cmd));
admin_cmd.common.opcode = SPRAID_ADMIN_ASYNC_EVENT;
- admin_cmd.common.command_id = SPRAID_AQ_BLK_MQ_DEPTH;
+ admin_cmd.common.command_id = cid;
spraid_submit_cmd(adminq, &admin_cmd);
- dev_info(hdev->dev, "send aen, cid[%d]\n", SPRAID_AQ_BLK_MQ_DEPTH);
+ dev_info(hdev->dev, "send aen, cid[%d]\n", cid);
+}
+
+static inline void spraid_send_all_aen(struct spraid_dev *hdev)
+{
+ u16 i;
+
+ for (i = 0; i < hdev->ctrl_info->aerl; i++)
+ spraid_send_aen(hdev, i + SPRAID_AQ_BLK_MQ_DEPTH);
}
static int spraid_add_device(struct spraid_dev *hdev, struct spraid_dev_info *device)
@@ -1958,6 +2072,10 @@ static int spraid_add_device(struct spraid_dev *hdev, struct spraid_dev_info *de
struct Scsi_Host *shost = hdev->shost;
struct scsi_device *sdev;
+ dev_info(hdev->dev, "add device, hdid: %u target: %d, channel: %d, lun: %d, attr[0x%x]\n",
+ le32_to_cpu(device->hdid), le16_to_cpu(device->target),
+ device->channel, device->lun, device->attr);
+
sdev = scsi_device_lookup(shost, device->channel, le16_to_cpu(device->target), 0);
if (sdev) {
dev_warn(hdev->dev, "Device is already exist, channel: %d, target_id: %d, lun: %d\n",
@@ -1974,9 +2092,13 @@ static int spraid_rescan_device(struct spraid_dev *hdev, struct spraid_dev_info
struct Scsi_Host *shost = hdev->shost;
struct scsi_device *sdev;
+ dev_info(hdev->dev, "rescan device, hdid: %u target: %d, channel: %d, lun: %d, attr[0x%x]\n",
+ le32_to_cpu(device->hdid), le16_to_cpu(device->target),
+ device->channel, device->lun, device->attr);
+
sdev = scsi_device_lookup(shost, device->channel, le16_to_cpu(device->target), 0);
if (!sdev) {
- dev_warn(hdev->dev, "Device is not exit, channel: %d, target_id: %d, lun: %d\n",
+ dev_warn(hdev->dev, "device is not exit rescan it, channel: %d, target_id: %d, lun: %d\n",
device->channel, le16_to_cpu(device->target), 0);
return -ENODEV;
}
@@ -1991,9 +2113,13 @@ static int spraid_remove_device(struct spraid_dev *hdev, struct spraid_dev_info
struct Scsi_Host *shost = hdev->shost;
struct scsi_device *sdev;
+ dev_info(hdev->dev, "remove device, hdid: %u target: %d, channel: %d, lun: %d, attr[0x%x]\n",
+ le32_to_cpu(org_device->hdid), le16_to_cpu(org_device->target),
+ org_device->channel, org_device->lun, org_device->attr);
+
sdev = scsi_device_lookup(shost, org_device->channel, le16_to_cpu(org_device->target), 0);
if (!sdev) {
- dev_warn(hdev->dev, "Device is not exit, channel: %d, target_id: %d, lun: %d\n",
+ dev_warn(hdev->dev, "device is not exit remove it, channel: %d, target_id: %d, lun: %d\n",
org_device->channel, le16_to_cpu(org_device->target), 0);
return -ENODEV;
}
@@ -2029,36 +2155,54 @@ static int spraid_dev_list_init(struct spraid_dev *hdev)
return 0;
}
+static int luntarget_cmp_func(const void *l, const void *r)
+{
+ const struct spraid_dev_info *ln = l;
+ const struct spraid_dev_info *rn = r;
+
+ if (ln->channel == rn->channel)
+ return le16_to_cpu(ln->target) - le16_to_cpu(rn->target);
+
+ return ln->channel - rn->channel;
+}
+
static void spraid_scan_work(struct work_struct *work)
{
struct spraid_dev *hdev =
container_of(work, struct spraid_dev, scan_work);
struct spraid_dev_info *devices, *org_devices;
+ struct spraid_dev_info *sortdevice;
u32 nd = le32_to_cpu(hdev->ctrl_info->nd);
u8 flag, org_flag;
int i, ret;
+ int count = 0;
devices = kcalloc(nd, sizeof(struct spraid_dev_info), GFP_KERNEL);
if (!devices)
return;
+
+ sortdevice = kcalloc(nd, sizeof(struct spraid_dev_info), GFP_KERNEL);
+ if (!sortdevice)
+ goto free_list;
+
ret = spraid_get_dev_list(hdev, devices);
if (ret)
- goto free_list;
+ goto free_all;
org_devices = hdev->devices;
for (i = 0; i < nd; i++) {
org_flag = org_devices[i].flag;
flag = devices[i].flag;
- dev_log_dbg(hdev->dev, "i: %d, org_flag: 0x%x, flag: 0x%x\n",
- i, org_flag, flag);
+ dev_log_dbg(hdev->dev, "i: %d, org_flag: 0x%x, flag: 0x%x\n", i, org_flag, flag);
if (SPRAID_DEV_INFO_FLAG_VALID(flag)) {
if (!SPRAID_DEV_INFO_FLAG_VALID(org_flag)) {
down_write(&hdev->devices_rwsem);
memcpy(&org_devices[i], &devices[i],
- sizeof(struct spraid_dev_info));
+ sizeof(struct spraid_dev_info));
+ memcpy(&sortdevice[count++], &devices[i],
+ sizeof(struct spraid_dev_info));
up_write(&hdev->devices_rwsem);
- spraid_add_device(hdev, &devices[i]);
} else if (SPRAID_DEV_INFO_FLAG_CHANGE(flag)) {
spraid_rescan_device(hdev, &devices[i]);
}
@@ -2071,6 +2215,16 @@ static void spraid_scan_work(struct work_struct *work)
}
}
}
+
+ dev_info(hdev->dev, "scan work add device count = %d\n", count);
+
+ sort(sortdevice, count, sizeof(sortdevice[0]), luntarget_cmp_func, NULL);
+
+ for (i = 0; i < count; i++)
+ spraid_add_device(hdev, &sortdevice[i]);
+
+free_all:
+ kfree(sortdevice);
free_list:
kfree(devices);
}
@@ -2083,6 +2237,15 @@ static void spraid_timesyn_work(struct work_struct *work)
spraid_configure_timestamp(hdev);
}
+static int spraid_init_ctrl_info(struct spraid_dev *hdev);
+static void spraid_fw_act_work(struct work_struct *work)
+{
+ struct spraid_dev *hdev = container_of(work, struct spraid_dev, fw_act_work);
+
+ if (spraid_init_ctrl_info(hdev))
+ dev_err(hdev->dev, "get ctrl info failed after fw act\n");
+}
+
static void spraid_queue_scan(struct spraid_dev *hdev)
{
queue_work(spraid_wq, &hdev->scan_work);
@@ -2094,6 +2257,9 @@ static void spraid_handle_aen_notice(struct spraid_dev *hdev, u32 result)
case SPRAID_AEN_DEV_CHANGED:
spraid_queue_scan(hdev);
break;
+ case SPRAID_AEN_FW_ACT_START:
+ dev_info(hdev->dev, "fw activation starting\n");
+ break;
case SPRAID_AEN_HOST_PROBING:
break;
default:
@@ -2101,25 +2267,25 @@ static void spraid_handle_aen_notice(struct spraid_dev *hdev, u32 result)
}
}
-static void spraid_handle_aen_vs(struct spraid_dev *hdev, u32 result)
+static void spraid_handle_aen_vs(struct spraid_dev *hdev, u32 result, u32 result1)
{
- switch (result) {
+ switch ((result & 0xff00) >> 8) {
case SPRAID_AEN_TIMESYN:
queue_work(spraid_wq, &hdev->timesyn_work);
break;
+ case SPRAID_AEN_FW_ACT_FINISH:
+ dev_info(hdev->dev, "fw activation finish\n");
+ queue_work(spraid_wq, &hdev->fw_act_work);
+ break;
+ case SPRAID_AEN_EVENT_MIN ... SPRAID_AEN_EVENT_MAX:
+ dev_info(hdev->dev, "rcv card event[%d], param1[0x%x] param2[0x%x]\n",
+ (result & 0xff00) >> 8, result, result1);
+ break;
default:
- dev_warn(hdev->dev, "async event result: %x\n", result);
+ dev_warn(hdev->dev, "async event result: 0x%x\n", result);
}
}
-static void spraid_async_event_work(struct work_struct *work)
-{
- struct spraid_dev *hdev =
- container_of(work, struct spraid_dev, aen_work);
-
- spraid_send_aen(hdev);
-}
-
static int spraid_alloc_resources(struct spraid_dev *hdev)
{
int ret, nqueue;
@@ -2149,10 +2315,16 @@ static int spraid_alloc_resources(struct spraid_dev *hdev)
goto destroy_dma_pools;
}
+ ret = spraid_alloc_admin_cmds(hdev);
+ if (ret)
+ goto free_queues;
+
dev_info(hdev->dev, "[%s] queues num: %d\n", __func__, nqueue);
return 0;
+free_queues:
+ kfree(hdev->queues);
destroy_dma_pools:
spraid_destroy_dma_pools(hdev);
free_ctrl_info:
@@ -2164,50 +2336,18 @@ static int spraid_alloc_resources(struct spraid_dev *hdev)
static void spraid_free_resources(struct spraid_dev *hdev)
{
+ spraid_free_admin_cmds(hdev);
kfree(hdev->queues);
spraid_destroy_dma_pools(hdev);
kfree(hdev->ctrl_info);
ida_free(&spraid_instance_ida, hdev->instance);
}
-static void spraid_setup_passthrough(struct request *req, struct spraid_admin_command *cmd)
-{
- memcpy(cmd, spraid_admin_req(req)->cmd, sizeof(*cmd));
- cmd->common.flags &= ~SPRAID_CMD_FLAG_SGL_ALL;
-}
-
-static inline void spraid_clear_hreq(struct request *req)
-{
- if (!(req->rq_flags & RQF_DONTPREP)) {
- spraid_admin_req(req)->flags = 0;
- req->rq_flags |= RQF_DONTPREP;
- }
-}
-
-static blk_status_t spraid_setup_admin_cmd(struct request *req, struct spraid_admin_command *cmd)
+static void spraid_bsg_unmap_data(struct spraid_dev *hdev, struct bsg_job *job)
{
- spraid_clear_hreq(req);
-
- memset(cmd, 0, sizeof(*cmd));
- switch (req_op(req)) {
- case REQ_OP_DRV_IN:
- case REQ_OP_DRV_OUT:
- spraid_setup_passthrough(req, cmd);
- break;
- default:
- WARN_ON_ONCE(1);
- return BLK_STS_IOERR;
- }
-
- cmd->common.command_id = req->tag;
- return BLK_STS_OK;
-}
-
-static void spraid_unmap_data(struct spraid_dev *hdev, struct request *req)
-{
- struct spraid_iod *iod = blk_mq_rq_to_pdu(req);
- enum dma_data_direction dma_dir = rq_data_dir(req) ?
- DMA_TO_DEVICE : DMA_FROM_DEVICE;
+ struct request *rq = blk_mq_rq_from_pdu(job);
+ struct spraid_iod *iod = job->dd_data;
+ enum dma_data_direction dma_dir = rq_data_dir(rq) ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
if (iod->nsge)
dma_unmap_sg(hdev->dev, iod->sg, iod->nsge, dma_dir);
@@ -2215,36 +2355,36 @@ static void spraid_unmap_data(struct spraid_dev *hdev, struct request *req)
spraid_free_iod_res(hdev, iod);
}
-static blk_status_t spraid_admin_map_data(struct spraid_dev *hdev, struct request *req,
- struct spraid_admin_command *cmd)
+static int spraid_bsg_map_data(struct spraid_dev *hdev, struct bsg_job *job,
+ struct spraid_admin_command *cmd)
{
- struct spraid_iod *iod = blk_mq_rq_to_pdu(req);
- struct request_queue *admin_q = req->q;
- enum dma_data_direction dma_dir = rq_data_dir(req) ?
- DMA_TO_DEVICE : DMA_FROM_DEVICE;
- blk_status_t ret = BLK_STS_IOERR;
- int nr_mapped;
- int res;
+ struct request *rq = blk_mq_rq_from_pdu(job);
+ struct spraid_iod *iod = job->dd_data;
+ enum dma_data_direction dma_dir = rq_data_dir(rq) ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
+ int ret = 0;
+
+ iod->sg = job->request_payload.sg_list;
+ iod->nsge = job->request_payload.sg_cnt;
+ iod->length = job->request_payload.payload_len;
+ iod->use_sgl = false;
+ iod->npages = -1;
+ iod->sg_drv_mgmt = false;
- sg_init_table(iod->sg, blk_rq_nr_phys_segments(req));
- iod->nsge = blk_rq_map_sg(admin_q, req, iod->sg);
if (!iod->nsge)
goto out;
- dev_info(hdev->dev, "nseg: %u, nsge: %u\n",
- blk_rq_nr_phys_segments(req), iod->nsge);
-
- ret = BLK_STS_RESOURCE;
- nr_mapped = dma_map_sg_attrs(hdev->dev, iod->sg, iod->nsge, dma_dir, DMA_ATTR_NO_WARN);
- if (!nr_mapped)
+ ret = dma_map_sg_attrs(hdev->dev, iod->sg, iod->nsge, dma_dir, DMA_ATTR_NO_WARN);
+ if (!ret)
goto out;
- res = spraid_setup_prps(hdev, iod);
- if (res)
+ ret = spraid_setup_prps(hdev, iod);
+ if (ret)
goto unmap;
+
cmd->common.dptr.prp1 = cpu_to_le64(sg_dma_address(iod->sg));
cmd->common.dptr.prp2 = cpu_to_le64(iod->first_dma);
- return BLK_STS_OK;
+
+ return 0;
unmap:
dma_unmap_sg(hdev->dev, iod->sg, iod->nsge, dma_dir);
@@ -2252,137 +2392,29 @@ static blk_status_t spraid_admin_map_data(struct spraid_dev *hdev, struct reques
return ret;
}
-static blk_status_t spraid_init_admin_iod(struct request *rq, struct spraid_dev *hdev)
-{
- struct spraid_iod *iod = blk_mq_rq_to_pdu(rq);
- int nents = blk_rq_nr_phys_segments(rq);
- unsigned int size = blk_rq_payload_bytes(rq);
-
- if (nents > SPRAID_INT_PAGES || size > SPRAID_INT_BYTES(hdev)) {
- iod->sg = mempool_alloc(hdev->iod_mempool, GFP_ATOMIC);
- if (!iod->sg)
- return BLK_STS_RESOURCE;
- } else {
- iod->sg = iod->inline_sg;
- }
-
- iod->nsge = 0;
- iod->use_sgl = false;
- iod->npages = -1;
- iod->length = size;
- iod->sg_drv_mgmt = true;
-
- return BLK_STS_OK;
-}
-
-static blk_status_t spraid_queue_admin_rq(struct blk_mq_hw_ctx *hctx,
- const struct blk_mq_queue_data *bd)
-{
- struct spraid_queue *adminq = hctx->driver_data;
- struct spraid_dev *hdev = adminq->hdev;
- struct request *req = bd->rq;
- struct spraid_iod *iod = blk_mq_rq_to_pdu(req);
- struct spraid_admin_command cmd;
- blk_status_t ret;
-
- ret = spraid_setup_admin_cmd(req, &cmd);
- if (ret)
- goto out;
-
- ret = spraid_init_admin_iod(req, hdev);
- if (ret)
- goto out;
-
- if (blk_rq_nr_phys_segments(req)) {
- ret = spraid_admin_map_data(hdev, req, &cmd);
- if (ret)
- goto cleanup_iod;
- }
-
- blk_mq_start_request(req);
- spraid_submit_cmd(adminq, &cmd);
- return BLK_STS_OK;
-
-cleanup_iod:
- spraid_free_iod_res(hdev, iod);
-out:
- return ret;
-}
-
-static blk_status_t spraid_error_status(struct request *req)
-{
- switch (spraid_admin_req(req)->status & 0x7ff) {
- case SPRAID_SC_SUCCESS:
- return BLK_STS_OK;
- default:
- return BLK_STS_IOERR;
- }
-}
-
-static void spraid_complete_admin_rq(struct request *req)
-{
- struct spraid_iod *iod = blk_mq_rq_to_pdu(req);
- struct spraid_dev *hdev = iod->spraidq->hdev;
-
- if (blk_rq_nr_phys_segments(req))
- spraid_unmap_data(hdev, req);
- blk_mq_end_request(req, spraid_error_status(req));
-}
-
-static int spraid_admin_init_hctx(struct blk_mq_hw_ctx *hctx, void *data, unsigned int hctx_idx)
-{
- struct spraid_dev *hdev = data;
- struct spraid_queue *adminq = &hdev->queues[0];
-
- WARN_ON(hctx_idx != 0);
- WARN_ON(hdev->admin_tagset.tags[0] != hctx->tags);
-
- hctx->driver_data = adminq;
- return 0;
-}
-
-static int spraid_admin_init_request(struct blk_mq_tag_set *set, struct request *req,
- unsigned int hctx_idx, unsigned int numa_node)
-{
- struct spraid_dev *hdev = set->driver_data;
- struct spraid_iod *iod = blk_mq_rq_to_pdu(req);
- struct spraid_queue *adminq = &hdev->queues[0];
-
- WARN_ON(!adminq);
- iod->spraidq = adminq;
- return 0;
-}
-
-static enum blk_eh_timer_return
-spraid_admin_timeout(struct request *req, bool reserved)
-{
- struct spraid_iod *iod = blk_mq_rq_to_pdu(req);
- struct spraid_queue *spraidq = iod->spraidq;
- struct spraid_dev *hdev = spraidq->hdev;
-
- dev_err(hdev->dev, "Admin cid[%d] qid[%d] timeout\n",
- req->tag, spraidq->qid);
-
- if (spraid_poll_cq(spraidq, req->tag)) {
- dev_warn(hdev->dev, "cid[%d] qid[%d] timeout, completion polled\n",
- req->tag, spraidq->qid);
- return BLK_EH_DONE;
- }
-
- spraid_end_admin_request(req, cpu_to_le16(-EINVAL), 0, 0);
- return BLK_EH_DONE;
-}
-
static int spraid_get_ctrl_info(struct spraid_dev *hdev, struct spraid_ctrl_info *ctrl_info)
{
struct spraid_admin_command admin_cmd;
+ u8 *data_ptr = NULL;
+ dma_addr_t data_dma = 0;
+ int ret;
+
+ data_ptr = dma_alloc_coherent(hdev->dev, PAGE_SIZE, &data_dma, GFP_KERNEL);
+ if (!data_ptr)
+ return -ENOMEM;
memset(&admin_cmd, 0, sizeof(admin_cmd));
admin_cmd.get_info.opcode = SPRAID_ADMIN_GET_INFO;
admin_cmd.get_info.type = SPRAID_GET_INFO_CTRL;
+ admin_cmd.common.dptr.prp1 = cpu_to_le64(data_dma);
+
+ ret = spraid_submit_admin_sync_cmd(hdev, &admin_cmd, NULL, NULL, 0);
+ if (!ret)
+ memcpy(ctrl_info, data_ptr, sizeof(struct spraid_ctrl_info));
- return spraid_submit_admin_sync_cmd(hdev->admin_q, &admin_cmd, NULL,
- ctrl_info, sizeof(struct spraid_ctrl_info), 0, 0, 0);
+ dma_free_coherent(hdev->dev, PAGE_SIZE, data_ptr, data_dma);
+
+ return ret;
}
static int spraid_init_ctrl_info(struct spraid_dev *hdev)
@@ -2416,6 +2448,11 @@ static int spraid_init_ctrl_info(struct spraid_dev *hdev)
dev_info(hdev->dev, "[%s]sn = %s\n", __func__, hdev->ctrl_info->sn);
dev_info(hdev->dev, "[%s]fr = %s\n", __func__, hdev->ctrl_info->fr);
+ if (!hdev->ctrl_info->aerl)
+ hdev->ctrl_info->aerl = 1;
+ if (hdev->ctrl_info->aerl > SPRAID_NR_AEN_COMMANDS)
+ hdev->ctrl_info->aerl = SPRAID_NR_AEN_COMMANDS;
+
return 0;
}
@@ -2444,98 +2481,51 @@ static void spraid_free_iod_ext_mem_pool(struct spraid_dev *hdev)
mempool_destroy(hdev->iod_mempool);
}
-static int spraid_submit_user_cmd(struct request_queue *q, struct spraid_admin_command *cmd,
- void __user *ubuffer, unsigned int bufflen, u32 *result,
- unsigned int timeout)
+static int spraid_user_admin_cmd(struct spraid_dev *hdev, struct bsg_job *job)
{
- struct request *req;
- struct bio *bio = NULL;
- int ret;
-
- req = spraid_alloc_admin_request(q, cmd, 0);
- if (IS_ERR(req))
- return PTR_ERR(req);
+ struct spraid_bsg_request *bsg_req = job->request;
+ struct spraid_passthru_common_cmd *cmd = &(bsg_req->admcmd);
+ struct spraid_admin_command admin_cmd;
+ u32 timeout = msecs_to_jiffies(cmd->timeout_ms);
+ u32 result[2] = {0};
+ int status;
- req->timeout = timeout ? timeout : ADMIN_TIMEOUT;
- spraid_admin_req(req)->flags |= SPRAID_REQ_USERCMD;
+ if (hdev->state >= SPRAID_RESETTING) {
+ dev_err(hdev->dev, "[%s] err, host state:[%d] is not right\n",
+ __func__, hdev->state);
+ return -EBUSY;
+ }
- if (ubuffer && bufflen) {
- ret = blk_rq_map_user(q, req, NULL, ubuffer, bufflen, GFP_KERNEL);
- if (ret)
- goto out;
- bio = req->bio;
+ memset(&admin_cmd, 0, sizeof(admin_cmd));
+ admin_cmd.common.opcode = cmd->opcode;
+ admin_cmd.common.flags = cmd->flags;
+ admin_cmd.common.hdid = cpu_to_le32(cmd->nsid);
+ admin_cmd.common.cdw2[0] = cpu_to_le32(cmd->cdw2);
+ admin_cmd.common.cdw2[1] = cpu_to_le32(cmd->cdw3);
+ admin_cmd.common.cdw10 = cpu_to_le32(cmd->cdw10);
+ admin_cmd.common.cdw11 = cpu_to_le32(cmd->cdw11);
+ admin_cmd.common.cdw12 = cpu_to_le32(cmd->cdw12);
+ admin_cmd.common.cdw13 = cpu_to_le32(cmd->cdw13);
+ admin_cmd.common.cdw14 = cpu_to_le32(cmd->cdw14);
+ admin_cmd.common.cdw15 = cpu_to_le32(cmd->cdw15);
+
+ status = spraid_bsg_map_data(hdev, job, &admin_cmd);
+ if (status) {
+ dev_err(hdev->dev, "[%s] err, map data failed\n", __func__);
+ return status;
}
- blk_execute_rq(req->q, NULL, req, 0);
- if (spraid_admin_req(req)->flags & SPRAID_REQ_CANCELLED)
- ret = -EINTR;
- else
- ret = spraid_admin_req(req)->status;
- if (result) {
- result[0] = spraid_admin_req(req)->result0;
- result[1] = spraid_admin_req(req)->result1;
- }
- if (bio)
- blk_rq_unmap_user(bio);
-out:
- blk_mq_free_request(req);
- return ret;
-}
-static int spraid_user_admin_cmd(struct spraid_dev *hdev,
- struct spraid_passthru_common_cmd __user *ucmd)
-{
- struct spraid_passthru_common_cmd cmd;
- struct spraid_admin_command admin_cmd;
- u32 timeout = 0;
- int status;
-
- if (!capable(CAP_SYS_ADMIN)) {
- dev_err(hdev->dev, "Current user hasn't administrator right, reject service\n");
- return -EACCES;
- }
-
- if (copy_from_user(&cmd, ucmd, sizeof(cmd))) {
- dev_err(hdev->dev, "Copy command from user space to kernel space failed\n");
- return -EFAULT;
- }
-
- if (cmd.flags) {
- dev_err(hdev->dev, "Invalid flags in user command\n");
- return -EINVAL;
+ status = spraid_submit_admin_sync_cmd(hdev, &admin_cmd, &result[0], &result[1], timeout);
+ if (status >= 0) {
+ job->reply_len = sizeof(result);
+ memcpy(job->reply, result, sizeof(result));
}
- dev_info(hdev->dev, "user_admin_cmd opcode: 0x%x, subopcode: 0x%x\n",
- cmd.opcode, cmd.cdw2 & 0x7ff);
+ if (status)
+ dev_info(hdev->dev, "[%s] opcode[0x%x] subopcode[0x%x], status[0x%x] result0[0x%x] result1[0x%x]\n",
+ __func__, cmd->opcode, cmd->info_0.subopcode, status, result[0], result[1]);
- memset(&admin_cmd, 0, sizeof(admin_cmd));
- admin_cmd.common.opcode = cmd.opcode;
- admin_cmd.common.flags = cmd.flags;
- admin_cmd.common.hdid = cpu_to_le32(cmd.nsid);
- admin_cmd.common.cdw2[0] = cpu_to_le32(cmd.cdw2);
- admin_cmd.common.cdw2[1] = cpu_to_le32(cmd.cdw3);
- admin_cmd.common.cdw10 = cpu_to_le32(cmd.cdw10);
- admin_cmd.common.cdw11 = cpu_to_le32(cmd.cdw11);
- admin_cmd.common.cdw12 = cpu_to_le32(cmd.cdw12);
- admin_cmd.common.cdw13 = cpu_to_le32(cmd.cdw13);
- admin_cmd.common.cdw14 = cpu_to_le32(cmd.cdw14);
- admin_cmd.common.cdw15 = cpu_to_le32(cmd.cdw15);
-
- if (cmd.timeout_ms)
- timeout = msecs_to_jiffies(cmd.timeout_ms);
-
- status = spraid_submit_user_cmd(hdev->admin_q, &admin_cmd,
- (void __user *)(uintptr_t)cmd.addr, cmd.info_1.data_len,
- &cmd.result0, timeout);
-
- dev_info(hdev->dev, "user_admin_cmd status: 0x%x, result0: 0x%x, result1: 0x%x\n",
- status, cmd.result0, cmd.result1);
-
- if (status >= 0) {
- if (put_user(cmd.result0, &ucmd->result0))
- return -EFAULT;
- if (put_user(cmd.result1, &ucmd->result1))
- return -EFAULT;
- }
+ spraid_bsg_unmap_data(hdev, job);
return status;
}
@@ -2548,8 +2538,8 @@ static int spraid_alloc_ioq_ptcmds(struct spraid_dev *hdev)
INIT_LIST_HEAD(&hdev->ioq_pt_list);
spin_lock_init(&hdev->ioq_pt_lock);
- hdev->ioq_ptcmds = kcalloc_node(ptnum, sizeof(struct spraid_ioq_ptcmd),
- GFP_KERNEL, hdev->numa_node);
+ hdev->ioq_ptcmds = kcalloc_node(ptnum, sizeof(struct spraid_cmd),
+ GFP_KERNEL, hdev->numa_node);
if (!hdev->ioq_ptcmds) {
dev_err(hdev->dev, "Alloc ioq_ptcmds failed\n");
@@ -2567,55 +2557,35 @@ static int spraid_alloc_ioq_ptcmds(struct spraid_dev *hdev)
return 0;
}
-static struct spraid_ioq_ptcmd *spraid_get_ioq_ptcmd(struct spraid_dev *hdev)
-{
- struct spraid_ioq_ptcmd *cmd = NULL;
- unsigned long flags;
-
- spin_lock_irqsave(&hdev->ioq_pt_lock, flags);
- if (list_empty(&hdev->ioq_pt_list)) {
- spin_unlock_irqrestore(&hdev->ioq_pt_lock, flags);
- dev_err(hdev->dev, "err, ioq ptcmd list empty\n");
- return NULL;
- }
- cmd = list_entry((&hdev->ioq_pt_list)->next, struct spraid_ioq_ptcmd, list);
- list_del_init(&cmd->list);
- spin_unlock_irqrestore(&hdev->ioq_pt_lock, flags);
-
- WRITE_ONCE(cmd->state, SPRAID_CMD_IDLE);
-
- return cmd;
-}
-
-static void spraid_put_ioq_ptcmd(struct spraid_dev *hdev, struct spraid_ioq_ptcmd *cmd)
+static void spraid_free_ioq_ptcmds(struct spraid_dev *hdev)
{
- unsigned long flags;
+ kfree(hdev->ioq_ptcmds);
+ hdev->ioq_ptcmds = NULL;
- spin_lock_irqsave(&hdev->ioq_pt_lock, flags);
- list_add(&cmd->list, (&hdev->ioq_pt_list)->next);
- spin_unlock_irqrestore(&hdev->ioq_pt_lock, flags);
+ INIT_LIST_HEAD(&hdev->ioq_pt_list);
}
static int spraid_submit_ioq_sync_cmd(struct spraid_dev *hdev, struct spraid_ioq_command *cmd,
- u32 *result, void **sense, u32 timeout)
+ u32 *result, u32 *reslen, u32 timeout)
{
- struct spraid_queue *ioq;
int ret;
dma_addr_t sense_dma;
- struct spraid_ioq_ptcmd *pt_cmd = spraid_get_ioq_ptcmd(hdev);
-
- *sense = NULL;
+ struct spraid_queue *ioq;
+ void *sense_addr = NULL;
+ struct spraid_cmd *pt_cmd = spraid_get_cmd(hdev, SPRAID_CMD_IOPT);
- if (!pt_cmd)
+ if (!pt_cmd) {
+ dev_err(hdev->dev, "err, get ioq cmd failed\n");
return -EFAULT;
+ }
- dev_info(hdev->dev, "[%s] ptcmd, cid[%d], qid[%d]\n", __func__, pt_cmd->cid, pt_cmd->qid);
+ timeout = timeout ? timeout : ADMIN_TIMEOUT;
init_completion(&pt_cmd->cmd_done);
ioq = &hdev->queues[pt_cmd->qid];
ret = pt_cmd->cid * SCSI_SENSE_BUFFERSIZE;
- pt_cmd->priv = ioq->sense + ret;
+ sense_addr = ioq->sense + ret;
sense_dma = ioq->sense_dma_addr + ret;
cmd->common.sense_addr = cpu_to_le64(sense_dma);
@@ -2625,260 +2595,87 @@ static int spraid_submit_ioq_sync_cmd(struct spraid_dev *hdev, struct spraid_ioq
spraid_submit_cmd(ioq, cmd);
if (!wait_for_completion_timeout(&pt_cmd->cmd_done, timeout)) {
- dev_err(hdev->dev, "[%s] cid[%d], qid[%d] timeout\n",
- __func__, pt_cmd->cid, pt_cmd->qid);
+ dev_err(hdev->dev, "[%s] cid[%d] qid[%d] timeout, opcode[0x%x] subopcode[0x%x]\n",
+ __func__, pt_cmd->cid, pt_cmd->qid, cmd->common.opcode,
+ (le32_to_cpu(cmd->common.cdw3[0]) & 0xffff));
WRITE_ONCE(pt_cmd->state, SPRAID_CMD_TIMEOUT);
- return -EINVAL;
+ spraid_put_cmd(hdev, pt_cmd, SPRAID_CMD_IOPT);
+ return -ETIME;
}
- if (result) {
- result[0] = pt_cmd->result0;
- result[1] = pt_cmd->result1;
+ if (result && reslen) {
+ if ((pt_cmd->status & 0x17f) == 0x101) {
+ memcpy(result, sense_addr, SCSI_SENSE_BUFFERSIZE);
+ *reslen = SCSI_SENSE_BUFFERSIZE;
+ }
}
- if ((pt_cmd->status & 0x17f) == 0x101)
- *sense = pt_cmd->priv;
+ spraid_put_cmd(hdev, pt_cmd, SPRAID_CMD_IOPT);
return pt_cmd->status;
}
-static int spraid_user_ioq_cmd(struct spraid_dev *hdev,
- struct spraid_ioq_passthru_cmd __user *ucmd)
+static int spraid_user_ioq_cmd(struct spraid_dev *hdev, struct bsg_job *job)
{
- struct spraid_ioq_passthru_cmd cmd;
+ struct spraid_bsg_request *bsg_req = (struct spraid_bsg_request *)(job->request);
+ struct spraid_ioq_passthru_cmd *cmd = &(bsg_req->ioqcmd);
struct spraid_ioq_command ioq_cmd;
- u32 timeout = 0;
int status = 0;
- u8 *data_ptr = NULL;
- dma_addr_t data_dma;
- enum dma_data_direction dma_dir = DMA_NONE;
- void *sense = NULL;
-
- if (!capable(CAP_SYS_ADMIN)) {
- dev_err(hdev->dev, "Current user hasn't administrator right, reject service\n");
- return -EACCES;
- }
+ u32 timeout = msecs_to_jiffies(cmd->timeout_ms);
- if (copy_from_user(&cmd, ucmd, sizeof(cmd))) {
- dev_err(hdev->dev, "Copy command from user space to kernel space failed\n");
- return -EFAULT;
- }
-
- if (cmd.data_len > PAGE_SIZE) {
+ if (cmd->data_len > PAGE_SIZE) {
dev_err(hdev->dev, "[%s] data len bigger than 4k\n", __func__);
return -EFAULT;
}
- dev_info(hdev->dev, "[%s] opcode: 0x%x, subopcode: 0x%x, datalen: %d\n",
- __func__, cmd.opcode, cmd.info_1.subopcode, cmd.data_len);
-
- if (cmd.addr && cmd.data_len) {
- data_ptr = dma_alloc_coherent(hdev->dev, PAGE_SIZE, &data_dma, GFP_KERNEL);
- if (!data_ptr)
- return -ENOMEM;
-
- dma_dir = (cmd.opcode & 1) ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
+ if (hdev->state != SPRAID_LIVE) {
+ dev_err(hdev->dev, "[%s] err, host state:[%d] is not live\n",
+ __func__, hdev->state);
+ return -EBUSY;
}
- if (dma_dir == DMA_TO_DEVICE) {
- if (copy_from_user(data_ptr, (void __user *)(uintptr_t)cmd.addr, cmd.data_len)) {
- dev_err(hdev->dev, "[%s] copy user data failed\n", __func__);
- status = -EFAULT;
- goto free_dma_mem;
- }
- }
+ dev_info(hdev->dev, "[%s] opcode[0x%x] subopcode[0x%x] init, datalen[%d]\n",
+ __func__, cmd->opcode, cmd->info_1.subopcode, cmd->data_len);
memset(&ioq_cmd, 0, sizeof(ioq_cmd));
- ioq_cmd.common.opcode = cmd.opcode;
- ioq_cmd.common.flags = cmd.flags;
- ioq_cmd.common.hdid = cpu_to_le32(cmd.nsid);
- ioq_cmd.common.sense_len = cpu_to_le16(cmd.info_0.res_sense_len);
- ioq_cmd.common.cdb_len = cmd.info_0.cdb_len;
- ioq_cmd.common.rsvd2 = cmd.info_0.rsvd0;
- ioq_cmd.common.cdw3[0] = cpu_to_le32(cmd.cdw3);
- ioq_cmd.common.cdw3[1] = cpu_to_le32(cmd.cdw4);
- ioq_cmd.common.cdw3[2] = cpu_to_le32(cmd.cdw5);
- ioq_cmd.common.dptr.prp1 = cpu_to_le64(data_dma);
-
- ioq_cmd.common.cdw10[0] = cpu_to_le32(cmd.cdw10);
- ioq_cmd.common.cdw10[1] = cpu_to_le32(cmd.cdw11);
- ioq_cmd.common.cdw10[2] = cpu_to_le32(cmd.cdw12);
- ioq_cmd.common.cdw10[3] = cpu_to_le32(cmd.cdw13);
- ioq_cmd.common.cdw10[4] = cpu_to_le32(cmd.cdw14);
- ioq_cmd.common.cdw10[5] = cpu_to_le32(cmd.data_len);
-
- memcpy(ioq_cmd.common.cdb, &cmd.cdw16, cmd.info_0.cdb_len);
-
- ioq_cmd.common.cdw26[0] = cpu_to_le32(cmd.cdw26[0]);
- ioq_cmd.common.cdw26[1] = cpu_to_le32(cmd.cdw26[1]);
- ioq_cmd.common.cdw26[2] = cpu_to_le32(cmd.cdw26[2]);
- ioq_cmd.common.cdw26[3] = cpu_to_le32(cmd.cdw26[3]);
-
- if (cmd.timeout_ms)
- timeout = msecs_to_jiffies(cmd.timeout_ms);
- timeout = timeout ? timeout : ADMIN_TIMEOUT;
-
- status = spraid_submit_ioq_sync_cmd(hdev, &ioq_cmd, &cmd.result0, &sense, timeout);
-
- if (status >= 0) {
- if (put_user(cmd.result0, &ucmd->result0)) {
- status = -EFAULT;
- goto free_dma_mem;
- }
- if (put_user(cmd.result1, &ucmd->result1)) {
- status = -EFAULT;
- goto free_dma_mem;
- }
- if (dma_dir == DMA_FROM_DEVICE &&
- copy_to_user((void __user *)(uintptr_t)cmd.addr, data_ptr, cmd.data_len)) {
- status = -EFAULT;
- goto free_dma_mem;
- }
- }
-
- if (sense) {
- if (copy_to_user((void *__user *)(uintptr_t)cmd.sense_addr,
- sense, cmd.info_0.res_sense_len)) {
- status = -EFAULT;
- goto free_dma_mem;
- }
- }
-
-free_dma_mem:
- if (data_ptr)
- dma_free_coherent(hdev->dev, PAGE_SIZE, data_ptr, data_dma);
-
- return status;
-
-}
-
-static int spraid_reset_work_sync(struct spraid_dev *hdev);
-
-static int spraid_user_reset_cmd(struct spraid_dev *hdev)
-{
- int ret;
-
- dev_info(hdev->dev, "[%s] start user reset cmd\n", __func__);
- ret = spraid_reset_work_sync(hdev);
- dev_info(hdev->dev, "[%s] stop user reset cmd[%d]\n", __func__, ret);
-
- return ret;
-}
-
-static int hdev_open(struct inode *inode, struct file *file)
-{
- struct spraid_dev *hdev =
- container_of(inode->i_cdev, struct spraid_dev, cdev);
- file->private_data = hdev;
- return 0;
-}
-
-static long hdev_ioctl(struct file *file, u32 cmd, unsigned long arg)
-{
- struct spraid_dev *hdev = file->private_data;
- void __user *argp = (void __user *)arg;
-
- switch (cmd) {
- case SPRAID_IOCTL_ADMIN_CMD:
- return spraid_user_admin_cmd(hdev, argp);
- case SPRAID_IOCTL_IOQ_CMD:
- return spraid_user_ioq_cmd(hdev, argp);
- case SPRAID_IOCTL_RESET_CMD:
- return spraid_user_reset_cmd(hdev);
- default:
- return -ENOTTY;
- }
-}
-
-static const struct file_operations spraid_dev_fops = {
- .owner = THIS_MODULE,
- .open = hdev_open,
- .unlocked_ioctl = hdev_ioctl,
- .compat_ioctl = hdev_ioctl,
-};
-
-static int spraid_create_cdev(struct spraid_dev *hdev)
-{
- int ret;
-
- device_initialize(&hdev->ctrl_device);
- hdev->ctrl_device.devt = MKDEV(MAJOR(spraid_chr_devt), hdev->instance);
- hdev->ctrl_device.class = spraid_class;
- hdev->ctrl_device.parent = hdev->dev;
- dev_set_drvdata(&hdev->ctrl_device, hdev);
- ret = dev_set_name(&hdev->ctrl_device, "spraid%d", hdev->instance);
- if (ret)
- return ret;
- cdev_init(&hdev->cdev, &spraid_dev_fops);
- hdev->cdev.owner = THIS_MODULE;
- ret = cdev_device_add(&hdev->cdev, &hdev->ctrl_device);
- if (ret) {
- dev_err(hdev->dev, "Add cdev failed, ret: %d", ret);
- put_device(&hdev->ctrl_device);
- kfree_const(hdev->ctrl_device.kobj.name);
- return ret;
- }
-
- return 0;
-}
-
-static inline void spraid_remove_cdev(struct spraid_dev *hdev)
-{
- cdev_device_del(&hdev->cdev, &hdev->ctrl_device);
-}
-
-static const struct blk_mq_ops spraid_admin_mq_ops = {
- .queue_rq = spraid_queue_admin_rq,
- .complete = spraid_complete_admin_rq,
- .init_hctx = spraid_admin_init_hctx,
- .init_request = spraid_admin_init_request,
- .timeout = spraid_admin_timeout,
-};
-
-static void spraid_remove_admin_tagset(struct spraid_dev *hdev)
-{
- if (hdev->admin_q && !blk_queue_dying(hdev->admin_q)) {
- blk_mq_unquiesce_queue(hdev->admin_q);
- blk_cleanup_queue(hdev->admin_q);
- blk_mq_free_tag_set(&hdev->admin_tagset);
+ ioq_cmd.common.opcode = cmd->opcode;
+ ioq_cmd.common.flags = cmd->flags;
+ ioq_cmd.common.hdid = cpu_to_le32(cmd->nsid);
+ ioq_cmd.common.sense_len = cpu_to_le16(cmd->info_0.res_sense_len);
+ ioq_cmd.common.cdb_len = cmd->info_0.cdb_len;
+ ioq_cmd.common.rsvd2 = cmd->info_0.rsvd0;
+ ioq_cmd.common.cdw3[0] = cpu_to_le32(cmd->cdw3);
+ ioq_cmd.common.cdw3[1] = cpu_to_le32(cmd->cdw4);
+ ioq_cmd.common.cdw3[2] = cpu_to_le32(cmd->cdw5);
+
+ ioq_cmd.common.cdw10[0] = cpu_to_le32(cmd->cdw10);
+ ioq_cmd.common.cdw10[1] = cpu_to_le32(cmd->cdw11);
+ ioq_cmd.common.cdw10[2] = cpu_to_le32(cmd->cdw12);
+ ioq_cmd.common.cdw10[3] = cpu_to_le32(cmd->cdw13);
+ ioq_cmd.common.cdw10[4] = cpu_to_le32(cmd->cdw14);
+ ioq_cmd.common.cdw10[5] = cpu_to_le32(cmd->data_len);
+
+ memcpy(ioq_cmd.common.cdb, &cmd->cdw16, cmd->info_0.cdb_len);
+
+ ioq_cmd.common.cdw26[0] = cpu_to_le32(cmd->cdw26[0]);
+ ioq_cmd.common.cdw26[1] = cpu_to_le32(cmd->cdw26[1]);
+ ioq_cmd.common.cdw26[2] = cpu_to_le32(cmd->cdw26[2]);
+ ioq_cmd.common.cdw26[3] = cpu_to_le32(cmd->cdw26[3]);
+
+ status = spraid_bsg_map_data(hdev, job, (struct spraid_admin_command *)&ioq_cmd);
+ if (status) {
+ dev_err(hdev->dev, "[%s] err, map data failed\n", __func__);
+ return status;
}
-}
-static int spraid_alloc_admin_tags(struct spraid_dev *hdev)
-{
- if (!hdev->admin_q) {
- hdev->admin_tagset.ops = &spraid_admin_mq_ops;
- hdev->admin_tagset.nr_hw_queues = 1;
+ status = spraid_submit_ioq_sync_cmd(hdev, &ioq_cmd, job->reply, &job->reply_len, timeout);
- hdev->admin_tagset.queue_depth = SPRAID_AQ_MQ_TAG_DEPTH;
- hdev->admin_tagset.timeout = ADMIN_TIMEOUT;
- hdev->admin_tagset.numa_node = hdev->numa_node;
- hdev->admin_tagset.cmd_size =
- spraid_cmd_size(hdev, true, false);
- hdev->admin_tagset.flags = BLK_MQ_F_NO_SCHED;
- hdev->admin_tagset.driver_data = hdev;
+ dev_info(hdev->dev, "[%s] opcode[0x%x] subopcode[0x%x], status[0x%x], reply_len[%d]\n",
+ __func__, cmd->opcode, cmd->info_1.subopcode, status, job->reply_len);
- if (blk_mq_alloc_tag_set(&hdev->admin_tagset)) {
- dev_err(hdev->dev, "Allocate admin tagset failed\n");
- return -ENOMEM;
- }
+ spraid_bsg_unmap_data(hdev, job);
- hdev->admin_q = blk_mq_init_queue(&hdev->admin_tagset);
- if (IS_ERR(hdev->admin_q)) {
- dev_err(hdev->dev, "Initialize admin request queue failed\n");
- blk_mq_free_tag_set(&hdev->admin_tagset);
- return -ENOMEM;
- }
- if (!blk_get_queue(hdev->admin_q)) {
- dev_err(hdev->dev, "Get admin request queue failed\n");
- spraid_remove_admin_tagset(hdev);
- hdev->admin_q = NULL;
- return -ENODEV;
- }
- } else {
- blk_mq_unquiesce_queue(hdev->admin_q);
- }
- return 0;
+ return status;
}
static bool spraid_check_scmd_completed(struct scsi_cmnd *scmd)
@@ -2891,7 +2688,7 @@ static bool spraid_check_scmd_completed(struct scsi_cmnd *scmd)
spraid_get_tag_from_scmd(scmd, &hwq, &cid);
spraidq = &hdev->queues[hwq];
if (READ_ONCE(iod->state) == SPRAID_CMD_COMPLETE || spraid_poll_cq(spraidq, cid)) {
- dev_warn(hdev->dev, "cid[%d], qid[%d] has been completed\n",
+ dev_warn(hdev->dev, "cid[%d] qid[%d] has been completed\n",
cid, spraidq->qid);
return true;
}
@@ -2927,8 +2724,7 @@ static int spraid_send_abort_cmd(struct spraid_dev *hdev, u32 hdid, u16 qid, u16
admin_cmd.abort.sqid = cpu_to_le16(qid);
admin_cmd.abort.cid = cpu_to_le16(cid);
- return spraid_submit_admin_sync_cmd(hdev->admin_q, &admin_cmd, NULL,
- NULL, 0, 0, 0, 0);
+ return spraid_submit_admin_sync_cmd(hdev, &admin_cmd, NULL, NULL, 0);
}
/* send reset command by admin quueue temporary */
@@ -2941,8 +2737,7 @@ static int spraid_send_reset_cmd(struct spraid_dev *hdev, int type, u32 hdid)
admin_cmd.reset.hdid = cpu_to_le32(hdid);
admin_cmd.reset.type = type;
- return spraid_submit_admin_sync_cmd(hdev->admin_q, &admin_cmd, NULL,
- NULL, 0, 0, 0, 0);
+ return spraid_submit_admin_sync_cmd(hdev, &admin_cmd, NULL, NULL, 0);
}
static bool spraid_change_host_state(struct spraid_dev *hdev, enum spraid_state newstate)
@@ -3022,7 +2817,7 @@ static void spraid_back_fault_cqe(struct spraid_queue *ioq, struct spraid_comple
scsi_dma_unmap(scmd);
spraid_free_iod_res(hdev, iod);
scmd->scsi_done(scmd);
- dev_warn(hdev->dev, "Back fault CQE, cid[%d], qid[%d]\n",
+ dev_warn(hdev->dev, "Back fault CQE, cid[%d] qid[%d]\n",
cqe->cmd_id, ioq->qid);
}
@@ -3032,6 +2827,8 @@ static void spraid_back_all_io(struct spraid_dev *hdev)
struct spraid_queue *ioq;
struct spraid_completion cqe = { 0 };
+ scsi_block_requests(hdev->shost);
+
for (i = 1; i <= hdev->shost->nr_hw_queues; i++) {
ioq = &hdev->queues[i];
for (j = 0; j < hdev->shost->can_queue; j++) {
@@ -3039,6 +2836,8 @@ static void spraid_back_all_io(struct spraid_dev *hdev)
spraid_back_fault_cqe(ioq, &cqe);
}
}
+
+ scsi_unblock_requests(hdev->shost);
}
static void spraid_dev_disable(struct spraid_dev *hdev, bool shutdown)
@@ -3106,17 +2905,13 @@ static void spraid_reset_work(struct work_struct *work)
if (ret)
goto pci_disable;
- ret = spraid_alloc_admin_tags(hdev);
- if (ret)
- goto pci_disable;
-
ret = spraid_setup_io_queues(hdev);
if (ret || hdev->online_queues <= hdev->shost->nr_hw_queues)
goto pci_disable;
spraid_change_host_state(hdev, SPRAID_LIVE);
- spraid_send_aen(hdev);
+ spraid_send_all_aen(hdev);
return;
@@ -3174,8 +2969,8 @@ static int spraid_abort_handler(struct scsi_cmnd *scmd)
scsi_print_command(scmd);
- if (!spraid_wait_abnl_cmd_done(iod) || spraid_check_scmd_completed(scmd) ||
- hdev->state != SPRAID_LIVE)
+ if (hdev->state != SPRAID_LIVE || !spraid_wait_abnl_cmd_done(iod) ||
+ spraid_check_scmd_completed(scmd))
return SUCCESS;
hostdata = scmd->device->hostdata;
@@ -3183,7 +2978,7 @@ static int spraid_abort_handler(struct scsi_cmnd *scmd)
dev_warn(hdev->dev, "cid[%d] qid[%d] timeout, aborting\n", cid, hwq);
ret = spraid_send_abort_cmd(hdev, hostdata->hdid, hwq, cid);
- if (ret != ADMIN_ERR_TIMEOUT) {
+ if (ret != -ETIME) {
ret = spraid_wait_abnl_cmd_done(iod);
if (ret) {
dev_warn(hdev->dev, "cid[%d] qid[%d] abort failed, not found\n", cid, hwq);
@@ -3206,8 +3001,8 @@ static int spraid_tgt_reset_handler(struct scsi_cmnd *scmd)
scsi_print_command(scmd);
- if (!spraid_wait_abnl_cmd_done(iod) || spraid_check_scmd_completed(scmd) ||
- hdev->state != SPRAID_LIVE)
+ if (hdev->state != SPRAID_LIVE || !spraid_wait_abnl_cmd_done(iod) ||
+ spraid_check_scmd_completed(scmd))
return SUCCESS;
hostdata = scmd->device->hostdata;
@@ -3241,8 +3036,8 @@ static int spraid_bus_reset_handler(struct scsi_cmnd *scmd)
scsi_print_command(scmd);
- if (!spraid_wait_abnl_cmd_done(iod) || spraid_check_scmd_completed(scmd) ||
- hdev->state != SPRAID_LIVE)
+ if (hdev->state != SPRAID_LIVE || !spraid_wait_abnl_cmd_done(iod) ||
+ spraid_check_scmd_completed(scmd))
return SUCCESS;
hostdata = scmd->device->hostdata;
@@ -3272,7 +3067,7 @@ static int spraid_shost_reset_handler(struct scsi_cmnd *scmd)
struct spraid_dev *hdev = shost_priv(scmd->device->host);
scsi_print_command(scmd);
- if (spraid_check_scmd_completed(scmd) || hdev->state != SPRAID_LIVE)
+ if (hdev->state != SPRAID_LIVE || spraid_check_scmd_completed(scmd))
return SUCCESS;
spraid_get_tag_from_scmd(scmd, &hwq, &cid);
@@ -3288,6 +3083,62 @@ static int spraid_shost_reset_handler(struct scsi_cmnd *scmd)
return SUCCESS;
}
+static pci_ers_result_t spraid_pci_error_detected(struct pci_dev *pdev,
+ pci_channel_state_t state)
+{
+ struct spraid_dev *hdev = pci_get_drvdata(pdev);
+
+ dev_info(hdev->dev, "enter pci error detect, state:%d\n", state);
+
+ switch (state) {
+ case pci_channel_io_normal:
+ dev_warn(hdev->dev, "channel is normal, do nothing\n");
+
+ return PCI_ERS_RESULT_CAN_RECOVER;
+ case pci_channel_io_frozen:
+ dev_warn(hdev->dev, "channel io frozen, need reset controller\n");
+
+ scsi_block_requests(hdev->shost);
+
+ spraid_change_host_state(hdev, SPRAID_RESETTING);
+
+ return PCI_ERS_RESULT_NEED_RESET;
+ case pci_channel_io_perm_failure:
+ dev_warn(hdev->dev, "channel io failure, request disconnect\n");
+
+ return PCI_ERS_RESULT_DISCONNECT;
+ }
+
+ return PCI_ERS_RESULT_NEED_RESET;
+}
+
+static pci_ers_result_t spraid_pci_slot_reset(struct pci_dev *pdev)
+{
+ struct spraid_dev *hdev = pci_get_drvdata(pdev);
+
+ dev_info(hdev->dev, "restart after slot reset\n");
+
+ pci_restore_state(pdev);
+
+ if (!queue_work(spraid_wq, &hdev->reset_work)) {
+ dev_err(hdev->dev, "[%s] err, the device is resetting state\n", __func__);
+ return PCI_ERS_RESULT_NONE;
+ }
+
+ flush_work(&hdev->reset_work);
+
+ scsi_unblock_requests(hdev->shost);
+
+ return PCI_ERS_RESULT_RECOVERED;
+}
+
+static void spraid_reset_done(struct pci_dev *pdev)
+{
+ struct spraid_dev *hdev = pci_get_drvdata(pdev);
+
+ dev_info(hdev->dev, "enter spraid reset done\n");
+}
+
static ssize_t csts_pp_show(struct device *cdev, struct device_attribute *attr, char *buf)
{
struct Scsi_Host *shost = class_to_shost(cdev);
@@ -3347,7 +3198,7 @@ static ssize_t fw_version_show(struct device *cdev, struct device_attribute *att
struct Scsi_Host *shost = class_to_shost(cdev);
struct spraid_dev *hdev = shost_priv(shost);
- return snprintf(buf, sizeof(hdev->ctrl_info->fr), "%s\n", hdev->ctrl_info->fr);
+ return snprintf(buf, PAGE_SIZE, "%s\n", hdev->ctrl_info->fr);
}
static DEVICE_ATTR_RO(csts_pp);
@@ -3365,6 +3216,185 @@ static struct device_attribute *spraid_host_attrs[] = {
NULL,
};
+static int spraid_get_vd_info(struct spraid_dev *hdev, struct spraid_vd_info *vd_info, u16 vid)
+{
+ struct spraid_admin_command admin_cmd;
+ u8 *data_ptr = NULL;
+ dma_addr_t data_dma = 0;
+ int ret;
+
+ data_ptr = dma_alloc_coherent(hdev->dev, PAGE_SIZE, &data_dma, GFP_KERNEL);
+ if (!data_ptr)
+ return -ENOMEM;
+
+ memset(&admin_cmd, 0, sizeof(admin_cmd));
+ admin_cmd.usr_cmd.opcode = USR_CMD_READ;
+ admin_cmd.usr_cmd.info_0.subopcode = cpu_to_le16(USR_CMD_VDINFO);
+ admin_cmd.usr_cmd.info_1.data_len = cpu_to_le16(USR_CMD_RDLEN);
+ admin_cmd.usr_cmd.info_1.param_len = cpu_to_le16(VDINFO_PARAM_LEN);
+ admin_cmd.usr_cmd.cdw10 = cpu_to_le32(vid);
+ admin_cmd.common.dptr.prp1 = cpu_to_le64(data_dma);
+
+ ret = spraid_submit_admin_sync_cmd(hdev, &admin_cmd, NULL, NULL, 0);
+ if (!ret)
+ memcpy(vd_info, data_ptr, sizeof(struct spraid_vd_info));
+
+ dma_free_coherent(hdev->dev, PAGE_SIZE, data_ptr, data_dma);
+
+ return ret;
+}
+
+static int spraid_get_bgtask(struct spraid_dev *hdev, struct spraid_bgtask *bgtask)
+{
+ struct spraid_admin_command admin_cmd;
+ u8 *data_ptr = NULL;
+ dma_addr_t data_dma = 0;
+ int ret;
+
+ data_ptr = dma_alloc_coherent(hdev->dev, PAGE_SIZE, &data_dma, GFP_KERNEL);
+ if (!data_ptr)
+ return -ENOMEM;
+
+ memset(&admin_cmd, 0, sizeof(admin_cmd));
+ admin_cmd.usr_cmd.opcode = USR_CMD_READ;
+ admin_cmd.usr_cmd.info_0.subopcode = cpu_to_le16(USR_CMD_BGTASK);
+ admin_cmd.usr_cmd.info_1.data_len = cpu_to_le16(USR_CMD_RDLEN);
+ admin_cmd.common.dptr.prp1 = cpu_to_le64(data_dma);
+
+ ret = spraid_submit_admin_sync_cmd(hdev, &admin_cmd, NULL, NULL, 0);
+ if (!ret)
+ memcpy(bgtask, data_ptr, sizeof(struct spraid_bgtask));
+
+ dma_free_coherent(hdev->dev, PAGE_SIZE, data_ptr, data_dma);
+
+ return ret;
+}
+
+static ssize_t raid_level_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct scsi_device *sdev;
+ struct spraid_dev *hdev;
+ struct spraid_vd_info *vd_info;
+ struct spraid_sdev_hostdata *hostdata;
+ int ret;
+
+ sdev = to_scsi_device(dev);
+ hdev = shost_priv(sdev->host);
+ hostdata = sdev->hostdata;
+
+ vd_info = kmalloc(sizeof(*vd_info), GFP_KERNEL);
+ if (!vd_info || !SPRAID_DEV_INFO_ATTR_VD(hostdata->attr))
+ return snprintf(buf, PAGE_SIZE, "NA\n");
+
+ ret = spraid_get_vd_info(hdev, vd_info, sdev->id);
+ if (ret)
+ vd_info->rg_level = ARRAY_SIZE(raid_levels) - 1;
+
+ ret = (vd_info->rg_level < ARRAY_SIZE(raid_levels)) ?
+ vd_info->rg_level : (ARRAY_SIZE(raid_levels) - 1);
+
+ kfree(vd_info);
+
+ return snprintf(buf, PAGE_SIZE, "RAID-%s\n", raid_levels[ret]);
+}
+
+static ssize_t raid_state_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct scsi_device *sdev;
+ struct spraid_dev *hdev;
+ struct spraid_vd_info *vd_info;
+ struct spraid_sdev_hostdata *hostdata;
+ int ret;
+
+ sdev = to_scsi_device(dev);
+ hdev = shost_priv(sdev->host);
+ hostdata = sdev->hostdata;
+
+ vd_info = kmalloc(sizeof(*vd_info), GFP_KERNEL);
+ if (!vd_info || !SPRAID_DEV_INFO_ATTR_VD(hostdata->attr))
+ return snprintf(buf, PAGE_SIZE, "NA\n");
+
+ ret = spraid_get_vd_info(hdev, vd_info, sdev->id);
+ if (ret) {
+ vd_info->vd_status = 0;
+ vd_info->rg_id = 0xff;
+ }
+
+ ret = (vd_info->vd_status < ARRAY_SIZE(raid_states)) ? vd_info->vd_status : 0;
+
+ kfree(vd_info);
+
+ return snprintf(buf, PAGE_SIZE, "%s\n", raid_states[ret]);
+}
+
+static ssize_t raid_resync_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct scsi_device *sdev;
+ struct spraid_dev *hdev;
+ struct spraid_vd_info *vd_info;
+ struct spraid_bgtask *bgtask;
+ struct spraid_sdev_hostdata *hostdata;
+ u8 rg_id, i, progress = 0;
+ int ret;
+
+ sdev = to_scsi_device(dev);
+ hdev = shost_priv(sdev->host);
+ hostdata = sdev->hostdata;
+
+ vd_info = kmalloc(sizeof(*vd_info), GFP_KERNEL);
+ if (!vd_info || !SPRAID_DEV_INFO_ATTR_VD(hostdata->attr))
+ return snprintf(buf, PAGE_SIZE, "NA\n");
+
+ ret = spraid_get_vd_info(hdev, vd_info, sdev->id);
+ if (ret)
+ goto out;
+
+ rg_id = vd_info->rg_id;
+
+ bgtask = (struct spraid_bgtask *)vd_info;
+ ret = spraid_get_bgtask(hdev, bgtask);
+ if (ret)
+ goto out;
+ for (i = 0; i < bgtask->task_num; i++) {
+ if ((bgtask->bgtask[i].type == BGTASK_TYPE_REBUILD) &&
+ (le16_to_cpu(bgtask->bgtask[i].vd_id) == rg_id))
+ progress = bgtask->bgtask[i].progress;
+ }
+
+out:
+ kfree(vd_info);
+ return snprintf(buf, PAGE_SIZE, "%d\n", progress);
+}
+
+static DEVICE_ATTR_RO(raid_level);
+static DEVICE_ATTR_RO(raid_state);
+static DEVICE_ATTR_RO(raid_resync);
+
+static struct device_attribute *spraid_dev_attrs[] = {
+ &dev_attr_raid_level,
+ &dev_attr_raid_state,
+ &dev_attr_raid_resync,
+ NULL,
+};
+
+static struct pci_error_handlers spraid_err_handler = {
+ .error_detected = spraid_pci_error_detected,
+ .slot_reset = spraid_pci_slot_reset,
+ .reset_done = spraid_reset_done,
+};
+
+static int spraid_sysfs_host_reset(struct Scsi_Host *shost, int reset_type)
+{
+ int ret;
+ struct spraid_dev *hdev = shost_priv(shost);
+
+ dev_info(hdev->dev, "[%s] start sysfs host reset cmd\n", __func__);
+ ret = spraid_reset_work_sync(hdev);
+ dev_info(hdev->dev, "[%s] stop sysfs host reset cmd[%d]\n", __func__, ret);
+
+ return ret;
+}
+
static struct scsi_host_template spraid_driver_template = {
.module = THIS_MODULE,
.name = "Ramaxel Logic spraid driver",
@@ -3379,9 +3409,11 @@ static struct scsi_host_template spraid_driver_template = {
.eh_bus_reset_handler = spraid_bus_reset_handler,
.eh_host_reset_handler = spraid_shost_reset_handler,
.change_queue_depth = scsi_change_queue_depth,
- .host_tagset = 1,
+ .host_tagset = 0,
.this_id = -1,
.shost_attrs = spraid_host_attrs,
+ .sdev_attrs = spraid_dev_attrs,
+ .host_reset = spraid_sysfs_host_reset,
};
static void spraid_shutdown(struct pci_dev *pdev)
@@ -3392,11 +3424,53 @@ static void spraid_shutdown(struct pci_dev *pdev)
spraid_disable_admin_queue(hdev, true);
}
+/* bsg dispatch user command */
+static int spraid_bsg_host_dispatch(struct bsg_job *job)
+{
+ struct Scsi_Host *shost = dev_to_shost(job->dev);
+ struct spraid_dev *hdev = shost_priv(shost);
+ struct request *rq = blk_mq_rq_from_pdu(job);
+ struct spraid_bsg_request *bsg_req = job->request;
+ int ret = 0;
+
+ dev_log_dbg(hdev->dev, "[%s] msgcode[%d], msglen[%d], timeout[%d], req_nsge[%d], req_len[%d]\n",
+ __func__, bsg_req->msgcode, job->request_len, rq->timeout,
+ job->request_payload.sg_cnt, job->request_payload.payload_len);
+
+ job->reply_len = 0;
+
+ switch (bsg_req->msgcode) {
+ case SPRAID_BSG_ADM:
+ ret = spraid_user_admin_cmd(hdev, job);
+ break;
+ case SPRAID_BSG_IOQ:
+ ret = spraid_user_ioq_cmd(hdev, job);
+ break;
+ default:
+ dev_info(hdev->dev, "[%s] unsupport msgcode[%d]\n", __func__, bsg_req->msgcode);
+ break;
+ }
+
+ if (ret > 0)
+ ret = ret | (ret << 8);
+
+ bsg_job_done(job, ret, 0);
+ return 0;
+}
+
+static inline void spraid_remove_bsg(struct spraid_dev *hdev)
+{
+ if (hdev->bsg_queue) {
+ bsg_unregister_queue(hdev->bsg_queue);
+ blk_cleanup_queue(hdev->bsg_queue);
+ }
+}
static int spraid_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{
struct spraid_dev *hdev;
struct Scsi_Host *shost;
int node, ret;
+ char bsg_name[15];
shost = scsi_host_alloc(&spraid_driver_template, sizeof(*hdev));
if (!shost) {
@@ -3421,10 +3495,10 @@ static int spraid_probe(struct pci_dev *pdev, const struct pci_device_id *id)
goto put_dev;
init_rwsem(&hdev->devices_rwsem);
- INIT_WORK(&hdev->aen_work, spraid_async_event_work);
INIT_WORK(&hdev->scan_work, spraid_scan_work);
INIT_WORK(&hdev->timesyn_work, spraid_timesyn_work);
INIT_WORK(&hdev->reset_work, spraid_reset_work);
+ INIT_WORK(&hdev->fw_act_work, spraid_fw_act_work);
spin_lock_init(&hdev->state_lock);
ret = spraid_alloc_resources(hdev);
@@ -3439,17 +3513,13 @@ static int spraid_probe(struct pci_dev *pdev, const struct pci_device_id *id)
if (ret)
goto pci_disable;
- ret = spraid_alloc_admin_tags(hdev);
- if (ret)
- goto disable_admin_q;
-
ret = spraid_init_ctrl_info(hdev);
if (ret)
- goto free_admin_tagset;
+ goto disable_admin_q;
ret = spraid_alloc_iod_ext_mem_pool(hdev);
if (ret)
- goto free_admin_tagset;
+ goto disable_admin_q;
ret = spraid_setup_io_queues(hdev);
if (ret)
@@ -3464,9 +3534,15 @@ static int spraid_probe(struct pci_dev *pdev, const struct pci_device_id *id)
goto remove_io_queues;
}
- ret = spraid_create_cdev(hdev);
- if (ret)
+ snprintf(bsg_name, sizeof(bsg_name), "spraid%d", shost->host_no);
+ hdev->bsg_queue = bsg_setup_queue(&shost->shost_gendev, bsg_name,
+ spraid_bsg_host_dispatch, NULL,
+ spraid_cmd_size(hdev, true, false));
+ if (IS_ERR(hdev->bsg_queue)) {
+ dev_err(hdev->dev, "err, setup bsg failed\n");
+ hdev->bsg_queue = NULL;
goto remove_io_queues;
+ }
if (hdev->online_queues == SPRAID_ADMIN_QUEUE_NUM) {
dev_warn(hdev->dev, "warn only admin queue can be used\n");
@@ -3475,11 +3551,11 @@ static int spraid_probe(struct pci_dev *pdev, const struct pci_device_id *id)
hdev->state = SPRAID_LIVE;
- spraid_send_aen(hdev);
+ spraid_send_all_aen(hdev);
ret = spraid_dev_list_init(hdev);
if (ret)
- goto remove_cdev;
+ goto remove_bsg;
ret = spraid_configure_timestamp(hdev);
if (ret)
@@ -3487,20 +3563,18 @@ static int spraid_probe(struct pci_dev *pdev, const struct pci_device_id *id)
ret = spraid_alloc_ioq_ptcmds(hdev);
if (ret)
- goto remove_cdev;
+ goto remove_bsg;
scsi_scan_host(hdev->shost);
return 0;
-remove_cdev:
- spraid_remove_cdev(hdev);
+remove_bsg:
+ spraid_remove_bsg(hdev);
remove_io_queues:
spraid_remove_io_queues(hdev);
free_iod_mempool:
spraid_free_iod_ext_mem_pool(hdev);
-free_admin_tagset:
- spraid_remove_admin_tagset(hdev);
disable_admin_q:
spraid_disable_admin_queue(hdev, false);
pci_disable:
@@ -3524,22 +3598,17 @@ static void spraid_remove(struct pci_dev *pdev)
dev_info(hdev->dev, "enter spraid remove\n");
spraid_change_host_state(hdev, SPRAID_DELETING);
+ flush_work(&hdev->reset_work);
- if (!pci_device_is_present(pdev)) {
- scsi_block_requests(shost);
+ if (!pci_device_is_present(pdev))
spraid_back_all_io(hdev);
- scsi_unblock_requests(shost);
- }
- flush_work(&hdev->reset_work);
+ spraid_remove_bsg(hdev);
scsi_remove_host(shost);
-
- kfree(hdev->ioq_ptcmds);
+ spraid_free_ioq_ptcmds(hdev);
kfree(hdev->devices);
- spraid_remove_cdev(hdev);
spraid_remove_io_queues(hdev);
spraid_free_iod_ext_mem_pool(hdev);
- spraid_remove_admin_tagset(hdev);
spraid_disable_admin_queue(hdev, false);
spraid_pci_disable(hdev);
spraid_free_resources(hdev);
@@ -3551,7 +3620,7 @@ static void spraid_remove(struct pci_dev *pdev)
}
static const struct pci_device_id spraid_id_table[] = {
- { PCI_DEVICE(PCI_VENDOR_ID_RAMAXEL_LOGIC, SPRAID_SERVER_DEVICE_HAB_DID) },
+ { PCI_DEVICE(PCI_VENDOR_ID_RAMAXEL_LOGIC, SPRAID_SERVER_DEVICE_HBA_DID) },
{ PCI_DEVICE(PCI_VENDOR_ID_RAMAXEL_LOGIC, SPRAID_SERVER_DEVICE_RAID_DID) },
{ 0, }
};
@@ -3563,6 +3632,7 @@ static struct pci_driver spraid_driver = {
.probe = spraid_probe,
.remove = spraid_remove,
.shutdown = spraid_shutdown,
+ .err_handler = &spraid_err_handler,
};
static int __init spraid_init(void)
@@ -3573,14 +3643,10 @@ static int __init spraid_init(void)
if (!spraid_wq)
return -ENOMEM;
- ret = alloc_chrdev_region(&spraid_chr_devt, 0, SPRAID_MINORS, "spraid");
- if (ret < 0)
- goto destroy_wq;
-
spraid_class = class_create(THIS_MODULE, "spraid");
if (IS_ERR(spraid_class)) {
ret = PTR_ERR(spraid_class);
- goto unregister_chrdev;
+ goto destroy_wq;
}
ret = pci_register_driver(&spraid_driver);
@@ -3591,8 +3657,6 @@ static int __init spraid_init(void)
destroy_class:
class_destroy(spraid_class);
-unregister_chrdev:
- unregister_chrdev_region(spraid_chr_devt, SPRAID_MINORS);
destroy_wq:
destroy_workqueue(spraid_wq);
@@ -3603,12 +3667,11 @@ static void __exit spraid_exit(void)
{
pci_unregister_driver(&spraid_driver);
class_destroy(spraid_class);
- unregister_chrdev_region(spraid_chr_devt, SPRAID_MINORS);
destroy_workqueue(spraid_wq);
ida_destroy(&spraid_instance_ida);
}
-MODULE_AUTHOR("Ramaxel Memory Technology");
+MODULE_AUTHOR("songyl(a)ramaxel.com");
MODULE_DESCRIPTION("Ramaxel Memory Technology SPraid Driver");
MODULE_LICENSE("GPL");
MODULE_VERSION(SPRAID_DRV_VERSION);
--
2.32.0
2
1
Ramaxel inclusion
category: features
bugzilla: https://gitee.com/openeuler/kernel/issues/I4ON8F
CVE: NA
Changes:
1. Split scmd_tmout_nonpt into two parameters:
scmd_tmout_vd/scmd_tmout_rawdisk
2. Return -ETIME instead of -EINVAL when command is timeout.
3. Add one module parameters: max_io_force.
Signed-off-by: Yanling Song <songyl(a)ramaxel.com>
Reviewed-by: Jiang Yu<yujiang(a)ramaxel.com>
---
drivers/scsi/spraid/spraid_main.c | 96 +++++++++++++++----------------
1 file changed, 45 insertions(+), 51 deletions(-)
diff --git a/drivers/scsi/spraid/spraid_main.c b/drivers/scsi/spraid/spraid_main.c
index 519b39f44e91..7069582d741a 100644
--- a/drivers/scsi/spraid/spraid_main.c
+++ b/drivers/scsi/spraid/spraid_main.c
@@ -42,10 +42,17 @@ static u32 admin_tmout = 60;
module_param(admin_tmout, uint, 0644);
MODULE_PARM_DESC(admin_tmout, "admin commands timeout (seconds)");
-static u32 scmd_tmout_nonpt = 180;
-module_param(scmd_tmout_nonpt, uint, 0644);
-MODULE_PARM_DESC(scmd_tmout_nonpt,
- "scsi commands timeout for rawdisk&raid(seconds)");
+static u32 scmd_tmout_rawdisk = 180;
+module_param(scmd_tmout_rawdisk, uint, 0644);
+MODULE_PARM_DESC(scmd_tmout_rawdisk, "scsi commands timeout for rawdisk(seconds)");
+
+static u32 scmd_tmout_vd = 180;
+module_param(scmd_tmout_vd, uint, 0644);
+MODULE_PARM_DESC(scmd_tmout_vd, "scsi commands timeout for vd(seconds)");
+
+static bool max_io_force;
+module_param(max_io_force, bool, 0644);
+MODULE_PARM_DESC(max_io_force, "force max_hw_sectors_kb = 1024, default false(performance first)");
static int ioq_depth_set(const char *val, const struct kernel_param *kp);
static const struct kernel_param_ops ioq_depth_ops = {
@@ -78,7 +85,7 @@ static unsigned char log_debug_switch;
module_param_cb(log_debug_switch, &log_debug_switch_ops,
&log_debug_switch, 0644);
MODULE_PARM_DESC(log_debug_switch,
- "set log state, default non-zero for switch on");
+ "set log state, default zero for switch off");
static int small_pool_num_set(const char *val, const struct kernel_param *kp)
{
@@ -132,7 +139,6 @@ static struct workqueue_struct *spraid_wq;
#define SPRAID_DRV_VERSION "1.0.0.0"
#define ADMIN_TIMEOUT (admin_tmout * HZ)
-#define ADMIN_ERR_TIMEOUT 32757
#define SPRAID_WAIT_ABNL_CMD_TIMEOUT (3 * 2)
@@ -242,13 +248,6 @@ static int spraid_pci_enable(struct spraid_dev *hdev)
goto disable;
}
- ret = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_ALL_TYPES);
- if (ret < 0) {
- dev_err(hdev->dev,
- "Allocate one IRQ for setup admin channel failed\n");
- goto disable;
- }
-
hdev->cap = lo_hi_readq(hdev->bar + SPRAID_REG_CAP);
hdev->ioq_depth = min_t(u32, SPRAID_CAP_MQES(hdev->cap) + 1,
io_queue_depth);
@@ -261,13 +260,21 @@ static int spraid_pci_enable(struct spraid_dev *hdev)
maskbit);
maskbit = SPRAID_DMA_MSK_BIT_MAX;
}
- if (dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(maskbit))) {
+ if (dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(maskbit)) &&
+ dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32))) {
dev_err(hdev->dev, "set dma mask and coherent failed\n");
goto disable;
}
dev_info(hdev->dev, "set dma mask[%llu] success\n", maskbit);
+ ret = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_ALL_TYPES);
+
+ if (ret < 0) {
+ dev_err(hdev->dev, "Allocate one IRQ for setup admin channel failed\n");
+ goto disable;
+ }
+
pci_enable_pcie_error_reporting(pdev);
pci_save_state(pdev);
@@ -840,6 +847,9 @@ static void spraid_map_status(struct spraid_iod *iod, struct scsi_cmnd *scmd,
break;
default:
set_host_byte(scmd, DID_BAD_TARGET);
+ dev_warn(iod->spraidq->hdev->dev, "[%s] cid[%d] qid[%d];"
+ "bad status[0x%x]\n", __func__, cqe->cmd_id,
+ le16_to_cpu(cqe->sq_id), le16_to_cpu(cqe->status));
break;
}
}
@@ -981,32 +991,17 @@ static void spraid_slave_destroy(struct scsi_device *sdev)
static int spraid_slave_configure(struct scsi_device *sdev)
{
- u16 idx;
- unsigned int timeout = scmd_tmout_nonpt * HZ;
+ unsigned int timeout = scmd_tmout_rawdisk * HZ;
struct spraid_dev *hdev = shost_priv(sdev->host);
struct spraid_sdev_hostdata *hostdata = sdev->hostdata;
u32 max_sec = sdev->host->max_sectors;
if (hostdata) {
- idx = hostdata->hdid - 1;
- if (sdev->channel == hdev->devices[idx].channel &&
- sdev->id == le16_to_cpu(hdev->devices[idx].target) &&
- sdev->lun < hdev->devices[idx].lun) {
- if (SPRAID_DEV_INFO_ATTR_PT(hdev->devices[idx].attr))
- timeout = 30 * HZ;
- else
- timeout = scmd_tmout_nonpt * HZ;
- max_sec = le16_to_cpu(hdev->devices[idx].max_io_kb)
- << 1;
- } else {
- dev_err(hdev->dev,
- "[%s] err, sdev->channel:id:lun[%d:%d:%lld];"
- "devices[%d], channel:target:lun[%d:%d:%d]\n",
- __func__, sdev->channel, sdev->id, sdev->lun,
- idx, hdev->devices[idx].channel,
- hdev->devices[idx].target,
- hdev->devices[idx].lun);
- }
+ if (SPRAID_DEV_INFO_ATTR_VD(hostdata->attr))
+ timeout = scmd_tmout_vd * HZ;
+ else if (SPRAID_DEV_INFO_ATTR_RAWDISK(hostdata->attr))
+ timeout = scmd_tmout_rawdisk * HZ;
+ max_sec = hostdata->max_io_kb << 1;
} else {
dev_err(hdev->dev, "[%s] err, sdev->hostdata is null\n",
__func__);
@@ -1018,11 +1013,12 @@ static int spraid_slave_configure(struct scsi_device *sdev)
if ((max_sec == 0) || (max_sec > sdev->host->max_sectors))
max_sec = sdev->host->max_sectors;
- dev_info(hdev->dev,
- "[%s] sdev->channel:id:lun[%d:%d:%lld];"
- " scmd_timeout[%d]s, maxsec[%d]\n",
- __func__, sdev->channel, sdev->id,
- sdev->lun, timeout / HZ, max_sec);
+ if (!max_io_force)
+ blk_queue_max_hw_sectors(sdev->request_queue, max_sec);
+
+ dev_info(hdev->dev, "[%s] sdev->channel:id:lun[%d:%d:%lld];"
+ "scmd_timeout[%d]s, maxsec[%d]\n", __func__, sdev->channel,
+ sdev->id, sdev->lun, timeout / HZ, max_sec);
return 0;
}
@@ -1677,7 +1673,7 @@ static int spraid_submit_admin_sync_cmd(struct spraid_dev *hdev,
cmd->usr_cmd.opcode, cmd->usr_cmd.info_0.subopcode);
WRITE_ONCE(adm_cmd->state, SPRAID_CMD_TIMEOUT);
spraid_put_cmd(hdev, adm_cmd, SPRAID_CMD_ADM);
- return -EINVAL;
+ return -ETIME;
}
if (result0)
@@ -2630,9 +2626,6 @@ static int spraid_user_admin_cmd(struct spraid_dev *hdev, struct bsg_job *job)
return -EBUSY;
}
- dev_info(hdev->dev, "[%s] opcode[0x%x] subopcode[0x%x] init\n",
- __func__, cmd->opcode, cmd->info_0.subopcode);
-
memset(&admin_cmd, 0, sizeof(admin_cmd));
admin_cmd.common.opcode = cmd->opcode;
admin_cmd.common.flags = cmd->flags;
@@ -2659,10 +2652,11 @@ static int spraid_user_admin_cmd(struct spraid_dev *hdev, struct bsg_job *job)
memcpy(job->reply, result, sizeof(result));
}
- dev_info(hdev->dev, "[%s] opcode[0x%x] subopcode[0x%x];"
- " status[0x%x] result0[0x%x] result1[0x%x]\n",
- __func__, cmd->opcode, cmd->info_0.subopcode,
- status, result[0], result[1]);
+ if (status)
+ dev_info(hdev->dev, "[%s] opcode[0x%x] subopcode[0x%x];"
+ " status[0x%x] result0[0x%x] result1[0x%x]\n",
+ __func__, cmd->opcode, cmd->info_0.subopcode,
+ status, result[0], result[1]);
spraid_bsg_unmap_data(hdev, job);
@@ -2742,7 +2736,7 @@ static int spraid_submit_ioq_sync_cmd(struct spraid_dev *hdev,
(le32_to_cpu(cmd->common.cdw3[0]) & 0xffff));
WRITE_ONCE(pt_cmd->state, SPRAID_CMD_TIMEOUT);
spraid_put_cmd(hdev, pt_cmd, SPRAID_CMD_IOPT);
- return -EINVAL;
+ return -ETIME;
}
if (result && reslen) {
@@ -3140,7 +3134,7 @@ static int spraid_abort_handler(struct scsi_cmnd *scmd)
dev_warn(hdev->dev, "cid[%d] qid[%d] timeout, aborting\n", cid, hwq);
ret = spraid_send_abort_cmd(hdev, hostdata->hdid, hwq, cid);
- if (ret != ADMIN_ERR_TIMEOUT) {
+ if (ret != -ETIME) {
ret = spraid_wait_abnl_cmd_done(iod);
if (ret) {
dev_warn(hdev->dev, "cid[%d] qid[%d] abort failed;"
@@ -3623,7 +3617,7 @@ static int spraid_bsg_host_dispatch(struct bsg_job *job)
struct spraid_bsg_request *bsg_req = job->request;
int ret = 0;
- dev_info(hdev->dev, "[%s] msgcode[%d], msglen[%d], timeout[%d];"
+ dev_log_dbg(hdev->dev, "[%s] msgcode[%d], msglen[%d], timeout[%d];"
" req_nsge[%d], req_len[%d]\n",
__func__, bsg_req->msgcode, job->request_len,
rq->timeout, job->request_payload.sg_cnt,
--
2.27.0
1
0
[PATCH openEuler-5.10 1/2] kabi: reserve space for arm64 cpufeature related structure
by Zheng Zengkai 04 Jan '22
by Zheng Zengkai 04 Jan '22
04 Jan '22
From: Jialin Zhang <zhangjialin11(a)huawei.com>
hulk inclusion
category: feature
bugzilla: https://gitee.com/openeuler/kernel/issues/I4JBL0
CVE: NA
-------------------------------
Reserve space for the structure cpu_hwcap_keys and cpu_hwcaps.
Signed-off-by: Jialin Zhang <zhangjialin11(a)huawei.com>
Reviewed-by: wangxiongfeng <wangxiongfeng2(a)huawei.com>
Reviewed-by: Yang Yingliang <yangyingliang(a)huawei.com>
Reviewed-by: Hanjun Guo <guohanjun(a)huawei.com>
Signed-off-by: Zheng Zengkai <zhengzengkai(a)huawei.com>
---
arch/arm64/include/asm/cpucaps.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/arm64/include/asm/cpucaps.h b/arch/arm64/include/asm/cpucaps.h
index 93bae3795165..c58a1919bfc9 100644
--- a/arch/arm64/include/asm/cpucaps.h
+++ b/arch/arm64/include/asm/cpucaps.h
@@ -72,6 +72,6 @@
#define ARM64_HAS_TWED 62
#define ARM64_WORKAROUND_HISILICON_1980005 63
-#define ARM64_NCAPS 64
+#define ARM64_NCAPS 80
#endif /* __ASM_CPUCAPS_H */
--
2.20.1
1
1
04 Jan '22
From: Linus Walleij <linus.walleij(a)linaro.org>
mainline inclusion
from mainline-v5.3-rc1
commit b3198c38f02d54a5e964258a2180d502abe6eaf0
category: bugfix
bugzilla: https://gitee.com/openeuler/kernel/issues/I4P7YB
CVE: N/A
---
The 50 ms default timeout waiting for vblanks is too small
for the first vblank from the ST-Ericsson MCDE display
controller over DSI. Presumably this is because the DSI
display is command-mode only and the state machine will
take some time setting up its state for the first display
update, and we hit a timeout. 100 ms makes it pass without
problems.
Signed-off-by: Linus Walleij <linus.walleij(a)linaro.org>
Reviewed-by: Ville Syrjälä <ville.syrjala(a)linux.intel.com>
Reviewed-by: Daniel Vetter <daniel.vetter(a)ffwll.ch>
Link: https://patchwork.freedesktop.org/patch/msgid/20190430093746.26485-1-linus.…
Signed-off-by: Gou Hao <gouhao(a)uniontech.com>
---
drivers/gpu/drm/drm_atomic_helper.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c
index 86efd2da37f9..553415fe8ede 100644
--- a/drivers/gpu/drm/drm_atomic_helper.c
+++ b/drivers/gpu/drm/drm_atomic_helper.c
@@ -1424,7 +1424,7 @@ drm_atomic_helper_wait_for_vblanks(struct drm_device *dev,
ret = wait_event_timeout(dev->vblank[i].queue,
old_state->crtcs[i].last_vblank_count !=
drm_crtc_vblank_count(crtc),
- msecs_to_jiffies(50));
+ msecs_to_jiffies(100));
WARN(!ret, "[CRTC:%d:%s] vblank wait timed out\n",
crtc->base.id, crtc->name);
--
2.20.1
1
0
04 Jan '22
From: Linus Walleij <linus.walleij(a)linaro.org>
mainline inclusion
from mainline-v5.3-rc1
commit b3198c38f02d54a5e964258a2180d502abe6eaf0
category: bugfix
bugzilla: https://gitee.com/openeuler/kernel/issues/I4P7YB
CVE: N/A
---
The 50 ms default timeout waiting for vblanks is too small
for the first vblank from the ST-Ericsson MCDE display
controller over DSI. Presumably this is because the DSI
display is command-mode only and the state machine will
take some time setting up its state for the first display
update, and we hit a timeout. 100 ms makes it pass without
problems.
Signed-off-by: Linus Walleij <linus.walleij(a)linaro.org>
Reviewed-by: Ville Syrjälä <ville.syrjala(a)linux.intel.com>
Reviewed-by: Daniel Vetter <daniel.vetter(a)ffwll.ch>
Link: https://patchwork.freedesktop.org/patch/msgid/20190430093746.26485-1-linus.…
Signed-off-by: Gou Hao <gouhao(a)uniontech.com>
---
drivers/gpu/drm/drm_atomic_helper.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c
index 86efd2da37f9..553415fe8ede 100644
--- a/drivers/gpu/drm/drm_atomic_helper.c
+++ b/drivers/gpu/drm/drm_atomic_helper.c
@@ -1424,7 +1424,7 @@ drm_atomic_helper_wait_for_vblanks(struct drm_device *dev,
ret = wait_event_timeout(dev->vblank[i].queue,
old_state->crtcs[i].last_vblank_count !=
drm_crtc_vblank_count(crtc),
- msecs_to_jiffies(50));
+ msecs_to_jiffies(100));
WARN(!ret, "[CRTC:%d:%s] vblank wait timed out\n",
crtc->base.id, crtc->name);
--
2.20.1
1
0
From: Zhang Jian <zhangjian210(a)huawei.com>
ascend inclusion
category: feature
bugzilla: https://gitee.com/openeuler/kernel/issues/I4OXH9
CVE: NA
-------------------------------------------------
Collect the processes who have the page mapped via collect_procs().
@page if the page is a part of the hugepages/compound-page, we must
using compound_head() to find it's head page to prevent the kernel panic,
and make the page be locked.
@to_kill the function will return a linked list, when we have used
this list, we must kfree the list.
@force_early if we want to find all process, we must make it be true, if
it's false, the function will only return the process who have PF_MCE_PROCESS
or PF_MCE_EARLY mark.
limits: if force_early is true, sysctl_memory_failure_early_kill is useless.
If it's false, no process have PF_MCE_PROCESS and PF_MCE_EARLY flag, and
the sysctl_memory_failure_early_kill is enabled, function will return all tasks
whether the task have the PF_MCE_PROCESS and PF_MCE_EARLY flag.
Signed-off-by: Zhang Jian <zhangjian210(a)huawei.com>
Reviewed-by: Weilong Chen <chenweilong(a)huawei.com>
Reviewed-by: Kefeng Wang<wangkefeng.wang(a)huawei.com>
Signed-off-by: Yang Yingliang <yangyingliang(a)huawei.com>
---
include/linux/mm.h | 2 ++
mm/memory-failure.c | 3 ++-
2 files changed, 4 insertions(+), 1 deletion(-)
diff --git a/include/linux/mm.h b/include/linux/mm.h
index f801fa5e60289..7b724d39e6ee0 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -2866,6 +2866,8 @@ extern int sysctl_memory_failure_recovery;
extern void shake_page(struct page *p, int access);
extern atomic_long_t num_poisoned_pages __read_mostly;
extern int soft_offline_page(struct page *page, int flags);
+extern void collect_procs(struct page *page, struct list_head *tokill,
+ int force_early);
/*
diff --git a/mm/memory-failure.c b/mm/memory-failure.c
index 52619a9bc3b0e..72e1746e5386f 100644
--- a/mm/memory-failure.c
+++ b/mm/memory-failure.c
@@ -512,7 +512,7 @@ static void collect_procs_file(struct page *page, struct list_head *to_kill,
* First preallocate one tokill structure outside the spin locks,
* so that we can kill at least one process reasonably reliable.
*/
-static void collect_procs(struct page *page, struct list_head *tokill,
+void collect_procs(struct page *page, struct list_head *tokill,
int force_early)
{
struct to_kill *tk;
@@ -529,6 +529,7 @@ static void collect_procs(struct page *page, struct list_head *tokill,
collect_procs_file(page, tokill, &tk, force_early);
kfree(tk);
}
+EXPORT_SYMBOL_GPL(collect_procs);
static const char *action_name[] = {
[MF_IGNORED] = "Ignored",
--
2.25.1
1
0
31 Dec '21
This initial commit contains Ramaxel's spraid module.
Signed-off-by: Yanling Song <songyl(a)ramaxel.com>
Changes from V3:
1. Use macro to repalce scmd_tmout_nonpt module parameter.
Changes from V2:
1. Change "depends BLK_DEV_BSGLIB" to "select BLK_DEV_BSGLIB".
2. Add more descriptions in help.
3. Use pr_debug() instead of introducing dev_log_dbg().
4. Use get_unaligned_be*() in spraid_setup_rw_cmd();
5. Remove some unncessarry module parameters:
scmd_tmout_pt, wait_abl_tmout, use_sgl_force
6. Some module parameters will be changed in the next version:
admin_tmout, scmd_tmout_nonpt
Changes from V1:
1. Use BSG module to replace with ioctrl
2. Use author's email as MODULE_AUTHOR
3. Remove "default=m" in drivers/scsi/spraid/Kconfig
4. To be changed in the next version:
a. Use get_unaligned_be*() in spraid_setup_rw_cmd();
b. Use pr_debug() instead of introducing dev_log_dbg().
---
Documentation/scsi/spraid.rst | 16 +
MAINTAINERS | 7 +
drivers/scsi/Kconfig | 1 +
drivers/scsi/Makefile | 1 +
drivers/scsi/spraid/Kconfig | 13 +
drivers/scsi/spraid/Makefile | 7 +
drivers/scsi/spraid/spraid.h | 695 ++++++
drivers/scsi/spraid/spraid_main.c | 3266 +++++++++++++++++++++++++++++
8 files changed, 4006 insertions(+)
create mode 100644 Documentation/scsi/spraid.rst
create mode 100644 drivers/scsi/spraid/Kconfig
create mode 100644 drivers/scsi/spraid/Makefile
create mode 100644 drivers/scsi/spraid/spraid.h
create mode 100644 drivers/scsi/spraid/spraid_main.c
diff --git a/Documentation/scsi/spraid.rst b/Documentation/scsi/spraid.rst
new file mode 100644
index 000000000000..f87b02a6907b
--- /dev/null
+++ b/Documentation/scsi/spraid.rst
@@ -0,0 +1,16 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+==============================================
+SPRAID - Ramaxel SCSI Raid Controller driver
+==============================================
+
+This file describes the spraid SCSI driver for Ramaxel
+raid controllers. The spraid driver is the first generation raid driver for
+Ramaxel Corp.
+
+For Ramaxel spraid controller support, enable the spraid driver
+when configuring the kernel.
+
+Supported devices
+=================
+<Controller names to be added as they become publicly available.>
diff --git a/MAINTAINERS b/MAINTAINERS
index 57f7656fe513..68560008b259 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -17973,6 +17973,13 @@ F: include/dt-bindings/spmi/spmi.h
F: include/linux/spmi.h
F: include/trace/events/spmi.h
+SPRAID SCSI/Raid DRIVERS
+M: Yanling Song <yanling.song(a)ramaxel.com>
+L: linux-scsi(a)vger.kernel.org
+S: Maintained
+F: Documentation/scsi/spraid.rst
+F: drivers/scsi/spraid/
+
SPU FILE SYSTEM
M: Jeremy Kerr <jk(a)ozlabs.org>
L: linuxppc-dev(a)lists.ozlabs.org
diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
index 6e3a04107bb6..3da5d26e1e11 100644
--- a/drivers/scsi/Kconfig
+++ b/drivers/scsi/Kconfig
@@ -501,6 +501,7 @@ source "drivers/scsi/mpt3sas/Kconfig"
source "drivers/scsi/mpi3mr/Kconfig"
source "drivers/scsi/smartpqi/Kconfig"
source "drivers/scsi/ufs/Kconfig"
+source "drivers/scsi/spraid/Kconfig"
config SCSI_HPTIOP
tristate "HighPoint RocketRAID 3xxx/4xxx Controller support"
diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile
index 19814c26c908..192f8fb10a19 100644
--- a/drivers/scsi/Makefile
+++ b/drivers/scsi/Makefile
@@ -96,6 +96,7 @@ obj-$(CONFIG_SCSI_ZALON) += zalon7xx.o
obj-$(CONFIG_SCSI_DC395x) += dc395x.o
obj-$(CONFIG_SCSI_AM53C974) += esp_scsi.o am53c974.o
obj-$(CONFIG_CXLFLASH) += cxlflash/
+obj-$(CONFIG_RAMAXEL_SPRAID) += spraid/
obj-$(CONFIG_MEGARAID_LEGACY) += megaraid.o
obj-$(CONFIG_MEGARAID_NEWGEN) += megaraid/
obj-$(CONFIG_MEGARAID_SAS) += megaraid/
diff --git a/drivers/scsi/spraid/Kconfig b/drivers/scsi/spraid/Kconfig
new file mode 100644
index 000000000000..bfbba3db8db0
--- /dev/null
+++ b/drivers/scsi/spraid/Kconfig
@@ -0,0 +1,13 @@
+#
+# Ramaxel driver configuration
+#
+
+config RAMAXEL_SPRAID
+ tristate "Ramaxel spraid Adapter"
+ depends on PCI && SCSI
+ select BLK_DEV_BSGLIB
+ depends on ARM64 || X86_64
+ help
+ This driver supports Ramaxel SPRxxx serial
+ raid controller, which has PCIE Gen4 interface
+ with host and supports SAS/SATA Hdd/ssd.
diff --git a/drivers/scsi/spraid/Makefile b/drivers/scsi/spraid/Makefile
new file mode 100644
index 000000000000..ad2c2a84ddaf
--- /dev/null
+++ b/drivers/scsi/spraid/Makefile
@@ -0,0 +1,7 @@
+#
+# Makefile for the Ramaxel device drivers.
+#
+
+obj-$(CONFIG_RAMAXEL_SPRAID) += spraid.o
+
+spraid-objs := spraid_main.o
diff --git a/drivers/scsi/spraid/spraid.h b/drivers/scsi/spraid/spraid.h
new file mode 100644
index 000000000000..617f5c2cdb82
--- /dev/null
+++ b/drivers/scsi/spraid/spraid.h
@@ -0,0 +1,695 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */
+
+#ifndef __SPRAID_H_
+#define __SPRAID_H_
+
+#define SPRAID_CAP_MQES(cap) ((cap) & 0xffff)
+#define SPRAID_CAP_STRIDE(cap) (((cap) >> 32) & 0xf)
+#define SPRAID_CAP_MPSMIN(cap) (((cap) >> 48) & 0xf)
+#define SPRAID_CAP_MPSMAX(cap) (((cap) >> 52) & 0xf)
+#define SPRAID_CAP_TIMEOUT(cap) (((cap) >> 24) & 0xff)
+#define SPRAID_CAP_DMAMASK(cap) (((cap) >> 37) & 0xff)
+
+#define SPRAID_DEFAULT_MAX_CHANNEL 4
+#define SPRAID_DEFAULT_MAX_ID 240
+#define SPRAID_DEFAULT_MAX_LUN_PER_HOST 8
+#define MAX_SECTORS 2048
+
+#define IO_SQE_SIZE sizeof(struct spraid_ioq_command)
+#define ADMIN_SQE_SIZE sizeof(struct spraid_admin_command)
+#define SQE_SIZE(qid) (((qid) > 0) ? IO_SQE_SIZE : ADMIN_SQE_SIZE)
+#define CQ_SIZE(depth) ((depth) * sizeof(struct spraid_completion))
+#define SQ_SIZE(qid, depth) ((depth) * SQE_SIZE(qid))
+
+#define SENSE_SIZE(depth) ((depth) * SCSI_SENSE_BUFFERSIZE)
+
+#define SPRAID_AQ_DEPTH 128
+#define SPRAID_NR_AEN_COMMANDS 16
+#define SPRAID_AQ_BLK_MQ_DEPTH (SPRAID_AQ_DEPTH - SPRAID_NR_AEN_COMMANDS)
+#define SPRAID_AQ_MQ_TAG_DEPTH (SPRAID_AQ_BLK_MQ_DEPTH - 1)
+
+#define SPRAID_ADMIN_QUEUE_NUM 1
+#define SPRAID_PTCMDS_PERQ 1
+#define SPRAID_IO_BLK_MQ_DEPTH (hdev->shost->can_queue)
+#define SPRAID_NR_IOQ_PTCMDS (SPRAID_PTCMDS_PERQ * hdev->shost->nr_hw_queues)
+
+#define FUA_MASK 0x08
+#define SPRAID_MINORS BIT(MINORBITS)
+
+#define COMMAND_IS_WRITE(cmd) ((cmd)->common.opcode & 1)
+
+#define SPRAID_IO_IOSQES 7
+#define SPRAID_IO_IOCQES 4
+#define PRP_ENTRY_SIZE 8
+
+#define SMALL_POOL_SIZE 256
+#define MAX_SMALL_POOL_NUM 16
+#define MAX_CMD_PER_DEV 64
+#define MAX_CDB_LEN 32
+
+#define SPRAID_UP_TO_MULTY4(x) (((x) + 4) & (~0x03))
+
+#define CQE_STATUS_SUCCESS (0x0)
+
+#define PCI_VENDOR_ID_RAMAXEL_LOGIC 0x1E81
+
+#define SPRAID_SERVER_DEVICE_HBA_DID 0x2100
+#define SPRAID_SERVER_DEVICE_RAID_DID 0x2200
+
+#define IO_6_DEFAULT_TX_LEN 256
+
+#define SPRAID_INT_PAGES 2
+#define SPRAID_INT_BYTES(hdev) (SPRAID_INT_PAGES * (hdev)->page_size)
+
+enum {
+ SPRAID_REQ_CANCELLED = (1 << 0),
+ SPRAID_REQ_USERCMD = (1 << 1),
+};
+
+enum {
+ SPRAID_SC_SUCCESS = 0x0,
+ SPRAID_SC_INVALID_OPCODE = 0x1,
+ SPRAID_SC_INVALID_FIELD = 0x2,
+
+ SPRAID_SC_ABORT_LIMIT = 0x103,
+ SPRAID_SC_ABORT_MISSING = 0x104,
+ SPRAID_SC_ASYNC_LIMIT = 0x105,
+
+ SPRAID_SC_DNR = 0x4000,
+};
+
+enum {
+ SPRAID_REG_CAP = 0x0000,
+ SPRAID_REG_CC = 0x0014,
+ SPRAID_REG_CSTS = 0x001c,
+ SPRAID_REG_AQA = 0x0024,
+ SPRAID_REG_ASQ = 0x0028,
+ SPRAID_REG_ACQ = 0x0030,
+ SPRAID_REG_DBS = 0x1000,
+};
+
+enum {
+ SPRAID_CC_ENABLE = 1 << 0,
+ SPRAID_CC_CSS_NVM = 0 << 4,
+ SPRAID_CC_MPS_SHIFT = 7,
+ SPRAID_CC_AMS_SHIFT = 11,
+ SPRAID_CC_SHN_SHIFT = 14,
+ SPRAID_CC_IOSQES_SHIFT = 16,
+ SPRAID_CC_IOCQES_SHIFT = 20,
+ SPRAID_CC_AMS_RR = 0 << SPRAID_CC_AMS_SHIFT,
+ SPRAID_CC_SHN_NONE = 0 << SPRAID_CC_SHN_SHIFT,
+ SPRAID_CC_IOSQES = SPRAID_IO_IOSQES << SPRAID_CC_IOSQES_SHIFT,
+ SPRAID_CC_IOCQES = SPRAID_IO_IOCQES << SPRAID_CC_IOCQES_SHIFT,
+ SPRAID_CC_SHN_NORMAL = 1 << SPRAID_CC_SHN_SHIFT,
+ SPRAID_CC_SHN_MASK = 3 << SPRAID_CC_SHN_SHIFT,
+ SPRAID_CSTS_CFS_SHIFT = 1,
+ SPRAID_CSTS_SHST_SHIFT = 2,
+ SPRAID_CSTS_PP_SHIFT = 5,
+ SPRAID_CSTS_RDY = 1 << 0,
+ SPRAID_CSTS_SHST_CMPLT = 2 << 2,
+ SPRAID_CSTS_SHST_MASK = 3 << 2,
+ SPRAID_CSTS_CFS_MASK = 1 << SPRAID_CSTS_CFS_SHIFT,
+ SPRAID_CSTS_PP_MASK = 1 << SPRAID_CSTS_PP_SHIFT,
+};
+
+enum {
+ SPRAID_ADMIN_DELETE_SQ = 0x00,
+ SPRAID_ADMIN_CREATE_SQ = 0x01,
+ SPRAID_ADMIN_DELETE_CQ = 0x04,
+ SPRAID_ADMIN_CREATE_CQ = 0x05,
+ SPRAID_ADMIN_ABORT_CMD = 0x08,
+ SPRAID_ADMIN_SET_FEATURES = 0x09,
+ SPRAID_ADMIN_ASYNC_EVENT = 0x0c,
+ SPRAID_ADMIN_GET_INFO = 0xc6,
+ SPRAID_ADMIN_RESET = 0xc8,
+};
+
+enum {
+ SPRAID_GET_INFO_CTRL = 0,
+ SPRAID_GET_INFO_DEV_LIST = 1,
+};
+
+enum {
+ SPRAID_RESET_TARGET = 0,
+ SPRAID_RESET_BUS = 1,
+};
+
+enum {
+ SPRAID_AEN_ERROR = 0,
+ SPRAID_AEN_NOTICE = 2,
+ SPRAID_AEN_VS = 7,
+};
+
+enum {
+ SPRAID_AEN_DEV_CHANGED = 0x00,
+ SPRAID_AEN_HOST_PROBING = 0x10,
+};
+
+enum {
+ SPRAID_AEN_TIMESYN = 0x07
+};
+
+enum {
+ SPRAID_CMD_WRITE = 0x01,
+ SPRAID_CMD_READ = 0x02,
+
+ SPRAID_CMD_NONIO_NONE = 0x80,
+ SPRAID_CMD_NONIO_TODEV = 0x81,
+ SPRAID_CMD_NONIO_FROMDEV = 0x82,
+};
+
+enum {
+ SPRAID_QUEUE_PHYS_CONTIG = (1 << 0),
+ SPRAID_CQ_IRQ_ENABLED = (1 << 1),
+
+ SPRAID_FEAT_NUM_QUEUES = 0x07,
+ SPRAID_FEAT_ASYNC_EVENT = 0x0b,
+ SPRAID_FEAT_TIMESTAMP = 0x0e,
+};
+
+enum spraid_state {
+ SPRAID_NEW,
+ SPRAID_LIVE,
+ SPRAID_RESETTING,
+ SPRAID_DELETING,
+ SPRAID_DEAD,
+};
+
+enum {
+ SPRAID_CARD_HBA,
+ SPRAID_CARD_RAID,
+};
+
+enum spraid_cmd_type {
+ SPRAID_CMD_ADM,
+ SPRAID_CMD_IOPT,
+};
+
+struct spraid_completion {
+ __le32 result;
+ union {
+ struct {
+ __u8 sense_len;
+ __u8 resv[3];
+ };
+ __le32 result1;
+ };
+ __le16 sq_head;
+ __le16 sq_id;
+ __u16 cmd_id;
+ __le16 status;
+};
+
+struct spraid_ctrl_info {
+ __le32 nd;
+ __le16 max_cmds;
+ __le16 max_channel;
+ __le32 max_tgt_id;
+ __le16 max_lun;
+ __le16 max_num_sge;
+ __le16 lun_num_in_boot;
+ __u8 mdts;
+ __u8 acl;
+ __u8 aerl;
+ __u8 card_type;
+ __u16 rsvd;
+ __u32 rtd3e;
+ __u8 sn[32];
+ __u8 fr[16];
+ __u8 rsvd1[4020];
+};
+
+struct spraid_dev {
+ struct pci_dev *pdev;
+ struct device *dev;
+ struct Scsi_Host *shost;
+ struct spraid_queue *queues;
+ struct dma_pool *prp_page_pool;
+ struct dma_pool *prp_small_pool[MAX_SMALL_POOL_NUM];
+ mempool_t *iod_mempool;
+ void __iomem *bar;
+ u32 max_qid;
+ u32 num_vecs;
+ u32 queue_count;
+ u32 ioq_depth;
+ int db_stride;
+ u32 __iomem *dbs;
+ struct rw_semaphore devices_rwsem;
+ int numa_node;
+ u32 page_size;
+ u32 ctrl_config;
+ u32 online_queues;
+ u64 cap;
+ int instance;
+ struct spraid_ctrl_info *ctrl_info;
+ struct spraid_dev_info *devices;
+
+ struct spraid_cmd *adm_cmds;
+ struct list_head adm_cmd_list;
+ spinlock_t adm_cmd_lock;
+
+ struct spraid_cmd *ioq_ptcmds;
+ struct list_head ioq_pt_list;
+ spinlock_t ioq_pt_lock;
+
+ struct work_struct scan_work;
+ struct work_struct timesyn_work;
+ struct work_struct reset_work;
+
+ enum spraid_state state;
+ spinlock_t state_lock;
+ struct request_queue *bsg_queue;
+};
+
+struct spraid_sgl_desc {
+ __le64 addr;
+ __le32 length;
+ __u8 rsvd[3];
+ __u8 type;
+};
+
+union spraid_data_ptr {
+ struct {
+ __le64 prp1;
+ __le64 prp2;
+ };
+ struct spraid_sgl_desc sgl;
+};
+
+struct spraid_admin_common_command {
+ __u8 opcode;
+ __u8 flags;
+ __u16 command_id;
+ __le32 hdid;
+ __le32 cdw2[4];
+ union spraid_data_ptr dptr;
+ __le32 cdw10;
+ __le32 cdw11;
+ __le32 cdw12;
+ __le32 cdw13;
+ __le32 cdw14;
+ __le32 cdw15;
+};
+
+struct spraid_features {
+ __u8 opcode;
+ __u8 flags;
+ __u16 command_id;
+ __le32 hdid;
+ __u64 rsvd2[2];
+ union spraid_data_ptr dptr;
+ __le32 fid;
+ __le32 dword11;
+ __le32 dword12;
+ __le32 dword13;
+ __le32 dword14;
+ __le32 dword15;
+};
+
+struct spraid_create_cq {
+ __u8 opcode;
+ __u8 flags;
+ __u16 command_id;
+ __u32 rsvd1[5];
+ __le64 prp1;
+ __u64 rsvd8;
+ __le16 cqid;
+ __le16 qsize;
+ __le16 cq_flags;
+ __le16 irq_vector;
+ __u32 rsvd12[4];
+};
+
+struct spraid_create_sq {
+ __u8 opcode;
+ __u8 flags;
+ __u16 command_id;
+ __u32 rsvd1[5];
+ __le64 prp1;
+ __u64 rsvd8;
+ __le16 sqid;
+ __le16 qsize;
+ __le16 sq_flags;
+ __le16 cqid;
+ __u32 rsvd12[4];
+};
+
+struct spraid_delete_queue {
+ __u8 opcode;
+ __u8 flags;
+ __u16 command_id;
+ __u32 rsvd1[9];
+ __le16 qid;
+ __u16 rsvd10;
+ __u32 rsvd11[5];
+};
+
+struct spraid_get_info {
+ __u8 opcode;
+ __u8 flags;
+ __u16 command_id;
+ __le32 hdid;
+ __u32 rsvd2[4];
+ union spraid_data_ptr dptr;
+ __u8 type;
+ __u8 rsvd10[3];
+ __le32 cdw11;
+ __u32 rsvd12[4];
+};
+
+struct spraid_usr_cmd {
+ __u8 opcode;
+ __u8 flags;
+ __u16 command_id;
+ __le32 hdid;
+ union {
+ struct {
+ __le16 subopcode;
+ __le16 rsvd1;
+ } info_0;
+ __le32 cdw2;
+ };
+ union {
+ struct {
+ __le16 data_len;
+ __le16 param_len;
+ } info_1;
+ __le32 cdw3;
+ };
+ __u64 metadata;
+ union spraid_data_ptr dptr;
+ __le32 cdw10;
+ __le32 cdw11;
+ __le32 cdw12;
+ __le32 cdw13;
+ __le32 cdw14;
+ __le32 cdw15;
+};
+
+enum {
+ SPRAID_CMD_FLAG_SGL_METABUF = (1 << 6),
+ SPRAID_CMD_FLAG_SGL_METASEG = (1 << 7),
+ SPRAID_CMD_FLAG_SGL_ALL = SPRAID_CMD_FLAG_SGL_METABUF | SPRAID_CMD_FLAG_SGL_METASEG,
+};
+
+enum spraid_cmd_state {
+ SPRAID_CMD_IDLE = 0,
+ SPRAID_CMD_IN_FLIGHT = 1,
+ SPRAID_CMD_COMPLETE = 2,
+ SPRAID_CMD_TIMEOUT = 3,
+ SPRAID_CMD_TMO_COMPLETE = 4,
+};
+
+struct spraid_abort_cmd {
+ __u8 opcode;
+ __u8 flags;
+ __u16 command_id;
+ __le32 hdid;
+ __u64 rsvd2[4];
+ __le16 sqid;
+ __le16 cid;
+ __u32 rsvd11[5];
+};
+
+struct spraid_reset_cmd {
+ __u8 opcode;
+ __u8 flags;
+ __u16 command_id;
+ __le32 hdid;
+ __u64 rsvd2[4];
+ __u8 type;
+ __u8 rsvd10[3];
+ __u32 rsvd11[5];
+};
+
+struct spraid_admin_command {
+ union {
+ struct spraid_admin_common_command common;
+ struct spraid_features features;
+ struct spraid_create_cq create_cq;
+ struct spraid_create_sq create_sq;
+ struct spraid_delete_queue delete_queue;
+ struct spraid_get_info get_info;
+ struct spraid_abort_cmd abort;
+ struct spraid_reset_cmd reset;
+ struct spraid_usr_cmd usr_cmd;
+ };
+};
+
+struct spraid_ioq_common_command {
+ __u8 opcode;
+ __u8 flags;
+ __u16 command_id;
+ __le32 hdid;
+ __le16 sense_len;
+ __u8 cdb_len;
+ __u8 rsvd2;
+ __le32 cdw3[3];
+ union spraid_data_ptr dptr;
+ __le32 cdw10[6];
+ __u8 cdb[32];
+ __le64 sense_addr;
+ __le32 cdw26[6];
+};
+
+struct spraid_rw_command {
+ __u8 opcode;
+ __u8 flags;
+ __u16 command_id;
+ __le32 hdid;
+ __le16 sense_len;
+ __u8 cdb_len;
+ __u8 rsvd2;
+ __u32 rsvd3[3];
+ union spraid_data_ptr dptr;
+ __le64 slba;
+ __le16 nlb;
+ __le16 control;
+ __u32 rsvd13[3];
+ __u8 cdb[32];
+ __le64 sense_addr;
+ __u32 rsvd26[6];
+};
+
+struct spraid_scsi_nonio {
+ __u8 opcode;
+ __u8 flags;
+ __u16 command_id;
+ __le32 hdid;
+ __le16 sense_len;
+ __u8 cdb_length;
+ __u8 rsvd2;
+ __u32 rsvd3[3];
+ union spraid_data_ptr dptr;
+ __u32 rsvd10[5];
+ __le32 buffer_len;
+ __u8 cdb[32];
+ __le64 sense_addr;
+ __u32 rsvd26[6];
+};
+
+struct spraid_ioq_command {
+ union {
+ struct spraid_ioq_common_command common;
+ struct spraid_rw_command rw;
+ struct spraid_scsi_nonio scsi_nonio;
+ };
+};
+
+struct spraid_passthru_common_cmd {
+ __u8 opcode;
+ __u8 flags;
+ __u16 rsvd0;
+ __u32 nsid;
+ union {
+ struct {
+ __u16 subopcode;
+ __u16 rsvd1;
+ } info_0;
+ __u32 cdw2;
+ };
+ union {
+ struct {
+ __u16 data_len;
+ __u16 param_len;
+ } info_1;
+ __u32 cdw3;
+ };
+ __u64 metadata;
+
+ __u64 addr;
+ __u64 prp2;
+
+ __u32 cdw10;
+ __u32 cdw11;
+ __u32 cdw12;
+ __u32 cdw13;
+ __u32 cdw14;
+ __u32 cdw15;
+ __u32 timeout_ms;
+ __u32 result0;
+ __u32 result1;
+};
+
+struct spraid_ioq_passthru_cmd {
+ __u8 opcode;
+ __u8 flags;
+ __u16 rsvd0;
+ __u32 nsid;
+ union {
+ struct {
+ __u16 res_sense_len;
+ __u8 cdb_len;
+ __u8 rsvd0;
+ } info_0;
+ __u32 cdw2;
+ };
+ union {
+ struct {
+ __u16 subopcode;
+ __u16 rsvd1;
+ } info_1;
+ __u32 cdw3;
+ };
+ union {
+ struct {
+ __u16 rsvd;
+ __u16 param_len;
+ } info_2;
+ __u32 cdw4;
+ };
+ __u32 cdw5;
+ __u64 addr;
+ __u64 prp2;
+ union {
+ struct {
+ __u16 eid;
+ __u16 sid;
+ } info_3;
+ __u32 cdw10;
+ };
+ union {
+ struct {
+ __u16 did;
+ __u8 did_flag;
+ __u8 rsvd2;
+ } info_4;
+ __u32 cdw11;
+ };
+ __u32 cdw12;
+ __u32 cdw13;
+ __u32 cdw14;
+ __u32 data_len;
+ __u32 cdw16;
+ __u32 cdw17;
+ __u32 cdw18;
+ __u32 cdw19;
+ __u32 cdw20;
+ __u32 cdw21;
+ __u32 cdw22;
+ __u32 cdw23;
+ __u64 sense_addr;
+ __u32 cdw26[4];
+ __u32 timeout_ms;
+ __u32 result0;
+ __u32 result1;
+};
+
+struct spraid_bsg_request {
+ u32 msgcode;
+ u32 control;
+ union {
+ struct spraid_passthru_common_cmd admcmd;
+ struct spraid_ioq_passthru_cmd ioqcmd;
+ };
+};
+
+enum {
+ SPRAID_BSG_ADM,
+ SPRAID_BSG_IOQ,
+};
+
+struct spraid_cmd {
+ int qid;
+ int cid;
+ u32 result0;
+ u32 result1;
+ u16 status;
+ void *priv;
+ enum spraid_cmd_state state;
+ struct completion cmd_done;
+ struct list_head list;
+};
+
+struct spraid_queue {
+ struct spraid_dev *hdev;
+ spinlock_t sq_lock; /* spinlock for lock handling */
+
+ spinlock_t cq_lock ____cacheline_aligned_in_smp; /* spinlock for lock handling */
+
+ void *sq_cmds;
+
+ struct spraid_completion *cqes;
+
+ dma_addr_t sq_dma_addr;
+ dma_addr_t cq_dma_addr;
+ u32 __iomem *q_db;
+ u8 cq_phase;
+ u8 sqes;
+ u16 qid;
+ u16 sq_tail;
+ u16 cq_head;
+ u16 last_cq_head;
+ u16 q_depth;
+ s16 cq_vector;
+ void *sense;
+ dma_addr_t sense_dma_addr;
+ struct dma_pool *prp_small_pool;
+};
+
+struct spraid_iod {
+ struct spraid_queue *spraidq;
+ enum spraid_cmd_state state;
+ int npages;
+ u32 nsge;
+ u32 length;
+ bool use_sgl;
+ bool sg_drv_mgmt;
+ dma_addr_t first_dma;
+ void *sense;
+ dma_addr_t sense_dma;
+ struct scatterlist *sg;
+ struct scatterlist inline_sg[0];
+};
+
+#define SPRAID_DEV_INFO_ATTR_BOOT(attr) ((attr) & 0x01)
+#define SPRAID_DEV_INFO_ATTR_VD(attr) (((attr) & 0x02) == 0x0)
+#define SPRAID_DEV_INFO_ATTR_PT(attr) (((attr) & 0x22) == 0x02)
+#define SPRAID_DEV_INFO_ATTR_RAWDISK(attr) ((attr) & 0x20)
+
+#define SPRAID_DEV_INFO_FLAG_VALID(flag) ((flag) & 0x01)
+#define SPRAID_DEV_INFO_FLAG_CHANGE(flag) ((flag) & 0x02)
+
+struct spraid_dev_info {
+ __le32 hdid;
+ __le16 target;
+ __u8 channel;
+ __u8 lun;
+ __u8 attr;
+ __u8 flag;
+ __le16 max_io_kb;
+};
+
+#define MAX_DEV_ENTRY_PER_PAGE_4K 340
+struct spraid_dev_list {
+ __le32 dev_num;
+ __u32 rsvd0[3];
+ struct spraid_dev_info devices[MAX_DEV_ENTRY_PER_PAGE_4K];
+};
+
+struct spraid_sdev_hostdata {
+ u32 hdid;
+};
+
+#endif
diff --git a/drivers/scsi/spraid/spraid_main.c b/drivers/scsi/spraid/spraid_main.c
new file mode 100644
index 000000000000..7edce06b62a4
--- /dev/null
+++ b/drivers/scsi/spraid/spraid_main.c
@@ -0,0 +1,3266 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2021 Ramaxel Memory Technology, Ltd */
+
+/* Ramaxel Raid SPXXX Series Linux Driver */
+
+#define pr_fmt(fmt) "spraid: " fmt
+
+#include <linux/sched/signal.h>
+#include <linux/pci.h>
+#include <linux/aer.h>
+#include <linux/module.h>
+#include <linux/ioport.h>
+#include <linux/device.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/cdev.h>
+#include <linux/sysfs.h>
+#include <linux/gfp.h>
+#include <linux/types.h>
+#include <linux/ratelimit.h>
+#include <linux/once.h>
+#include <linux/debugfs.h>
+#include <linux/io-64-nonatomic-lo-hi.h>
+#include <linux/blkdev.h>
+#include <linux/bsg-lib.h>
+#include <asm/unaligned.h>
+
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_host.h>
+#include <scsi/scsi_transport.h>
+#include <scsi/scsi_dbg.h>
+#include <scsi/sg.h>
+
+
+#include "spraid.h"
+
+#define SCMD_TMOUT_RAWDISK 180
+
+#define SCMD_TMOUT_VD 180
+
+static int ioq_depth_set(const char *val, const struct kernel_param *kp);
+static const struct kernel_param_ops ioq_depth_ops = {
+ .set = ioq_depth_set,
+ .get = param_get_uint,
+};
+
+static u32 io_queue_depth = 1024;
+module_param_cb(io_queue_depth, &ioq_depth_ops, &io_queue_depth, 0644);
+MODULE_PARM_DESC(io_queue_depth, "set io queue depth, should >= 2");
+
+static int small_pool_num_set(const char *val, const struct kernel_param *kp)
+{
+ u8 n = 0;
+ int ret;
+
+ ret = kstrtou8(val, 10, &n);
+ if (ret != 0)
+ return -EINVAL;
+ if (n > MAX_SMALL_POOL_NUM)
+ n = MAX_SMALL_POOL_NUM;
+ if (n < 1)
+ n = 1;
+ *((u8 *)kp->arg) = n;
+
+ return 0;
+}
+
+static const struct kernel_param_ops small_pool_num_ops = {
+ .set = small_pool_num_set,
+ .get = param_get_byte,
+};
+
+/* It was found that the spindlock of a single pool conflicts
+ * a lot with multiple CPUs.So multiple pools are introduced
+ * to reduce the conflictions.
+ */
+static unsigned char small_pool_num = 4;
+module_param_cb(small_pool_num, &small_pool_num_ops, &small_pool_num, 0644);
+MODULE_PARM_DESC(small_pool_num, "set prp small pool num, default 4, MAX 16");
+
+static void spraid_free_queue(struct spraid_queue *spraidq);
+static void spraid_handle_aen_notice(struct spraid_dev *hdev, u32 result);
+static void spraid_handle_aen_vs(struct spraid_dev *hdev, u32 result, u32 result1);
+
+static DEFINE_IDA(spraid_instance_ida);
+
+static struct class *spraid_class;
+
+#define SPRAID_CAP_TIMEOUT_UNIT_MS (HZ / 2)
+
+static struct workqueue_struct *spraid_wq;
+
+#define SPRAID_DRV_VERSION "1.0.0.0"
+
+#define ADMIN_TIMEOUT (60 * HZ)
+#define ADMIN_ERR_TIMEOUT 32757
+
+#define SPRAID_WAIT_ABNL_CMD_TIMEOUT (3 * 2)
+
+#define SPRAID_DMA_MSK_BIT_MAX 64
+
+enum FW_STAT_CODE {
+ FW_STAT_OK = 0,
+ FW_STAT_NEED_CHECK,
+ FW_STAT_ERROR,
+ FW_STAT_EP_PCIE_ERROR,
+ FW_STAT_NAC_DMA_ERROR,
+ FW_STAT_ABORTED,
+ FW_STAT_NEED_RETRY
+};
+
+static int ioq_depth_set(const char *val, const struct kernel_param *kp)
+{
+ int n = 0;
+ int ret;
+
+ ret = kstrtoint(val, 10, &n);
+ if (ret != 0 || n < 2)
+ return -EINVAL;
+
+ return param_set_int(val, kp);
+}
+
+static int spraid_remap_bar(struct spraid_dev *hdev, u32 size)
+{
+ struct pci_dev *pdev = hdev->pdev;
+
+ if (size > pci_resource_len(pdev, 0)) {
+ dev_err(hdev->dev, "Input size[%u] exceed bar0 length[%llu]\n",
+ size, pci_resource_len(pdev, 0));
+ return -ENOMEM;
+ }
+
+ if (hdev->bar)
+ iounmap(hdev->bar);
+
+ hdev->bar = ioremap(pci_resource_start(pdev, 0), size);
+ if (!hdev->bar) {
+ dev_err(hdev->dev, "ioremap for bar0 failed\n");
+ return -ENOMEM;
+ }
+ hdev->dbs = hdev->bar + SPRAID_REG_DBS;
+
+ return 0;
+}
+
+static int spraid_dev_map(struct spraid_dev *hdev)
+{
+ struct pci_dev *pdev = hdev->pdev;
+ int ret;
+
+ ret = pci_request_mem_regions(pdev, "spraid");
+ if (ret) {
+ dev_err(hdev->dev, "fail to request memory regions\n");
+ return ret;
+ }
+
+ ret = spraid_remap_bar(hdev, SPRAID_REG_DBS + 4096);
+ if (ret) {
+ pci_release_mem_regions(pdev);
+ return ret;
+ }
+
+ return 0;
+}
+
+static void spraid_dev_unmap(struct spraid_dev *hdev)
+{
+ struct pci_dev *pdev = hdev->pdev;
+
+ if (hdev->bar) {
+ iounmap(hdev->bar);
+ hdev->bar = NULL;
+ }
+ pci_release_mem_regions(pdev);
+}
+
+static int spraid_pci_enable(struct spraid_dev *hdev)
+{
+ struct pci_dev *pdev = hdev->pdev;
+ int ret = -ENOMEM;
+ u64 maskbit = SPRAID_DMA_MSK_BIT_MAX;
+
+ if (pci_enable_device_mem(pdev)) {
+ dev_err(hdev->dev, "Enable pci device memory resources failed\n");
+ return ret;
+ }
+ pci_set_master(pdev);
+
+ if (readl(hdev->bar + SPRAID_REG_CSTS) == U32_MAX) {
+ ret = -ENODEV;
+ dev_err(hdev->dev, "Read csts register failed\n");
+ goto disable;
+ }
+
+ ret = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_ALL_TYPES);
+ if (ret < 0) {
+ dev_err(hdev->dev, "Allocate one IRQ for setup admin channel failed\n");
+ goto disable;
+ }
+
+ hdev->cap = lo_hi_readq(hdev->bar + SPRAID_REG_CAP);
+ hdev->ioq_depth = min_t(u32, SPRAID_CAP_MQES(hdev->cap) + 1, io_queue_depth);
+ hdev->db_stride = 1 << SPRAID_CAP_STRIDE(hdev->cap);
+
+ maskbit = SPRAID_CAP_DMAMASK(hdev->cap);
+ if (maskbit < 32 || maskbit > SPRAID_DMA_MSK_BIT_MAX) {
+ dev_err(hdev->dev, "err, dma mask invalid[%llu], set to default\n", maskbit);
+ maskbit = SPRAID_DMA_MSK_BIT_MAX;
+ }
+ if (dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(maskbit))) {
+ dev_err(hdev->dev, "set dma mask and coherent failed\n");
+ goto disable;
+ }
+
+ dev_info(hdev->dev, "set dma mask[%llu] success\n", maskbit);
+
+ pci_enable_pcie_error_reporting(pdev);
+ pci_save_state(pdev);
+
+ return 0;
+
+disable:
+ pci_disable_device(pdev);
+ return ret;
+}
+
+static int spraid_npages_prp(u32 size, struct spraid_dev *hdev)
+{
+ u32 nprps = DIV_ROUND_UP(size + hdev->page_size, hdev->page_size);
+
+ return DIV_ROUND_UP(PRP_ENTRY_SIZE * nprps, PAGE_SIZE - PRP_ENTRY_SIZE);
+}
+
+static int spraid_npages_sgl(u32 nseg)
+{
+ return DIV_ROUND_UP(nseg * sizeof(struct spraid_sgl_desc), PAGE_SIZE);
+}
+
+static void **spraid_iod_list(struct spraid_iod *iod)
+{
+ return (void **)(iod->inline_sg + (iod->sg_drv_mgmt ? iod->nsge : 0));
+}
+
+static u32 spraid_iod_ext_size(struct spraid_dev *hdev, u32 size, u32 nsge,
+ bool sg_drv_mgmt, bool use_sgl)
+{
+ size_t alloc_size, sg_size;
+
+ if (use_sgl)
+ alloc_size = sizeof(__le64 *) * spraid_npages_sgl(nsge);
+ else
+ alloc_size = sizeof(__le64 *) * spraid_npages_prp(size, hdev);
+
+ sg_size = sg_drv_mgmt ? (sizeof(struct scatterlist) * nsge) : 0;
+ return sg_size + alloc_size;
+}
+
+static u32 spraid_cmd_size(struct spraid_dev *hdev, bool sg_drv_mgmt, bool use_sgl)
+{
+ u32 alloc_size = spraid_iod_ext_size(hdev, SPRAID_INT_BYTES(hdev),
+ SPRAID_INT_PAGES, sg_drv_mgmt, use_sgl);
+
+ dev_info(hdev->dev, "sg_drv_mgmt: %s, use_sgl: %s, iod size: %lu, alloc_size: %u\n",
+ sg_drv_mgmt ? "true" : "false", use_sgl ? "true" : "false",
+ sizeof(struct spraid_iod), alloc_size);
+
+ return sizeof(struct spraid_iod) + alloc_size;
+}
+
+static int spraid_setup_prps(struct spraid_dev *hdev, struct spraid_iod *iod)
+{
+ struct scatterlist *sg = iod->sg;
+ u64 dma_addr = sg_dma_address(sg);
+ int dma_len = sg_dma_len(sg);
+ __le64 *prp_list, *old_prp_list;
+ u32 page_size = hdev->page_size;
+ int offset = dma_addr & (page_size - 1);
+ void **list = spraid_iod_list(iod);
+ int length = iod->length;
+ struct dma_pool *pool;
+ dma_addr_t prp_dma;
+ int nprps, i;
+
+ length -= (page_size - offset);
+ if (length <= 0) {
+ iod->first_dma = 0;
+ return 0;
+ }
+
+ dma_len -= (page_size - offset);
+ if (dma_len) {
+ dma_addr += (page_size - offset);
+ } else {
+ sg = sg_next(sg);
+ dma_addr = sg_dma_address(sg);
+ dma_len = sg_dma_len(sg);
+ }
+
+ if (length <= page_size) {
+ iod->first_dma = dma_addr;
+ return 0;
+ }
+
+ nprps = DIV_ROUND_UP(length, page_size);
+ if (nprps <= (SMALL_POOL_SIZE / PRP_ENTRY_SIZE)) {
+ pool = iod->spraidq->prp_small_pool;
+ iod->npages = 0;
+ } else {
+ pool = hdev->prp_page_pool;
+ iod->npages = 1;
+ }
+
+ prp_list = dma_pool_alloc(pool, GFP_ATOMIC, &prp_dma);
+ if (!prp_list) {
+ dev_err_ratelimited(hdev->dev, "Allocate first prp_list memory failed\n");
+ iod->first_dma = dma_addr;
+ iod->npages = -1;
+ return -ENOMEM;
+ }
+ list[0] = prp_list;
+ iod->first_dma = prp_dma;
+ i = 0;
+ for (;;) {
+ if (i == page_size / PRP_ENTRY_SIZE) {
+ old_prp_list = prp_list;
+
+ prp_list = dma_pool_alloc(pool, GFP_ATOMIC, &prp_dma);
+ if (!prp_list) {
+ dev_err_ratelimited(hdev->dev, "Allocate %dth prp_list memory failed\n",
+ iod->npages + 1);
+ return -ENOMEM;
+ }
+ list[iod->npages++] = prp_list;
+ prp_list[0] = old_prp_list[i - 1];
+ old_prp_list[i - 1] = cpu_to_le64(prp_dma);
+ i = 1;
+ }
+ prp_list[i++] = cpu_to_le64(dma_addr);
+ dma_len -= page_size;
+ dma_addr += page_size;
+ length -= page_size;
+ if (length <= 0)
+ break;
+ if (dma_len > 0)
+ continue;
+ if (unlikely(dma_len < 0))
+ goto bad_sgl;
+ sg = sg_next(sg);
+ dma_addr = sg_dma_address(sg);
+ dma_len = sg_dma_len(sg);
+ }
+
+ return 0;
+
+bad_sgl:
+ dev_err(hdev->dev, "Setup prps, invalid SGL for payload: %d nents: %d\n",
+ iod->length, iod->nsge);
+ return -EIO;
+}
+
+#define SGES_PER_PAGE (PAGE_SIZE / sizeof(struct spraid_sgl_desc))
+
+static void spraid_submit_cmd(struct spraid_queue *spraidq, const void *cmd)
+{
+ u32 sqes = SQE_SIZE(spraidq->qid);
+ unsigned long flags;
+ struct spraid_admin_common_command *acd = (struct spraid_admin_common_command *)cmd;
+
+ spin_lock_irqsave(&spraidq->sq_lock, flags);
+ memcpy((spraidq->sq_cmds + sqes * spraidq->sq_tail), cmd, sqes);
+ if (++spraidq->sq_tail == spraidq->q_depth)
+ spraidq->sq_tail = 0;
+
+ writel(spraidq->sq_tail, spraidq->q_db);
+ spin_unlock_irqrestore(&spraidq->sq_lock, flags);
+
+ pr_debug("cid[%d], qid[%d], opcode[0x%x], flags[0x%x], hdid[%u]\n",
+ acd->command_id, spraidq->qid, acd->opcode, acd->flags, le32_to_cpu(acd->hdid));
+}
+
+static u32 spraid_mod64(u64 dividend, u32 divisor)
+{
+ u64 d;
+ u32 remainder;
+
+ if (!divisor)
+ pr_err("DIVISOR is zero, in div fn\n");
+
+ d = dividend;
+ remainder = do_div(d, divisor);
+ return remainder;
+}
+
+static inline bool spraid_is_rw_scmd(struct scsi_cmnd *scmd)
+{
+ switch (scmd->cmnd[0]) {
+ case READ_6:
+ case READ_10:
+ case READ_12:
+ case READ_16:
+ case READ_32:
+ case WRITE_6:
+ case WRITE_10:
+ case WRITE_12:
+ case WRITE_16:
+ case WRITE_32:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static bool spraid_is_prp(struct spraid_dev *hdev, struct scsi_cmnd *scmd, u32 nsge)
+{
+ struct scatterlist *sg = scsi_sglist(scmd);
+ u32 page_size = hdev->page_size;
+ bool is_prp = true;
+ int i = 0;
+
+ scsi_for_each_sg(scmd, sg, nsge, i) {
+ if (i != 0 && i != nsge - 1) {
+ if (spraid_mod64(sg_dma_len(sg), page_size) ||
+ spraid_mod64(sg_dma_address(sg), page_size)) {
+ is_prp = false;
+ break;
+ }
+ }
+
+ if (nsge > 1 && i == 0) {
+ if ((spraid_mod64((sg_dma_address(sg) + sg_dma_len(sg)), page_size))) {
+ is_prp = false;
+ break;
+ }
+ }
+
+ if (nsge > 1 && i == (nsge - 1)) {
+ if (spraid_mod64(sg_dma_address(sg), page_size)) {
+ is_prp = false;
+ break;
+ }
+ }
+ }
+
+ return is_prp;
+}
+
+enum {
+ SPRAID_SGL_FMT_DATA_DESC = 0x00,
+ SPRAID_SGL_FMT_SEG_DESC = 0x02,
+ SPRAID_SGL_FMT_LAST_SEG_DESC = 0x03,
+ SPRAID_KEY_SGL_FMT_DATA_DESC = 0x04,
+ SPRAID_TRANSPORT_SGL_DATA_DESC = 0x05
+};
+
+static void spraid_sgl_set_data(struct spraid_sgl_desc *sge, struct scatterlist *sg)
+{
+ sge->addr = cpu_to_le64(sg_dma_address(sg));
+ sge->length = cpu_to_le32(sg_dma_len(sg));
+ sge->type = SPRAID_SGL_FMT_DATA_DESC << 4;
+}
+
+static void spraid_sgl_set_seg(struct spraid_sgl_desc *sge, dma_addr_t dma_addr, int entries)
+{
+ sge->addr = cpu_to_le64(dma_addr);
+ if (entries <= SGES_PER_PAGE) {
+ sge->length = cpu_to_le32(entries * sizeof(*sge));
+ sge->type = SPRAID_SGL_FMT_LAST_SEG_DESC << 4;
+ } else {
+ sge->length = cpu_to_le32(PAGE_SIZE);
+ sge->type = SPRAID_SGL_FMT_SEG_DESC << 4;
+ }
+}
+
+static int spraid_setup_ioq_cmd_sgl(struct spraid_dev *hdev,
+ struct scsi_cmnd *scmd, struct spraid_ioq_command *ioq_cmd,
+ struct spraid_iod *iod)
+{
+ struct spraid_sgl_desc *sg_list, *link, *old_sg_list;
+ struct scatterlist *sg = scsi_sglist(scmd);
+ void **list = spraid_iod_list(iod);
+ struct dma_pool *pool;
+ int nsge = iod->nsge;
+ dma_addr_t sgl_dma;
+ int i = 0;
+
+ ioq_cmd->common.flags |= SPRAID_CMD_FLAG_SGL_METABUF;
+
+ if (nsge == 1) {
+ spraid_sgl_set_data(&ioq_cmd->common.dptr.sgl, sg);
+ return 0;
+ }
+
+ if (nsge <= (SMALL_POOL_SIZE / sizeof(struct spraid_sgl_desc))) {
+ pool = iod->spraidq->prp_small_pool;
+ iod->npages = 0;
+ } else {
+ pool = hdev->prp_page_pool;
+ iod->npages = 1;
+ }
+
+ sg_list = dma_pool_alloc(pool, GFP_ATOMIC, &sgl_dma);
+ if (!sg_list) {
+ dev_err_ratelimited(hdev->dev, "Allocate first sgl_list failed\n");
+ iod->npages = -1;
+ return -ENOMEM;
+ }
+
+ list[0] = sg_list;
+ iod->first_dma = sgl_dma;
+ spraid_sgl_set_seg(&ioq_cmd->common.dptr.sgl, sgl_dma, nsge);
+ do {
+ if (i == SGES_PER_PAGE) {
+ old_sg_list = sg_list;
+ link = &old_sg_list[SGES_PER_PAGE - 1];
+
+ sg_list = dma_pool_alloc(pool, GFP_ATOMIC, &sgl_dma);
+ if (!sg_list) {
+ dev_err_ratelimited(hdev->dev, "Allocate %dth sgl_list failed\n",
+ iod->npages + 1);
+ return -ENOMEM;
+ }
+ list[iod->npages++] = sg_list;
+
+ i = 0;
+ memcpy(&sg_list[i++], link, sizeof(*link));
+ spraid_sgl_set_seg(link, sgl_dma, nsge);
+ }
+
+ spraid_sgl_set_data(&sg_list[i++], sg);
+ sg = sg_next(sg);
+ } while (--nsge > 0);
+
+ return 0;
+}
+
+#define SPRAID_RW_FUA BIT(14)
+
+static void spraid_setup_rw_cmd(struct spraid_dev *hdev,
+ struct spraid_rw_command *rw,
+ struct scsi_cmnd *scmd)
+{
+ u32 start_lba_lo, start_lba_hi;
+ u32 datalength = 0;
+ u16 control = 0;
+
+ start_lba_lo = 0;
+ start_lba_hi = 0;
+
+ if (scmd->sc_data_direction == DMA_TO_DEVICE) {
+ rw->opcode = SPRAID_CMD_WRITE;
+ } else if (scmd->sc_data_direction == DMA_FROM_DEVICE) {
+ rw->opcode = SPRAID_CMD_READ;
+ } else {
+ dev_err(hdev->dev, "Invalid IO for unsupported data direction: %d\n",
+ scmd->sc_data_direction);
+ WARN_ON(1);
+ }
+
+ /* 6-byte READ(0x08) or WRITE(0x0A) cdb */
+ if (scmd->cmd_len == 6) {
+ datalength = (u32)(scmd->cmnd[4] == 0 ?
+ IO_6_DEFAULT_TX_LEN : scmd->cmnd[4]);
+ start_lba_lo = (u32)get_unaligned_be24(&scmd->cmnd[1]);
+
+ start_lba_lo &= 0x1FFFFF;
+ }
+
+ /* 10-byte READ(0x28) or WRITE(0x2A) cdb */
+ else if (scmd->cmd_len == 10) {
+ datalength = (u32)get_unaligned_be16(&scmd->cmnd[7]);
+ start_lba_lo = get_unaligned_be32(&scmd->cmnd[2]);
+
+ if (scmd->cmnd[1] & FUA_MASK)
+ control |= SPRAID_RW_FUA;
+ }
+
+ /* 12-byte READ(0xA8) or WRITE(0xAA) cdb */
+ else if (scmd->cmd_len == 12) {
+ datalength = get_unaligned_be32(&scmd->cmnd[6]);
+ start_lba_lo = get_unaligned_be32(&scmd->cmnd[2]);
+
+ if (scmd->cmnd[1] & FUA_MASK)
+ control |= SPRAID_RW_FUA;
+ }
+ /* 16-byte READ(0x88) or WRITE(0x8A) cdb */
+ else if (scmd->cmd_len == 16) {
+ datalength = get_unaligned_be32(&scmd->cmnd[10]);
+ start_lba_lo = get_unaligned_be32(&scmd->cmnd[6]);
+ start_lba_hi = get_unaligned_be32(&scmd->cmnd[2]);
+
+ if (scmd->cmnd[1] & FUA_MASK)
+ control |= SPRAID_RW_FUA;
+ }
+ /* 32-byte READ(0x88) or WRITE(0x8A) cdb */
+ else if (scmd->cmd_len == 32) {
+ datalength = get_unaligned_be32(&scmd->cmnd[28]);
+ start_lba_lo = get_unaligned_be32(&scmd->cmnd[16]);
+ start_lba_hi = get_unaligned_be32(&scmd->cmnd[12]);
+
+ if (scmd->cmnd[10] & FUA_MASK)
+ control |= SPRAID_RW_FUA;
+ }
+
+ if (unlikely(datalength > U16_MAX || datalength == 0)) {
+ dev_err(hdev->dev, "Invalid IO for illegal transfer data length: %u\n",
+ datalength);
+ WARN_ON(1);
+ }
+
+ rw->slba = cpu_to_le64(((u64)start_lba_hi << 32) | start_lba_lo);
+ /* 0base for nlb */
+ rw->nlb = cpu_to_le16((u16)(datalength - 1));
+ rw->control = cpu_to_le16(control);
+}
+
+static void spraid_setup_nonio_cmd(struct spraid_dev *hdev,
+ struct spraid_scsi_nonio *scsi_nonio, struct scsi_cmnd *scmd)
+{
+ scsi_nonio->buffer_len = cpu_to_le32(scsi_bufflen(scmd));
+
+ switch (scmd->sc_data_direction) {
+ case DMA_NONE:
+ scsi_nonio->opcode = SPRAID_CMD_NONIO_NONE;
+ break;
+ case DMA_TO_DEVICE:
+ scsi_nonio->opcode = SPRAID_CMD_NONIO_TODEV;
+ break;
+ case DMA_FROM_DEVICE:
+ scsi_nonio->opcode = SPRAID_CMD_NONIO_FROMDEV;
+ break;
+ default:
+ dev_err(hdev->dev, "Invalid IO for unsupported data direction: %d\n",
+ scmd->sc_data_direction);
+ WARN_ON(1);
+ }
+}
+
+static void spraid_setup_ioq_cmd(struct spraid_dev *hdev,
+ struct spraid_ioq_command *ioq_cmd, struct scsi_cmnd *scmd)
+{
+ memcpy(ioq_cmd->common.cdb, scmd->cmnd, scmd->cmd_len);
+ ioq_cmd->common.cdb_len = scmd->cmd_len;
+
+ if (spraid_is_rw_scmd(scmd))
+ spraid_setup_rw_cmd(hdev, &ioq_cmd->rw, scmd);
+ else
+ spraid_setup_nonio_cmd(hdev, &ioq_cmd->scsi_nonio, scmd);
+}
+
+static int spraid_init_iod(struct spraid_dev *hdev,
+ struct spraid_iod *iod, struct spraid_ioq_command *ioq_cmd,
+ struct scsi_cmnd *scmd)
+{
+ if (unlikely(!iod->sense)) {
+ dev_err(hdev->dev, "Allocate sense data buffer failed\n");
+ return -ENOMEM;
+ }
+ ioq_cmd->common.sense_addr = cpu_to_le64(iod->sense_dma);
+ ioq_cmd->common.sense_len = cpu_to_le16(SCSI_SENSE_BUFFERSIZE);
+
+ iod->nsge = 0;
+ iod->npages = -1;
+ iod->use_sgl = 0;
+ iod->sg_drv_mgmt = false;
+ WRITE_ONCE(iod->state, SPRAID_CMD_IDLE);
+
+ return 0;
+}
+
+static void spraid_free_iod_res(struct spraid_dev *hdev, struct spraid_iod *iod)
+{
+ const int last_prp = hdev->page_size / sizeof(__le64) - 1;
+ dma_addr_t dma_addr, next_dma_addr;
+ struct spraid_sgl_desc *sg_list;
+ __le64 *prp_list;
+ void *addr;
+ int i;
+
+ dma_addr = iod->first_dma;
+ if (iod->npages == 0)
+ dma_pool_free(iod->spraidq->prp_small_pool, spraid_iod_list(iod)[0], dma_addr);
+
+ for (i = 0; i < iod->npages; i++) {
+ addr = spraid_iod_list(iod)[i];
+
+ if (iod->use_sgl) {
+ sg_list = addr;
+ next_dma_addr =
+ le64_to_cpu((sg_list[SGES_PER_PAGE - 1]).addr);
+ } else {
+ prp_list = addr;
+ next_dma_addr = le64_to_cpu(prp_list[last_prp]);
+ }
+
+ dma_pool_free(hdev->prp_page_pool, addr, dma_addr);
+ dma_addr = next_dma_addr;
+ }
+
+ if (iod->sg_drv_mgmt && iod->sg != iod->inline_sg) {
+ iod->sg_drv_mgmt = false;
+ mempool_free(iod->sg, hdev->iod_mempool);
+ }
+
+ iod->sense = NULL;
+ iod->npages = -1;
+}
+
+static int spraid_io_map_data(struct spraid_dev *hdev, struct spraid_iod *iod,
+ struct scsi_cmnd *scmd, struct spraid_ioq_command *ioq_cmd)
+{
+ int ret;
+
+ iod->nsge = scsi_dma_map(scmd);
+
+ /* No data to DMA, it may be scsi no-rw command */
+ if (unlikely(iod->nsge == 0))
+ return 0;
+
+ iod->length = scsi_bufflen(scmd);
+ iod->sg = scsi_sglist(scmd);
+ iod->use_sgl = !spraid_is_prp(hdev, scmd, iod->nsge);
+
+ if (iod->use_sgl) {
+ ret = spraid_setup_ioq_cmd_sgl(hdev, scmd, ioq_cmd, iod);
+ } else {
+ ret = spraid_setup_prps(hdev, iod);
+ ioq_cmd->common.dptr.prp1 =
+ cpu_to_le64(sg_dma_address(iod->sg));
+ ioq_cmd->common.dptr.prp2 = cpu_to_le64(iod->first_dma);
+ }
+
+ if (ret)
+ scsi_dma_unmap(scmd);
+
+ return ret;
+}
+
+static void spraid_map_status(struct spraid_iod *iod, struct scsi_cmnd *scmd,
+ struct spraid_completion *cqe)
+{
+ scsi_set_resid(scmd, 0);
+
+ switch ((le16_to_cpu(cqe->status) >> 1) & 0x7f) {
+ case FW_STAT_OK:
+ set_host_byte(scmd, DID_OK);
+ break;
+ case FW_STAT_NEED_CHECK:
+ set_host_byte(scmd, DID_OK);
+ scmd->result |= le16_to_cpu(cqe->status) >> 8;
+ if (scmd->result & SAM_STAT_CHECK_CONDITION) {
+ memset(scmd->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE);
+ memcpy(scmd->sense_buffer, iod->sense, SCSI_SENSE_BUFFERSIZE);
+ scmd->result = (scmd->result & 0x00ffffff) | (DRIVER_SENSE << 24);
+ }
+ break;
+ case FW_STAT_ABORTED:
+ set_host_byte(scmd, DID_ABORT);
+ break;
+ case FW_STAT_NEED_RETRY:
+ set_host_byte(scmd, DID_REQUEUE);
+ break;
+ default:
+ set_host_byte(scmd, DID_BAD_TARGET);
+ break;
+ }
+}
+
+static inline void spraid_get_tag_from_scmd(struct scsi_cmnd *scmd, u16 *qid, u16 *cid)
+{
+ u32 tag = blk_mq_unique_tag(scsi_cmd_to_rq(scmd));
+
+ *qid = blk_mq_unique_tag_to_hwq(tag) + 1;
+ *cid = blk_mq_unique_tag_to_tag(tag);
+}
+
+static int spraid_queue_command(struct Scsi_Host *shost, struct scsi_cmnd *scmd)
+{
+ struct spraid_iod *iod = scsi_cmd_priv(scmd);
+ struct spraid_dev *hdev = shost_priv(shost);
+ struct scsi_device *sdev = scmd->device;
+ struct spraid_sdev_hostdata *hostdata;
+ struct spraid_ioq_command ioq_cmd;
+ struct spraid_queue *ioq;
+ unsigned long elapsed;
+ u16 hwq, cid;
+ int ret;
+
+ if (unlikely(!scmd)) {
+ dev_err(hdev->dev, "err, scmd is null, return 0\n");
+ return 0;
+ }
+
+ if (unlikely(hdev->state != SPRAID_LIVE)) {
+ set_host_byte(scmd, DID_NO_CONNECT);
+ scsi_done(scmd);
+ dev_err(hdev->dev, "[%s] err, hdev state is not live\n", __func__);
+ return 0;
+ }
+
+ spraid_get_tag_from_scmd(scmd, &hwq, &cid);
+ hostdata = sdev->hostdata;
+ ioq = &hdev->queues[hwq];
+ memset(&ioq_cmd, 0, sizeof(ioq_cmd));
+ ioq_cmd.rw.hdid = cpu_to_le32(hostdata->hdid);
+ ioq_cmd.rw.command_id = cid;
+
+ spraid_setup_ioq_cmd(hdev, &ioq_cmd, scmd);
+
+ ret = cid * SCSI_SENSE_BUFFERSIZE;
+ iod->sense = ioq->sense + ret;
+ iod->sense_dma = ioq->sense_dma_addr + ret;
+
+ ret = spraid_init_iod(hdev, iod, &ioq_cmd, scmd);
+ if (unlikely(ret))
+ return SCSI_MLQUEUE_HOST_BUSY;
+
+ iod->spraidq = ioq;
+ ret = spraid_io_map_data(hdev, iod, scmd, &ioq_cmd);
+ if (unlikely(ret)) {
+ dev_err(hdev->dev, "spraid_io_map_data Err.\n");
+ set_host_byte(scmd, DID_ERROR);
+ scsi_done(scmd);
+ ret = 0;
+ goto deinit_iod;
+ }
+
+ WRITE_ONCE(iod->state, SPRAID_CMD_IN_FLIGHT);
+ spraid_submit_cmd(ioq, &ioq_cmd);
+ elapsed = jiffies - scmd->jiffies_at_alloc;
+ pr_debug("cid[%d], qid[%d] submit IO cost %3ld.%3ld seconds\n",
+ cid, hwq, elapsed / HZ, elapsed % HZ);
+ return 0;
+
+deinit_iod:
+ spraid_free_iod_res(hdev, iod);
+ return ret;
+}
+
+static int spraid_match_dev(struct spraid_dev *hdev, u16 idx, struct scsi_device *sdev)
+{
+ if (SPRAID_DEV_INFO_FLAG_VALID(hdev->devices[idx].flag)) {
+ if (sdev->channel == hdev->devices[idx].channel &&
+ sdev->id == le16_to_cpu(hdev->devices[idx].target) &&
+ sdev->lun < hdev->devices[idx].lun) {
+ dev_info(hdev->dev, "Match device success, channel:target:lun[%d:%d:%d]\n",
+ hdev->devices[idx].channel,
+ hdev->devices[idx].target,
+ hdev->devices[idx].lun);
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+static int spraid_slave_alloc(struct scsi_device *sdev)
+{
+ struct spraid_sdev_hostdata *hostdata;
+ struct spraid_dev *hdev;
+ u16 idx;
+
+ hdev = shost_priv(sdev->host);
+ hostdata = kzalloc(sizeof(*hostdata), GFP_KERNEL);
+ if (!hostdata) {
+ dev_err(hdev->dev, "Alloc scsi host data memory failed\n");
+ return -ENOMEM;
+ }
+
+ down_read(&hdev->devices_rwsem);
+ for (idx = 0; idx < le32_to_cpu(hdev->ctrl_info->nd); idx++) {
+ if (spraid_match_dev(hdev, idx, sdev))
+ goto scan_host;
+ }
+ up_read(&hdev->devices_rwsem);
+
+ kfree(hostdata);
+ return -ENXIO;
+
+scan_host:
+ hostdata->hdid = le32_to_cpu(hdev->devices[idx].hdid);
+ sdev->hostdata = hostdata;
+ up_read(&hdev->devices_rwsem);
+ return 0;
+}
+
+static void spraid_slave_destroy(struct scsi_device *sdev)
+{
+ kfree(sdev->hostdata);
+ sdev->hostdata = NULL;
+}
+
+static int spraid_slave_configure(struct scsi_device *sdev)
+{
+ u16 idx;
+ unsigned int timeout = SCMD_TMOUT_RAWDISK * HZ;
+ struct spraid_dev *hdev = shost_priv(sdev->host);
+ struct spraid_sdev_hostdata *hostdata = sdev->hostdata;
+ u32 max_sec = sdev->host->max_sectors;
+
+ if (hostdata) {
+ idx = hostdata->hdid - 1;
+ if (sdev->channel == hdev->devices[idx].channel &&
+ sdev->id == le16_to_cpu(hdev->devices[idx].target) &&
+ sdev->lun < hdev->devices[idx].lun) {
+ if (SPRAID_DEV_INFO_ATTR_VD(hdev->devices[idx].attr))
+ timeout = SCMD_TMOUT_VD * HZ;
+ else if (SPRAID_DEV_INFO_ATTR_RAWDISK(hdev->devices[idx].attr))
+ timeout = SCMD_TMOUT_RAWDISK * HZ;
+ max_sec = le16_to_cpu(hdev->devices[idx].max_io_kb) << 1;
+ } else {
+ dev_err(hdev->dev, "[%s] err, sdev->channel:id:lun[%d:%d:%lld];"
+ "devices[%d], channel:target:lun[%d:%d:%d]\n",
+ __func__, sdev->channel, sdev->id, sdev->lun,
+ idx, hdev->devices[idx].channel,
+ hdev->devices[idx].target,
+ hdev->devices[idx].lun);
+ }
+ } else {
+ dev_err(hdev->dev, "[%s] err, sdev->hostdata is null\n", __func__);
+ }
+
+ blk_queue_rq_timeout(sdev->request_queue, timeout);
+ sdev->eh_timeout = timeout;
+
+ if ((max_sec == 0) || (max_sec > sdev->host->max_sectors))
+ max_sec = sdev->host->max_sectors;
+ blk_queue_max_hw_sectors(sdev->request_queue, max_sec);
+
+ dev_info(hdev->dev, "[%s] sdev->channel:id:lun[%d:%d:%lld], scmd_timeout[%d]s, maxsec[%d]\n",
+ __func__, sdev->channel, sdev->id, sdev->lun, timeout / HZ, max_sec);
+
+ return 0;
+}
+
+static void spraid_shost_init(struct spraid_dev *hdev)
+{
+ struct pci_dev *pdev = hdev->pdev;
+ u8 domain, bus;
+ u32 dev_func;
+
+ domain = pci_domain_nr(pdev->bus);
+ bus = pdev->bus->number;
+ dev_func = pdev->devfn;
+
+ hdev->shost->nr_hw_queues = hdev->online_queues - 1;
+ hdev->shost->can_queue = (hdev->ioq_depth - SPRAID_PTCMDS_PERQ);
+
+ hdev->shost->sg_tablesize = le16_to_cpu(hdev->ctrl_info->max_num_sge);
+ /* 512B per sector */
+ hdev->shost->max_sectors = (1U << ((hdev->ctrl_info->mdts) * 1U) << 12) / 512;
+ hdev->shost->cmd_per_lun = MAX_CMD_PER_DEV;
+ hdev->shost->max_channel = le16_to_cpu(hdev->ctrl_info->max_channel) - 1;
+ hdev->shost->max_id = le32_to_cpu(hdev->ctrl_info->max_tgt_id);
+ hdev->shost->max_lun = le16_to_cpu(hdev->ctrl_info->max_lun);
+
+ hdev->shost->this_id = -1;
+ hdev->shost->unique_id = (domain << 16) | (bus << 8) | dev_func;
+ hdev->shost->max_cmd_len = MAX_CDB_LEN;
+ hdev->shost->hostt->cmd_size = max(spraid_cmd_size(hdev, false, true),
+ spraid_cmd_size(hdev, false, false));
+}
+
+static inline void spraid_host_deinit(struct spraid_dev *hdev)
+{
+ ida_free(&spraid_instance_ida, hdev->instance);
+}
+
+static int spraid_alloc_queue(struct spraid_dev *hdev, u16 qid, u16 depth)
+{
+ struct spraid_queue *spraidq = &hdev->queues[qid];
+ int ret = 0;
+
+ if (hdev->queue_count > qid) {
+ dev_info(hdev->dev, "[%s] warn: queue[%d] is exist\n", __func__, qid);
+ return 0;
+ }
+
+ spraidq->cqes = dma_alloc_coherent(hdev->dev, CQ_SIZE(depth),
+ &spraidq->cq_dma_addr, GFP_KERNEL | __GFP_ZERO);
+ if (!spraidq->cqes)
+ return -ENOMEM;
+
+ spraidq->sq_cmds = dma_alloc_coherent(hdev->dev, SQ_SIZE(qid, depth),
+ &spraidq->sq_dma_addr, GFP_KERNEL);
+ if (!spraidq->sq_cmds) {
+ ret = -ENOMEM;
+ goto free_cqes;
+ }
+
+ spin_lock_init(&spraidq->sq_lock);
+ spin_lock_init(&spraidq->cq_lock);
+ spraidq->hdev = hdev;
+ spraidq->q_depth = depth;
+ spraidq->qid = qid;
+ spraidq->cq_vector = -1;
+ hdev->queue_count++;
+
+ /* alloc sense buffer */
+ spraidq->sense = dma_alloc_coherent(hdev->dev, SENSE_SIZE(depth),
+ &spraidq->sense_dma_addr, GFP_KERNEL | __GFP_ZERO);
+ if (!spraidq->sense) {
+ ret = -ENOMEM;
+ goto free_sq_cmds;
+ }
+
+ return 0;
+
+free_sq_cmds:
+ dma_free_coherent(hdev->dev, SQ_SIZE(qid, depth), (void *)spraidq->sq_cmds,
+ spraidq->sq_dma_addr);
+free_cqes:
+ dma_free_coherent(hdev->dev, CQ_SIZE(depth), (void *)spraidq->cqes,
+ spraidq->cq_dma_addr);
+ return ret;
+}
+
+static int spraid_wait_ready(struct spraid_dev *hdev, u64 cap, bool enabled)
+{
+ unsigned long timeout =
+ ((SPRAID_CAP_TIMEOUT(cap) + 1) * SPRAID_CAP_TIMEOUT_UNIT_MS) + jiffies;
+ u32 bit = enabled ? SPRAID_CSTS_RDY : 0;
+
+ while ((readl(hdev->bar + SPRAID_REG_CSTS) & SPRAID_CSTS_RDY) != bit) {
+ usleep_range(1000, 2000);
+ if (fatal_signal_pending(current))
+ return -EINTR;
+
+ if (time_after(jiffies, timeout)) {
+ dev_err(hdev->dev, "Device not ready; aborting %s\n",
+ enabled ? "initialisation" : "reset");
+ return -ENODEV;
+ }
+ }
+ return 0;
+}
+
+static int spraid_shutdown_ctrl(struct spraid_dev *hdev)
+{
+ unsigned long timeout = hdev->ctrl_info->rtd3e + jiffies;
+
+ hdev->ctrl_config &= ~SPRAID_CC_SHN_MASK;
+ hdev->ctrl_config |= SPRAID_CC_SHN_NORMAL;
+ writel(hdev->ctrl_config, hdev->bar + SPRAID_REG_CC);
+
+ while ((readl(hdev->bar + SPRAID_REG_CSTS) & SPRAID_CSTS_SHST_MASK) !=
+ SPRAID_CSTS_SHST_CMPLT) {
+ msleep(100);
+ if (fatal_signal_pending(current))
+ return -EINTR;
+ if (time_after(jiffies, timeout)) {
+ dev_err(hdev->dev, "Device shutdown incomplete; abort shutdown\n");
+ return -ENODEV;
+ }
+ }
+ return 0;
+}
+
+static int spraid_disable_ctrl(struct spraid_dev *hdev)
+{
+ hdev->ctrl_config &= ~SPRAID_CC_SHN_MASK;
+ hdev->ctrl_config &= ~SPRAID_CC_ENABLE;
+ writel(hdev->ctrl_config, hdev->bar + SPRAID_REG_CC);
+
+ return spraid_wait_ready(hdev, hdev->cap, false);
+}
+
+static int spraid_enable_ctrl(struct spraid_dev *hdev)
+{
+ u64 cap = hdev->cap;
+ u32 dev_page_min = SPRAID_CAP_MPSMIN(cap) + 12;
+ u32 page_shift = PAGE_SHIFT;
+
+ if (page_shift < dev_page_min) {
+ dev_err(hdev->dev, "Minimum device page size[%u], too large for host[%u]\n",
+ 1U << dev_page_min, 1U << page_shift);
+ return -ENODEV;
+ }
+
+ page_shift = min_t(unsigned int, SPRAID_CAP_MPSMAX(cap) + 12, PAGE_SHIFT);
+ hdev->page_size = 1U << page_shift;
+
+ hdev->ctrl_config = SPRAID_CC_CSS_NVM;
+ hdev->ctrl_config |= (page_shift - 12) << SPRAID_CC_MPS_SHIFT;
+ hdev->ctrl_config |= SPRAID_CC_AMS_RR | SPRAID_CC_SHN_NONE;
+ hdev->ctrl_config |= SPRAID_CC_IOSQES | SPRAID_CC_IOCQES;
+ hdev->ctrl_config |= SPRAID_CC_ENABLE;
+ writel(hdev->ctrl_config, hdev->bar + SPRAID_REG_CC);
+
+ return spraid_wait_ready(hdev, cap, true);
+}
+
+static void spraid_init_queue(struct spraid_queue *spraidq, u16 qid)
+{
+ struct spraid_dev *hdev = spraidq->hdev;
+
+ memset((void *)spraidq->cqes, 0, CQ_SIZE(spraidq->q_depth));
+
+ spraidq->sq_tail = 0;
+ spraidq->cq_head = 0;
+ spraidq->cq_phase = 1;
+ spraidq->q_db = &hdev->dbs[qid * 2 * hdev->db_stride];
+ spraidq->prp_small_pool = hdev->prp_small_pool[qid % small_pool_num];
+ hdev->online_queues++;
+}
+
+static inline bool spraid_cqe_pending(struct spraid_queue *spraidq)
+{
+ return (le16_to_cpu(spraidq->cqes[spraidq->cq_head].status) & 1) ==
+ spraidq->cq_phase;
+}
+
+static void spraid_complete_ioq_cmnd(struct spraid_queue *ioq, struct spraid_completion *cqe)
+{
+ struct spraid_dev *hdev = ioq->hdev;
+ struct blk_mq_tags *tags;
+ struct scsi_cmnd *scmd;
+ struct spraid_iod *iod;
+ struct request *req;
+ unsigned long elapsed;
+
+ tags = hdev->shost->tag_set.tags[ioq->qid - 1];
+ req = blk_mq_tag_to_rq(tags, cqe->cmd_id);
+ if (unlikely(!req || !blk_mq_request_started(req))) {
+ dev_warn(hdev->dev, "Invalid id %d completed on queue %d\n",
+ cqe->cmd_id, ioq->qid);
+ return;
+ }
+
+ scmd = blk_mq_rq_to_pdu(req);
+ iod = scsi_cmd_priv(scmd);
+
+ elapsed = jiffies - scmd->jiffies_at_alloc;
+ pr_debug("cid[%d], qid[%d] finish IO cost %3ld.%3ld seconds\n",
+ cqe->cmd_id, ioq->qid, elapsed / HZ, elapsed % HZ);
+
+ if (cmpxchg(&iod->state, SPRAID_CMD_IN_FLIGHT, SPRAID_CMD_COMPLETE) !=
+ SPRAID_CMD_IN_FLIGHT) {
+ dev_warn(hdev->dev, "cid[%d], qid[%d] enters abnormal handler, cost %3ld.%3ld seconds\n",
+ cqe->cmd_id, ioq->qid, elapsed / HZ, elapsed % HZ);
+ WRITE_ONCE(iod->state, SPRAID_CMD_TMO_COMPLETE);
+
+ if (iod->nsge) {
+ iod->nsge = 0;
+ scsi_dma_unmap(scmd);
+ }
+ spraid_free_iod_res(hdev, iod);
+
+ return;
+ }
+
+ spraid_map_status(iod, scmd, cqe);
+ if (iod->nsge) {
+ iod->nsge = 0;
+ scsi_dma_unmap(scmd);
+ }
+ spraid_free_iod_res(hdev, iod);
+ scsi_done(scmd);
+}
+
+
+static void spraid_complete_adminq_cmnd(struct spraid_queue *adminq, struct spraid_completion *cqe)
+{
+ struct spraid_dev *hdev = adminq->hdev;
+ struct spraid_cmd *adm_cmd;
+
+ adm_cmd = hdev->adm_cmds + cqe->cmd_id;
+ if (unlikely(adm_cmd->state == SPRAID_CMD_IDLE)) {
+ dev_warn(adminq->hdev->dev, "Invalid id %d completed on queue %d\n",
+ cqe->cmd_id, le16_to_cpu(cqe->sq_id));
+ return;
+ }
+
+ adm_cmd->status = le16_to_cpu(cqe->status) >> 1;
+ adm_cmd->result0 = le32_to_cpu(cqe->result);
+ adm_cmd->result1 = le32_to_cpu(cqe->result1);
+
+ complete(&adm_cmd->cmd_done);
+}
+
+static void spraid_send_aen(struct spraid_dev *hdev, u16 cid);
+
+static void spraid_complete_aen(struct spraid_queue *spraidq, struct spraid_completion *cqe)
+{
+ struct spraid_dev *hdev = spraidq->hdev;
+ u32 result = le32_to_cpu(cqe->result);
+
+ dev_info(hdev->dev, "rcv aen, status[%x], result[%x]\n",
+ le16_to_cpu(cqe->status) >> 1, result);
+
+ spraid_send_aen(hdev, cqe->cmd_id);
+
+ if ((le16_to_cpu(cqe->status) >> 1) != SPRAID_SC_SUCCESS)
+ return;
+ switch (result & 0x7) {
+ case SPRAID_AEN_NOTICE:
+ spraid_handle_aen_notice(hdev, result);
+ break;
+ case SPRAID_AEN_VS:
+ spraid_handle_aen_vs(hdev, result, le32_to_cpu(cqe->result1));
+ break;
+ default:
+ dev_warn(hdev->dev, "Unsupported async event type: %u\n",
+ result & 0x7);
+ break;
+ }
+}
+
+static void spraid_complete_ioq_sync_cmnd(struct spraid_queue *ioq, struct spraid_completion *cqe)
+{
+ struct spraid_dev *hdev = ioq->hdev;
+ struct spraid_cmd *ptcmd;
+
+ ptcmd = hdev->ioq_ptcmds + (ioq->qid - 1) * SPRAID_PTCMDS_PERQ +
+ cqe->cmd_id - SPRAID_IO_BLK_MQ_DEPTH;
+
+ ptcmd->status = le16_to_cpu(cqe->status) >> 1;
+ ptcmd->result0 = le32_to_cpu(cqe->result);
+ ptcmd->result1 = le32_to_cpu(cqe->result1);
+
+ complete(&ptcmd->cmd_done);
+}
+
+static inline void spraid_handle_cqe(struct spraid_queue *spraidq, u16 idx)
+{
+ struct spraid_completion *cqe = &spraidq->cqes[idx];
+ struct spraid_dev *hdev = spraidq->hdev;
+
+ if (unlikely(cqe->cmd_id >= spraidq->q_depth)) {
+ dev_err(hdev->dev, "Invalid command id[%d] completed on queue %d\n",
+ cqe->cmd_id, cqe->sq_id);
+ return;
+ }
+
+ pr_debug("cid[%d], qid[%d], result[0x%x], sq_id[%d], status[0x%x]\n",
+ cqe->cmd_id, spraidq->qid, le32_to_cpu(cqe->result),
+ le16_to_cpu(cqe->sq_id), le16_to_cpu(cqe->status));
+
+ if (unlikely(spraidq->qid == 0 && cqe->cmd_id >= SPRAID_AQ_BLK_MQ_DEPTH)) {
+ spraid_complete_aen(spraidq, cqe);
+ return;
+ }
+
+ if (unlikely(spraidq->qid && cqe->cmd_id >= SPRAID_IO_BLK_MQ_DEPTH)) {
+ spraid_complete_ioq_sync_cmnd(spraidq, cqe);
+ return;
+ }
+
+ if (spraidq->qid)
+ spraid_complete_ioq_cmnd(spraidq, cqe);
+ else
+ spraid_complete_adminq_cmnd(spraidq, cqe);
+}
+
+static void spraid_complete_cqes(struct spraid_queue *spraidq, u16 start, u16 end)
+{
+ while (start != end) {
+ spraid_handle_cqe(spraidq, start);
+ if (++start == spraidq->q_depth)
+ start = 0;
+ }
+}
+
+static inline void spraid_update_cq_head(struct spraid_queue *spraidq)
+{
+ if (++spraidq->cq_head == spraidq->q_depth) {
+ spraidq->cq_head = 0;
+ spraidq->cq_phase = !spraidq->cq_phase;
+ }
+}
+
+static inline bool spraid_process_cq(struct spraid_queue *spraidq, u16 *start, u16 *end, int tag)
+{
+ bool found = false;
+
+ *start = spraidq->cq_head;
+ while (!found && spraid_cqe_pending(spraidq)) {
+ if (spraidq->cqes[spraidq->cq_head].cmd_id == tag)
+ found = true;
+ spraid_update_cq_head(spraidq);
+ }
+ *end = spraidq->cq_head;
+
+ if (*start != *end)
+ writel(spraidq->cq_head, spraidq->q_db + spraidq->hdev->db_stride);
+
+ return found;
+}
+
+static bool spraid_poll_cq(struct spraid_queue *spraidq, int cid)
+{
+ u16 start, end;
+ bool found;
+
+ if (!spraid_cqe_pending(spraidq))
+ return 0;
+
+ spin_lock_irq(&spraidq->cq_lock);
+ found = spraid_process_cq(spraidq, &start, &end, cid);
+ spin_unlock_irq(&spraidq->cq_lock);
+
+ spraid_complete_cqes(spraidq, start, end);
+ return found;
+}
+
+static irqreturn_t spraid_irq(int irq, void *data)
+{
+ struct spraid_queue *spraidq = data;
+ irqreturn_t ret = IRQ_NONE;
+ u16 start, end;
+
+ spin_lock(&spraidq->cq_lock);
+ if (spraidq->cq_head != spraidq->last_cq_head)
+ ret = IRQ_HANDLED;
+
+ spraid_process_cq(spraidq, &start, &end, -1);
+ spraidq->last_cq_head = spraidq->cq_head;
+ spin_unlock(&spraidq->cq_lock);
+
+ if (start != end) {
+ spraid_complete_cqes(spraidq, start, end);
+ ret = IRQ_HANDLED;
+ }
+ return ret;
+}
+
+static int spraid_setup_admin_queue(struct spraid_dev *hdev)
+{
+ struct spraid_queue *adminq = &hdev->queues[0];
+ u32 aqa;
+ int ret;
+
+ dev_info(hdev->dev, "[%s] start disable ctrl\n", __func__);
+
+ ret = spraid_disable_ctrl(hdev);
+ if (ret)
+ return ret;
+
+ ret = spraid_alloc_queue(hdev, 0, SPRAID_AQ_DEPTH);
+ if (ret)
+ return ret;
+
+ aqa = adminq->q_depth - 1;
+ aqa |= aqa << 16;
+ writel(aqa, hdev->bar + SPRAID_REG_AQA);
+ lo_hi_writeq(adminq->sq_dma_addr, hdev->bar + SPRAID_REG_ASQ);
+ lo_hi_writeq(adminq->cq_dma_addr, hdev->bar + SPRAID_REG_ACQ);
+
+ dev_info(hdev->dev, "[%s] start enable ctrl\n", __func__);
+
+ ret = spraid_enable_ctrl(hdev);
+ if (ret) {
+ ret = -ENODEV;
+ goto free_queue;
+ }
+
+ adminq->cq_vector = 0;
+ spraid_init_queue(adminq, 0);
+ ret = pci_request_irq(hdev->pdev, adminq->cq_vector, spraid_irq, NULL,
+ adminq, "spraid%d_q%d", hdev->instance, adminq->qid);
+
+ if (ret) {
+ adminq->cq_vector = -1;
+ hdev->online_queues--;
+ goto free_queue;
+ }
+
+ dev_info(hdev->dev, "[%s] success, queuecount:[%d], onlinequeue:[%d]\n",
+ __func__, hdev->queue_count, hdev->online_queues);
+
+ return 0;
+
+free_queue:
+ spraid_free_queue(adminq);
+ return ret;
+}
+
+static u32 spraid_bar_size(struct spraid_dev *hdev, u32 nr_ioqs)
+{
+ return (SPRAID_REG_DBS + ((nr_ioqs + 1) * 8 * hdev->db_stride));
+}
+
+static int spraid_alloc_admin_cmds(struct spraid_dev *hdev)
+{
+ int i;
+
+ INIT_LIST_HEAD(&hdev->adm_cmd_list);
+ spin_lock_init(&hdev->adm_cmd_lock);
+
+ hdev->adm_cmds = kcalloc_node(SPRAID_AQ_BLK_MQ_DEPTH, sizeof(struct spraid_cmd),
+ GFP_KERNEL, hdev->numa_node);
+
+ if (!hdev->adm_cmds) {
+ dev_err(hdev->dev, "Alloc admin cmds failed\n");
+ return -ENOMEM;
+ }
+
+ for (i = 0; i < SPRAID_AQ_BLK_MQ_DEPTH; i++) {
+ hdev->adm_cmds[i].qid = 0;
+ hdev->adm_cmds[i].cid = i;
+ list_add_tail(&(hdev->adm_cmds[i].list), &hdev->adm_cmd_list);
+ }
+
+ dev_info(hdev->dev, "Alloc admin cmds success, num[%d]\n", SPRAID_AQ_BLK_MQ_DEPTH);
+
+ return 0;
+}
+
+static void spraid_free_admin_cmds(struct spraid_dev *hdev)
+{
+ kfree(hdev->adm_cmds);
+ INIT_LIST_HEAD(&hdev->adm_cmd_list);
+}
+
+static struct spraid_cmd *spraid_get_cmd(struct spraid_dev *hdev, enum spraid_cmd_type type)
+{
+ struct spraid_cmd *cmd = NULL;
+ unsigned long flags;
+ struct list_head *head = &hdev->adm_cmd_list;
+ spinlock_t *slock = &hdev->adm_cmd_lock;
+
+ if (type == SPRAID_CMD_IOPT) {
+ head = &hdev->ioq_pt_list;
+ slock = &hdev->ioq_pt_lock;
+ }
+
+ spin_lock_irqsave(slock, flags);
+ if (list_empty(head)) {
+ spin_unlock_irqrestore(slock, flags);
+ dev_err(hdev->dev, "err, cmd[%d] list empty\n", type);
+ return NULL;
+ }
+ cmd = list_entry(head->next, struct spraid_cmd, list);
+ list_del_init(&cmd->list);
+ spin_unlock_irqrestore(slock, flags);
+
+ WRITE_ONCE(cmd->state, SPRAID_CMD_IN_FLIGHT);
+
+ return cmd;
+}
+
+static void spraid_put_cmd(struct spraid_dev *hdev, struct spraid_cmd *cmd,
+ enum spraid_cmd_type type)
+{
+ unsigned long flags;
+ struct list_head *head = &hdev->adm_cmd_list;
+ spinlock_t *slock = &hdev->adm_cmd_lock;
+
+ if (type == SPRAID_CMD_IOPT) {
+ head = &hdev->ioq_pt_list;
+ slock = &hdev->ioq_pt_lock;
+ }
+
+ spin_lock_irqsave(slock, flags);
+ WRITE_ONCE(cmd->state, SPRAID_CMD_IDLE);
+ list_add_tail(&cmd->list, head);
+ spin_unlock_irqrestore(slock, flags);
+}
+
+
+static int spraid_submit_admin_sync_cmd(struct spraid_dev *hdev, struct spraid_admin_command *cmd,
+ u32 *result0, u32 *result1, u32 timeout)
+{
+ struct spraid_cmd *adm_cmd = spraid_get_cmd(hdev, SPRAID_CMD_ADM);
+
+ if (!adm_cmd) {
+ dev_err(hdev->dev, "err, get admin cmd failed\n");
+ return -EFAULT;
+ }
+
+ timeout = timeout ? timeout : ADMIN_TIMEOUT;
+
+ init_completion(&adm_cmd->cmd_done);
+
+ cmd->common.command_id = adm_cmd->cid;
+ spraid_submit_cmd(&hdev->queues[0], cmd);
+
+ if (!wait_for_completion_timeout(&adm_cmd->cmd_done, timeout)) {
+ dev_err(hdev->dev, "[%s] cid[%d] qid[%d] timeout, opcode[0x%x] subopcode[0x%x]\n",
+ __func__, adm_cmd->cid, adm_cmd->qid, cmd->usr_cmd.opcode,
+ cmd->usr_cmd.info_0.subopcode);
+ WRITE_ONCE(adm_cmd->state, SPRAID_CMD_TIMEOUT);
+ return -EINVAL;
+ }
+
+ if (result0)
+ *result0 = adm_cmd->result0;
+ if (result1)
+ *result1 = adm_cmd->result1;
+
+ spraid_put_cmd(hdev, adm_cmd, SPRAID_CMD_ADM);
+
+ return adm_cmd->status;
+}
+
+static int spraid_create_cq(struct spraid_dev *hdev, u16 qid,
+ struct spraid_queue *spraidq, u16 cq_vector)
+{
+ struct spraid_admin_command admin_cmd;
+ int flags = SPRAID_QUEUE_PHYS_CONTIG | SPRAID_CQ_IRQ_ENABLED;
+
+ memset(&admin_cmd, 0, sizeof(admin_cmd));
+ admin_cmd.create_cq.opcode = SPRAID_ADMIN_CREATE_CQ;
+ admin_cmd.create_cq.prp1 = cpu_to_le64(spraidq->cq_dma_addr);
+ admin_cmd.create_cq.cqid = cpu_to_le16(qid);
+ admin_cmd.create_cq.qsize = cpu_to_le16(spraidq->q_depth - 1);
+ admin_cmd.create_cq.cq_flags = cpu_to_le16(flags);
+ admin_cmd.create_cq.irq_vector = cpu_to_le16(cq_vector);
+
+ return spraid_submit_admin_sync_cmd(hdev, &admin_cmd, NULL, NULL, 0);
+}
+
+static int spraid_create_sq(struct spraid_dev *hdev, u16 qid,
+ struct spraid_queue *spraidq)
+{
+ struct spraid_admin_command admin_cmd;
+ int flags = SPRAID_QUEUE_PHYS_CONTIG;
+
+ memset(&admin_cmd, 0, sizeof(admin_cmd));
+ admin_cmd.create_sq.opcode = SPRAID_ADMIN_CREATE_SQ;
+ admin_cmd.create_sq.prp1 = cpu_to_le64(spraidq->sq_dma_addr);
+ admin_cmd.create_sq.sqid = cpu_to_le16(qid);
+ admin_cmd.create_sq.qsize = cpu_to_le16(spraidq->q_depth - 1);
+ admin_cmd.create_sq.sq_flags = cpu_to_le16(flags);
+ admin_cmd.create_sq.cqid = cpu_to_le16(qid);
+
+ return spraid_submit_admin_sync_cmd(hdev, &admin_cmd, NULL, NULL, 0);
+}
+
+static void spraid_free_queue(struct spraid_queue *spraidq)
+{
+ struct spraid_dev *hdev = spraidq->hdev;
+
+ hdev->queue_count--;
+ dma_free_coherent(hdev->dev, CQ_SIZE(spraidq->q_depth),
+ (void *)spraidq->cqes, spraidq->cq_dma_addr);
+ dma_free_coherent(hdev->dev, SQ_SIZE(spraidq->qid, spraidq->q_depth),
+ spraidq->sq_cmds, spraidq->sq_dma_addr);
+ dma_free_coherent(hdev->dev, SENSE_SIZE(spraidq->q_depth),
+ spraidq->sense, spraidq->sense_dma_addr);
+}
+
+static void spraid_free_admin_queue(struct spraid_dev *hdev)
+{
+ spraid_free_queue(&hdev->queues[0]);
+}
+
+static void spraid_free_io_queues(struct spraid_dev *hdev)
+{
+ int i;
+
+ for (i = hdev->queue_count - 1; i >= 1; i--)
+ spraid_free_queue(&hdev->queues[i]);
+}
+
+static int spraid_delete_queue(struct spraid_dev *hdev, u8 op, u16 id)
+{
+ struct spraid_admin_command admin_cmd;
+ int ret;
+
+ memset(&admin_cmd, 0, sizeof(admin_cmd));
+ admin_cmd.delete_queue.opcode = op;
+ admin_cmd.delete_queue.qid = cpu_to_le16(id);
+
+ ret = spraid_submit_admin_sync_cmd(hdev, &admin_cmd, NULL, NULL, 0);
+
+ if (ret)
+ dev_err(hdev->dev, "Delete %s:[%d] failed\n",
+ (op == SPRAID_ADMIN_DELETE_CQ) ? "cq" : "sq", id);
+
+ return ret;
+}
+
+static int spraid_delete_cq(struct spraid_dev *hdev, u16 cqid)
+{
+ return spraid_delete_queue(hdev, SPRAID_ADMIN_DELETE_CQ, cqid);
+}
+
+static int spraid_delete_sq(struct spraid_dev *hdev, u16 sqid)
+{
+ return spraid_delete_queue(hdev, SPRAID_ADMIN_DELETE_SQ, sqid);
+}
+
+static int spraid_create_queue(struct spraid_queue *spraidq, u16 qid)
+{
+ struct spraid_dev *hdev = spraidq->hdev;
+ u16 cq_vector;
+ int ret;
+
+ cq_vector = (hdev->num_vecs == 1) ? 0 : qid;
+ ret = spraid_create_cq(hdev, qid, spraidq, cq_vector);
+ if (ret)
+ return ret;
+
+ ret = spraid_create_sq(hdev, qid, spraidq);
+ if (ret)
+ goto delete_cq;
+
+ spraid_init_queue(spraidq, qid);
+ spraidq->cq_vector = cq_vector;
+
+ ret = pci_request_irq(hdev->pdev, cq_vector, spraid_irq, NULL,
+ spraidq, "spraid%d_q%d", hdev->instance, qid);
+
+ if (ret) {
+ dev_err(hdev->dev, "Request queue[%d] irq failed\n", qid);
+ goto delete_sq;
+ }
+
+ return 0;
+
+delete_sq:
+ spraidq->cq_vector = -1;
+ hdev->online_queues--;
+ spraid_delete_sq(hdev, qid);
+delete_cq:
+ spraid_delete_cq(hdev, qid);
+
+ return ret;
+}
+
+static int spraid_create_io_queues(struct spraid_dev *hdev)
+{
+ u32 i, max;
+ int ret = 0;
+
+ max = min(hdev->max_qid, hdev->queue_count - 1);
+ for (i = hdev->online_queues; i <= max; i++) {
+ ret = spraid_create_queue(&hdev->queues[i], i);
+ if (ret) {
+ dev_err(hdev->dev, "Create queue[%d] failed\n", i);
+ break;
+ }
+ }
+
+ dev_info(hdev->dev, "[%s] queue_count[%d], online_queue[%d]",
+ __func__, hdev->queue_count, hdev->online_queues);
+
+ return ret >= 0 ? 0 : ret;
+}
+
+static int spraid_set_features(struct spraid_dev *hdev, u32 fid, u32 dword11, void *buffer,
+ size_t buflen, u32 *result)
+{
+ struct spraid_admin_command admin_cmd;
+ int ret;
+ u8 *data_ptr = NULL;
+ dma_addr_t data_dma = 0;
+
+ if (buffer && buflen) {
+ data_ptr = dma_alloc_coherent(hdev->dev, buflen, &data_dma, GFP_KERNEL);
+ if (!data_ptr)
+ return -ENOMEM;
+
+ memcpy(data_ptr, buffer, buflen);
+ }
+
+ memset(&admin_cmd, 0, sizeof(admin_cmd));
+ admin_cmd.features.opcode = SPRAID_ADMIN_SET_FEATURES;
+ admin_cmd.features.fid = cpu_to_le32(fid);
+ admin_cmd.features.dword11 = cpu_to_le32(dword11);
+ admin_cmd.common.dptr.prp1 = cpu_to_le64(data_dma);
+
+ ret = spraid_submit_admin_sync_cmd(hdev, &admin_cmd, result, NULL, 0);
+
+ if (data_ptr)
+ dma_free_coherent(hdev->dev, buflen, data_ptr, data_dma);
+
+ return ret;
+}
+
+static int spraid_configure_timestamp(struct spraid_dev *hdev)
+{
+ __le64 ts;
+ int ret;
+
+ ts = cpu_to_le64(ktime_to_ms(ktime_get_real()));
+ ret = spraid_set_features(hdev, SPRAID_FEAT_TIMESTAMP, 0, &ts, sizeof(ts), NULL);
+
+ if (ret)
+ dev_err(hdev->dev, "set timestamp failed: %d\n", ret);
+ return ret;
+}
+
+static int spraid_set_queue_cnt(struct spraid_dev *hdev, u32 *cnt)
+{
+ u32 q_cnt = (*cnt - 1) | ((*cnt - 1) << 16);
+ u32 nr_ioqs, result;
+ int status;
+
+ status = spraid_set_features(hdev, SPRAID_FEAT_NUM_QUEUES, q_cnt, NULL, 0, &result);
+ if (status) {
+ dev_err(hdev->dev, "Set queue count failed, status: %d\n",
+ status);
+ return -EIO;
+ }
+
+ nr_ioqs = min(result & 0xffff, result >> 16) + 1;
+ *cnt = min(*cnt, nr_ioqs);
+ if (*cnt == 0) {
+ dev_err(hdev->dev, "Illegal queue count: zero\n");
+ return -EIO;
+ }
+ return 0;
+}
+
+static int spraid_setup_io_queues(struct spraid_dev *hdev)
+{
+ struct spraid_queue *adminq = &hdev->queues[0];
+ struct pci_dev *pdev = hdev->pdev;
+ u32 nr_ioqs = num_online_cpus();
+ u32 i, size;
+ int ret;
+
+ struct irq_affinity affd = {
+ .pre_vectors = 1
+ };
+
+ ret = spraid_set_queue_cnt(hdev, &nr_ioqs);
+ if (ret < 0)
+ return ret;
+
+ size = spraid_bar_size(hdev, nr_ioqs);
+ ret = spraid_remap_bar(hdev, size);
+ if (ret)
+ return -ENOMEM;
+
+ adminq->q_db = hdev->dbs;
+
+ pci_free_irq(pdev, 0, adminq);
+ pci_free_irq_vectors(pdev);
+
+ ret = pci_alloc_irq_vectors_affinity(pdev, 1, (nr_ioqs + 1),
+ PCI_IRQ_ALL_TYPES | PCI_IRQ_AFFINITY, &affd);
+ if (ret <= 0)
+ return -EIO;
+
+ hdev->num_vecs = ret;
+
+ hdev->max_qid = max(ret - 1, 1);
+
+ ret = pci_request_irq(pdev, adminq->cq_vector, spraid_irq, NULL,
+ adminq, "spraid%d_q%d", hdev->instance, adminq->qid);
+ if (ret) {
+ dev_err(hdev->dev, "Request admin irq failed\n");
+ adminq->cq_vector = -1;
+ return ret;
+ }
+
+ for (i = hdev->queue_count; i <= hdev->max_qid; i++) {
+ ret = spraid_alloc_queue(hdev, i, hdev->ioq_depth);
+ if (ret)
+ break;
+ }
+ dev_info(hdev->dev, "[%s] max_qid: %d, queue_count: %d, online_queue: %d, ioq_depth: %d\n",
+ __func__, hdev->max_qid, hdev->queue_count, hdev->online_queues, hdev->ioq_depth);
+
+ return spraid_create_io_queues(hdev);
+}
+
+static void spraid_delete_io_queues(struct spraid_dev *hdev)
+{
+ u16 queues = hdev->online_queues - 1;
+ u8 opcode = SPRAID_ADMIN_DELETE_SQ;
+ u16 i, pass;
+
+ if (!pci_device_is_present(hdev->pdev)) {
+ dev_err(hdev->dev, "pci_device is not present, skip disable io queues\n");
+ return;
+ }
+
+ if (hdev->online_queues < 2) {
+ dev_err(hdev->dev, "[%s] err, io queue has been delete\n", __func__);
+ return;
+ }
+
+ for (pass = 0; pass < 2; pass++) {
+ for (i = queues; i > 0; i--)
+ if (spraid_delete_queue(hdev, opcode, i))
+ break;
+
+ opcode = SPRAID_ADMIN_DELETE_CQ;
+ }
+}
+
+static void spraid_remove_io_queues(struct spraid_dev *hdev)
+{
+ spraid_delete_io_queues(hdev);
+ spraid_free_io_queues(hdev);
+}
+
+static void spraid_pci_disable(struct spraid_dev *hdev)
+{
+ struct pci_dev *pdev = hdev->pdev;
+ u32 i;
+
+ for (i = 0; i < hdev->online_queues; i++)
+ pci_free_irq(pdev, hdev->queues[i].cq_vector, &hdev->queues[i]);
+ pci_free_irq_vectors(pdev);
+ if (pci_is_enabled(pdev)) {
+ pci_disable_pcie_error_reporting(pdev);
+ pci_disable_device(pdev);
+ }
+ hdev->online_queues = 0;
+}
+
+static void spraid_disable_admin_queue(struct spraid_dev *hdev, bool shutdown)
+{
+ struct spraid_queue *adminq = &hdev->queues[0];
+ u16 start, end;
+
+ if (pci_device_is_present(hdev->pdev)) {
+ if (shutdown)
+ spraid_shutdown_ctrl(hdev);
+ else
+ spraid_disable_ctrl(hdev);
+ }
+
+ if (hdev->queue_count == 0) {
+ dev_err(hdev->dev, "[%s] err, admin queue has been delete\n", __func__);
+ return;
+ }
+
+ spin_lock_irq(&adminq->cq_lock);
+ spraid_process_cq(adminq, &start, &end, -1);
+ spin_unlock_irq(&adminq->cq_lock);
+
+ spraid_complete_cqes(adminq, start, end);
+ spraid_free_admin_queue(hdev);
+}
+
+static int spraid_create_dma_pools(struct spraid_dev *hdev)
+{
+ int i;
+ char poolname[20] = { 0 };
+
+ hdev->prp_page_pool = dma_pool_create("prp list page", hdev->dev,
+ PAGE_SIZE, PAGE_SIZE, 0);
+
+ if (!hdev->prp_page_pool) {
+ dev_err(hdev->dev, "create prp_page_pool failed\n");
+ return -ENOMEM;
+ }
+
+ for (i = 0; i < small_pool_num; i++) {
+ sprintf(poolname, "prp_list_256_%d", i);
+ hdev->prp_small_pool[i] = dma_pool_create(poolname, hdev->dev, SMALL_POOL_SIZE,
+ SMALL_POOL_SIZE, 0);
+
+ if (!hdev->prp_small_pool[i]) {
+ dev_err(hdev->dev, "create prp_small_pool %d failed\n", i);
+ goto destroy_prp_small_pool;
+ }
+ }
+
+ return 0;
+
+destroy_prp_small_pool:
+ while (i > 0)
+ dma_pool_destroy(hdev->prp_small_pool[--i]);
+ dma_pool_destroy(hdev->prp_page_pool);
+
+ return -ENOMEM;
+}
+
+static void spraid_destroy_dma_pools(struct spraid_dev *hdev)
+{
+ int i;
+
+ for (i = 0; i < small_pool_num; i++)
+ dma_pool_destroy(hdev->prp_small_pool[i]);
+ dma_pool_destroy(hdev->prp_page_pool);
+}
+
+static int spraid_get_dev_list(struct spraid_dev *hdev, struct spraid_dev_info *devices)
+{
+ u32 nd = le32_to_cpu(hdev->ctrl_info->nd);
+ struct spraid_admin_command admin_cmd;
+ struct spraid_dev_list *list_buf;
+ dma_addr_t data_dma = 0;
+ u32 i, idx, hdid, ndev;
+ int ret = 0;
+
+ list_buf = dma_alloc_coherent(hdev->dev, PAGE_SIZE, &data_dma, GFP_KERNEL);
+ if (!list_buf)
+ return -ENOMEM;
+
+ for (idx = 0; idx < nd;) {
+ memset(&admin_cmd, 0, sizeof(admin_cmd));
+ admin_cmd.get_info.opcode = SPRAID_ADMIN_GET_INFO;
+ admin_cmd.get_info.type = SPRAID_GET_INFO_DEV_LIST;
+ admin_cmd.get_info.cdw11 = cpu_to_le32(idx);
+ admin_cmd.common.dptr.prp1 = cpu_to_le64(data_dma);
+
+ ret = spraid_submit_admin_sync_cmd(hdev, &admin_cmd, NULL, NULL, 0);
+
+ if (ret) {
+ dev_err(hdev->dev, "Get device list failed, nd: %u, idx: %u, ret: %d\n",
+ nd, idx, ret);
+ goto out;
+ }
+ ndev = le32_to_cpu(list_buf->dev_num);
+
+ dev_info(hdev->dev, "ndev numbers: %u\n", ndev);
+
+ for (i = 0; i < ndev; i++) {
+ hdid = le32_to_cpu(list_buf->devices[i].hdid);
+ dev_info(hdev->dev, "list_buf->devices[%d], hdid: %u target: %d, channel: %d, lun: %d, attr[0x%x]\n",
+ i, hdid, le16_to_cpu(list_buf->devices[i].target),
+ list_buf->devices[i].channel,
+ list_buf->devices[i].lun,
+ list_buf->devices[i].attr);
+ if (hdid > nd || hdid == 0) {
+ dev_err(hdev->dev, "err, hdid[%d] invalid\n", hdid);
+ continue;
+ }
+ memcpy(&devices[hdid - 1], &list_buf->devices[i],
+ sizeof(struct spraid_dev_info));
+ }
+ idx += ndev;
+
+ if (idx < MAX_DEV_ENTRY_PER_PAGE_4K)
+ break;
+ }
+
+out:
+ dma_free_coherent(hdev->dev, PAGE_SIZE, list_buf, data_dma);
+ return ret;
+}
+
+static void spraid_send_aen(struct spraid_dev *hdev, u16 cid)
+{
+ struct spraid_queue *adminq = &hdev->queues[0];
+ struct spraid_admin_command admin_cmd;
+
+ memset(&admin_cmd, 0, sizeof(admin_cmd));
+ admin_cmd.common.opcode = SPRAID_ADMIN_ASYNC_EVENT;
+ admin_cmd.common.command_id = cid;
+
+ spraid_submit_cmd(adminq, &admin_cmd);
+ dev_info(hdev->dev, "send aen, cid[%d]\n", cid);
+}
+static inline void spraid_send_all_aen(struct spraid_dev *hdev)
+{
+ u16 i;
+
+ for (i = 0; i < hdev->ctrl_info->aerl; i++)
+ spraid_send_aen(hdev, i + SPRAID_AQ_BLK_MQ_DEPTH);
+}
+
+static int spraid_add_device(struct spraid_dev *hdev, struct spraid_dev_info *device)
+{
+ struct Scsi_Host *shost = hdev->shost;
+ struct scsi_device *sdev;
+
+ sdev = scsi_device_lookup(shost, device->channel, le16_to_cpu(device->target), 0);
+ if (sdev) {
+ dev_warn(hdev->dev, "Device is already exist, channel: %d, target_id: %d, lun: %d\n",
+ device->channel, le16_to_cpu(device->target), 0);
+ scsi_device_put(sdev);
+ return -EEXIST;
+ }
+ scsi_add_device(shost, device->channel, le16_to_cpu(device->target), 0);
+ return 0;
+}
+
+static int spraid_rescan_device(struct spraid_dev *hdev, struct spraid_dev_info *device)
+{
+ struct Scsi_Host *shost = hdev->shost;
+ struct scsi_device *sdev;
+
+ sdev = scsi_device_lookup(shost, device->channel, le16_to_cpu(device->target), 0);
+ if (!sdev) {
+ dev_warn(hdev->dev, "Device is not exit, channel: %d, target_id: %d, lun: %d\n",
+ device->channel, le16_to_cpu(device->target), 0);
+ return -ENODEV;
+ }
+
+ scsi_rescan_device(&sdev->sdev_gendev);
+ scsi_device_put(sdev);
+ return 0;
+}
+
+static int spraid_remove_device(struct spraid_dev *hdev, struct spraid_dev_info *org_device)
+{
+ struct Scsi_Host *shost = hdev->shost;
+ struct scsi_device *sdev;
+
+ sdev = scsi_device_lookup(shost, org_device->channel, le16_to_cpu(org_device->target), 0);
+ if (!sdev) {
+ dev_warn(hdev->dev, "Device is not exit, channel: %d, target_id: %d, lun: %d\n",
+ org_device->channel, le16_to_cpu(org_device->target), 0);
+ return -ENODEV;
+ }
+
+ scsi_remove_device(sdev);
+ scsi_device_put(sdev);
+ return 0;
+}
+
+static int spraid_dev_list_init(struct spraid_dev *hdev)
+{
+ u32 nd = le32_to_cpu(hdev->ctrl_info->nd);
+ int i, ret;
+
+ hdev->devices = kzalloc_node(nd * sizeof(struct spraid_dev_info),
+ GFP_KERNEL, hdev->numa_node);
+ if (!hdev->devices)
+ return -ENOMEM;
+
+ ret = spraid_get_dev_list(hdev, hdev->devices);
+ if (ret) {
+ dev_err(hdev->dev, "Ignore failure of getting device list within initialization\n");
+ return 0;
+ }
+
+ for (i = 0; i < nd; i++) {
+ if (SPRAID_DEV_INFO_FLAG_VALID(hdev->devices[i].flag) &&
+ SPRAID_DEV_INFO_ATTR_BOOT(hdev->devices[i].attr)) {
+ spraid_add_device(hdev, &hdev->devices[i]);
+ break;
+ }
+ }
+ return 0;
+}
+
+static void spraid_scan_work(struct work_struct *work)
+{
+ struct spraid_dev *hdev =
+ container_of(work, struct spraid_dev, scan_work);
+ struct spraid_dev_info *devices, *org_devices;
+ u32 nd = le32_to_cpu(hdev->ctrl_info->nd);
+ u8 flag, org_flag;
+ int i, ret;
+
+ devices = kcalloc(nd, sizeof(struct spraid_dev_info), GFP_KERNEL);
+ if (!devices)
+ return;
+ ret = spraid_get_dev_list(hdev, devices);
+ if (ret)
+ goto free_list;
+ org_devices = hdev->devices;
+ for (i = 0; i < nd; i++) {
+ org_flag = org_devices[i].flag;
+ flag = devices[i].flag;
+
+ pr_debug("i: %d, org_flag: 0x%x, flag: 0x%x\n",
+ i, org_flag, flag);
+
+ if (SPRAID_DEV_INFO_FLAG_VALID(flag)) {
+ if (!SPRAID_DEV_INFO_FLAG_VALID(org_flag)) {
+ down_write(&hdev->devices_rwsem);
+ memcpy(&org_devices[i], &devices[i],
+ sizeof(struct spraid_dev_info));
+ up_write(&hdev->devices_rwsem);
+ spraid_add_device(hdev, &devices[i]);
+ } else if (SPRAID_DEV_INFO_FLAG_CHANGE(flag)) {
+ spraid_rescan_device(hdev, &devices[i]);
+ }
+ } else {
+ if (SPRAID_DEV_INFO_FLAG_VALID(org_flag)) {
+ down_write(&hdev->devices_rwsem);
+ org_devices[i].flag &= 0xfe;
+ up_write(&hdev->devices_rwsem);
+ spraid_remove_device(hdev, &org_devices[i]);
+ }
+ }
+ }
+free_list:
+ kfree(devices);
+}
+
+static void spraid_timesyn_work(struct work_struct *work)
+{
+ struct spraid_dev *hdev =
+ container_of(work, struct spraid_dev, timesyn_work);
+
+ spraid_configure_timestamp(hdev);
+}
+
+static void spraid_queue_scan(struct spraid_dev *hdev)
+{
+ queue_work(spraid_wq, &hdev->scan_work);
+}
+
+static void spraid_handle_aen_notice(struct spraid_dev *hdev, u32 result)
+{
+ switch ((result & 0xff00) >> 8) {
+ case SPRAID_AEN_DEV_CHANGED:
+ spraid_queue_scan(hdev);
+ break;
+ case SPRAID_AEN_HOST_PROBING:
+ break;
+ default:
+ dev_warn(hdev->dev, "async event result %08x\n", result);
+ }
+}
+
+static void spraid_handle_aen_vs(struct spraid_dev *hdev, u32 result, u32 result1)
+{
+ switch ((result & 0xff00) >> 8) {
+ case SPRAID_AEN_TIMESYN:
+ queue_work(spraid_wq, &hdev->timesyn_work);
+ break;
+ default:
+ dev_warn(hdev->dev, "async event result: 0x%x\n", result);
+ }
+}
+
+static int spraid_alloc_resources(struct spraid_dev *hdev)
+{
+ int ret, nqueue;
+
+ ret = ida_alloc(&spraid_instance_ida, GFP_KERNEL);
+ if (ret < 0) {
+ dev_err(hdev->dev, "Get instance id failed\n");
+ return ret;
+ }
+ hdev->instance = ret;
+
+ hdev->ctrl_info = kzalloc_node(sizeof(*hdev->ctrl_info),
+ GFP_KERNEL, hdev->numa_node);
+ if (!hdev->ctrl_info) {
+ ret = -ENOMEM;
+ goto release_instance;
+ }
+
+ ret = spraid_create_dma_pools(hdev);
+ if (ret)
+ goto free_ctrl_info;
+ nqueue = num_possible_cpus() + 1;
+ hdev->queues = kcalloc_node(nqueue, sizeof(struct spraid_queue),
+ GFP_KERNEL, hdev->numa_node);
+ if (!hdev->queues) {
+ ret = -ENOMEM;
+ goto destroy_dma_pools;
+ }
+
+ ret = spraid_alloc_admin_cmds(hdev);
+ if (ret)
+ goto free_queues;
+
+ dev_info(hdev->dev, "[%s] queues num: %d\n", __func__, nqueue);
+
+ return 0;
+
+free_queues:
+ kfree(hdev->queues);
+destroy_dma_pools:
+ spraid_destroy_dma_pools(hdev);
+free_ctrl_info:
+ kfree(hdev->ctrl_info);
+release_instance:
+ ida_free(&spraid_instance_ida, hdev->instance);
+ return ret;
+}
+
+static void spraid_free_resources(struct spraid_dev *hdev)
+{
+ spraid_free_admin_cmds(hdev);
+ kfree(hdev->queues);
+ spraid_destroy_dma_pools(hdev);
+ kfree(hdev->ctrl_info);
+ ida_free(&spraid_instance_ida, hdev->instance);
+}
+
+
+
+static void spraid_bsg_unmap_data(struct spraid_dev *hdev, struct bsg_job *job)
+{
+ struct request *rq = blk_mq_rq_from_pdu(job);
+ struct spraid_iod *iod = job->dd_data;
+ enum dma_data_direction dma_dir = rq_data_dir(rq) ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
+
+ if (iod->nsge)
+ dma_unmap_sg(hdev->dev, iod->sg, iod->nsge, dma_dir);
+
+ spraid_free_iod_res(hdev, iod);
+}
+
+static int spraid_bsg_map_data(struct spraid_dev *hdev, struct bsg_job *job,
+ struct spraid_admin_command *cmd)
+{
+ struct request *rq = blk_mq_rq_from_pdu(job);
+ struct spraid_iod *iod = job->dd_data;
+ enum dma_data_direction dma_dir = rq_data_dir(rq) ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
+ int ret = 0;
+
+ iod->sg = job->request_payload.sg_list;
+ iod->nsge = job->request_payload.sg_cnt;
+ iod->length = job->request_payload.payload_len;
+ iod->use_sgl = false;
+ iod->npages = -1;
+ iod->sg_drv_mgmt = false;
+
+ if (!iod->nsge)
+ goto out;
+
+ ret = dma_map_sg_attrs(hdev->dev, iod->sg, iod->nsge, dma_dir, DMA_ATTR_NO_WARN);
+ if (!ret)
+ goto out;
+
+ ret = spraid_setup_prps(hdev, iod);
+ if (ret)
+ goto unmap;
+
+ cmd->common.dptr.prp1 = cpu_to_le64(sg_dma_address(iod->sg));
+ cmd->common.dptr.prp2 = cpu_to_le64(iod->first_dma);
+
+ return 0;
+
+unmap:
+ dma_unmap_sg(hdev->dev, iod->sg, iod->nsge, dma_dir);
+out:
+ return ret;
+}
+
+static int spraid_get_ctrl_info(struct spraid_dev *hdev, struct spraid_ctrl_info *ctrl_info)
+{
+ struct spraid_admin_command admin_cmd;
+ u8 *data_ptr = NULL;
+ dma_addr_t data_dma = 0;
+ int ret;
+
+ data_ptr = dma_alloc_coherent(hdev->dev, PAGE_SIZE, &data_dma, GFP_KERNEL);
+ if (!data_ptr)
+ return -ENOMEM;
+
+ memset(&admin_cmd, 0, sizeof(admin_cmd));
+ admin_cmd.get_info.opcode = SPRAID_ADMIN_GET_INFO;
+ admin_cmd.get_info.type = SPRAID_GET_INFO_CTRL;
+ admin_cmd.common.dptr.prp1 = cpu_to_le64(data_dma);
+
+ ret = spraid_submit_admin_sync_cmd(hdev, &admin_cmd, NULL, NULL, 0);
+ if (!ret)
+ memcpy(ctrl_info, data_ptr, sizeof(struct spraid_ctrl_info));
+
+ dma_free_coherent(hdev->dev, PAGE_SIZE, data_ptr, data_dma);
+
+ return ret;
+}
+
+static int spraid_init_ctrl_info(struct spraid_dev *hdev)
+{
+ int ret;
+
+ hdev->ctrl_info->nd = cpu_to_le32(240);
+ hdev->ctrl_info->mdts = 8;
+ hdev->ctrl_info->max_cmds = cpu_to_le16(4096);
+ hdev->ctrl_info->max_num_sge = cpu_to_le16(128);
+ hdev->ctrl_info->max_channel = cpu_to_le16(4);
+ hdev->ctrl_info->max_tgt_id = cpu_to_le32(3239);
+ hdev->ctrl_info->max_lun = cpu_to_le16(2);
+
+ ret = spraid_get_ctrl_info(hdev, hdev->ctrl_info);
+ if (ret)
+ dev_err(hdev->dev, "get controller info failed: %d\n", ret);
+
+ dev_info(hdev->dev, "[%s]nd = %d\n", __func__, hdev->ctrl_info->nd);
+ dev_info(hdev->dev, "[%s]max_cmd = %d\n", __func__, hdev->ctrl_info->max_cmds);
+ dev_info(hdev->dev, "[%s]max_channel = %d\n", __func__, hdev->ctrl_info->max_channel);
+ dev_info(hdev->dev, "[%s]max_tgt_id = %d\n", __func__, hdev->ctrl_info->max_tgt_id);
+ dev_info(hdev->dev, "[%s]max_lun = %d\n", __func__, hdev->ctrl_info->max_lun);
+ dev_info(hdev->dev, "[%s]max_num_sge = %d\n", __func__, hdev->ctrl_info->max_num_sge);
+ dev_info(hdev->dev, "[%s]lun_num_boot = %d\n", __func__, hdev->ctrl_info->lun_num_in_boot);
+ dev_info(hdev->dev, "[%s]mdts = %d\n", __func__, hdev->ctrl_info->mdts);
+ dev_info(hdev->dev, "[%s]acl = %d\n", __func__, hdev->ctrl_info->acl);
+ dev_info(hdev->dev, "[%s]aer1 = %d\n", __func__, hdev->ctrl_info->aerl);
+ dev_info(hdev->dev, "[%s]card_type = %d\n", __func__, hdev->ctrl_info->card_type);
+ dev_info(hdev->dev, "[%s]rtd3e = %d\n", __func__, hdev->ctrl_info->rtd3e);
+ dev_info(hdev->dev, "[%s]sn = %s\n", __func__, hdev->ctrl_info->sn);
+ dev_info(hdev->dev, "[%s]fr = %s\n", __func__, hdev->ctrl_info->fr);
+
+ return 0;
+}
+
+#define SPRAID_MAX_ADMIN_PAYLOAD_SIZE BIT(16)
+static int spraid_alloc_iod_ext_mem_pool(struct spraid_dev *hdev)
+{
+ u16 max_sge = le16_to_cpu(hdev->ctrl_info->max_num_sge);
+ size_t alloc_size;
+
+ alloc_size = spraid_iod_ext_size(hdev, SPRAID_MAX_ADMIN_PAYLOAD_SIZE,
+ max_sge, true, false);
+ if (alloc_size > PAGE_SIZE)
+ dev_warn(hdev->dev, "It is unreasonable for sg allocation more than one page\n");
+ hdev->iod_mempool = mempool_create_node(1, mempool_kmalloc, mempool_kfree,
+ (void *)alloc_size, GFP_KERNEL, hdev->numa_node);
+ if (!hdev->iod_mempool) {
+ dev_err(hdev->dev, "Create iod extension memory pool failed\n");
+ return -ENOMEM;
+ }
+
+ return 0;
+}
+
+static void spraid_free_iod_ext_mem_pool(struct spraid_dev *hdev)
+{
+ mempool_destroy(hdev->iod_mempool);
+}
+
+static int spraid_user_admin_cmd(struct spraid_dev *hdev, struct bsg_job *job)
+{
+ struct spraid_bsg_request *bsg_req = (struct spraid_bsg_request *)(job->request);
+ struct spraid_passthru_common_cmd *cmd = &(bsg_req->admcmd);
+ struct spraid_admin_command admin_cmd;
+ u32 timeout = msecs_to_jiffies(cmd->timeout_ms);
+ u32 result[2] = {0};
+ int status;
+
+ if (hdev->state >= SPRAID_RESETTING) {
+ dev_err(hdev->dev, "[%s] err, host state:[%d] is not right\n",
+ __func__, hdev->state);
+ return -EBUSY;
+ }
+
+ dev_info(hdev->dev, "[%s] opcode[0x%x] subopcode[0x%x] init\n",
+ __func__, cmd->opcode, cmd->info_0.subopcode);
+
+ memset(&admin_cmd, 0, sizeof(admin_cmd));
+ admin_cmd.common.opcode = cmd->opcode;
+ admin_cmd.common.flags = cmd->flags;
+ admin_cmd.common.hdid = cpu_to_le32(cmd->nsid);
+ admin_cmd.common.cdw2[0] = cpu_to_le32(cmd->cdw2);
+ admin_cmd.common.cdw2[1] = cpu_to_le32(cmd->cdw3);
+ admin_cmd.common.cdw10 = cpu_to_le32(cmd->cdw10);
+ admin_cmd.common.cdw11 = cpu_to_le32(cmd->cdw11);
+ admin_cmd.common.cdw12 = cpu_to_le32(cmd->cdw12);
+ admin_cmd.common.cdw13 = cpu_to_le32(cmd->cdw13);
+ admin_cmd.common.cdw14 = cpu_to_le32(cmd->cdw14);
+ admin_cmd.common.cdw15 = cpu_to_le32(cmd->cdw15);
+
+ status = spraid_bsg_map_data(hdev, job, &admin_cmd);
+ if (status) {
+ dev_err(hdev->dev, "[%s] err, map data failed\n", __func__);
+ return status;
+ }
+
+ status = spraid_submit_admin_sync_cmd(hdev, &admin_cmd, &result[0], &result[1], timeout);
+ if (status >= 0) {
+ job->reply_len = sizeof(result);
+ memcpy(job->reply, result, sizeof(result));
+ }
+
+ dev_info(hdev->dev, "[%s] opcode[0x%x] subopcode[0x%x], status[0x%x] result0[0x%x] result1[0x%x]\n",
+ __func__, cmd->opcode, cmd->info_0.subopcode, status, result[0], result[1]);
+
+ spraid_bsg_unmap_data(hdev, job);
+
+ return status;
+}
+
+static int spraid_alloc_ioq_ptcmds(struct spraid_dev *hdev)
+{
+ int i;
+ int ptnum = SPRAID_NR_IOQ_PTCMDS;
+
+ INIT_LIST_HEAD(&hdev->ioq_pt_list);
+ spin_lock_init(&hdev->ioq_pt_lock);
+
+ hdev->ioq_ptcmds = kcalloc_node(ptnum, sizeof(struct spraid_cmd),
+ GFP_KERNEL, hdev->numa_node);
+
+ if (!hdev->ioq_ptcmds) {
+ dev_err(hdev->dev, "Alloc ioq_ptcmds failed\n");
+ return -ENOMEM;
+ }
+
+ for (i = 0; i < ptnum; i++) {
+ hdev->ioq_ptcmds[i].qid = i / SPRAID_PTCMDS_PERQ + 1;
+ hdev->ioq_ptcmds[i].cid = i % SPRAID_PTCMDS_PERQ + SPRAID_IO_BLK_MQ_DEPTH;
+ list_add_tail(&(hdev->ioq_ptcmds[i].list), &hdev->ioq_pt_list);
+ }
+
+ dev_info(hdev->dev, "Alloc ioq_ptcmds success, ptnum[%d]\n", ptnum);
+
+ return 0;
+}
+
+static void spraid_free_ioq_ptcmds(struct spraid_dev *hdev)
+{
+ kfree(hdev->ioq_ptcmds);
+ INIT_LIST_HEAD(&hdev->ioq_pt_list);
+}
+
+static int spraid_submit_ioq_sync_cmd(struct spraid_dev *hdev, struct spraid_ioq_command *cmd,
+ u32 *result, u32 *reslen, u32 timeout)
+{
+ int ret;
+ dma_addr_t sense_dma;
+ struct spraid_queue *ioq;
+ void *sense_addr = NULL;
+ struct spraid_cmd *pt_cmd = spraid_get_cmd(hdev, SPRAID_CMD_IOPT);
+
+ if (!pt_cmd) {
+ dev_err(hdev->dev, "err, get ioq cmd failed\n");
+ return -EFAULT;
+ }
+
+ timeout = timeout ? timeout : ADMIN_TIMEOUT;
+
+ init_completion(&pt_cmd->cmd_done);
+
+ ioq = &hdev->queues[pt_cmd->qid];
+ ret = pt_cmd->cid * SCSI_SENSE_BUFFERSIZE;
+ sense_addr = ioq->sense + ret;
+ sense_dma = ioq->sense_dma_addr + ret;
+
+ cmd->common.sense_addr = cpu_to_le64(sense_dma);
+ cmd->common.sense_len = cpu_to_le16(SCSI_SENSE_BUFFERSIZE);
+ cmd->common.command_id = pt_cmd->cid;
+
+ spraid_submit_cmd(ioq, cmd);
+
+ if (!wait_for_completion_timeout(&pt_cmd->cmd_done, timeout)) {
+ dev_err(hdev->dev, "[%s] cid[%d] qid[%d] timeout, opcode[0x%x] subopcode[0x%x]\n",
+ __func__, pt_cmd->cid, pt_cmd->qid, cmd->common.opcode,
+ (le32_to_cpu(cmd->common.cdw3[0]) & 0xffff));
+ WRITE_ONCE(pt_cmd->state, SPRAID_CMD_TIMEOUT);
+ return -EINVAL;
+ }
+
+ if (result && reslen) {
+ if ((pt_cmd->status & 0x17f) == 0x101) {
+ memcpy(result, sense_addr, SCSI_SENSE_BUFFERSIZE);
+ *reslen = SCSI_SENSE_BUFFERSIZE;
+ }
+ }
+
+ spraid_put_cmd(hdev, pt_cmd, SPRAID_CMD_IOPT);
+
+ return pt_cmd->status;
+}
+
+static int spraid_user_ioq_cmd(struct spraid_dev *hdev, struct bsg_job *job)
+{
+ struct spraid_bsg_request *bsg_req = (struct spraid_bsg_request *)(job->request);
+ struct spraid_ioq_passthru_cmd *cmd = &(bsg_req->ioqcmd);
+ struct spraid_ioq_command ioq_cmd;
+ int status = 0;
+ u32 timeout = msecs_to_jiffies(cmd->timeout_ms);
+
+ if (cmd->data_len > PAGE_SIZE) {
+ dev_err(hdev->dev, "[%s] data len bigger than 4k\n", __func__);
+ return -EFAULT;
+ }
+
+ if (hdev->state != SPRAID_LIVE) {
+ dev_err(hdev->dev, "[%s] err, host state:[%d] is not live\n",
+ __func__, hdev->state);
+ return -EBUSY;
+ }
+
+ dev_info(hdev->dev, "[%s] opcode[0x%x] subopcode[0x%x] init, datalen[%d]\n",
+ __func__, cmd->opcode, cmd->info_1.subopcode, cmd->data_len);
+
+ memset(&ioq_cmd, 0, sizeof(ioq_cmd));
+ ioq_cmd.common.opcode = cmd->opcode;
+ ioq_cmd.common.flags = cmd->flags;
+ ioq_cmd.common.hdid = cpu_to_le32(cmd->nsid);
+ ioq_cmd.common.sense_len = cpu_to_le16(cmd->info_0.res_sense_len);
+ ioq_cmd.common.cdb_len = cmd->info_0.cdb_len;
+ ioq_cmd.common.rsvd2 = cmd->info_0.rsvd0;
+ ioq_cmd.common.cdw3[0] = cpu_to_le32(cmd->cdw3);
+ ioq_cmd.common.cdw3[1] = cpu_to_le32(cmd->cdw4);
+ ioq_cmd.common.cdw3[2] = cpu_to_le32(cmd->cdw5);
+
+ ioq_cmd.common.cdw10[0] = cpu_to_le32(cmd->cdw10);
+ ioq_cmd.common.cdw10[1] = cpu_to_le32(cmd->cdw11);
+ ioq_cmd.common.cdw10[2] = cpu_to_le32(cmd->cdw12);
+ ioq_cmd.common.cdw10[3] = cpu_to_le32(cmd->cdw13);
+ ioq_cmd.common.cdw10[4] = cpu_to_le32(cmd->cdw14);
+ ioq_cmd.common.cdw10[5] = cpu_to_le32(cmd->data_len);
+
+ memcpy(ioq_cmd.common.cdb, &cmd->cdw16, cmd->info_0.cdb_len);
+
+ ioq_cmd.common.cdw26[0] = cpu_to_le32(cmd->cdw26[0]);
+ ioq_cmd.common.cdw26[1] = cpu_to_le32(cmd->cdw26[1]);
+ ioq_cmd.common.cdw26[2] = cpu_to_le32(cmd->cdw26[2]);
+ ioq_cmd.common.cdw26[3] = cpu_to_le32(cmd->cdw26[3]);
+
+ status = spraid_bsg_map_data(hdev, job, (struct spraid_admin_command *)&ioq_cmd);
+ if (status) {
+ dev_err(hdev->dev, "[%s] err, map data failed\n", __func__);
+ return status;
+ }
+
+ status = spraid_submit_ioq_sync_cmd(hdev, &ioq_cmd, job->reply, &job->reply_len, timeout);
+
+ dev_info(hdev->dev, "[%s] opcode[0x%x] subopcode[0x%x], status[0x%x] reply_len[%d]\n",
+ __func__, cmd->opcode, cmd->info_1.subopcode, status, job->reply_len);
+
+ spraid_bsg_unmap_data(hdev, job);
+
+ return status;
+}
+
+static int spraid_reset_work_sync(struct spraid_dev *hdev);
+
+static bool spraid_check_scmd_completed(struct scsi_cmnd *scmd)
+{
+ struct spraid_dev *hdev = shost_priv(scmd->device->host);
+ struct spraid_iod *iod = scsi_cmd_priv(scmd);
+ struct spraid_queue *spraidq;
+ u16 hwq, cid;
+
+ spraid_get_tag_from_scmd(scmd, &hwq, &cid);
+ spraidq = &hdev->queues[hwq];
+ if (READ_ONCE(iod->state) == SPRAID_CMD_COMPLETE || spraid_poll_cq(spraidq, cid)) {
+ dev_warn(hdev->dev, "cid[%d], qid[%d] has been completed\n",
+ cid, spraidq->qid);
+ return true;
+ }
+ return false;
+}
+
+static enum blk_eh_timer_return spraid_scmd_timeout(struct scsi_cmnd *scmd)
+{
+ struct spraid_iod *iod = scsi_cmd_priv(scmd);
+ unsigned int timeout = scmd->device->request_queue->rq_timeout;
+
+ if (spraid_check_scmd_completed(scmd))
+ goto out;
+
+ if (time_after(jiffies, scmd->jiffies_at_alloc + timeout)) {
+ if (cmpxchg(&iod->state, SPRAID_CMD_IN_FLIGHT, SPRAID_CMD_TIMEOUT) ==
+ SPRAID_CMD_IN_FLIGHT) {
+ return BLK_EH_DONE;
+ }
+ }
+out:
+ return BLK_EH_RESET_TIMER;
+}
+
+/* send abort command by admin queue temporary */
+static int spraid_send_abort_cmd(struct spraid_dev *hdev, u32 hdid, u16 qid, u16 cid)
+{
+ struct spraid_admin_command admin_cmd;
+
+ memset(&admin_cmd, 0, sizeof(admin_cmd));
+ admin_cmd.abort.opcode = SPRAID_ADMIN_ABORT_CMD;
+ admin_cmd.abort.hdid = cpu_to_le32(hdid);
+ admin_cmd.abort.sqid = cpu_to_le16(qid);
+ admin_cmd.abort.cid = cpu_to_le16(cid);
+
+ return spraid_submit_admin_sync_cmd(hdev, &admin_cmd, NULL, NULL, 0);
+}
+
+/* send reset command by admin quueue temporary */
+static int spraid_send_reset_cmd(struct spraid_dev *hdev, int type, u32 hdid)
+{
+ struct spraid_admin_command admin_cmd;
+
+ memset(&admin_cmd, 0, sizeof(admin_cmd));
+ admin_cmd.reset.opcode = SPRAID_ADMIN_RESET;
+ admin_cmd.reset.hdid = cpu_to_le32(hdid);
+ admin_cmd.reset.type = type;
+
+ return spraid_submit_admin_sync_cmd(hdev, &admin_cmd, NULL, NULL, 0);
+}
+
+static bool spraid_change_host_state(struct spraid_dev *hdev, enum spraid_state newstate)
+{
+ unsigned long flags;
+ enum spraid_state oldstate;
+ bool change = false;
+
+ spin_lock_irqsave(&hdev->state_lock, flags);
+
+ oldstate = hdev->state;
+ switch (newstate) {
+ case SPRAID_LIVE:
+ switch (oldstate) {
+ case SPRAID_NEW:
+ case SPRAID_RESETTING:
+ change = true;
+ break;
+ default:
+ break;
+ }
+ break;
+ case SPRAID_RESETTING:
+ switch (oldstate) {
+ case SPRAID_LIVE:
+ change = true;
+ break;
+ default:
+ break;
+ }
+ break;
+ case SPRAID_DELETING:
+ if (oldstate != SPRAID_DELETING)
+ change = true;
+ break;
+ case SPRAID_DEAD:
+ switch (oldstate) {
+ case SPRAID_NEW:
+ case SPRAID_LIVE:
+ case SPRAID_RESETTING:
+ change = true;
+ break;
+ default:
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+ if (change)
+ hdev->state = newstate;
+ spin_unlock_irqrestore(&hdev->state_lock, flags);
+
+ dev_info(hdev->dev, "[%s][%d]->[%d], change[%d]\n", __func__, oldstate, newstate, change);
+
+ return change;
+}
+
+static void spraid_back_fault_cqe(struct spraid_queue *ioq, struct spraid_completion *cqe)
+{
+ struct spraid_dev *hdev = ioq->hdev;
+ struct blk_mq_tags *tags;
+ struct scsi_cmnd *scmd;
+ struct spraid_iod *iod;
+ struct request *req;
+
+ tags = hdev->shost->tag_set.tags[ioq->qid - 1];
+ req = blk_mq_tag_to_rq(tags, cqe->cmd_id);
+ if (unlikely(!req || !blk_mq_request_started(req)))
+ return;
+
+ scmd = blk_mq_rq_to_pdu(req);
+ iod = scsi_cmd_priv(scmd);
+
+ set_host_byte(scmd, DID_NO_CONNECT);
+ if (iod->nsge)
+ scsi_dma_unmap(scmd);
+ spraid_free_iod_res(hdev, iod);
+ scsi_done(scmd);
+ dev_warn(hdev->dev, "Back fault CQE, cid[%d], qid[%d]\n",
+ cqe->cmd_id, ioq->qid);
+}
+
+static void spraid_back_all_io(struct spraid_dev *hdev)
+{
+ int i, j;
+ struct spraid_queue *ioq;
+ struct spraid_completion cqe = { 0 };
+
+ for (i = 1; i <= hdev->shost->nr_hw_queues; i++) {
+ ioq = &hdev->queues[i];
+ for (j = 0; j < hdev->shost->can_queue; j++) {
+ cqe.cmd_id = j;
+ spraid_back_fault_cqe(ioq, &cqe);
+ }
+ }
+}
+
+static void spraid_dev_disable(struct spraid_dev *hdev, bool shutdown)
+{
+ struct spraid_queue *adminq = &hdev->queues[0];
+ u16 start, end;
+ unsigned long timeout = jiffies + 600 * HZ;
+
+ if (pci_device_is_present(hdev->pdev)) {
+ if (shutdown)
+ spraid_shutdown_ctrl(hdev);
+ else
+ spraid_disable_ctrl(hdev);
+ }
+
+ while (!time_after(jiffies, timeout)) {
+ if (!pci_device_is_present(hdev->pdev)) {
+ dev_info(hdev->dev, "[%s] pci_device not present, skip wait\n", __func__);
+ break;
+ }
+ if (!spraid_wait_ready(hdev, hdev->cap, false)) {
+ dev_info(hdev->dev, "[%s] wait ready success after reset\n", __func__);
+ break;
+ }
+ dev_info(hdev->dev, "[%s] waiting csts_rdy ready\n", __func__);
+ }
+
+ if (hdev->queue_count == 0) {
+ dev_err(hdev->dev, "[%s] warn, queue has been delete\n", __func__);
+ return;
+ }
+
+ spin_lock_irq(&adminq->cq_lock);
+ spraid_process_cq(adminq, &start, &end, -1);
+ spin_unlock_irq(&adminq->cq_lock);
+ spraid_complete_cqes(adminq, start, end);
+
+ spraid_pci_disable(hdev);
+
+ spraid_back_all_io(hdev);
+}
+
+static void spraid_reset_work(struct work_struct *work)
+{
+ int ret;
+ struct spraid_dev *hdev = container_of(work, struct spraid_dev, reset_work);
+
+ if (hdev->state != SPRAID_RESETTING) {
+ dev_err(hdev->dev, "[%s] err, host is not reset state\n", __func__);
+ return;
+ }
+
+ dev_info(hdev->dev, "[%s] enter host reset\n", __func__);
+
+ if (hdev->ctrl_config & SPRAID_CC_ENABLE) {
+ dev_info(hdev->dev, "[%s] start dev_disable\n", __func__);
+ spraid_dev_disable(hdev, false);
+ }
+
+ ret = spraid_pci_enable(hdev);
+ if (ret)
+ goto out;
+
+ ret = spraid_setup_admin_queue(hdev);
+ if (ret)
+ goto pci_disable;
+
+ ret = spraid_setup_io_queues(hdev);
+ if (ret || hdev->online_queues <= hdev->shost->nr_hw_queues)
+ goto pci_disable;
+
+ spraid_change_host_state(hdev, SPRAID_LIVE);
+
+ spraid_send_all_aen(hdev);
+
+ return;
+
+pci_disable:
+ spraid_pci_disable(hdev);
+out:
+ spraid_change_host_state(hdev, SPRAID_DEAD);
+ dev_err(hdev->dev, "[%s] err, host reset failed\n", __func__);
+}
+
+static int spraid_reset_work_sync(struct spraid_dev *hdev)
+{
+ if (!spraid_change_host_state(hdev, SPRAID_RESETTING)) {
+ dev_info(hdev->dev, "[%s] can't change to reset state\n", __func__);
+ return -EBUSY;
+ }
+
+ if (!queue_work(spraid_wq, &hdev->reset_work)) {
+ dev_err(hdev->dev, "[%s] err, host is already in reset state\n", __func__);
+ return -EBUSY;
+ }
+
+ flush_work(&hdev->reset_work);
+ if (hdev->state != SPRAID_LIVE)
+ return -ENODEV;
+
+ return 0;
+}
+
+static int spraid_wait_abnl_cmd_done(struct spraid_iod *iod)
+{
+ u16 times = 0;
+
+ do {
+ if (READ_ONCE(iod->state) == SPRAID_CMD_TMO_COMPLETE)
+ break;
+ msleep(500);
+ times++;
+ } while (times <= SPRAID_WAIT_ABNL_CMD_TIMEOUT);
+
+ /* wait command completion timeout after abort/reset success */
+ if (times >= SPRAID_WAIT_ABNL_CMD_TIMEOUT)
+ return -ETIMEDOUT;
+
+ return 0;
+}
+
+static int spraid_abort_handler(struct scsi_cmnd *scmd)
+{
+ struct spraid_dev *hdev = shost_priv(scmd->device->host);
+ struct spraid_iod *iod = scsi_cmd_priv(scmd);
+ struct spraid_sdev_hostdata *hostdata;
+ u16 hwq, cid;
+ int ret;
+
+ scsi_print_command(scmd);
+
+ if (!spraid_wait_abnl_cmd_done(iod) || spraid_check_scmd_completed(scmd) ||
+ hdev->state != SPRAID_LIVE)
+ return SUCCESS;
+
+ hostdata = scmd->device->hostdata;
+ spraid_get_tag_from_scmd(scmd, &hwq, &cid);
+
+ dev_warn(hdev->dev, "cid[%d] qid[%d] timeout, aborting\n", cid, hwq);
+ ret = spraid_send_abort_cmd(hdev, hostdata->hdid, hwq, cid);
+ if (ret != ADMIN_ERR_TIMEOUT) {
+ ret = spraid_wait_abnl_cmd_done(iod);
+ if (ret) {
+ dev_warn(hdev->dev, "cid[%d] qid[%d] abort failed, not found\n", cid, hwq);
+ return FAILED;
+ }
+ dev_warn(hdev->dev, "cid[%d] qid[%d] abort succ\n", cid, hwq);
+ return SUCCESS;
+ }
+ dev_warn(hdev->dev, "cid[%d] qid[%d] abort failed, timeout\n", cid, hwq);
+ return FAILED;
+}
+
+static int spraid_tgt_reset_handler(struct scsi_cmnd *scmd)
+{
+ struct spraid_dev *hdev = shost_priv(scmd->device->host);
+ struct spraid_iod *iod = scsi_cmd_priv(scmd);
+ struct spraid_sdev_hostdata *hostdata;
+ u16 hwq, cid;
+ int ret;
+
+ scsi_print_command(scmd);
+
+ if (!spraid_wait_abnl_cmd_done(iod) || spraid_check_scmd_completed(scmd) ||
+ hdev->state != SPRAID_LIVE)
+ return SUCCESS;
+
+ hostdata = scmd->device->hostdata;
+ spraid_get_tag_from_scmd(scmd, &hwq, &cid);
+
+ dev_warn(hdev->dev, "cid[%d] qid[%d] timeout, target reset\n", cid, hwq);
+ ret = spraid_send_reset_cmd(hdev, SPRAID_RESET_TARGET, hostdata->hdid);
+ if (ret == 0) {
+ ret = spraid_wait_abnl_cmd_done(iod);
+ if (ret) {
+ dev_warn(hdev->dev, "cid[%d] qid[%d]target reset failed, not found\n",
+ cid, hwq);
+ return FAILED;
+ }
+
+ dev_warn(hdev->dev, "cid[%d] qid[%d] target reset success\n", cid, hwq);
+ return SUCCESS;
+ }
+
+ dev_warn(hdev->dev, "cid[%d] qid[%d] ret[%d] target reset failed\n", cid, hwq, ret);
+ return FAILED;
+}
+
+static int spraid_bus_reset_handler(struct scsi_cmnd *scmd)
+{
+ struct spraid_dev *hdev = shost_priv(scmd->device->host);
+ struct spraid_iod *iod = scsi_cmd_priv(scmd);
+ struct spraid_sdev_hostdata *hostdata;
+ u16 hwq, cid;
+ int ret;
+
+ scsi_print_command(scmd);
+
+ if (!spraid_wait_abnl_cmd_done(iod) || spraid_check_scmd_completed(scmd) ||
+ hdev->state != SPRAID_LIVE)
+ return SUCCESS;
+
+ hostdata = scmd->device->hostdata;
+ spraid_get_tag_from_scmd(scmd, &hwq, &cid);
+
+ dev_warn(hdev->dev, "cid[%d] qid[%d] timeout, bus reset\n", cid, hwq);
+ ret = spraid_send_reset_cmd(hdev, SPRAID_RESET_BUS, hostdata->hdid);
+ if (ret == 0) {
+ ret = spraid_wait_abnl_cmd_done(iod);
+ if (ret) {
+ dev_warn(hdev->dev, "cid[%d] qid[%d] bus reset failed, not found\n",
+ cid, hwq);
+ return FAILED;
+ }
+
+ dev_warn(hdev->dev, "cid[%d] qid[%d] bus reset succ\n", cid, hwq);
+ return SUCCESS;
+ }
+
+ dev_warn(hdev->dev, "cid[%d] qid[%d] ret[%d] bus reset failed\n", cid, hwq, ret);
+ return FAILED;
+}
+
+static int spraid_shost_reset_handler(struct scsi_cmnd *scmd)
+{
+ u16 hwq, cid;
+ struct spraid_dev *hdev = shost_priv(scmd->device->host);
+
+ scsi_print_command(scmd);
+ if (spraid_check_scmd_completed(scmd) || hdev->state != SPRAID_LIVE)
+ return SUCCESS;
+
+ spraid_get_tag_from_scmd(scmd, &hwq, &cid);
+ dev_warn(hdev->dev, "cid[%d] qid[%d] host reset\n", cid, hwq);
+
+ if (spraid_reset_work_sync(hdev)) {
+ dev_warn(hdev->dev, "cid[%d] qid[%d] host reset failed\n", cid, hwq);
+ return FAILED;
+ }
+
+ dev_warn(hdev->dev, "cid[%d] qid[%d] host reset success\n", cid, hwq);
+
+ return SUCCESS;
+}
+
+static ssize_t csts_pp_show(struct device *cdev, struct device_attribute *attr, char *buf)
+{
+ struct Scsi_Host *shost = class_to_shost(cdev);
+ struct spraid_dev *hdev = shost_priv(shost);
+ int ret = -1;
+
+ if (pci_device_is_present(hdev->pdev)) {
+ ret = (readl(hdev->bar + SPRAID_REG_CSTS) & SPRAID_CSTS_PP_MASK);
+ ret >>= SPRAID_CSTS_PP_SHIFT;
+ }
+
+ return snprintf(buf, PAGE_SIZE, "%d\n", ret);
+}
+
+static ssize_t csts_shst_show(struct device *cdev, struct device_attribute *attr, char *buf)
+{
+ struct Scsi_Host *shost = class_to_shost(cdev);
+ struct spraid_dev *hdev = shost_priv(shost);
+ int ret = -1;
+
+ if (pci_device_is_present(hdev->pdev)) {
+ ret = (readl(hdev->bar + SPRAID_REG_CSTS) & SPRAID_CSTS_SHST_MASK);
+ ret >>= SPRAID_CSTS_SHST_SHIFT;
+ }
+
+ return snprintf(buf, PAGE_SIZE, "%d\n", ret);
+}
+
+static ssize_t csts_cfs_show(struct device *cdev, struct device_attribute *attr, char *buf)
+{
+ struct Scsi_Host *shost = class_to_shost(cdev);
+ struct spraid_dev *hdev = shost_priv(shost);
+ int ret = -1;
+
+ if (pci_device_is_present(hdev->pdev)) {
+ ret = (readl(hdev->bar + SPRAID_REG_CSTS) & SPRAID_CSTS_CFS_MASK);
+ ret >>= SPRAID_CSTS_CFS_SHIFT;
+ }
+
+ return snprintf(buf, PAGE_SIZE, "%d\n", ret);
+}
+
+static ssize_t csts_rdy_show(struct device *cdev, struct device_attribute *attr, char *buf)
+{
+ struct Scsi_Host *shost = class_to_shost(cdev);
+ struct spraid_dev *hdev = shost_priv(shost);
+ int ret = -1;
+
+ if (pci_device_is_present(hdev->pdev))
+ ret = (readl(hdev->bar + SPRAID_REG_CSTS) & SPRAID_CSTS_RDY);
+
+ return snprintf(buf, PAGE_SIZE, "%d\n", ret);
+}
+
+static ssize_t fw_version_show(struct device *cdev, struct device_attribute *attr, char *buf)
+{
+ struct Scsi_Host *shost = class_to_shost(cdev);
+ struct spraid_dev *hdev = shost_priv(shost);
+
+ return snprintf(buf, PAGE_SIZE, "%s\n", hdev->ctrl_info->fr);
+}
+
+static DEVICE_ATTR_RO(csts_pp);
+static DEVICE_ATTR_RO(csts_shst);
+static DEVICE_ATTR_RO(csts_cfs);
+static DEVICE_ATTR_RO(csts_rdy);
+static DEVICE_ATTR_RO(fw_version);
+
+static struct attribute *spraid_host_attrs[] = {
+ &dev_attr_csts_pp.attr,
+ &dev_attr_csts_shst.attr,
+ &dev_attr_csts_cfs.attr,
+ &dev_attr_csts_rdy.attr,
+ &dev_attr_fw_version.attr,
+ NULL,
+};
+
+static const struct attribute_group spraid_host_attr_group = {
+ .attrs = spraid_host_attrs
+};
+
+static const struct attribute_group *spraid_host_attr_groups[] = {
+ &spraid_host_attr_group,
+ NULL,
+};
+
+static struct scsi_host_template spraid_driver_template = {
+ .module = THIS_MODULE,
+ .name = "Ramaxel Logic spraid driver",
+ .proc_name = "spraid",
+ .queuecommand = spraid_queue_command,
+ .slave_alloc = spraid_slave_alloc,
+ .slave_destroy = spraid_slave_destroy,
+ .slave_configure = spraid_slave_configure,
+ .eh_timed_out = spraid_scmd_timeout,
+ .eh_abort_handler = spraid_abort_handler,
+ .eh_target_reset_handler = spraid_tgt_reset_handler,
+ .eh_bus_reset_handler = spraid_bus_reset_handler,
+ .eh_host_reset_handler = spraid_shost_reset_handler,
+ .change_queue_depth = scsi_change_queue_depth,
+ .host_tagset = 0,
+ .this_id = -1,
+ .shost_groups = spraid_host_attr_groups,
+};
+
+static void spraid_shutdown(struct pci_dev *pdev)
+{
+ struct spraid_dev *hdev = pci_get_drvdata(pdev);
+
+ spraid_remove_io_queues(hdev);
+ spraid_disable_admin_queue(hdev, true);
+}
+
+/* bsg dispatch user command */
+static int spraid_bsg_host_dispatch(struct bsg_job *job)
+{
+ struct Scsi_Host *shost = dev_to_shost(job->dev);
+ struct spraid_dev *hdev = shost_priv(shost);
+ struct request *rq = blk_mq_rq_from_pdu(job);
+ struct spraid_bsg_request *bsg_req = job->request;
+ int ret = 0;
+
+ dev_info(hdev->dev, "[%s]msgcode[%d], msglen[%d], timeout[%d], req_nsge[%d], req_len[%d]\n",
+ __func__, bsg_req->msgcode, job->request_len, rq->timeout,
+ job->request_payload.sg_cnt, job->request_payload.payload_len);
+
+ job->reply_len = 0;
+
+ switch (bsg_req->msgcode) {
+ case SPRAID_BSG_ADM:
+ ret = spraid_user_admin_cmd(hdev, job);
+ break;
+ case SPRAID_BSG_IOQ:
+ ret = spraid_user_ioq_cmd(hdev, job);
+ break;
+ default:
+ dev_info(hdev->dev, "[%s] unsupport msgcode[%d]\n", __func__, bsg_req->msgcode);
+ break;
+ }
+
+ bsg_job_done(job, ret, 0);
+ return 0;
+}
+
+static inline void spraid_remove_bsg(struct spraid_dev *hdev)
+{
+ struct request_queue *q = hdev->bsg_queue;
+
+ if (q)
+ bsg_remove_queue(q);
+}
+static int spraid_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+{
+ struct spraid_dev *hdev;
+ struct Scsi_Host *shost;
+ int node, ret;
+ char bsg_name[15];
+
+ shost = scsi_host_alloc(&spraid_driver_template, sizeof(*hdev));
+ if (!shost) {
+ dev_err(&pdev->dev, "Failed to allocate scsi host\n");
+ return -ENOMEM;
+ }
+ hdev = shost_priv(shost);
+ hdev->pdev = pdev;
+ hdev->dev = get_device(&pdev->dev);
+
+ node = dev_to_node(hdev->dev);
+ if (node == NUMA_NO_NODE) {
+ node = first_memory_node;
+ set_dev_node(hdev->dev, node);
+ }
+ hdev->numa_node = node;
+ hdev->shost = shost;
+ pci_set_drvdata(pdev, hdev);
+
+ ret = spraid_dev_map(hdev);
+ if (ret)
+ goto put_dev;
+
+ init_rwsem(&hdev->devices_rwsem);
+ INIT_WORK(&hdev->scan_work, spraid_scan_work);
+ INIT_WORK(&hdev->timesyn_work, spraid_timesyn_work);
+ INIT_WORK(&hdev->reset_work, spraid_reset_work);
+ spin_lock_init(&hdev->state_lock);
+
+ ret = spraid_alloc_resources(hdev);
+ if (ret)
+ goto dev_unmap;
+
+ ret = spraid_pci_enable(hdev);
+ if (ret)
+ goto resources_free;
+
+ ret = spraid_setup_admin_queue(hdev);
+ if (ret)
+ goto pci_disable;
+
+ ret = spraid_init_ctrl_info(hdev);
+ if (ret)
+ goto disable_admin_q;
+
+ ret = spraid_alloc_iod_ext_mem_pool(hdev);
+ if (ret)
+ goto disable_admin_q;
+
+ ret = spraid_setup_io_queues(hdev);
+ if (ret)
+ goto free_iod_mempool;
+
+ spraid_shost_init(hdev);
+
+ ret = scsi_add_host(hdev->shost, hdev->dev);
+ if (ret) {
+ dev_err(hdev->dev, "Add shost to system failed, ret: %d\n",
+ ret);
+ goto remove_io_queues;
+ }
+
+ snprintf(bsg_name, sizeof(bsg_name), "spraid%d", shost->host_no);
+ hdev->bsg_queue = bsg_setup_queue(&shost->shost_gendev, bsg_name,
+ spraid_bsg_host_dispatch, NULL,
+ spraid_cmd_size(hdev, true, false));
+ if (IS_ERR(hdev->bsg_queue)) {
+ dev_err(hdev->dev, "err, setup bsg failed\n");
+ hdev->bsg_queue = NULL;
+ goto remove_io_queues;
+ }
+
+ if (hdev->online_queues == SPRAID_ADMIN_QUEUE_NUM) {
+ dev_warn(hdev->dev, "warn only admin queue can be used\n");
+ return 0;
+ }
+
+ hdev->state = SPRAID_LIVE;
+
+ spraid_send_all_aen(hdev);
+
+ ret = spraid_dev_list_init(hdev);
+ if (ret)
+ goto remove_bsg;
+
+ ret = spraid_configure_timestamp(hdev);
+ if (ret)
+ dev_warn(hdev->dev, "init set timestamp failed\n");
+
+ ret = spraid_alloc_ioq_ptcmds(hdev);
+ if (ret)
+ goto remove_bsg;
+
+ scsi_scan_host(hdev->shost);
+
+ return 0;
+
+remove_bsg:
+ spraid_remove_bsg(hdev);
+remove_io_queues:
+ spraid_remove_io_queues(hdev);
+free_iod_mempool:
+ spraid_free_iod_ext_mem_pool(hdev);
+disable_admin_q:
+ spraid_disable_admin_queue(hdev, false);
+pci_disable:
+ spraid_pci_disable(hdev);
+resources_free:
+ spraid_free_resources(hdev);
+dev_unmap:
+ spraid_dev_unmap(hdev);
+put_dev:
+ put_device(hdev->dev);
+ scsi_host_put(shost);
+
+ return -ENODEV;
+}
+
+static void spraid_remove(struct pci_dev *pdev)
+{
+ struct spraid_dev *hdev = pci_get_drvdata(pdev);
+ struct Scsi_Host *shost = hdev->shost;
+
+ dev_info(hdev->dev, "enter spraid remove\n");
+
+ spraid_change_host_state(hdev, SPRAID_DELETING);
+
+ if (!pci_device_is_present(pdev)) {
+ scsi_block_requests(shost);
+ spraid_back_all_io(hdev);
+ scsi_unblock_requests(shost);
+ }
+
+ flush_work(&hdev->reset_work);
+ spraid_remove_bsg(hdev);
+ scsi_remove_host(shost);
+ spraid_free_ioq_ptcmds(hdev);
+ kfree(hdev->devices);
+ spraid_remove_io_queues(hdev);
+ spraid_free_iod_ext_mem_pool(hdev);
+ spraid_disable_admin_queue(hdev, false);
+ spraid_pci_disable(hdev);
+ spraid_free_resources(hdev);
+ spraid_dev_unmap(hdev);
+ put_device(hdev->dev);
+ scsi_host_put(shost);
+
+ dev_info(hdev->dev, "exit spraid remove\n");
+}
+
+static const struct pci_device_id spraid_id_table[] = {
+ { PCI_DEVICE(PCI_VENDOR_ID_RAMAXEL_LOGIC, SPRAID_SERVER_DEVICE_HBA_DID) },
+ { PCI_DEVICE(PCI_VENDOR_ID_RAMAXEL_LOGIC, SPRAID_SERVER_DEVICE_RAID_DID) },
+ { 0, }
+};
+MODULE_DEVICE_TABLE(pci, spraid_id_table);
+
+static struct pci_driver spraid_driver = {
+ .name = "spraid",
+ .id_table = spraid_id_table,
+ .probe = spraid_probe,
+ .remove = spraid_remove,
+ .shutdown = spraid_shutdown,
+};
+
+static int __init spraid_init(void)
+{
+ int ret;
+
+ spraid_wq = alloc_workqueue("spraid-wq", WQ_UNBOUND | WQ_MEM_RECLAIM | WQ_SYSFS, 0);
+ if (!spraid_wq)
+ return -ENOMEM;
+
+ spraid_class = class_create(THIS_MODULE, "spraid");
+ if (IS_ERR(spraid_class)) {
+ ret = PTR_ERR(spraid_class);
+ goto destroy_wq;
+ }
+
+ ret = pci_register_driver(&spraid_driver);
+ if (ret < 0)
+ goto destroy_class;
+
+ return 0;
+
+destroy_class:
+ class_destroy(spraid_class);
+destroy_wq:
+ destroy_workqueue(spraid_wq);
+
+ return ret;
+}
+
+static void __exit spraid_exit(void)
+{
+ pci_unregister_driver(&spraid_driver);
+ class_destroy(spraid_class);
+ destroy_workqueue(spraid_wq);
+ ida_destroy(&spraid_instance_ida);
+}
+
+MODULE_AUTHOR("songyl(a)ramaxel.com");
+MODULE_DESCRIPTION("Ramaxel Memory Technology SPraid Driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(SPRAID_DRV_VERSION);
+module_init(spraid_init);
+module_exit(spraid_exit);
--
2.27.0
1
0
31 Dec '21
KABI: Add KABI paddings for base structures
Alexey Gladkov (1):
Increase size of ucounts to atomic_long_t
Cui GaoSheng (1):
kabi: reserve space for net_namespace
GONG, Ruiqi (1):
kabi: reserve space for cred and user_namespace
Guan Jing (1):
KABI:reserve space for sched structures
Guo Zihua (1):
KABI: reserve space for IMA IPE
Gustavo A. R. Silva (1):
UAPI: nfsfh.h: Replace one-element array with flexible-array member
Jialin Zhang (2):
kabi: reserve space for posix clock related structure
kabi: reserve space for power management related structure
Lin Ruizhe (6):
bootparam: Add kabi_reserve in bootparam
interrupt: Add kabi_reserve in interrupt.h
irq: Add kabi_reserve in irq
irq_desc: Add kabi_reserve in irq_desc
irqdomain: Add kabi_reserve in irqdomain
msi: Add kabi_reserve in msi.h
Lu Jialin (4):
kabi: reserve space for cgroup framework related structures
kabi: reserve space for memcg related structures
kabi: reserve space for cpu cgroup and cpuset cgroup related
structures
kabi: reserve space for cgroup bpf structures
Tan Xiaojun (1):
kabi: reserve space for pci subsystem related structure
Wang Hai (6):
kabi: net: reserve space for net base subsystem related structure
kabi: net: reserve space for net can subsystem related structure
kabi: net: reserve space for net sunrpc subsystem related structure
kabi: net: reserve space for net rdma subsystem related structure
kabi: net: reserve space for net bpf subsystem related structure
kabi: net: reserve space for net netfilter subsystem related structure
Wang ShaoBo (8):
kabi: reserve space for io subsystem related structures
kabi: reserve space for kobject related structures
kabi: reserve space for struct module
kabi: reserve space for struct ptp_clock
kabi: reserve space for struct ptp_clock_info
kabi: reserve space for ptp_clock.h
kabi: reserve space for iommu.h
kabi: reserve space for fwnode.h
Xie XiuQi (6):
kabi: add kabi helper macros
kabi: add KABI_SIZE_ALIGN_CHECKS for more stringent kabi checks
kabi: enables more stringent kabi checks
kabi: add script tools to check kabi symbol
kabi: add a tool to generate the kabi reference relationship
kabi: add kABI reference checking tool
Yang Jihong (1):
kabi: reserve space for perf subsystem related structures
Yang Yingliang (2):
kabi: reserve space for struct cpu_stop_work
kabi: reserve space for struct dma_map_ops
Yongqiang Liu (1):
kabi: mm: reserve space for memory subsystem related
Yu Liao (3):
kabi: reserve space for struct worker
kabi: reserve space for time and workqueue subsystem related structure
kabi: reserve space for hrtimer related structures
Zheng Zengkai (2):
KABI: add KABI padding to cpuidle structures
KABI: add KABI padding to x86/paravirt ops structures
Zhihao Cheng (1):
kabi: Add kabi reservation for storage module
Kconfig | 7 +
arch/arm64/configs/openeuler_defconfig | 1 +
arch/x86/configs/openeuler_defconfig | 1 +
arch/x86/include/asm/paravirt_types.h | 9 +
arch/x86/include/uapi/asm/bootparam.h | 2 +
block/blk-mq-tag.h | 7 +
drivers/nvme/host/nvme.h | 6 +
drivers/pci/pci.h | 9 +
drivers/ptp/ptp_private.h | 4 +
include/linux/backing-dev-defs.h | 11 +
include/linux/bio.h | 10 +
include/linux/blk-cgroup.h | 11 +
include/linux/blk-mq.h | 30 ++
include/linux/blk_types.h | 12 +
include/linux/blkdev.h | 16 +
include/linux/bpf-cgroup.h | 18 +
include/linux/can/core.h | 4 +
include/linux/can/dev.h | 6 +
include/linux/can/rx-offload.h | 4 +
include/linux/can/skb.h | 1 +
include/linux/cgroup-defs.h | 29 ++
include/linux/cpuidle.h | 15 +
include/linux/cred.h | 12 +
include/linux/dcache.h | 9 +
include/linux/delayacct.h | 4 +
include/linux/device.h | 19 +
include/linux/device/class.h | 7 +
include/linux/device/driver.h | 6 +
include/linux/dma-map-ops.h | 7 +
include/linux/elevator.h | 15 +
include/linux/ethtool.h | 6 +
include/linux/exportfs.h | 4 +
include/linux/fs.h | 48 +++
include/linux/fsnotify_backend.h | 3 +
include/linux/fwnode.h | 7 +
include/linux/genhd.h | 14 +
include/linux/hrtimer.h | 10 +
include/linux/interrupt.h | 3 +
include/linux/iomap.h | 6 +
include/linux/iommu.h | 12 +
include/linux/ioport.h | 6 +
include/linux/ipv6.h | 6 +
include/linux/irq.h | 6 +
include/linux/irqdesc.h | 3 +-
include/linux/irqdomain.h | 2 +
include/linux/jbd2.h | 6 +
include/linux/kabi.h | 494 ++++++++++++++++++++++++-
include/linux/kernfs.h | 9 +
include/linux/kobject.h | 13 +
include/linux/lsm_hooks.h | 2 +
include/linux/memcontrol.h | 20 +
include/linux/mm.h | 6 +
include/linux/mm_types.h | 15 +
include/linux/mmu_notifier.h | 9 +
include/linux/mmzone.h | 9 +
include/linux/module.h | 4 +
include/linux/mount.h | 3 +
include/linux/msi.h | 3 +
include/linux/net.h | 6 +
include/linux/netdevice.h | 47 +++
include/linux/netfilter.h | 9 +
include/linux/netfilter/ipset/ip_set.h | 7 +
include/linux/netfilter/nfnetlink.h | 5 +
include/linux/netfilter_ipv6.h | 3 +
include/linux/ns_common.h | 4 +
include/linux/pci.h | 34 ++
include/linux/pci_hotplug.h | 18 +
include/linux/perf_event.h | 8 +
include/linux/pm.h | 14 +
include/linux/pm_domain.h | 9 +
include/linux/pm_qos.h | 7 +
include/linux/pm_wakeup.h | 4 +
include/linux/posix-clock.h | 17 +
include/linux/ptp_clock_kernel.h | 4 +
include/linux/quota.h | 7 +
include/linux/sbitmap.h | 3 +
include/linux/sched.h | 30 ++
include/linux/sched/signal.h | 6 +
include/linux/sched/topology.h | 4 +
include/linux/sched/user.h | 4 +
include/linux/skbuff.h | 6 +
include/linux/skmsg.h | 11 +
include/linux/stop_machine.h | 2 +
include/linux/sunrpc/cache.h | 4 +
include/linux/sunrpc/clnt.h | 10 +
include/linux/sunrpc/sched.h | 14 +
include/linux/sunrpc/stats.h | 5 +
include/linux/sunrpc/xprt.h | 17 +
include/linux/swap.h | 4 +
include/linux/sysfs.h | 3 +
include/linux/timer.h | 6 +
include/linux/user_namespace.h | 36 +-
include/linux/workqueue.h | 11 +
include/linux/writeback.h | 4 +
include/linux/xattr.h | 3 +
include/net/dcbnl.h | 9 +
include/net/dst.h | 10 +
include/net/dst_ops.h | 10 +
include/net/fib_rules.h | 10 +
include/net/flow.h | 10 +
include/net/genetlink.h | 10 +
include/net/inet_connection_sock.h | 5 +
include/net/ip6_fib.h | 9 +
include/net/l3mdev.h | 6 +
include/net/lwtunnel.h | 7 +
include/net/neighbour.h | 8 +
include/net/net_namespace.h | 6 +
include/net/netfilter/nf_conntrack.h | 4 +
include/net/netlink.h | 5 +
include/net/netns/can.h | 3 +
include/net/netns/ipv4.h | 8 +
include/net/netns/ipv6.h | 3 +
include/net/netns/netfilter.h | 3 +
include/net/netns/nftables.h | 3 +
include/net/netns/xfrm.h | 3 +
include/net/page_pool.h | 3 +
include/net/rtnetlink.h | 10 +
include/net/sch_generic.h | 7 +
include/net/sock.h | 19 +
include/net/switchdev.h | 6 +
include/net/tcp.h | 6 +
include/net/tls.h | 5 +
include/net/xdp.h | 6 +
include/net/xfrm.h | 6 +
include/rdma/ib_addr.h | 3 +
include/rdma/rdma_cm.h | 8 +
include/rdma/rdma_counter.h | 3 +
include/rdma/rdma_netlink.h | 4 +
include/rdma/rdma_vt.h | 6 +
include/rdma/rdmavt_qp.h | 5 +
include/scsi/scsi_cmnd.h | 6 +
include/scsi/scsi_device.h | 15 +
include/scsi/scsi_host.h | 13 +
include/scsi/scsi_transport_fc.h | 25 ++
include/target/target_core_base.h | 7 +
include/uapi/linux/nfsd/nfsfh.h | 27 +-
include/uapi/linux/ptp_clock.h | 4 +
kernel/cgroup/cpuset.c | 6 +
kernel/sched/sched.h | 23 ++
kernel/ucount.c | 32 +-
kernel/workqueue_internal.h | 6 +
scripts/check-kabi | 147 ++++++++
scripts/kabideps | 161 ++++++++
scripts/kabisyms | 141 +++++++
144 files changed, 2220 insertions(+), 29 deletions(-)
create mode 100755 scripts/check-kabi
create mode 100755 scripts/kabideps
create mode 100755 scripts/kabisyms
--
2.20.1
1
49
[PATCH openEuler-5.10 01/71] perf mem: Search event name with more flexible path
by Zheng Zengkai 31 Dec '21
by Zheng Zengkai 31 Dec '21
31 Dec '21
From: Leo Yan <leo.yan(a)linaro.org>
mainline inclusion
from mainline-v5.11-rc1
commit f9f16dfbe76e
category: feature
bugzilla: https://gitee.com/openeuler/kernel/issues/I4NGPV
CVE: NA
-------------------------------------------------
The perf tool searches a memory event name under the folder
'/sys/devices/cpu/events/', this leads to the limitation for the
selection of a memory profiling event which must be under this folder.
Thus it's impossible to use any other event as memory event which is not
under this specific folder, e.g. Arm SPE hardware event is not located
in '/sys/devices/cpu/events/' so it cannot be enabled for memory
profiling.
This patch changes to search folder from '/sys/devices/cpu/events/' to
'/sys/devices', so it give flexibility to find events which can be used
for memory profiling.
Signed-off-by: Leo Yan <leo.yan(a)linaro.org>
Acked-by: Jiri Olsa <jolsa(a)redhat.com>
Link: https://lore.kernel.org/r/20201106094853.21082-2-leo.yan@linaro.org
Signed-off-by: Arnaldo Carvalho de Melo <acme(a)redhat.com>
Signed-off-by: Wei Li <liwei391(a)huawei.com>
Reviewed-by: Yang Jihong <yangjihong1(a)huawei.com>
Signed-off-by: Zheng Zengkai <zhengzengkai(a)huawei.com>
---
tools/perf/util/mem-events.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/tools/perf/util/mem-events.c b/tools/perf/util/mem-events.c
index ea0af0bc4314..35c8d175a9d2 100644
--- a/tools/perf/util/mem-events.c
+++ b/tools/perf/util/mem-events.c
@@ -18,8 +18,8 @@ unsigned int perf_mem_events__loads_ldlat = 30;
#define E(t, n, s) { .tag = t, .name = n, .sysfs_name = s }
struct perf_mem_event perf_mem_events[PERF_MEM_EVENTS__MAX] = {
- E("ldlat-loads", "cpu/mem-loads,ldlat=%u/P", "mem-loads"),
- E("ldlat-stores", "cpu/mem-stores/P", "mem-stores"),
+ E("ldlat-loads", "cpu/mem-loads,ldlat=%u/P", "cpu/events/mem-loads"),
+ E("ldlat-stores", "cpu/mem-stores/P", "cpu/events/mem-stores"),
};
#undef E
@@ -93,7 +93,7 @@ int perf_mem_events__init(void)
struct perf_mem_event *e = &perf_mem_events[j];
struct stat st;
- scnprintf(path, PATH_MAX, "%s/devices/cpu/events/%s",
+ scnprintf(path, PATH_MAX, "%s/devices/%s",
mnt, e->sysfs_name);
if (!stat(path, &st))
--
2.20.1
1
70
[PATCH openEuler-1.0-LTS 1/4] net: hns3: fix the concurrency between functions reading debugfs
by Yang Yingliang 31 Dec '21
by Yang Yingliang 31 Dec '21
31 Dec '21
From: Yufeng Mo <moyufeng(a)huawei.com>
driver inclusion
category: bugfix
bugzilla: https://gitee.com/openeuler/kernel/issues/I4OSRU
CVE: NA
----------------------------
[1298504.847848] Call trace:
[1298504.847859] [<ffff000008089e14>] dump_backtrace+0x0/0x23c
[1298504.847865] [<ffff00000808a074>] show_stack+0x24/0x2c
[1298504.847870] [<ffff0000088568a8>] dump_stack+0x84/0xa8
[1298504.847878] [<ffff0000082122fc>] bad_page+0xec/0x14c
[1298504.847883] [<ffff000008219384>] free_pages_check_bad+0x90/0x9c
[1298504.847888] [<ffff00000821307c>] __free_pages_ok+0x2b8/0x2ec
[1298504.847894] [<ffff0000082153ec>] __free_pages+0x44/0x64
[1298504.847900] [<ffff000008288788>] kfree+0x198/0x1a0
[1298504.847905] [<ffff00000823432c>] kvfree+0x3c/0x58
[1298504.847937] [<ffff0000014fabf4>] hns3_dbg_read+0xf4/0x278 [hns3]
[1298504.847944] [<ffff000008359550>] full_proxy_read+0x60/0x90
[1298504.847949] [<ffff0000082b22a4>] __vfs_read+0x58/0x178
[1298504.847952] [<ffff0000082b2454>] vfs_read+0x90/0x14c
[1298504.847956] [<ffff0000082b2b70>] SyS_read+0x60/0xc0
When different functions reading the same debugfs node, it will
cause double free problem, because different functions shared
the same node buffer.
This patch make different functions have their own buffer to fix
the problem.
Fixes: 319ba0a4d154 ("net: hns3: fix race condition in debugfs")
Fixes: c91910efc03a ("net: hns3: refactor the debugfs process")
Signed-off-by: Yufeng Mo <moyufeng(a)huawei.com>
Signed-off-by: Yonglong Liu <liuyonglong(a)huawei.com>
Reviewed-by: Jian Shen <shenjian15(a)huawei.com>
Signed-off-by: Yang Yingliang <yangyingliang(a)huawei.com>
---
drivers/net/ethernet/hisilicon/hns3/hnae3.h | 1 +
.../net/ethernet/hisilicon/hns3/hns3_debugfs.c | 15 +++++++++++----
.../net/ethernet/hisilicon/hns3/hns3_debugfs.h | 1 -
3 files changed, 12 insertions(+), 5 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hnae3.h b/drivers/net/ethernet/hisilicon/hns3/hnae3.h
index 0d849c13f22f5..61b92430e56db 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hnae3.h
+++ b/drivers/net/ethernet/hisilicon/hns3/hnae3.h
@@ -765,6 +765,7 @@ struct hnae3_handle {
u8 netdev_flags;
struct dentry *hnae3_dbgfs;
struct mutex dbgfs_lock;
+ char **dbgfs_buf;
/* Network interface message level enabled bits */
u32 msg_enable;
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c
index c68e5f3d0ba52..8dbbf597d8a2c 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c
@@ -808,7 +808,7 @@ static ssize_t hns3_dbg_read(struct file *filp, char __user *buffer,
return ret;
mutex_lock(&handle->dbgfs_lock);
- save_buf = &hns3_dbg_cmd[index].buf;
+ save_buf = &handle->dbgfs_buf[index];
if (!test_bit(HNS3_NIC_STATE_INITED, &priv->state) ||
test_bit(HNS3_NIC_STATE_RESETTING, &priv->state)) {
@@ -911,6 +911,13 @@ int hns3_dbg_init(struct hnae3_handle *handle)
int ret;
u32 i;
+ handle->dbgfs_buf = devm_kcalloc(&handle->pdev->dev,
+ ARRAY_SIZE(hns3_dbg_cmd),
+ sizeof(*handle->dbgfs_buf),
+ GFP_KERNEL);
+ if (!handle->dbgfs_buf)
+ return -ENOMEM;
+
hns3_dbg_dentry[HNS3_DBG_DENTRY_COMMON].dentry =
debugfs_create_dir(name, hns3_dbgfs_root);
handle->hnae3_dbgfs = hns3_dbg_dentry[HNS3_DBG_DENTRY_COMMON].dentry;
@@ -952,9 +959,9 @@ void hns3_dbg_uninit(struct hnae3_handle *handle)
u32 i;
for (i = 0; i < ARRAY_SIZE(hns3_dbg_cmd); i++)
- if (hns3_dbg_cmd[i].buf) {
- kvfree(hns3_dbg_cmd[i].buf);
- hns3_dbg_cmd[i].buf = NULL;
+ if (handle->dbgfs_buf[i]) {
+ kvfree(handle->dbgfs_buf[i]);
+ handle->dbgfs_buf[i] = NULL;
}
mutex_destroy(&handle->dbgfs_lock);
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.h b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.h
index ea65e5174ea98..902e16d99fb7c 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.h
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.h
@@ -49,7 +49,6 @@ struct hns3_dbg_cmd_info {
enum hnae3_dbg_cmd cmd;
enum hns3_dbg_dentry_type dentry;
u32 buf_len;
- char *buf;
int (*init)(struct hnae3_handle *handle, unsigned int cmd);
};
--
2.25.1
1
3
[PATCH openEuler-1.0-LTS v2] f2fs: fix to do sanity check on last xattr entry in __f2fs_setxattr()
by Yang Yingliang 31 Dec '21
by Yang Yingliang 31 Dec '21
31 Dec '21
From: Chao Yu <chao(a)kernel.org>
mainline inclusion
from mainline-v5.17
commit 5598b24efaf4892741c798b425d543e4bed357a1
category: bugfix
CVE: CVE-2021-45469
--------------------------------
As Wenqing Liu reported in bugzilla:
https://bugzilla.kernel.org/show_bug.cgi?id=215235
- Overview
page fault in f2fs_setxattr() when mount and operate on corrupted image
- Reproduce
tested on kernel 5.16-rc3, 5.15.X under root
1. unzip tmp7.zip
2. ./single.sh f2fs 7
Sometimes need to run the script several times
- Kernel dump
loop0: detected capacity change from 0 to 131072
F2FS-fs (loop0): Found nat_bits in checkpoint
F2FS-fs (loop0): Mounted with checkpoint version = 7548c2ee
BUG: unable to handle page fault for address: ffffe47bc7123f48
RIP: 0010:kfree+0x66/0x320
Call Trace:
__f2fs_setxattr+0x2aa/0xc00 [f2fs]
f2fs_setxattr+0xfa/0x480 [f2fs]
__f2fs_set_acl+0x19b/0x330 [f2fs]
__vfs_removexattr+0x52/0x70
__vfs_removexattr_locked+0xb1/0x140
vfs_removexattr+0x56/0x100
removexattr+0x57/0x80
path_removexattr+0xa3/0xc0
__x64_sys_removexattr+0x17/0x20
do_syscall_64+0x37/0xb0
entry_SYSCALL_64_after_hwframe+0x44/0xae
The root cause is in __f2fs_setxattr(), we missed to do sanity check on
last xattr entry, result in out-of-bound memory access during updating
inconsistent xattr data of target inode.
After the fix, it can detect such xattr inconsistency as below:
F2FS-fs (loop11): inode (7) has invalid last xattr entry, entry_size: 60676
F2FS-fs (loop11): inode (8) has corrupted xattr
F2FS-fs (loop11): inode (8) has corrupted xattr
F2FS-fs (loop11): inode (8) has invalid last xattr entry, entry_size: 47736
Cc: stable(a)vger.kernel.org
Reported-by: Wenqing Liu <wenqingliu0120(a)gmail.com>
Signed-off-by: Chao Yu <chao(a)kernel.org>
Signed-off-by: Jaegeuk Kim <jaegeuk(a)kernel.org>
Conflicts:
fs/f2fs/xattr.c
[yyl: replace f2fs_err() with f2fs_msg(KERN_ERR)]
Signed-off-by: Yang Yingliang <yangyingliang(a)huawei.com>
Reviewed-by: Xiu Jianfeng <xiujianfeng(a)huawei.com>
Reviewed-by: fang wei <fangwei1(a)huawei.com>
Signed-off-by: Yang Yingliang <yangyingliang(a)huawei.com>
---
fs/f2fs/xattr.c | 11 ++++++++++-
1 file changed, 10 insertions(+), 1 deletion(-)
diff --git a/fs/f2fs/xattr.c b/fs/f2fs/xattr.c
index 90d0d305f6a36..1858c66d871d1 100644
--- a/fs/f2fs/xattr.c
+++ b/fs/f2fs/xattr.c
@@ -657,8 +657,17 @@ static int __f2fs_setxattr(struct inode *inode, int index,
}
last = here;
- while (!IS_XATTR_LAST_ENTRY(last))
+ while (!IS_XATTR_LAST_ENTRY(last)) {
+ if ((void *)(last) + sizeof(__u32) > last_base_addr ||
+ (void *)XATTR_NEXT_ENTRY(last) > last_base_addr) {
+ f2fs_msg(F2FS_I_SB(inode)->sb, KERN_ERR, "inode (%lu) has invalid last xattr entry, entry_size: %zu",
+ inode->i_ino, ENTRY_SIZE(last));
+ set_sbi_flag(F2FS_I_SB(inode), SBI_NEED_FSCK);
+ error = -EFSCORRUPTED;
+ goto exit;
+ }
last = XATTR_NEXT_ENTRY(last);
+ }
newsize = XATTR_ALIGN(sizeof(struct f2fs_xattr_entry) + len + size);
--
2.25.1
1
0
patch #1 ~ #2 prepare for backporting fix patch
patch #3 fix CVE-2021-44733
Jens Wiklander (3):
tee: remove linked list of struct tee_shm
tee: don't assign shm id for private shms
tee: handle lookup of shm with reference count 0
drivers/tee/tee_core.c | 1 -
drivers/tee/tee_private.h | 3 +-
drivers/tee/tee_shm.c | 196 ++++++++++++++------------------------
include/linux/tee_drv.h | 7 +-
4 files changed, 77 insertions(+), 130 deletions(-)
--
2.25.1
1
3
[PATCH] f2fs: fix to do sanity check on last xattr entry in __f2fs_setxattr()
by Yang Yingliang 30 Dec '21
by Yang Yingliang 30 Dec '21
30 Dec '21
From: Chao Yu <chao(a)kernel.org>
mainline inclusion
from mainline-v5.17
commit 5598b24efaf4892741c798b425d543e4bed357a1
category: bugfix
CVE: CVE-2021-45469
--------------------------------
As Wenqing Liu reported in bugzilla:
https://bugzilla.kernel.org/show_bug.cgi?id=215235
- Overview
page fault in f2fs_setxattr() when mount and operate on corrupted image
- Reproduce
tested on kernel 5.16-rc3, 5.15.X under root
1. unzip tmp7.zip
2. ./single.sh f2fs 7
Sometimes need to run the script several times
- Kernel dump
loop0: detected capacity change from 0 to 131072
F2FS-fs (loop0): Found nat_bits in checkpoint
F2FS-fs (loop0): Mounted with checkpoint version = 7548c2ee
BUG: unable to handle page fault for address: ffffe47bc7123f48
RIP: 0010:kfree+0x66/0x320
Call Trace:
__f2fs_setxattr+0x2aa/0xc00 [f2fs]
f2fs_setxattr+0xfa/0x480 [f2fs]
__f2fs_set_acl+0x19b/0x330 [f2fs]
__vfs_removexattr+0x52/0x70
__vfs_removexattr_locked+0xb1/0x140
vfs_removexattr+0x56/0x100
removexattr+0x57/0x80
path_removexattr+0xa3/0xc0
__x64_sys_removexattr+0x17/0x20
do_syscall_64+0x37/0xb0
entry_SYSCALL_64_after_hwframe+0x44/0xae
The root cause is in __f2fs_setxattr(), we missed to do sanity check on
last xattr entry, result in out-of-bound memory access during updating
inconsistent xattr data of target inode.
After the fix, it can detect such xattr inconsistency as below:
F2FS-fs (loop11): inode (7) has invalid last xattr entry, entry_size: 60676
F2FS-fs (loop11): inode (8) has corrupted xattr
F2FS-fs (loop11): inode (8) has corrupted xattr
F2FS-fs (loop11): inode (8) has invalid last xattr entry, entry_size: 47736
Cc: stable(a)vger.kernel.org
Reported-by: Wenqing Liu <wenqingliu0120(a)gmail.com>
Signed-off-by: Chao Yu <chao(a)kernel.org>
Signed-off-by: Jaegeuk Kim <jaegeuk(a)kernel.org>
Signed-off-by: Yang Yingliang <yangyingliang(a)huawei.com>
---
fs/f2fs/xattr.c | 11 ++++++++++-
1 file changed, 10 insertions(+), 1 deletion(-)
diff --git a/fs/f2fs/xattr.c b/fs/f2fs/xattr.c
index 90d0d305f6a36..b55d0920e777c 100644
--- a/fs/f2fs/xattr.c
+++ b/fs/f2fs/xattr.c
@@ -657,8 +657,17 @@ static int __f2fs_setxattr(struct inode *inode, int index,
}
last = here;
- while (!IS_XATTR_LAST_ENTRY(last))
+ while (!IS_XATTR_LAST_ENTRY(last)) {
+ if ((void *)(last) + sizeof(__u32) > last_base_addr ||
+ (void *)XATTR_NEXT_ENTRY(last) > last_base_addr) {
+ f2fs_err(F2FS_I_SB(inode), "inode (%lu) has invalid last xattr entry, entry_size: %zu",
+ inode->i_ino, ENTRY_SIZE(last));
+ set_sbi_flag(F2FS_I_SB(inode), SBI_NEED_FSCK);
+ error = -EFSCORRUPTED;
+ goto exit;
+ }
last = XATTR_NEXT_ENTRY(last);
+ }
newsize = XATTR_ALIGN(sizeof(struct f2fs_xattr_entry) + len + size);
--
2.25.1
1
0