Compare commits

...

256 Commits

Author SHA1 Message Date
Linus Torvalds
416f99c3b1 Merge tag 'driver-core-6.19-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/driver-core/driver-core
Pull driver core updates from Danilo Krummrich:
 "Arch Topology:
   - Move parse_acpi_topology() from arm64 to common code for reuse in
     RISC-V

  CPU:
   - Expose housekeeping CPUs through /sys/devices/system/cpu/housekeeping
   - Print a newline (or 0x0A) instead of '(null)' reading
     /sys/devices/system/cpu/nohz_full when nohz_full= is not set

  debugfs
   - Remove (broken) 'no-mount' mode
   - Remove redundant access mode checks in debugfs_get_tree() and
     debugfs_create_*() functions

  Devres:
   - Remove unused devm_free_percpu() helper
   - Move devm_alloc_percpu() from device.h to devres.h

  Firmware Loader:
   - Replace simple_strtol() with kstrtoint()
   - Do not call cancel_store() when no upload is in progress

  kernfs:
   - Increase struct super_block::maxbytes to MAX_LFS_FILESIZE
   - Fix a missing unwind path in __kernfs_new_node()

  Misc:
   - Increase the name size in struct auxiliary_device_id to 40
     characters
   - Replace system_unbound_wq with system_dfl_wq and add WQ_PERCPU to
     alloc_workqueue()

  Platform:
   - Replace ERR_PTR() with IOMEM_ERR_PTR() in platform ioremap
     functions

  Rust:
   - Auxiliary:
      - Unregister auxiliary device on parent device unbind
      - Move parent() to impl Device; implement device context aware
        parent() for Device<Bound>
      - Illustrate how to safely obtain a driver's device private data
        when calling from an auxiliary driver into the parant device
        driver

   - DebugFs:
      - Implement support for binary large objects

   - Device:
      - Let probe() return the driver's device private data as pinned
        initializer, i.e. impl PinInit<Self, Error>
      - Implement safe accessor for a driver's device private data for
        Device<Bound> (returned reference can't out-live driver binding
        and guarantees the correct private data type)
      - Implement AsBusDevice trait, to be used by class device
        abstractions to derive the bus device type of the parent device

   - DMA:
      - Store raw pointer of allocation as NonNull
      - Use start_ptr() and start_ptr_mut() to inherit correct
        mutability of self

   - FS:
      - Add file::Offset type alias

   - I2C:
      - Add abstractions for I2C device / driver infrastructure
      - Implement abstractions for manual I2C device registrations

   - I/O:
      - Use "kernel vertical" style for imports
      - Define ResourceSize as resource_size_t
      - Move ResourceSize to top-level I/O module
      - Add type alias for phys_addr_t
      - Implement Rust version of read_poll_timeout_atomic()

   - PCI:
      - Use "kernel vertical" style for imports
      - Move I/O and IRQ infrastructure to separate files
      - Add support for PCI interrupt vectors
      - Implement TryInto<IrqRequest<'a>> for IrqVector<'a> to convert
        an IrqVector bound to specific pci::Device into an IrqRequest
        bound to the same pci::Device's parent Device
      - Leverage pin_init_scope() to get rid of redundant Result in IRQ
        methods

   - PinInit:
      - Add {pin_}init_scope() to execute code before creating an
        initializer

   - Platform:
      - Leverage pin_init_scope() to get rid of redundant Result in IRQ
        methods

   - Timekeeping:
      - Implement abstraction of udelay()

   - Uaccess:
      - Implement read_slice_partial() and read_slice_file() for
        UserSliceReader
      - Implement write_slice_partial() and write_slice_file() for
        UserSliceWriter

  sysfs:
   - Prepare the constification of struct attribute"

* tag 'driver-core-6.19-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/driver-core/driver-core: (75 commits)
  rust: pci: fix build failure when CONFIG_PCI_MSI is disabled
  debugfs: Fix default access mode config check
  debugfs: Remove broken no-mount mode
  debugfs: Remove redundant access mode checks
  driver core: Check drivers_autoprobe for all added devices
  driver core: WQ_PERCPU added to alloc_workqueue users
  driver core: replace use of system_unbound_wq with system_dfl_wq
  tick/nohz: Expose housekeeping CPUs in sysfs
  tick/nohz: avoid showing '(null)' if nohz_full= not set
  sysfs/cpu: Use DEVICE_ATTR_RO for nohz_full attribute
  kernfs: fix memory leak of kernfs_iattrs in __kernfs_new_node
  fs/kernfs: raise sb->maxbytes to MAX_LFS_FILESIZE
  mod_devicetable: Bump auxiliary_device_id name size
  sysfs: simplify attribute definition macros
  samples/kobject: constify 'struct foo_attribute'
  samples/kobject: add is_visible() callback to attribute group
  sysfs: attribute_group: enable const variants of is_visible()
  sysfs: introduce __SYSFS_FUNCTION_ALTERNATIVE()
  sysfs: transparently handle const pointers in ATTRIBUTE_GROUPS()
  sysfs: attribute_group: allow registration of const attribute
  ...
2025-12-05 21:29:02 -08:00
Linus Torvalds
b1ae17cd0f Merge tag 'for-linus-6.19-1' of https://github.com/cminyard/linux-ipmi
Pull IPMI updates from Corey Minyard:
 "Minor IPMI fixes:

   - Some device tree cleanups and a maintainer add

   - Fix a race when handling channel updates that could result in
     errors being reported to the user in some cases"

* tag 'for-linus-6.19-1' of https://github.com/cminyard/linux-ipmi:
  MAINTAINERS: Add entry on Loongson-2K IPMI driver
  dt-bindings: ipmi: Convert aspeed,ast2400-ibt-bmc to DT schema
  dt-bindings: ipmi: Convert nuvoton,npcm750-kcs-bmc to DT schema
  ipmi: Skip channel scan if channels are already marked ready
  ipmi: Fix __scan_channels() failing to rescan channels
  ipmi: Fix the race between __scan_channels() and deliver_response()
2025-12-05 20:49:24 -08:00
Linus Torvalds
096571bb89 Merge tag 'ata-6.19-rc1-part2' of git://git.kernel.org/pub/scm/linux/kernel/git/libata/linux
Pull ata fix from Niklas Cassel:

 - The DELLBOSS VD SATA controller times out when sending I/Os of size
   4096 KiB or larger, even though it claims LBA48 support, which per
   the ACS standard requires support for a maximum command size of
   65535 sectors, i.e. 32 MiB - 512. Thus, quirk the device so that it
   sets a lower maximum command size (me)

* tag 'ata-6.19-rc1-part2' of git://git.kernel.org/pub/scm/linux/kernel/git/libata/linux:
  ata: libata-core: Quirk DELLBOSS VD max_sectors
  ata: libata: Move quirk flags to their own enum
2025-12-05 20:41:20 -08:00
Linus Torvalds
001eefb503 Merge tag 'tpmdd-sessions-next-6.19-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/jarkko/linux-tpmdd
Pull more tpm updates from Jarkko Sakkinen:
 "This is targeted for tpm2-sessions updates.

  There's two bug fixes and two more cosmetic tweaks for HMAC protected
  sessions. They provide a baseine for further improvements to be
  implemented during the the course of the release cycle"

* tag 'tpmdd-sessions-next-6.19-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/jarkko/linux-tpmdd:
  tpm2-sessions: Open code tpm_buf_append_hmac_session()
  tpm2-sessions: Remove 'attributes' parameter from tpm_buf_append_auth
  tpm2-sessions: Fix tpm2_read_public range checks
  tpm2-sessions: Fix out of range indexing in name_size
2025-12-05 20:36:28 -08:00
Linus Torvalds
f19b84186d Merge tag 'media/v6.19-2' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media
Pull media kernel-doc fix from Mauro Carvalho Chehab:
 "A fix to shut up a kernel-doc warning on c3-isp driver"

* tag 'media/v6.19-2' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media:
  media: uapi: c3-isp: Fix documentation warning
2025-12-05 20:17:50 -08:00
Linus Torvalds
7eb7f5723d Merge tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi
Pull SCSI updates from James Bottomley:
 "Usual driver updates (ufs, lpfc, target, qla2xxx) plus assorted
  cleanups and fixes including the WQ_PERCPU series.

  The biggest core change is the new allocation of pseudo-devices which
  allow the sending of internal commands to a given SCSI target"

* tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi: (147 commits)
  scsi: MAINTAINERS: Add the UFS include directory
  scsi: scsi_debug: Support injecting unaligned write errors
  scsi: qla2xxx: Fix improper freeing of purex item
  scsi: ufs: rockchip: Fix compile error without CONFIG_GPIOLIB
  scsi: ufs: rockchip: Reset controller on PRE_CHANGE of hce enable notify
  scsi: ufs: core: Use scsi_device_busy()
  scsi: ufs: core: Fix single doorbell mode support
  scsi: pm80xx: Add WQ_PERCPU to alloc_workqueue() users
  scsi: target: Add WQ_PERCPU to alloc_workqueue() users
  scsi: qedi: Add WQ_PERCPU to alloc_workqueue() users
  scsi: target: ibmvscsi: Add WQ_PERCPU to alloc_workqueue() users
  scsi: qedf: Add WQ_PERCPU to alloc_workqueue() users
  scsi: bnx2fc: Add WQ_PERCPU to alloc_workqueue() users
  scsi: be2iscsi: Add WQ_PERCPU to alloc_workqueue() users
  scsi: message: fusion: Add WQ_PERCPU to alloc_workqueue() users
  scsi: lpfc: WQ_PERCPU added to alloc_workqueue() users
  scsi: scsi_transport_fc: WQ_PERCPU added to alloc_workqueue users()
  scsi: scsi_dh_alua: WQ_PERCPU added to alloc_workqueue() users
  scsi: qla2xxx: WQ_PERCPU added to alloc_workqueue() users
  scsi: target: sbp: Replace use of system_unbound_wq with system_dfl_wq
  ...
2025-12-05 19:56:50 -08:00
Jarkko Sakkinen
b7960b9048 tpm2-sessions: Open code tpm_buf_append_hmac_session()
Open code 'tpm_buf_append_hmac_session_opt' to the call site, as it only
masks a call sequence and does otherwise nothing particularly useful.

Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@opinsys.com>
Reviewed-by: Jonathan McDowell <noodles@meta.com>
2025-12-05 06:42:51 +02:00
Jarkko Sakkinen
bc677a9216 tpm2-sessions: Remove 'attributes' parameter from tpm_buf_append_auth
Remove 'attributes' parameter from 'tpm_buf_append_auth', as it is not used
by the function.

Fixes: 27184f8905 ("tpm: Opt-in in disable PCR integrity protection")
Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@opinsys.com>
Reviewed-by: Jonathan McDowell <noodles@meta.com>
2025-12-05 06:42:51 +02:00
Jarkko Sakkinen
bda1cbf73c tpm2-sessions: Fix tpm2_read_public range checks
tpm2_read_public() has some rudimentary range checks but the function does
not ensure that the response buffer has enough bytes for the full TPMT_HA
payload.

Re-implement the function with necessary checks and validation, and return
name and name size for all handle types back to the caller.

Cc: stable@vger.kernel.org # v6.10+
Fixes: d0a25bb961 ("tpm: Add HMAC session name/handle append")
Signed-off-by: Jarkko Sakkinen <jarkko@kernel.org>
Reviewed-by: Jonathan McDowell <noodles@meta.com>
2025-12-05 06:42:44 +02:00
Jarkko Sakkinen
6e9722e9a7 tpm2-sessions: Fix out of range indexing in name_size
'name_size' does not have any range checks, and it just directly indexes
with TPM_ALG_ID, which could lead into memory corruption at worst.

Address the issue by only processing known values and returning -EINVAL for
unrecognized values.

Make also 'tpm_buf_append_name' and 'tpm_buf_fill_hmac_session' fallible so
that errors are detected before causing any spurious TPM traffic.

End also the authorization session on failure in both of the functions, as
the session state would be then by definition corrupted.

Cc: stable@vger.kernel.org # v6.10+
Fixes: 1085b8276b ("tpm: Add the rest of the session HMAC API")
Reviewed-by: Jonathan McDowell <noodles@meta.com>
Signed-off-by: Jarkko Sakkinen <jarkko@kernel.org>
2025-12-05 06:31:07 +02:00
Danilo Krummrich
473b9f3317 rust: pci: fix build failure when CONFIG_PCI_MSI is disabled
When CONFIG_PCI_MSI is disabled pci_alloc_irq_vectors() and
pci_free_irq_vectors() are defined as inline functions and hence require
a Rust helper.

	error[E0425]: cannot find function `pci_alloc_irq_vectors` in crate `bindings`
	    --> rust/kernel/pci/irq.rs:144:23
	     |
	 144 | ...s::pci_alloc_irq_vectors(dev.as_raw(), min_vecs, max_vecs, irq_types.as_raw())
	     |       ^^^^^^^^^^^^^^^^^^^^^ help: a function with a similar name exists: `pci_irq_vector`
	     |
	    ::: .../rust/bindings/bindings_helpers_generated.rs:1197:5
	     |
	1197 |     pub fn pci_irq_vector(pdev: *mut pci_dev, nvec: ffi::c_uint) -> ffi::c_int;
	     |     --------------------------------------------------------------------------- similarly named function `pci_irq_vector` defined here

	error[E0425]: cannot find function `pci_free_irq_vectors` in crate `bindings`
	    --> rust/kernel/pci/irq.rs:170:28
	     |
	 170 |         unsafe { bindings::pci_free_irq_vectors(self.dev.as_raw()) };
	     |                            ^^^^^^^^^^^^^^^^^^^^ help: a function with a similar name exists: `pci_irq_vector`
	     |
	    ::: .../rust/bindings/bindings_helpers_generated.rs:1197:5
	     |
	1197 |     pub fn pci_irq_vector(pdev: *mut pci_dev, nvec: ffi::c_uint) -> ffi::c_int;
	     |     --------------------------------------------------------------------------- similarly named function `pci_irq_vector` defined here

	error: aborting due to 2 previous errors

Fix this by adding the corresponding helpers.

Fixes: 340ccc9735 ("rust: pci: Allocate and manage PCI interrupt vectors")
Reported-by: kernel test robot <lkp@intel.com>
Closes: https://lore.kernel.org/oe-kbuild-all/202512012238.YgVvRRUx-lkp@intel.com/
Reviewed-by: Alice Ryhl <aliceryhl@google.com>
Reviewed-by: Joel Fernandes <joelagnelf@nvidia.com>
Link: https://patch.msgid.link/20251202210501.40998-1-dakr@kernel.org
Signed-off-by: Danilo Krummrich <dakr@kernel.org>
2025-12-04 00:24:47 +13:00
Jacopo Mondi
f7231cff1f media: uapi: c3-isp: Fix documentation warning
Building htmldocs generates a warning:

WARNING: include/uapi/linux/media/amlogic/c3-isp-config.h:199
error: Cannot parse struct or union!

Which correctly highlights that the c3_isp_params_block_header symbol
is wrongly documented as a struct while it's a plain #define instead.

Fix this by removing the 'struct' identifier from the documentation of
the c3_isp_params_block_header symbol.

[ribalda: Add Closes:]

Reported-by: Stephen Rothwell <sfr@canb.auug.org.au>
Closes: https://lore.kernel.org/all/20251127131425.4b5b6644@canb.auug.org.au/
Fixes: 4566208285 ("media: uapi: Convert Amlogic C3 to V4L2 extensible params")
Cc: stable@vger.kernel.org
Signed-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
Signed-off-by: Ricardo Ribalda <ribalda@chromium.org>
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
2025-12-03 10:07:37 +01:00
Niklas Cassel
2e98327136 ata: libata-core: Quirk DELLBOSS VD max_sectors
Commit 9b8b84879d ("block: Increase BLK_DEF_MAX_SECTORS_CAP") increased
the default max_sectors_kb from 1280 KiB to 4096 KiB.

DELLBOSS VD with FW rev MV.R00-0 times out when sending I/Os of size
4096 KiB.

Enable ATA_QUIRK_MAX_SEC, with value 8191 (sectors) for this device,
since any I/O with more sectors than that lead to I/O timeouts.

With this, the DELLBOSS VD SATA controller is usable again.

Cc: stable+noautosel@kernel.org # depends on Move quirk flags to their own enum
Fixes: 9b8b84879d ("block: Increase BLK_DEF_MAX_SECTORS_CAP")
Reviewed-by: Damien Le Moal <dlemoal@kernel.org>
Signed-off-by: Niklas Cassel <cassel@kernel.org>
2025-12-02 11:17:56 +01:00
Niklas Cassel
a42b71d499 ata: libata: Move quirk flags to their own enum
The anonymous enum in include/linux/libata.h that is used to store
various global constants can currently be backed by type int.
(It contains both negative and positive constants.)

__ATA_QUIRK_MAX is currently 31.
The quirk flags in the various global constants enum are defined as
"1U << quirk_flag_bit".

Thus if we simply add an additional quirk, the quirk flag will be 1 << 31,
which is a value that is too large to be represented by a signed int.
The various global constants enum will thus therefore be backed by type
long.

This will lead to error prints like e.g.:
ata_port_err(ap, "EH pending after %d tries, giving up\n",
	     ATA_EH_MAX_TRIES);

now failing to build, with build error:
error: format ‘%d’ expects argument of type ‘int’, but argument 4 has type ‘long int’ [-Werror=format=]

This is because all constants in the various global constants enum now
has to be printed as a long, as that is now the backing type of the enum.

Since the compiler will use the smallest possible backing type for an
enum, it is good practice to not mix unrelated things in a single enum.

Move the quirk flags to a separate enum, so that we don't need to change
the printf specifier for all other constants in the "various global
constants" enum when adding an additional quirk.

Reviewed-by: Damien Le Moal <dlemoal@kernel.org>
Reviewed-by: Martin K. Petersen <martin.petersen@oracle.com>
Signed-off-by: Niklas Cassel <cassel@kernel.org>
2025-12-02 11:17:56 +01:00
Aaron Thompson
d3666c1f8a debugfs: Fix default access mode config check
This typo caused debugfs to always behave as if
CONFIG_DEBUG_FS_ALLOW_NONE was selected.

Fixes: f278809475 ("debugfs: Remove broken no-mount mode")
Reported-by: Mark Brown <broonie@kernel.org>
Tested-by: Chen-Yu Tsai <wenst@chromium.org>
Signed-off-by: Aaron Thompson <dev@aaront.org>
Link: https://patch.msgid.link/20251202070927.14198-1-dev@null.aaront.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2025-12-02 09:31:51 +01:00
Aaron Thompson
f278809475 debugfs: Remove broken no-mount mode
debugfs access modes were added in Linux 5.10 (Dec 2020) [1], but the
no-mount mode has behaved effectively the same as the off mode since
Linux 5.12 (Apr 2021) [2]. The only difference is the specific error
code returned by the debugfs_create_* functions, which is -ENOENT in
no-mount mode and -EPERM in off mode.

Given that no-mount hasn't worked for several years with no complaints,
just remove it.

[1] a24c6f7bc9 ("debugfs: Add access restriction option")

[2] bc6de804d3 ("debugfs: be more robust at handling improper input in debugfs_lookup()")
    56348560d4 ("debugfs: do not attempt to create a new file before the filesystem is initalized")

Signed-off-by: Aaron Thompson <dev@aaront.org>
Link: https://patch.msgid.link/20251120102222.18371-3-dev@null.aaront.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2025-11-27 10:45:20 +01:00
Aaron Thompson
3ae94a55d0 debugfs: Remove redundant access mode checks
debugfs_get_tree() can only be called if debugfs itself calls
simple_pin_fs() or register_filesystem(), and those call paths also
check the access mode.

debugfs_start_creating() checks the access mode so the checks in the
debugfs_create_* functions are unnecessary.

An upcoming change will affect debugfs_allow, so doing this cleanup
first will make that change simpler.

Signed-off-by: Aaron Thompson <dev@aaront.org>
Link: https://patch.msgid.link/20251120102222.18371-2-dev@null.aaront.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2025-11-27 10:45:20 +01:00
Vincent Liu
ea34511aaf driver core: Check drivers_autoprobe for all added devices
When a device is hot-plugged, the drivers_autoprobe sysfs attribute is
not checked (at least for PCI devices). This means that
drivers_autoprobe is not working as intended, e.g. hot-plugged PCI
devices will still be autoprobed and bound to drivers even with
drivers_autoprobe disabled.

The problem likely started when device_add() was removed from
pci_bus_add_device() in commit 4f535093cf ("PCI: Put pci_dev in device
tree as early as possible") which means that the check for
drivers_autoprobe which used to happen in bus_probe_device() is no
longer present (previously bus_add_device() calls bus_probe_device()).
Conveniently, in commit 9170304169 ("PCI: Allow built-in drivers to
use async initial probing") device_attach() was replaced with
device_initial_probe() which faciliates this change to push the check
for drivers_autoprobe into device_initial_probe().

Make sure all devices check drivers_autoprobe by pushing the
drivers_autoprobe check into device_initial_probe(). This will only
affect devices on the PCI bus for now as device_initial_probe() is only
called by pci_bus_add_device() and bus_probe_device(), but
bus_probe_device() already checks for autoprobe, so callers of
bus_probe_device() should not observe changes on autoprobing.
Note also that pushing this check into device_initial_probe() rather
than device_attach() makes it only affect automatic probing of
drivers (e.g. when a device is hot-plugged), userspace can still choose
to manually bind a driver by writing to drivers_probe sysfs attribute,
even with autoprobe disabled.

Any future callers of device_initial_probe() will respect the
drivers_autoprobe sysfs attribute, which is the intended purpose of
drivers_autoprobe.

Signed-off-by: Vincent Liu <vincent.liu@nutanix.com>
Link: https://patch.msgid.link/20251022120740.2476482-1-vincent.liu@nutanix.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2025-11-26 15:22:19 +01:00
Marco Crivellari
ac1ab906d7 driver core: WQ_PERCPU added to alloc_workqueue users
Currently if a user enqueue a work item using schedule_delayed_work() the
used wq is "system_wq" (per-cpu wq) while queue_delayed_work() use
WORK_CPU_UNBOUND (used when a cpu is not specified). The same applies to
schedule_work() that is using system_wq and queue_work(), that makes use
again of WORK_CPU_UNBOUND.
This lack of consistency cannot be addressed without refactoring the API.

alloc_workqueue() treats all queues as per-CPU by default, while unbound
workqueues must opt-in via WQ_UNBOUND.

This default is suboptimal: most workloads benefit from unbound queues,
allowing the scheduler to place worker threads where they’re needed and
reducing noise when CPUs are isolated.

This continues the effort to refactor workqueue APIs, which began with
the introduction of new workqueues and a new alloc_workqueue flag in:

commit 128ea9f6cc ("workqueue: Add system_percpu_wq and system_dfl_wq")
commit 930c2ea566 ("workqueue: Add new WQ_PERCPU flag")

This change adds a new WQ_PERCPU flag to explicitly request
alloc_workqueue() to be per-cpu when WQ_UNBOUND has not been specified.

With the introduction of the WQ_PERCPU flag (equivalent to !WQ_UNBOUND),
any alloc_workqueue() caller that doesn’t explicitly specify WQ_UNBOUND
must now use WQ_PERCPU.

Once migration is complete, WQ_UNBOUND can be removed and unbound will
become the implicit default.

Suggested-by: Tejun Heo <tj@kernel.org>
Signed-off-by: Marco Crivellari <marco.crivellari@suse.com>
Link: https://patch.msgid.link/20251114141618.172154-3-marco.crivellari@suse.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2025-11-26 15:21:29 +01:00
Marco Crivellari
e40ad215ce driver core: replace use of system_unbound_wq with system_dfl_wq
Currently if a user enqueue a work item using schedule_delayed_work() the
used wq is "system_wq" (per-cpu wq) while queue_delayed_work() use
WORK_CPU_UNBOUND (used when a cpu is not specified). The same applies to
schedule_work() that is using system_wq and queue_work(), that makes use
again of WORK_CPU_UNBOUND.

This lack of consistentcy cannot be addressed without refactoring the API.

This continues the effort to refactor workqueue APIs, which began with
the introduction of new workqueues and a new alloc_workqueue flag in:

commit 128ea9f6cc ("workqueue: Add system_percpu_wq and system_dfl_wq")
commit 930c2ea566 ("workqueue: Add new WQ_PERCPU flag")

Switch to using system_dfl_wq because system_unbound_wq is going away as part of
a workqueue restructuring.

Suggested-by: Tejun Heo <tj@kernel.org>
Signed-off-by: Marco Crivellari <marco.crivellari@suse.com>
Link: https://patch.msgid.link/20251114141618.172154-2-marco.crivellari@suse.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2025-11-26 15:21:29 +01:00
Aaron Tomlin
cd22926af4 tick/nohz: Expose housekeeping CPUs in sysfs
Expose the current system-defined list of housekeeping CPUs in a new
sysfs file: /sys/devices/system/cpu/housekeeping.

This provides userspace performance tuning tools and resource managers
with a canonical, reliable method to accurately identify the cores
responsible for essential kernel maintenance workloads (RCU, timer
callbacks, and unbound workqueues). Currently, tooling must manually
calculate the housekeeping set by parsing complex kernel boot parameters
(like isolcpus= and nohz_full=) and system topology, which is prone to
error. This dedicated file simplifies the configuration of low-latency
workloads.

Signed-off-by: Aaron Tomlin <atomlin@atomlin.com>
Link: https://patch.msgid.link/20251011012853.7539-2-atomlin@atomlin.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2025-11-26 15:20:51 +01:00
Aaron Tomlin
f10c23fa15 tick/nohz: avoid showing '(null)' if nohz_full= not set
In the context of CONFIG_NO_HZ_FULL=y, tick_nohz_full_mask (of type
cpumask_var_t) is initialised to 0. Memory is only allocated to the cpumask
data structure, in tick_nohz_full_setup(), when Linux kernel boot-time
parameter "nohz_full=" is correctly specified (see housekeeping_setup()).
If "nohz_full=" is not set and an attempt is made to read
/sys/devices/system/cpu/nohz_full, '(null)' can be displayed:

    ❯ cat /sys/devices/system/cpu/nohz_full
    (null)

This patch changes the output to print a newline (or 0x0A) instead of
'(null)', making it consistent with print_cpus_isolated() behaviour.

Signed-off-by: Aaron Tomlin <atomlin@atomlin.com>
Link: https://patch.msgid.link/20251011011830.6670-3-atomlin@atomlin.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2025-11-26 15:20:49 +01:00
Aaron Tomlin
76987bac71 sysfs/cpu: Use DEVICE_ATTR_RO for nohz_full attribute
The /sys/devices/system/cpu/nohz_full file is a read-only attribute that
reports the CPUs configured for tickless operation (CONFIG_NO_HZ_FULL=y).

The current definition uses the generic DEVICE_ATTR macro, which
unnecessarily requires specifying the file mode (0444) and a NULL
store operation pointer.

This patch converts the definition to use the dedicated DEVICE_ATTR_RO
macro. This correctly expresses the read-only nature of the attribute,
removes the redundant mode field, and simplifies the code. As a related
cleanup, rename the show function from print_cpus_nohz_full() to the
standard nohz_full_show() for consistency with common sysfs attribute
naming conventions.

Signed-off-by: Aaron Tomlin <atomlin@atomlin.com>
Link: https://patch.msgid.link/20251011011830.6670-2-atomlin@atomlin.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2025-11-26 15:20:49 +01:00
Will Rosenberg
382b1e8f30 kernfs: fix memory leak of kernfs_iattrs in __kernfs_new_node
There exists a memory leak of kernfs_iattrs contained as an element
of kernfs_node allocated in __kernfs_new_node(). __kernfs_setattr()
allocates kernfs_iattrs as a sub-object, and the LSM security check
incorrectly errors out and does not free the kernfs_iattrs sub-object.

Make an additional error out case that properly frees kernfs_iattrs if
security_kernfs_init_security() fails.

Fixes: e19dfdc83b ("kernfs: initialize security of newly created nodes")
Co-developed-by: Oliver Rosenberg <olrose55@gmail.com>
Signed-off-by: Oliver Rosenberg <olrose55@gmail.com>
Signed-off-by: Will Rosenberg <whrosenb@asu.edu>
Link: https://patch.msgid.link/20251125151332.2010687-1-whrosenb@asu.edu
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2025-11-26 15:19:11 +01:00
Jane Chu
2467f9928c fs/kernfs: raise sb->maxbytes to MAX_LFS_FILESIZE
On an ARM64 A1 system, it's possible to have physical memory span
up to the 64T boundary, like below

$ lsmem -b -r -n -o range,size
0x0000000080000000-0x00000000bfffffff 1073741824
0x0000080000000000-0x000008007fffffff 2147483648
0x00000800c0000000-0x0000087fffffffff 546534588416
0x0000400000000000-0x00004000bfffffff 3221225472
0x0000400100000000-0x0000407fffffffff 545460846592

So it's time to extend /sys/kernel/mm/page_idle/bitmap to be able
to account for >2G number of pages, by raising the kernfs file size
limit.

Signed-off-by: Jane Chu <jane.chu@oracle.com>
Link: https://patch.msgid.link/20251111202606.1505437-1-jane.chu@oracle.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2025-11-26 15:18:13 +01:00
Raag Jadav
d3d25f430c mod_devicetable: Bump auxiliary_device_id name size
We have an upcoming driver named "intel_ehl_pse_io". This creates an
auxiliary child device for it's GPIO sub-functionality, which matches
against "intel_ehl_pse_io.gpio-elkhartlake" and overshoots the current
maximum limit of 32 bytes for auxiliary device id string. Bump the size
to 40 bytes to satisfy such cases.

Suggested-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Signed-off-by: Raag Jadav <raag.jadav@intel.com>
Link: https://patch.msgid.link/20251106052838.433673-1-raag.jadav@intel.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2025-11-26 15:17:37 +01:00
Thomas Weißschuh
71464949b1 sysfs: simplify attribute definition macros
Define the macros in terms of each other.
This makes them easier to understand and also will make it easier to
implement the transition machinery for 'const struct attribute'.

__ATTR_RO_MODE() can't be implemented in terms of __ATTR() as not all
attributes have a .store callback. The same issue theoretically exists
for __ATTR_WO(), but practically that does not occur today.

Reorder __ATTR_RO() below __ATTR_RO_MODE() to keep the order of the
macro definition consistent with respect to each other.

Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>
Link: https://patch.msgid.link/20251029-sysfs-const-attr-prep-v5-7-ea7d745acff4@weissschuh.net
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2025-11-26 15:16:35 +01:00
Thomas Weißschuh
2d76fdc1c9 samples/kobject: constify 'struct foo_attribute'
Showcase and test the new 'struct attribute' constification facilities.

Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>
Link: https://patch.msgid.link/20251029-sysfs-const-attr-prep-v5-6-ea7d745acff4@weissschuh.net
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2025-11-26 15:16:35 +01:00
Thomas Weißschuh
c301a2e2d7 samples/kobject: add is_visible() callback to attribute group
There was no example for the is_visible() callback so far.

It will also become an example and test for the constification of
'struct attribute' later.

Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>
Link: https://patch.msgid.link/20251029-sysfs-const-attr-prep-v5-5-ea7d745acff4@weissschuh.net
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2025-11-26 15:16:35 +01:00
Thomas Weißschuh
7dd9fdb493 sysfs: attribute_group: enable const variants of is_visible()
When constifying instances of struct attribute, for consistency the
corresponding .is_visible() callback should be adapted, too.
Introduce a temporary transition mechanism until all callbacks are
converted.

Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>
Link: https://patch.msgid.link/20251029-sysfs-const-attr-prep-v5-4-ea7d745acff4@weissschuh.net
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2025-11-26 15:16:35 +01:00
Thomas Weißschuh
02ac5335a5 sysfs: introduce __SYSFS_FUNCTION_ALTERNATIVE()
For the constification phase of 'struct attribute' various callback
struct members will need to exist in both const and non-const variants.
Keeping both members in a union avoids memory and CPU overhead but will
be detected and trapped by Control Flow Integrity (CFI). By deciding
between a struct and a union depending whether CFI is enabled, most
configurations can avoid this overhead. Code using these callbacks will
still need to be updated to handle both members explicitly.
In the union case the compiler will recognize that testing for one union
member is enough and optimize away the code for the other one.

Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>
Link: https://patch.msgid.link/20251029-sysfs-const-attr-prep-v5-3-ea7d745acff4@weissschuh.net
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2025-11-26 15:16:35 +01:00
Thomas Weißschuh
964c93b1ee sysfs: transparently handle const pointers in ATTRIBUTE_GROUPS()
To ease the constification process of 'struct attribute', transparently
handle the const pointers in ATTRIBUTE_GROUPS(). A cast is used instead
of assigning to .attrs_new as it keeps the macro smaller. As both
members are aliased to each other the result is identical.

Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>
Link: https://patch.msgid.link/20251029-sysfs-const-attr-prep-v5-2-ea7d745acff4@weissschuh.net
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2025-11-26 15:16:35 +01:00
Thomas Weißschuh
f85d90dd8d sysfs: attribute_group: allow registration of const attribute
To be able to constify instances of struct attribute it has to be
possible to add them to struct attribute_group. The current type of the
attrs member however is not compatible with that. Introduce a union that
allows registration of both const and non-const attributes to enable a
piecewise transition. As both union member types are compatible no
logic needs to be adapted.

Technically it is now possible register a const struct attribute and
receive it as mutable pointer in the callbacks. This is a soundness
issue.  But this same soundness issue already exists today in
sysfs_create_file(). Also the struct definition and callback
implementation are always closely linked and are meant to be moved to
const in lockstep.

Similar to commit 906c508afd ("sysfs: attribute_group: allow
registration of const bin_attribute")

Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>
Link: https://patch.msgid.link/20251029-sysfs-const-attr-prep-v5-1-ea7d745acff4@weissschuh.net
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2025-11-26 15:16:34 +01:00
Miguel Ojeda
a762f883ec rust: i2c: prepare for core::ffi::CStr
The rust-next tree contains commit:

    3b83f5d5e7 ("rust: replace `CStr` with `core::ffi::CStr`")

which, when merged together with commits:

    57c5bd9aee ("rust: i2c: add basic I2C device and driver abstractions")
    f3cc26a417 ("rust: i2c: add manual I2C device creation abstractions")

from this tree (driver-core), produces errors like the following:

    error[E0599]: no method named `len_with_nul` found for reference `&'static ffi::CStr` in the current scope
      --> rust/kernel/i2c.rs:48:16
       |
    48 |             id.len_with_nul() <= Self::I2C_NAME_SIZE,
       |                ^^^^^^^^^^^^ method not found in `&CStr`

    error[E0599]: no method named `as_bytes_with_nul` found for reference `&'static ffi::CStr` in the current scope
      --> rust/kernel/i2c.rs:51:22
       |
    51 |         let src = id.as_bytes_with_nul();
       |                      ^^^^^^^^^^^^^^^^^
       |
    help: there is a method `to_bytes_with_nul` with a similar name
       |
    51 |         let src = id.to_bytes_with_nul();
       |                      ~~~~~~~~~~~~~~~~~

which were detected in linux-next by Stephen [1].

The `i2c` code can be independently prepared to be ready for the change,
thus do so.

The change is similar to the one done by Tamir in commit 657403637f
("rust: acpi: use `core::ffi::CStr` method names").

Link: https://lore.kernel.org/all/20251120181111.65ce75a0@canb.auug.org.au/ [1]
Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
Link: https://patch.msgid.link/20251123163536.1771801-1-ojeda@kernel.org
Signed-off-by: Danilo Krummrich <dakr@kernel.org>
2025-11-24 09:14:47 +13:00
Peter Colberg
4635406417 samples: rust: fix module name for Rust PCI driver sample
Replace driver_pci -> rust_driver_pci in config SAMPLE_RUST_DRIVER_PCI.

Signed-off-by: Peter Colberg <pcolberg@redhat.com>
Fixes: 685376d18e ("samples: rust: add Rust PCI sample driver")
Link: https://patch.msgid.link/20251120-rust-driver-pci-fix-module-name-v1-1-430cee310dc0@redhat.com
Signed-off-by: Danilo Krummrich <dakr@kernel.org>
2025-11-22 08:28:58 +13:00
Martin K. Petersen
82f78acd5a Merge patch series "Add OP-TEE based RPMB driver for UFS devices"
Bean Huo <beanhuo@iokpp.de> says:

This patch series introduces OP-TEE based RPMB (Replay Protected
Memory Block) support for UFS devices, extending the kernel-level
secure storage capabilities that are currently available for eMMC
devices.

Previously, OP-TEE required a userspace supplicant to access RPMB
partitions, which created complex dependencies and reliability issues,
especially during early boot scenarios. Recent work by Linaro has
moved core supplicant functionality directly into the Linux kernel for
eMMC devices, eliminating userspace dependencies and enabling
immediate secure storage access. This series extends the same approach
to UFS devices, which are used in enterprise and mobile applications
that require secure storage capabilities.

Benefits:

 - Eliminates dependency on userspace supplicant for UFS RPMB access

 - Enables early boot secure storage access (e.g., fTPM, secure UEFI
   variables)

 - Provides kernel-level RPMB access as soon as UFS driver is
   initialized

 - Removes complex initramfs dependencies and boot ordering
   requirements

 - Ensures reliable and deterministic secure storage operations

 - Supports both built-in and modular fTPM configurations.

Prerequisites:
--------------

This patch series depends on commit 7e8242405b ("rpmb: move struct
rpmb_frame to common header") which has been merged into mainline
v6.18-rc2.

Link: https://patch.msgid.link/20251107230518.4060231-1-beanhuo@iokpp.de
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-11-20 10:26:13 -05:00
Bart Van Assche
38725491e7 scsi: MAINTAINERS: Add the UFS include directory
Make sure that the linux-scsi mailing list is Cc-ed for changes to UFS
include headers.

Signed-off-by: Bart Van Assche <bvanassche@acm.org>
Link: https://patch.msgid.link/20251119165742.536170-1-bvanassche@acm.org
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-11-19 23:03:35 -05:00
Martin K. Petersen
e54f7b4b81 Merge branch 6.18/scsi-fixes into 6.19/scsi-staging
Pull in fixes branch to resolve UFS merge conflict.

Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-11-19 22:59:25 -05:00
Bart Van Assche
13b77ed9c2 scsi: scsi_debug: Support injecting unaligned write errors
Allow user space software, e.g. a blktests test, to inject unaligned
write errors.

Acked-by: Douglas Gilbert <dgilbert@interlog.com>
Reviewed-by: Damien Le Moal <dlemoal@kernel.org>
Cc: Martin K. Petersen <martin.petersen@oracle.com>
Cc: Christoph Hellwig <hch@lst.de>
Cc: Ming Lei <ming.lei@redhat.com>
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
Link: https://patch.msgid.link/20251113174151.1095574-1-bvanassche@acm.org
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-11-19 22:42:09 -05:00
Zilin Guan
78b1a242fe scsi: qla2xxx: Fix improper freeing of purex item
In qla2xxx_process_purls_iocb(), an item is allocated via
qla27xx_copy_multiple_pkt(), which internally calls
qla24xx_alloc_purex_item().

The qla24xx_alloc_purex_item() function may return a pre-allocated item
from a per-adapter pool for small allocations, instead of dynamically
allocating memory with kzalloc().

An error handling path in qla2xxx_process_purls_iocb() incorrectly uses
kfree() to release the item. If the item was from the pre-allocated
pool, calling kfree() on it is a bug that can lead to memory corruption.

Fix this by using the correct deallocation function,
qla24xx_free_purex_item(), which properly handles both dynamically
allocated and pre-allocated items.

Fixes: 875386b988 ("scsi: qla2xxx: Add Unsolicited LS Request and Response Support for NVMe")
Signed-off-by: Zilin Guan <zilin@seu.edu.cn>
Reviewed-by: Himanshu Madhani <hmadhani2024@gmail.com>
Link: https://patch.msgid.link/20251113151246.762510-1-zilin@seu.edu.cn
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-11-19 22:38:27 -05:00
Shawn Lin
cda5f23eed scsi: ufs: rockchip: Fix compile error without CONFIG_GPIOLIB
drivers/ufs/host/ufs-rockchip.c:168:19: error: implicit declaration of function
'devm_gpiod_get'; did you mean 'em_pd_get'? [-Werror=implicit-function-declaration]

drivers/ufs/host/ufs-rockchip.c:214:2: error: implicit declaration of function
'gpiod_set_value_cansleep'; did you mean 'gpio_set_value_cansleep'?
[-Werror=implicit-function-declaration]

Reported-by: kernel test robot <lkp@intel.com>
Closes: https://lore.kernel.org/oe-kbuild-all/202511130238.LlA0MKxW-lkp@intel.com/
Signed-off-by: Shawn Lin <shawn.lin@rock-chips.com>
Reviewed-by: Bart Van Assche <bvanassche@acm.org>
Link: https://patch.msgid.link/1763011091-243727-1-git-send-email-shawn.lin@rock-chips.com
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-11-19 22:34:41 -05:00
Shawn Lin
b0ee72db91 scsi: ufs: rockchip: Reset controller on PRE_CHANGE of hce enable notify
This fixes the dme-reset failed when doing recovery. Because device
reset is not enough, we could occasionally see the error below:

ufshcd-rockchip 2a2d0000.ufs: uic cmd 0x14 with arg3 0x0 completion timeout
ufshcd-rockchip 2a2d0000.ufs: dme-reset: error code -110
ufshcd-rockchip 2a2d0000.ufs: DME_RESET failed
ufshcd-rockchip 2a2d0000.ufs: ufshcd_host_reset_and_restore: Host init failed -110

Fix this by resetting the controller on PRE_CHANGE stage of hce enable
notify.

Fixes: d3cbe455d6 ("scsi: ufs: rockchip: Initial support for UFS")
Signed-off-by: Shawn Lin <shawn.lin@rock-chips.com>
Link: https://patch.msgid.link/1763009575-237552-1-git-send-email-shawn.lin@rock-chips.com
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-11-19 22:33:36 -05:00
Bart Van Assche
31e6e7e54b scsi: ufs: core: Use scsi_device_busy()
Use scsi_device_busy() instead of open-coding it. This patch prepares
for skipping the SCSI device budget map initialization in certain cases.

Reviewed-by: Peter Wang <peter.wang@mediatek.com>
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
Link: https://patch.msgid.link/20251113235252.2015185-1-bvanassche@acm.org
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-11-19 12:06:00 -05:00
Bart Van Assche
02b5822d2f scsi: ufs: core: Fix single doorbell mode support
Commit 22089c2180 ("scsi: ufs: core: Optimize the hot path")
accidentally broke support for the legacy single doorbell mode.  The
tag_set.shared_tags pointer is only != NULL if shared tag support is
enabled. The UFS driver only enables shared tag support in MCQ mode.

Fix this by handling legacy and MCQ modes differently in
ufshcd_tag_to_cmd().

Reported-by: Marek Szyprowski <m.szyprowski@samsung.com>
Closes: https://lore.kernel.org/linux-scsi/c988a6dd-588d-4dbc-ab83-bbee17f2a686@samsung.com/
Reported-by: André Draszik <andre.draszik@linaro.org>
Closes: https://lore.kernel.org/linux-scsi/83ffbceb9e66b2a3b6096231551d969034ed8a74.camel@linaro.org/
Tested-by: Marek Szyprowski <m.szyprowski@samsung.com>
Fixes: 22089c2180 ("scsi: ufs: core: Optimize the hot path")
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
Tested-by: André Draszik <andre.draszik@linaro.org>
Link: https://patch.msgid.link/20251114193406.3097237-1-bvanassche@acm.org
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-11-19 12:02:22 -05:00
Andy Shevchenko
0a75f3d90e devres: Move devm_alloc_percpu() and related to devres.h
Move devm_alloc_percpu() and related to devres.h where it belongs.

Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Link: https://patch.msgid.link/20251111145046.997309-3-andriy.shevchenko@linux.intel.com
[ Fix minor typo in commit message. - Danilo ]
Signed-off-by: Danilo Krummrich <dakr@kernel.org>
2025-11-20 01:18:26 +13:00
Andy Shevchenko
4d24145a78 devres: Remove unused devm_free_percpu()
Remove unused devm_free_percpu().

By the way, it was never used in the drivers/ from day 1.

Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Link: https://patch.msgid.link/20251111145046.997309-2-andriy.shevchenko@linux.intel.com
Signed-off-by: Danilo Krummrich <dakr@kernel.org>
2025-11-19 10:26:22 +13:00
Markus Probst
e4addc7cc2 rust: Add trait to convert a device reference to a bus device reference
Implement the `AsBusDevice` trait for converting a `Device` reference to a
bus device reference for all bus devices.

The `AsBusDevice` trait allows abstractions to provide the bus device in
class device callbacks. It must not be used by drivers and is intended for
bus and class device abstractions only.

Signed-off-by: Markus Probst <markus.probst@posteo.de>
Link: https://patch.msgid.link/20251027200547.1038967-2-markus.probst@posteo.de
[ * Remove unused import.
  * Change visibility of AsBusDevice to public.
  * Fix build for USB.
  * Add impl for I2cClient.
  - Danilo ]
Signed-off-by: Danilo Krummrich <dakr@kernel.org>
2025-11-18 11:00:51 +13:00
Igor Korotin
13ae55e24a samples: rust: add Rust I2C client registration sample
Add a new `rust_i2c_client` sample, showing how to create a new
i2c client using `i2c::Registration`

Acked-by: Wolfram Sang <wsa+renesas@sang-engineering.com>
Signed-off-by: Igor Korotin <igor.korotin.linux@gmail.com>
Link: https://patch.msgid.link/20251116162210.171542-1-igor.korotin.linux@gmail.com
[ * Remove dependency to I2C_CHARDEV, depend on I2C=y.
  * Remove unnecessary impl Drop for SampleDriver.
  * Rename i2c::Registration, import Devres.
  * Fixup module description.
  * Add new source file to MAINTAINERS.
  - Danilo ]
Signed-off-by: Danilo Krummrich <dakr@kernel.org>
2025-11-18 10:31:41 +13:00
Igor Korotin
d05b8e9769 samples: rust: add Rust I2C sample driver
Add a new `rust_driver_i2c` sample, showing how to create a new
i2c driver using ACPI/OF/Legacy ID tables.

Acked-by: Wolfram Sang <wsa+renesas@sang-engineering.com>
Signed-off-by: Igor Korotin <igor.korotin.linux@gmail.com>
Link: https://patch.msgid.link/20251116162204.171518-1-igor.korotin.linux@gmail.com
Signed-off-by: Danilo Krummrich <dakr@kernel.org>
2025-11-18 10:28:25 +13:00
Igor Korotin
f3cc26a417 rust: i2c: add manual I2C device creation abstractions
In addition to the basic I2C device support, add rust abstractions
upon `i2c_new_client_device`/`i2c_unregister_device` C functions.

Implement the core abstractions needed for manual creation/deletion
of I2C devices, including:

 * `i2c::Registration` — a NonNull pointer created by the function
                          `i2c_new_client_device`

 * `i2c::I2cAdapter` — a ref counted wrapper around `struct i2c_adapter`

 * `i2c::I2cBoardInfo` — a safe wrapper around `struct i2c_board_info`

Acked-by: Wolfram Sang <wsa+renesas@sang-engineering.com>
Signed-off-by: Igor Korotin <igor.korotin.linux@gmail.com>
Link: https://patch.msgid.link/20251116162154.171493-1-igor.korotin.linux@gmail.com
[ Remove unnecessary safety comment. - Danilo ]
Signed-off-by: Danilo Krummrich <dakr@kernel.org>
2025-11-18 10:28:19 +13:00
Igor Korotin
57c5bd9aee rust: i2c: add basic I2C device and driver abstractions
Implement the core abstractions needed for I2C drivers, including:

* `i2c::Driver` — the trait drivers must implement, including `probe`

* `i2c::I2cClient` — a safe wrapper around `struct i2c_client`

* `i2c::Adapter` — implements `driver::RegistrationOps` to hook into the
  generic `driver::Registration` machinery

* `i2c::DeviceId` — a `RawDeviceIdIndex` implementation for I2C device IDs

Acked-by: Wolfram Sang <wsa+renesas@sang-engineering.com>
Signed-off-by: Igor Korotin <igor.korotin.linux@gmail.com>
Link: https://patch.msgid.link/20251116162144.171469-1-igor.korotin.linux@gmail.com
[ Remove unnecessary safety comment; fix rustdoc `Device` -> `I2cClient`.
  - Danilo ]
Signed-off-by: Danilo Krummrich <dakr@kernel.org>
2025-11-18 10:26:42 +13:00
Alice Ryhl
dd6ff5cf56 rust: io: add typedef for phys_addr_t
The C typedef phys_addr_t is missing an analogue in Rust, meaning that
we end up using bindings::phys_addr_t or ResourceSize as a replacement
in various places throughout the kernel. Fix that by introducing a new
typedef on the Rust side. Place it next to the existing ResourceSize
typedef since they're quite related to each other.

Cc: stable@vger.kernel.org # for v6.18 [1]
Signed-off-by: Alice Ryhl <aliceryhl@google.com>
Link: https://patch.msgid.link/20251112-resource-phys-typedefs-v2-4-538307384f82@google.com
Link: https://lore.kernel.org/all/20251112-resource-phys-typedefs-v2-0-538307384f82@google.com/ [1]
Signed-off-by: Danilo Krummrich <dakr@kernel.org>
2025-11-13 20:17:24 +11:00
Alice Ryhl
ee2776e54b rust: scatterlist: import ResourceSize from kernel::io
Now that ResourceSize has been moved to kernel::io, import it from the
io module instead of the io::resource sub-module. It makes sense in this
case since the dma_len isn't really related to the Resource type even
though both are sizes of allocations in physical ram.

Signed-off-by: Alice Ryhl <aliceryhl@google.com>
Link: https://patch.msgid.link/20251112-resource-phys-typedefs-v2-3-538307384f82@google.com
Signed-off-by: Danilo Krummrich <dakr@kernel.org>
2025-11-13 20:17:24 +11:00
Alice Ryhl
dfd6799304 rust: io: move ResourceSize to top-level io module
Resource sizes are a general concept for dealing with physical
addresses, and not specific to the Resource type, which is just one way
to access physical addresses. Thus, move the typedef to the io module.

Still keep a re-export under resource. This avoids this commit from
being a flag-day, but I also think it's a useful re-export in general so
that you can import

	use kernel::io::resource::{Resource, ResourceSize};

instead of having to write

	use kernel::io::{
	    resource::Resource,
	    ResourceSize,
	};

in the specific cases where you need ResourceSize because you are using
the Resource type. Therefore I think it makes sense to keep this
re-export indefinitely and it is *not* intended as a temporary re-export
for migration purposes.

Cc: stable@vger.kernel.org # for v6.18 [1]
Signed-off-by: Alice Ryhl <aliceryhl@google.com>
Link: https://patch.msgid.link/20251112-resource-phys-typedefs-v2-2-538307384f82@google.com
Link: https://lore.kernel.org/all/20251112-resource-phys-typedefs-v2-0-538307384f82@google.com/ [1]
Signed-off-by: Danilo Krummrich <dakr@kernel.org>
2025-11-13 20:16:51 +11:00
Alice Ryhl
919b729227 rust: io: define ResourceSize as resource_size_t
These typedefs are always equivalent so this should not change anything,
but the code makes a lot more sense like this.

Cc: stable@vger.kernel.org
Signed-off-by: Alice Ryhl <aliceryhl@google.com>
Fixes: 493fc33ec2 ("rust: io: add resource abstraction")
Link: https://patch.msgid.link/20251112-resource-phys-typedefs-v2-1-538307384f82@google.com
Signed-off-by: Danilo Krummrich <dakr@kernel.org>
2025-11-13 19:58:24 +11:00
Martin K. Petersen
e360bb6dc8 Merge patch series "replace old wq(s), added WQ_PERCPU to alloc_workqueue"
Marco Crivellari <marco.crivellari@suse.com> says:

Hi,

=== Current situation: problems ===

Let's consider a nohz_full system with isolated CPUs: wq_unbound_cpumask is
set to the housekeeping CPUs, for !WQ_UNBOUND the local CPU is selected.

This leads to different scenarios if a work item is scheduled on an
isolated CPU where "delay" value is 0 or greater then 0:
        schedule_delayed_work(, 0);

This will be handled by __queue_work() that will queue the work item on the
current local (isolated) CPU, while:

        schedule_delayed_work(, 1);

Will move the timer on an housekeeping CPU, and schedule the work there.

Currently if a user enqueue a work item using schedule_delayed_work() the
used wq is "system_wq" (per-cpu wq) while queue_delayed_work() use
WORK_CPU_UNBOUND (used when a cpu is not specified). The same applies to
schedule_work() that is using system_wq and queue_work(), that makes use
again of WORK_CPU_UNBOUND.

This lack of consistency cannot be addressed without refactoring the API.

=== Recent changes to the WQ API ===

The following, address the recent changes in the Workqueue API:

- commit 128ea9f6cc ("workqueue: Add system_percpu_wq and system_dfl_wq")
- commit 930c2ea566 ("workqueue: Add new WQ_PERCPU flag")

The old workqueues will be removed in a future release cycle.

=== Introduced Changes by this series ===

1) [P 1]  Replace uses of system_wq and system_unbound_wq

    system_unbound_wq is to be used when locality is not required.

    Because of that, system_unbound_wq has been replaced with
	system_dfl_wq, to make clear it should be used when locality
	is not required.

2) [P 2-3-4] WQ_PERCPU added to alloc_workqueue()

    This change adds a new WQ_PERCPU flag to explicitly request
    alloc_workqueue() to be per-cpu when WQ_UNBOUND has not been specified.

Thanks!

Link: https://patch.msgid.link/20251031095643.74246-1-marco.crivellari@suse.com
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-11-12 21:30:23 -05:00
Marco Crivellari
8d5cad38cf scsi: pm80xx: Add WQ_PERCPU to alloc_workqueue() users
Currently if a user enqueues a work item using schedule_delayed_work()
the used wq is "system_wq" (per-cpu wq) while queue_delayed_work() use
WORK_CPU_UNBOUND (used when a cpu is not specified). The same applies to
schedule_work() that is using system_wq and queue_work(), that makes use
again of WORK_CPU_UNBOUND.  This lack of consistency cannot be addressed
without refactoring the API.

alloc_workqueue() treats all queues as per-CPU by default, while unbound
workqueues must opt-in via WQ_UNBOUND.

This default is suboptimal: most workloads benefit from unbound queues,
allowing the scheduler to place worker threads where they’re needed and
reducing noise when CPUs are isolated.

This continues the effort to refactor workqueue APIs, which began with
the introduction of new workqueues and a new alloc_workqueue flag in:

commit 128ea9f6cc ("workqueue: Add system_percpu_wq and system_dfl_wq")
commit 930c2ea566 ("workqueue: Add new WQ_PERCPU flag")

This  adds a new WQ_PERCPU flag to explicitly request to alloc_workqueue()
to be per-cpu when WQ_UNBOUND has not been specified.

With the introduction of the WQ_PERCPU flag (equivalent to !WQ_UNBOUND),
any alloc_workqueue() caller that doesn’t explicitly specify WQ_UNBOUND
must now use WQ_PERCPU.

Once migration is complete, WQ_UNBOUND can be removed and unbound will
become the implicit default.

Suggested-by: Tejun Heo <tj@kernel.org>
Signed-off-by: Marco Crivellari <marco.crivellari@suse.com>
Link: https://patch.msgid.link/20251107155257.316728-1-marco.crivellari@suse.com
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-11-12 21:28:27 -05:00
Marco Crivellari
2e2e559390 scsi: target: Add WQ_PERCPU to alloc_workqueue() users
Currently if a user enqueues a work item using schedule_delayed_work()
the used wq is "system_wq" (per-cpu wq) while queue_delayed_work() use
WORK_CPU_UNBOUND (used when a cpu is not specified). The same applies to
schedule_work() that is using system_wq and queue_work(), that makes use
again of WORK_CPU_UNBOUND.  This lack of consistency cannot be addressed
without refactoring the API.

alloc_workqueue() treats all queues as per-CPU by default, while unbound
workqueues must opt-in via WQ_UNBOUND.

This default is suboptimal: most workloads benefit from unbound queues,
allowing the scheduler to place worker threads where they’re needed and
reducing noise when CPUs are isolated.

This continues the effort to refactor workqueue APIs, which began with
the introduction of new workqueues and a new alloc_workqueue flag in:

commit 128ea9f6cc ("workqueue: Add system_percpu_wq and system_dfl_wq")
commit 930c2ea566 ("workqueue: Add new WQ_PERCPU flag")

This change adds a new WQ_PERCPU flag to explicitly request
alloc_workqueue() to be per-cpu when WQ_UNBOUND has not been specified.

With the introduction of the WQ_PERCPU flag (equivalent to !WQ_UNBOUND),
any alloc_workqueue() caller that doesn’t explicitly specify WQ_UNBOUND
must now use WQ_PERCPU.

Once migration is complete, WQ_UNBOUND can be removed and unbound will
become the implicit default.

Suggested-by: Tejun Heo <tj@kernel.org>
Signed-off-by: Marco Crivellari <marco.crivellari@suse.com>
Link: https://patch.msgid.link/20251107154008.304127-1-marco.crivellari@suse.com
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-11-12 21:28:27 -05:00
Marco Crivellari
f60b8957d8 scsi: qedi: Add WQ_PERCPU to alloc_workqueue() users
Currently if a user enqueues a work item using schedule_delayed_work()
the used wq is "system_wq" (per-cpu wq) while queue_delayed_work() use
WORK_CPU_UNBOUND (used when a cpu is not specified). The same applies to
schedule_work() that is using system_wq and queue_work(), that makes use
again of WORK_CPU_UNBOUND.  This lack of consistency cannot be addressed
without refactoring the API.

alloc_workqueue() treats all queues as per-CPU by default, while unbound
workqueues must opt-in via WQ_UNBOUND.

This default is suboptimal: most workloads benefit from unbound queues,
allowing the scheduler to place worker threads where they’re needed and
reducing noise when CPUs are isolated.

This continues the effort to refactor workqueue APIs, which began with
the introduction of new workqueues and a new alloc_workqueue flag in:

commit 128ea9f6cc ("workqueue: Add system_percpu_wq and system_dfl_wq")
commit 930c2ea566 ("workqueue: Add new WQ_PERCPU flag")

This change adds a new WQ_PERCPU flag to explicitly request
alloc_workqueue() to be per-cpu when WQ_UNBOUND has not been specified.

With the introduction of the WQ_PERCPU flag (equivalent to !WQ_UNBOUND),
any alloc_workqueue() caller that doesn’t explicitly specify WQ_UNBOUND
must now use WQ_PERCPU.

Once migration is complete, WQ_UNBOUND can be removed and unbound will
become the implicit default.

Suggested-by: Tejun Heo <tj@kernel.org>
Signed-off-by: Marco Crivellari <marco.crivellari@suse.com>
Link: https://patch.msgid.link/20251107151618.281250-1-marco.crivellari@suse.com
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-11-12 21:28:26 -05:00
Marco Crivellari
42312d3acd scsi: target: ibmvscsi: Add WQ_PERCPU to alloc_workqueue() users
Currently if a user enqueues a work item using schedule_delayed_work()
the used wq is "system_wq" (per-cpu wq) while queue_delayed_work() use
WORK_CPU_UNBOUND (used when a cpu is not specified). The same applies to
schedule_work() that is using system_wq and queue_work(), that makes use
again of WORK_CPU_UNBOUND.  This lack of consistency cannot be addressed
without refactoring the API.

alloc_workqueue() treats all queues as per-CPU by default, while unbound
workqueues must opt-in via WQ_UNBOUND.

This default is suboptimal: most workloads benefit from unbound queues,
allowing the scheduler to place worker threads where they’re needed and
reducing noise when CPUs are isolated.

This continues the effort to refactor workqueue APIs, which began with
the introduction of new workqueues and a new alloc_workqueue flag in:

commit 128ea9f6cc ("workqueue: Add system_percpu_wq and system_dfl_wq")
commit 930c2ea566 ("workqueue: Add new WQ_PERCPU flag")

This change adds a new WQ_PERCPU flag to explicitly request
alloc_workqueue() to be per-cpu when WQ_UNBOUND has not been specified.

With the introduction of the WQ_PERCPU flag (equivalent to !WQ_UNBOUND),
any alloc_workqueue() caller that doesn’t explicitly specify WQ_UNBOUND
must now use WQ_PERCPU.

Once migration is complete, WQ_UNBOUND can be removed and unbound will
become the implicit default.

Suggested-by: Tejun Heo <tj@kernel.org>
Signed-off-by: Marco Crivellari <marco.crivellari@suse.com>
Link: https://patch.msgid.link/20251107150542.271229-1-marco.crivellari@suse.com
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-11-12 21:28:26 -05:00
Marco Crivellari
e036dadf78 scsi: qedf: Add WQ_PERCPU to alloc_workqueue() users
Currently if a user enqueues a work item using schedule_delayed_work()
the used wq is "system_wq" (per-cpu wq) while queue_delayed_work() use
WORK_CPU_UNBOUND (used when a cpu is not specified). The same applies to
schedule_work() that is using system_wq and queue_work(), that makes use
again of WORK_CPU_UNBOUND.  This lack of consistency cannot be addressed
without refactoring the API.

alloc_workqueue() treats all queues as per-CPU by default, while unbound
workqueues must opt-in via WQ_UNBOUND.

This default is suboptimal: most workloads benefit from unbound queues,
allowing the scheduler to place worker threads where they’re needed and
reducing noise when CPUs are isolated.

This continues the effort to refactor workqueue APIs, which began with
the introduction of new workqueues and a new alloc_workqueue flag in:

commit 128ea9f6cc ("workqueue: Add system_percpu_wq and system_dfl_wq")
commit 930c2ea566 ("workqueue: Add new WQ_PERCPU flag")

This change adds a new WQ_PERCPU flag to explicitly request
alloc_workqueue() to be per-cpu when WQ_UNBOUND has not been specified.

With the introduction of the WQ_PERCPU flag (equivalent to !WQ_UNBOUND),
any alloc_workqueue() caller that doesn’t explicitly specify WQ_UNBOUND
must now use WQ_PERCPU.

Once migration is complete, WQ_UNBOUND can be removed and unbound will
become the implicit default.

Suggested-by: Tejun Heo <tj@kernel.org>
Signed-off-by: Marco Crivellari <marco.crivellari@suse.com>
Link: https://patch.msgid.link/20251107150155.267651-3-marco.crivellari@suse.com
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-11-12 21:28:26 -05:00
Marco Crivellari
a43a2e48d5 scsi: bnx2fc: Add WQ_PERCPU to alloc_workqueue() users
Currently if a user enqueues a work item using schedule_delayed_work()
the used wq is "system_wq" (per-cpu wq) while queue_delayed_work() use
WORK_CPU_UNBOUND (used when a cpu is not specified). The same applies to
schedule_work() that is using system_wq and queue_work(), that makes use
again of WORK_CPU_UNBOUND.  This lack of consistency cannot be addressed
without refactoring the API.

alloc_workqueue() treats all queues as per-CPU by default, while unbound
workqueues must opt-in via WQ_UNBOUND.

This default is suboptimal: most workloads benefit from unbound queues,
allowing the scheduler to place worker threads where they’re needed and
reducing noise when CPUs are isolated.

This continues the effort to refactor workqueue APIs, which began with
the introduction of new workqueues and a new alloc_workqueue flag in:

commit 128ea9f6cc ("workqueue: Add system_percpu_wq and system_dfl_wq")
commit 930c2ea566 ("workqueue: Add new WQ_PERCPU flag")

This change adds a new WQ_PERCPU flag to explicitly request
alloc_workqueue() to be per-cpu when WQ_UNBOUND has not been specified.

With the introduction of the WQ_PERCPU flag (equivalent to !WQ_UNBOUND),
any alloc_workqueue() caller that doesn’t explicitly specify WQ_UNBOUND
must now use WQ_PERCPU.

Once migration is complete, WQ_UNBOUND can be removed and unbound will
become the implicit default.

Suggested-by: Tejun Heo <tj@kernel.org>
Signed-off-by: Marco Crivellari <marco.crivellari@suse.com>
Link: https://patch.msgid.link/20251107150155.267651-2-marco.crivellari@suse.com
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-11-12 21:28:26 -05:00
Marco Crivellari
6184ec8b63 scsi: be2iscsi: Add WQ_PERCPU to alloc_workqueue() users
Currently if a user enqueues a work item using schedule_delayed_work()
the used wq is "system_wq" (per-cpu wq) while queue_delayed_work() use
WORK_CPU_UNBOUND (used when a cpu is not specified). The same applies to
schedule_work() that is using system_wq and queue_work(), that makes use
again of WORK_CPU_UNBOUND.  This lack of consistency cannot be addressed
without refactoring the API.

alloc_workqueue() treats all queues as per-CPU by default, while unbound
workqueues must opt-in via WQ_UNBOUND.

This default is suboptimal: most workloads benefit from unbound queues,
allowing the scheduler to place worker threads where they’re needed and
reducing noise when CPUs are isolated.

This continues the effort to refactor workqueue APIs, which began with
the introduction of new workqueues and a new alloc_workqueue flag in:

commit 128ea9f6cc ("workqueue: Add system_percpu_wq and system_dfl_wq")
commit 930c2ea566 ("workqueue: Add new WQ_PERCPU flag")

This change adds a new WQ_PERCPU flag to explicitly request
alloc_workqueue() to be per-cpu when WQ_UNBOUND has not been specified.

With the introduction of the WQ_PERCPU flag (equivalent to !WQ_UNBOUND),
any alloc_workqueue() caller that doesn’t explicitly specify WQ_UNBOUND
must now use WQ_PERCPU.

Once migration is complete, WQ_UNBOUND can be removed and unbound will
become the implicit default.

Suggested-by: Tejun Heo <tj@kernel.org>
Signed-off-by: Marco Crivellari <marco.crivellari@suse.com>
Link: https://patch.msgid.link/20251107144949.256894-1-marco.crivellari@suse.com
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-11-12 21:28:26 -05:00
Marco Crivellari
f0dc44177a scsi: message: fusion: Add WQ_PERCPU to alloc_workqueue() users
Currently if a user enqueues a work item using schedule_delayed_work()
the used wq is "system_wq" (per-cpu wq) while queue_delayed_work() use
WORK_CPU_UNBOUND (used when a cpu is not specified). The same applies to
schedule_work() that is using system_wq and queue_work(), that makes use
again of WORK_CPU_UNBOUND.  This lack of consistency cannot be addressed
without refactoring the API.

alloc_workqueue() treats all queues as per-CPU by default, while unbound
workqueues must opt-in via WQ_UNBOUND.

This default is suboptimal: most workloads benefit from unbound queues,
allowing the scheduler to place worker threads where they’re needed and
reducing noise when CPUs are isolated.

This continues the effort to refactor workqueue APIs, which began with
the introduction of new workqueues and a new alloc_workqueue flag in:

commit 128ea9f6cc ("workqueue: Add system_percpu_wq and system_dfl_wq")
commit 930c2ea566 ("workqueue: Add new WQ_PERCPU flag")

This change adds a new WQ_PERCPU flag to explicitly request
alloc_workqueue() to be per-cpu when WQ_UNBOUND has not been specified.

With the introduction of the WQ_PERCPU flag (equivalent to !WQ_UNBOUND),
any alloc_workqueue() caller that doesn’t explicitly specify WQ_UNBOUND
must now use WQ_PERCPU.

Once migration is complete, WQ_UNBOUND can be removed and unbound will
become the implicit default.

Suggested-by: Tejun Heo <tj@kernel.org>
Signed-off-by: Marco Crivellari <marco.crivellari@suse.com>
Link: https://patch.msgid.link/20251107141458.225119-1-marco.crivellari@suse.com
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-11-12 21:28:26 -05:00
Marco Crivellari
84150ef06f scsi: lpfc: WQ_PERCPU added to alloc_workqueue() users
Currently if a user enqueue a work item using schedule_delayed_work()
the used wq is "system_wq" (per-cpu wq) while queue_delayed_work() use
WORK_CPU_UNBOUND (used when a cpu is not specified). The same applies to
schedule_work() that is using system_wq and queue_work(), that makes use
again of WORK_CPU_UNBOUND.  This lack of consistentcy cannot be
addressed without refactoring the API.

alloc_workqueue() treats all queues as per-CPU by default, while unbound
workqueues must opt-in via WQ_UNBOUND.

This default is suboptimal: most workloads benefit from unbound queues,
allowing the scheduler to place worker threads where they’re needed and
reducing noise when CPUs are isolated.

This change adds a new WQ_PERCPU flag to explicitly request
alloc_workqueue() to be per-cpu when WQ_UNBOUND has not been specified.

This patch continues the effort to refactor worqueue APIs, which has
begun with the change introducing new workqueues and a new
alloc_workqueue flag:

commit 128ea9f6cc ("workqueue: Add system_percpu_wq and system_dfl_wq")
commit 930c2ea566 ("workqueue: Add new WQ_PERCPU flag")

With the introduction of the WQ_PERCPU flag (equivalent to !WQ_UNBOUND),
any alloc_workqueue() caller that doesn’t explicitly specify WQ_UNBOUND
must now use WQ_PERCPU.

Once migration is complete, WQ_UNBOUND can be removed and unbound will
become the implicit default.

Suggested-by: Tejun Heo <tj@kernel.org>
Signed-off-by: Marco Crivellari <marco.crivellari@suse.com>
Reviewed-by: Justin Tee <justin.tee@broadcom.com>
Link: https://patch.msgid.link/20251104110808.123424-1-marco.crivellari@suse.com
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-11-12 21:28:26 -05:00
Marco Crivellari
f76e4e1e83 scsi: scsi_transport_fc: WQ_PERCPU added to alloc_workqueue users()
Currently if a user enqueue a work item using schedule_delayed_work() the
used wq is "system_wq" (per-cpu wq) while queue_delayed_work() use
WORK_CPU_UNBOUND (used when a cpu is not specified). The same applies to
schedule_work() that is using system_wq and queue_work(), that makes use
again of WORK_CPU_UNBOUND.
This lack of consistentcy cannot be addressed without refactoring the API.

alloc_workqueue() treats all queues as per-CPU by default, while unbound
workqueues must opt-in via WQ_UNBOUND.

This default is suboptimal: most workloads benefit from unbound queues,
allowing the scheduler to place worker threads where they’re needed and
reducing noise when CPUs are isolated.

This change adds a new WQ_PERCPU flag to explicitly request
alloc_workqueue() to be per-cpu when WQ_UNBOUND has not been specified.

With the introduction of the WQ_PERCPU flag (equivalent to !WQ_UNBOUND),
any alloc_workqueue() caller that doesn’t explicitly specify WQ_UNBOUND
must now use WQ_PERCPU.

Once migration is complete, WQ_UNBOUND can be removed and unbound will
become the implicit default.

Suggested-by: Tejun Heo <tj@kernel.org>
Signed-off-by: Marco Crivellari <marco.crivellari@suse.com>
Reviewed-by: Justin Tee <justin.tee@broadcom.com>
Link: https://patch.msgid.link/20251031095643.74246-5-marco.crivellari@suse.com
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-11-12 21:28:26 -05:00
Marco Crivellari
afad6b34de scsi: scsi_dh_alua: WQ_PERCPU added to alloc_workqueue() users
Currently if a user enqueue a work item using schedule_delayed_work() the
used wq is "system_wq" (per-cpu wq) while queue_delayed_work() use
WORK_CPU_UNBOUND (used when a cpu is not specified). The same applies to
schedule_work() that is using system_wq and queue_work(), that makes use
again of WORK_CPU_UNBOUND.
This lack of consistentcy cannot be addressed without refactoring the API.

alloc_workqueue() treats all queues as per-CPU by default, while unbound
workqueues must opt-in via WQ_UNBOUND.

This default is suboptimal: most workloads benefit from unbound queues,
allowing the scheduler to place worker threads where they’re needed and
reducing noise when CPUs are isolated.

This change adds a new WQ_PERCPU flag to explicitly request
alloc_workqueue() to be per-cpu when WQ_UNBOUND has not been specified.

With the introduction of the WQ_PERCPU flag (equivalent to !WQ_UNBOUND),
any alloc_workqueue() caller that doesn’t explicitly specify WQ_UNBOUND
must now use WQ_PERCPU.

Once migration is complete, WQ_UNBOUND can be removed and unbound will
become the implicit default.

Suggested-by: Tejun Heo <tj@kernel.org>
Signed-off-by: Marco Crivellari <marco.crivellari@suse.com>
Link: https://patch.msgid.link/20251031095643.74246-4-marco.crivellari@suse.com
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-11-12 21:28:26 -05:00
Marco Crivellari
5ca003bb43 scsi: qla2xxx: WQ_PERCPU added to alloc_workqueue() users
Currently if a user enqueue a work item using schedule_delayed_work() the
used wq is "system_wq" (per-cpu wq) while queue_delayed_work() use
WORK_CPU_UNBOUND (used when a cpu is not specified). The same applies to
schedule_work() that is using system_wq and queue_work(), that makes use
again of WORK_CPU_UNBOUND.
This lack of consistentcy cannot be addressed without refactoring the API.

alloc_workqueue() treats all queues as per-CPU by default, while unbound
workqueues must opt-in via WQ_UNBOUND.

This default is suboptimal: most workloads benefit from unbound queues,
allowing the scheduler to place worker threads where they’re needed and
reducing noise when CPUs are isolated.

This change adds a new WQ_PERCPU flag to explicitly request
alloc_workqueue() to be per-cpu when WQ_UNBOUND has not been specified.

With the introduction of the WQ_PERCPU flag (equivalent to !WQ_UNBOUND),
any alloc_workqueue() caller that doesn’t explicitly specify WQ_UNBOUND
must now use WQ_PERCPU.

Once migration is complete, WQ_UNBOUND can be removed and unbound will
become the implicit default.

Suggested-by: Tejun Heo <tj@kernel.org>
Signed-off-by: Marco Crivellari <marco.crivellari@suse.com>
Link: https://patch.msgid.link/20251031095643.74246-3-marco.crivellari@suse.com
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-11-12 21:28:25 -05:00
Marco Crivellari
0ba2fc767a scsi: target: sbp: Replace use of system_unbound_wq with system_dfl_wq
Currently if a user enqueue a work item using schedule_delayed_work()
the used wq is "system_wq" (per-cpu wq) while queue_delayed_work() use
WORK_CPU_UNBOUND (used when a cpu is not specified). The same applies to
schedule_work() that is using system_wq and queue_work(), that makes use
again of WORK_CPU_UNBOUND.

This lack of consistentcy cannot be addressed without refactoring the
API.

This patch continues the effort to refactor worqueue APIs, which has
begun with the change introducing new workqueues and a new
alloc_workqueue flag:

commit 128ea9f6cc ("workqueue: Add system_percpu_wq and system_dfl_wq")
commit 930c2ea566 ("workqueue: Add new WQ_PERCPU flag")

system_dfl_wq should be the default workqueue so as not to enforce
locality constraints for random work whenever it's not required.

The old system_unbound_wq will be kept for a few release cycles.

Suggested-by: Tejun Heo <tj@kernel.org>
Signed-off-by: Marco Crivellari <marco.crivellari@suse.com>
Link: https://patch.msgid.link/20251104104518.102130-1-marco.crivellari@suse.com
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-11-12 21:28:25 -05:00
Marco Crivellari
cd87aa2e50 scsi: scsi_transport_iscsi: Replace use of system_unbound_wq with system_dfl_wq
Currently if a user enqueue a work item using schedule_delayed_work()
the used wq is "system_wq" (per-cpu wq) while queue_delayed_work() use
WORK_CPU_UNBOUND (used when a cpu is not specified). The same applies to
schedule_work() that is using system_wq and queue_work(), that makes use
again of WORK_CPU_UNBOUND.

This lack of consistency cannot be addressed without refactoring the
API.

system_unbound_wq should be the default workqueue so as not to enforce
locality constraints for random work whenever it's not required.

Adding system_dfl_wq to encourage its use when unbound work should be
used.

The old system_unbound_wq will be kept for a few release cycles.

Suggested-by: Tejun Heo <tj@kernel.org>
Signed-off-by: Marco Crivellari <marco.crivellari@suse.com>
Link: https://patch.msgid.link/20251031095643.74246-2-marco.crivellari@suse.com
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-11-12 21:15:18 -05:00
Marco Crivellari
49783aca15 scsi: qla2xxx: Replace use of system_unbound_wq with system_dfl_wq
Currently if a user enqueue a work item using schedule_delayed_work()
the used wq is "system_wq" (per-cpu wq) while queue_delayed_work() use
WORK_CPU_UNBOUND (used when a cpu is not specified). The same applies to
schedule_work() that is using system_wq and queue_work(), that makes use
again of WORK_CPU_UNBOUND.

This lack of consistency cannot be addressed without refactoring the
API.

system_unbound_wq should be the default workqueue so as not to enforce
locality constraints for random work whenever it's not required.

Adding system_dfl_wq to encourage its use when unbound work should be
used.

The old system_unbound_wq will be kept for a few release cycles.

Suggested-by: Tejun Heo <tj@kernel.org>
Signed-off-by: Marco Crivellari <marco.crivellari@suse.com>
Link: https://patch.msgid.link/20251031095643.74246-2-marco.crivellari@suse.com
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-11-12 21:15:18 -05:00
Ally Heev
3813d28b2b scsi: scsi_debug: Fix uninitialized pointers with __free attr
Uninitialized pointers with '__free' attribute can cause undefined
behaviour as the memory assigned(randomly) to the pointer is freed
automatically when the pointer goes out of scope

scsi doesn't have any bugs related to this as of now, but it is better
to initialize and assign pointers with '__free' attr in one statement to
ensure proper scope-based cleanup

Reported-by: Dan Carpenter <dan.carpenter@linaro.org>
Closes: https://lore.kernel.org/all/aPiG_F5EBQUjZqsl@stanley.mountain/
Signed-off-by: Ally Heev <allyheev@gmail.com>
Link: https://patch.msgid.link/20251105-aheev-uninitialized-free-attr-scsi-v1-1-d28435a0a7ea@gmail.com
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-11-12 21:08:05 -05:00
Bart Van Assche
18987143d4 scsi: ufs: core: Remove an unnecessary NULL pointer check
The !payload check tests the address of a member of a data structure. We
know that the start address of this data structure (job) is not NULL
since the 'job' pointer has already been dereferenced. Hence, the
!payload check is superfluous. Remove this test. This was reported by
the CodeSonar static analyzer.

Signed-off-by: Bart Van Assche <bvanassche@acm.org>
Link: https://patch.msgid.link/20251111184802.125111-1-bvanassche@acm.org
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-11-12 20:58:28 -05:00
Nuno Sá
1028258914 scsi: pm: Drop unneeded call to pm_runtime_mark_last_busy()
There's no need to explicitly call pm_runtime_mark_last_busy() since
pm_runtime_autosuspend() is now doing it since commit 08071e64cb ("PM:
runtime: Mark last busy stamp in pm_runtime_autosuspend()")

Signed-off-by: Nuno Sá <nuno.sa@analog.com>
Link: https://patch.msgid.link/20251111-scsi-pm-improv-v2-1-626b8491f4b4@analog.com
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-11-12 20:56:38 -05:00
Haotian Zhang
acd194d9b5 scsi: sim710: Fix resource leak by adding missing ioport_unmap() calls
The driver calls ioport_map() to map I/O ports in sim710_probe_common()
but never calls ioport_unmap() to release the mapping. This causes
resource leaks in both the error path when request_irq() fails and in
the normal device removal path via sim710_device_remove().

Add ioport_unmap() calls in the out_release error path and in
sim710_device_remove().

Fixes: 56fece2008 ("[PATCH] finally fix 53c700 to use the generic iomem infrastructure")
Signed-off-by: Haotian Zhang <vulab@iscas.ac.cn>
Link: https://patch.msgid.link/20251029032555.1476-1-vulab@iscas.ac.cn
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-11-12 20:53:41 -05:00
Junrui Luo
f6ab594672 scsi: aic94xx: fix use-after-free in device removal path
The asd_pci_remove() function fails to synchronize with pending tasklets
before freeing the asd_ha structure, leading to a potential
use-after-free vulnerability.

When a device removal is triggered (via hot-unplug or module unload),
race condition can occur.

The fix adds tasklet_kill() before freeing the asd_ha structure,
ensuring all scheduled tasklets complete before cleanup proceeds.

Reported-by: Yuhao Jiang <danisjiang@gmail.com>
Reported-by: Junrui Luo <moonafterrain@outlook.com>
Fixes: 2908d778ab ("[SCSI] aic94xx: new driver")
Cc: stable@vger.kernel.org
Signed-off-by: Junrui Luo <moonafterrain@outlook.com>
Link: https://patch.msgid.link/ME2PR01MB3156AB7DCACA206C845FC7E8AFFDA@ME2PR01MB3156.ausprd01.prod.outlook.com
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-11-12 20:50:43 -05:00
Martin K. Petersen
d204087a59 Merge patch series "qla2xxx target mode improvements"
Tony Battersby <tonyb@cybernetics.com> says:

This patch series improves the qla2xxx FC driver in target mode. I
developed these patches using the out-of-tree SCST target-mode
subsystem (https://scst.sourceforge.net/), although most of the
improvements will also apply to the other target-mode subsystems such
as the in-tree LIO.  Unfortunately qla2xxx+LIO does not pass all of my
tests, but my patches do not make it any worse (results below). These
patches have been well-tested at my employer with qla2xxx+SCST in both
initiator mode and target mode and with a variety of FC HBAs and
initiators. Since SCST is out-of-tree, some of the patches have parts
that apply in-tree and other parts that apply out-of-tree to SCST. The
SCST patches can be found in the v2 posting linked above.

All patches apply to linux 6.17 and SCST 3.10 master branch.

Summary of patches:
- bugfixes
- cleanups
- improve handling of aborts and task management requests
- improve log message
- add back SLER / SRR support (removed in 2017)

Some of these patches improve handling of aborts and task management
requests. This is some of the testing that I did:

Test 1: Use /dev/sg to queue random disk I/O with short timeouts; make
sure cmds are aborted successfully.
Test 2: Queue lots of disk I/O, then use "sg_reset -N -d /dev/sg" on
initiator to reset logical unit.
Test 3: Queue lots of disk I/O, then use "sg_reset -N -t /dev/sg" on
initiator to reset target.
Test 4: Queue lots of disk I/O, then use "sg_reset -N -b /dev/sg" on
initiator to reset bus.
Test 5: Queue lots of disk I/O, then use "sg_reset -N -H /dev/sg" on
initiator to reset host.
Test 6: Use fiber channel attenuator to trigger SRR during
write/read/compare test; check data integrity.

With my patches, SCST passes all of these tests.

Results with in-tree LIO target-mode subsystem:

Test 1: Seems to abort the same cmd multiple times (both
qlt_24xx_retry_term_exchange() and __qlt_send_term_exchange()). But
cmds get aborted, so give it a pass?

Test 2: Seems to work; cmds are aborted.

Test 3: Target reset doesn't seem to abort cmds, instead, a few seconds
later:
qla2xxx [0000:04:00.0]-f058:9: qla_target(0): tag 1314312, op 2a: CTIO
with TIMEOUT status 0xb received (state 1, port 51:40:2e:c0:18:1d:9f:cc,
LUN 0)

Tests 4 and 5: The initiator is unable to log back in to the target; the
following messages are repeated over and over on the target:
qla2xxx [0000:04:00.0]-e01c:9: Sending TERM ELS CTIO (ha=00000000f8811390)
qla2xxx [0000:04:00.0]-f097:9: Linking sess 000000008df5aba8 [0] wwn
51:40:2e:c0:18:1d:9f:cc with PLOGI ACK to wwn 51:40:2e:c0:18:1d:9f:cc
s_id 00:00:01, ref=2 pla 00000000835a9271 link 0

Test 6: passes with my patches; SRR not supported previously.

So qla2xxx+LIO seems a bit flaky when handling exceptions, but my
patches do not make it any worse. Perhaps someone who is more familiar
with LIO can look at the difference between LIO and SCST and figure out
how to improve it.

Tony Battersby
https://www.cybernetics.com/

v1: https://lore.kernel.org/r/f8977250-638c-4d7d-ac0c-65f742b8d535@cybernetics.com/
v2: https://lore.kernel.org/linux-scsi/e95ee7d0-3580-4124-b854-7f73ca3a3a84@cybernetics.com/
Link: https://patch.msgid.link/aaea0ab0-da8b-4153-9369-60db7507ff7a@cybernetics.com
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-11-12 18:17:50 -05:00
Tony Battersby
4f5eb50f7c scsi: qla2xxx: target: Improve safety of cmd lookup by handle
The driver associates two different structs with numeric handles and
passes the handles to the hardware.  When the hardware passes the handle
back to the driver, the driver consults a table of void * to convert the
handle back to the struct without checking the type of struct.  This can
lead to type confusion if the HBA firmware misbehaves (and some firmware
versions do).  So verify the type of struct is what is expected before
using it.

But we can also do better than that.  Also verify that the exchange
address of the message sent from the hardware matches the exchange
address of the command being returned.  This adds an extra guard against
buggy HBA firmware that returns duplicate messages multiple times (which
has also been seen) in case the driver has reused the handle for a
different command of the same type.

These problems were seen on a QLE2694L with firmware 9.08.02 when
testing SLER / SRR support.  The SRR caused the HBA to flood the
response queue with hundreds of bogus entries.

Signed-off-by: Tony Battersby <tonyb@cybernetics.com>
Link: https://patch.msgid.link/7c7cb574-fe62-42ae-b800-d136d8dd89ca@cybernetics.com
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-11-12 18:17:28 -05:00
Tony Battersby
c7bd85a7b9 scsi: qla2xxx: target: Add back SRR support
Background: loading qla2xxx with "ql2xtgt_tape_enable=1" enables
Sequence Level Error Recovery (SLER), which is most commonly used for
tape drives.  With SLER enabled, if there is a recoverable I/O error
during a SCSI command, a Sequence Retransmission Request (SRR) will be
used to retry the I/O at a low-level completely within the driver
without propagating the error to the upper levels of the SCSI stack.

SRR support was removed in 2017 by commit 2c39b5ca2a ("qla2xxx: Remove
SRR code"). Add it back, new and improved.

The old removed SRR code used sequence numbers to correlate the SRR
CTIOs with SRR immediate notify messages.  I don't see how that would
work reliably with MSI-X interrupts and multiple queues.  So instead use
the exchange address to find the command associated with the immediate
notify (qlt_srr_to_cmd).

The old removed SRR code had a function qlt_check_srr_debug() to
simulate a SRR, but it didn't work for me.  Instead I just used fiber
optic attenuators attached to the FC cable to reduce the strength of the
signal and induce errors.  Unfortunately this only worked for inducing
SRRs on Data-Out (write) commands, so that is all I was able to test.

The code to build a new scatterlist for a SRR with nonzero offset has
been improved to reduce memory requirements and has been well-tested.
However it does not support protection information.

When a single cmd gets multiple SRRs, the old removed SRR code would
restore the data buffer from the values in cmd->se_cmd before processing
the new SRR.  That might be needed if the offset for the new SRR was
lower than the offset for the previous SRR, but I am not sure if that
can happen.  In my testing, when a single cmd gets multiple SRRs, the
SRR offset always increases or stays the same.  But in case it can
decrease, I added the function qlt_restore_orig_sg().  If this is not
supposed to happen then qlt_restore_orig_sg() can be removed to simplify
the code.

I ran into some HBA firmware bugs with QLE269x, QLE27xx, and QLE28xx
firmware 9.05.xx - 9.08.xx where a SRR would cause the HBA to misbehave
badly.  Since SRRs are rare and therefore difficult to test, I figured
it would be worth checking for the buggy firmware and disabling SLER
with a warning instead of letting others run into the same problem on
the rare occasion that they get a SRR.  This turned out to be difficult
because the firmware version isn't known in the normal NVRAM config
routine, so I added a second NVRAM config routine that is called after
the firmware version is known.

Signed-off-by: Tony Battersby <tonyb@cybernetics.com>
Link: https://patch.msgid.link/654b7181-b79e-40ed-a15b-6d6e441a5d5f@cybernetics.com
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-11-12 18:17:28 -05:00
Tony Battersby
04957d8c98 scsi: qla2xxx: target: Improve cmd logging
- Add the command tag to various messages so that different messages
   about the same command can be correlated.

 - For CTIO errors (i.e. when the HW reports an error about a cmd),
   print the cmd tag, opcode, state, initiator WWPN, and LUN.  This info
   helps an administrator determine what is going wrong.

 - When a command experiences a transport error, log a message when it
   is freed.  This makes debugging exceptions easier.

Signed-off-by: Tony Battersby <tonyb@cybernetics.com>
Link: https://patch.msgid.link/c579987d-5658-41ae-9653-f0e58c9d1880@cybernetics.com
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-11-12 18:17:28 -05:00
Tony Battersby
f4199d5812 scsi: qla2xxx: target: Add cmd->rsp_sent
Add cmd->rsp_sent to indicate that the SCSI status has been sent
successfully, so that SCST can be informed of any transport errors.
This will also be used for logging in later patches.

Signed-off-by: Tony Battersby <tonyb@cybernetics.com>
Link: https://patch.msgid.link/d4b0203f-7817-4517-9789-5866bb24fad7@cybernetics.com
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-11-12 18:17:28 -05:00
Tony Battersby
091719c21d scsi: qla2xxx: target: Fix invalid memory access with big CDBs
struct atio7_fcp_cmnd is a variable-length data structure because of
add_cdb_len, but it is embedded in struct atio_from_isp and copied
around like a fixed-length data structure.  For big CDBs > 16 bytes,
get_datalen_for_atio() called on a fixed-length copy of the atio will
access invalid memory.

In some cases this can be fixed by moving the atio to the end of the
data structure and using a variable-length allocation.  In other cases
such as allocating struct qla_tgt_cmd, the fixed-length data structures
are preallocated for speed, so in the case that add_cdb_len != 0,
allocate a separate buffer for the CDB.  Also add memcpy_atio() as a
safeguard against invalid memory accesses.

Signed-off-by: Tony Battersby <tonyb@cybernetics.com>
Link: https://patch.msgid.link/306a9d0b-3c89-42fc-a69c-eebca8171347@cybernetics.com
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-11-12 18:17:28 -05:00
Tony Battersby
3d56983cc6 scsi: qla2xxx: Fix TMR failure handling
(target mode)

If handle_tmr() fails:

 - The code for QLA_TGT_ABTS results in memory-use-after-free and
   double-free:
	qlt_do_tmr_work()
		qlt_build_abts_resp_iocb()
			qpair->req->outstanding_cmds[h] = (srb_t *)mcmd;
		mempool_free(mcmd, qla_tgt_mgmt_cmd_mempool); FIRST FREE
	qlt_handle_abts_completion()
		mcmd = qlt_ctio_to_cmd()
			cmd = req->outstanding_cmds[h];
			return cmd;
		vha  = mcmd->vha; USE-AFTER-FREE
		ha->tgt.tgt_ops->free_mcmd(mcmd); SECOND FREE

 - qlt_send_busy() makes no sense because it sends a SCSI command
   response instead of a TMR response.

Instead just call qlt_xmit_tm_rsp() to send a TMR failed response, since
that code is well-tested and handles a number of corner cases.  But it
would be incorrect to call ha->tgt.tgt_ops->free_mcmd() after
handle_tmr() failed, so add a flag to mcmd indicating the proper way to
free the mcmd so that qlt_xmit_tm_rsp() can be used for both cases.

Signed-off-by: Tony Battersby <tonyb@cybernetics.com>
Link: https://patch.msgid.link/09a1ff3d-6738-4953-a31b-10e89c540462@cybernetics.com
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-11-12 18:17:28 -05:00
Tony Battersby
5c50d84798 scsi: qla2xxx: target: Improve checks in qlt_xmit_response() / qlt_rdy_to_xfer()
Similar fixes to both functions:

qlt_xmit_response:

 - If the cmd cannot be processed, remember to call ->free_cmd() to
   prevent the target-mode midlevel from seeing a cmd lockup.

 - Do not try to send the response if the exchange has been terminated.

 - Check for chip reset once after lock instead of both before and after
   lock.

 - Give errors from qlt_pre_xmit_response() a lower priority to
   compensate for removing the first check for chip reset.

qlt_rdy_to_xfer:

 - Check for chip reset after lock instead of before lock to avoid
   races.

 - Do not try to receive data if the exchange has been terminated.

 - Give errors from qlt_pci_map_calc_cnt() a lower priority to
   compensate for moving the check for chip reset.

Signed-off-by: Tony Battersby <tonyb@cybernetics.com>
Link: https://patch.msgid.link/cd6ccd31-33fa-4454-be36-507bf578a546@cybernetics.com
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-11-12 18:17:28 -05:00
Tony Battersby
17488f1390 scsi: qla2xxx: target: Fix races with aborting commands
cmd->cmd_lock only protects cmd->aborted, but when deciding how to
process a cmd, it is necessary to consider other factors such as
cmd->state and if the chip has been reset, which are protected by
qpair->qp_lock_ptr.  So replace cmd_lock with qp_lock_ptr, whick makes
it possible to check additional values and make decisions about what to
do without racing with the CTIO handler and other code.

 - Lock cmd->qpair->qp_lock_ptr when aborting a cmd.

 - Eliminate cmd->cmd_lock and change cmd->aborted to a bitfield since
   it is now protected by qp_lock_ptr just like all the other flags.

 - Add another command state QLA_TGT_STATE_DONE to avoid any possible
   races between qlt_abort_cmd() and tgt_ops->free_cmd().

 - Add the cmd->sent_term_exchg flag to indicate if
   qlt_send_term_exchange() has already been called.

 - Export qlt_send_term_exchange() for SCST so that it can be called
   directly instead of trying to make qlt_abort_cmd() work for both TMR
   abort and HW timeout.

Signed-off-by: Tony Battersby <tonyb@cybernetics.com>
Link: https://patch.msgid.link/2c8d03e4-308b-4d5a-a418-a334be23f815@cybernetics.com
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-11-12 18:17:28 -05:00
Tony Battersby
d46c69a087 scsi: qla2xxx: Clear cmds after chip reset
Commit aefed3e554 ("scsi: qla2xxx: target: Fix offline port handling
and host reset handling") caused two problems:

1. Commands sent to FW, after chip reset got stuck and never freed as FW
   is not going to respond to them anymore.

2. BUG_ON(cmd->sg_mapped) in qlt_free_cmd().  Commit 26f9ce5381
   ("scsi: qla2xxx: Fix missed DMA unmap for aborted commands")
   attempted to fix this, but introduced another bug under different
   circumstances when two different CPUs were racing to call
   qlt_unmap_sg() at the same time: BUG_ON(!valid_dma_direction(dir)) in
   dma_unmap_sg_attrs().

So revert "scsi: qla2xxx: Fix missed DMA unmap for aborted commands" and
partially revert "scsi: qla2xxx: target: Fix offline port handling and
host reset handling" at __qla2x00_abort_all_cmds.

Fixes: aefed3e554 ("scsi: qla2xxx: target: Fix offline port handling and host reset handling")
Fixes: 26f9ce5381 ("scsi: qla2xxx: Fix missed DMA unmap for aborted commands")
Co-developed-by: Dmitry Bogdanov <d.bogdanov@yadro.com>
Signed-off-by: Dmitry Bogdanov <d.bogdanov@yadro.com>
Signed-off-by: Tony Battersby <tonyb@cybernetics.com>
Link: https://patch.msgid.link/0e7e5d26-e7a0-42d1-8235-40eeb27f3e98@cybernetics.com
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-11-12 18:17:03 -05:00
Martin K. Petersen
ab57a18665 Merge patch series "Optimize the hot path in the UFS driver"
Bart Van Assche <bvanassche@acm.org> says:

Hi Martin,

This patch series optimizes the hot path of the UFS driver by making
struct scsi_cmnd and struct ufshcd_lrb adjacent. Making these two data
structures adjacent is realized as follows:

@@ -9040,6 +9046,7 @@ static const struct scsi_host_template ufshcd_driver_template = {
     .name           = UFSHCD,
     .proc_name      = UFSHCD,
     .map_queues     = ufshcd_map_queues,
+    .cmd_size       = sizeof(struct ufshcd_lrb),
     .init_cmd_priv  = ufshcd_init_cmd_priv,
     .queuecommand   = ufshcd_queuecommand,
     .mq_poll        = ufshcd_poll,

The following changes had to be made prior to making these two data
structures adjacent:
* Add support for driver-internal and reserved commands in the SCSI core.
* Instead of making the reserved command slot (hba->reserved_slot)
  invisible to the SCSI core, let the SCSI core allocate a reserved command.
* Remove all UFS data structure members that are no longer needed
  because struct scsi_cmnd and struct ufshcd_lrb are now adjacent
* Call ufshcd_init_lrb() from inside the code for queueing a command instead of
  calling this function before I/O starts. This is necessary because
  ufshcd_memory_alloc() allocates fewer instances than the block layer
  allocates requests. See also the following code in the block layer
  core:

    if (blk_mq_init_request(set, hctx->fq->flush_rq, hctx_idx,
                hctx->numa_node))

  Although the UFS driver could be modified such that ufshcd_init_lrb()
  is called from ufshcd_init_cmd_priv(), realizing this would require
  moving the memory allocations that happen from inside
  ufshcd_memory_alloc() into ufshcd_init_cmd_priv(). That would make
  this patch series even larger. Although ufshcd_init_lrb() is called for each
  command, the benefits of reduced indirection and better cache efficiency
  outweigh the small overhead of per-command lrb initialization.
* ufshcd_add_scsi_host() happens now before any device management
  commands are submitted. This change is necessary because this patch
  makes device management command allocation happen when the SCSI host
  is allocated.
* Allocate as many command slots as the host controller supports. Decrease
  host->cmds_per_lun if necessary once it is clear whether or not the UFS
  device supports less command slots than the host controller.

Please consider this patch series for the next merge window.

Thanks,

Bart.

Link: https://patch.msgid.link/20251031204029.2883185-1-bvanassche@acm.org
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-11-12 18:16:05 -05:00
Tony Battersby
ed382b95f5 scsi: qla2xxx: target: Fix term exchange when cmd_sent_to_fw == 1
Properly set the nport_handle field of the terminate exchange message.
Previously when this field was not set properly, the term exchange would
fail when cmd_sent_to_fw == 1 but work when cmd_sent_to_fw == 0 (i.e. it
would fail when the HW was actively transferring data or status for the
cmd but work when the HW was idle).  With this change, term exchange
works in any cmd state, which now makes it possible to abort a command
that is locked up in the HW.

Signed-off-by: Tony Battersby <tonyb@cybernetics.com>
Link: https://patch.msgid.link/1a221699-969b-4f28-8ea4-395d2f7a7c0a@cybernetics.com
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-11-12 18:07:50 -05:00
Tony Battersby
c34e373f53 scsi: qla2xxx: target: Improve debug output for term exchange
Print better debug info when terminating a command, and print the
response status from the hardware.

Signed-off-by: Tony Battersby <tonyb@cybernetics.com>
Link: https://patch.msgid.link/22f8a0b6-0e24-474d-9f28-9d65c9b7af03@cybernetics.com
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-11-12 18:07:50 -05:00
Tony Battersby
9da4e1dcea scsi: qla2xxx: target: Remove code for unsupported hardware
As far as I can tell, CONTINUE_TGT_IO_TYPE and CTIO_A64_TYPE are message
types from non-FWI2 boards (older than ISP24xx), which are not supported
by qla_target.c.  Removing them makes it possible to turn a void * into
the real type and avoid some typecasts.

Signed-off-by: Tony Battersby <tonyb@cybernetics.com>
Link: https://patch.msgid.link/cb006628-e321-4e30-a60b-08b37b8685a5@cybernetics.com
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-11-12 18:07:50 -05:00
Tony Battersby
957aa59749 scsi: qla2xxx: Use reinit_completion on mbx_intr_comp
If a mailbox command completes immediately after
wait_for_completion_timeout() times out, ha->mbx_intr_comp could be left
in an inconsistent state, causing the next mailbox command not to wait
for the hardware.  Fix by reinitializing the completion before use.

Signed-off-by: Tony Battersby <tonyb@cybernetics.com>
Link: https://patch.msgid.link/11b6485e-0bfd-4784-8f99-c06a196dad94@cybernetics.com
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-11-12 18:07:50 -05:00
Tony Battersby
4f6aaade2a scsi: qla2xxx: Fix lost interrupts with qlini_mode=disabled
When qla2xxx is loaded with qlini_mode=disabled,
ha->flags.disable_msix_handshake is used before it is set, resulting in
the wrong interrupt handler being used on certain HBAs
(qla2xxx_msix_rsp_q_hs() is used when qla2xxx_msix_rsp_q() should be
used).  The only difference between these two interrupt handlers is that
the _hs() version writes to a register to clear the "RISC" interrupt,
whereas the other version does not.  So this bug results in the RISC
interrupt being cleared when it should not be.  This occasionally causes
a different interrupt handler qla24xx_msix_default() for a different
vector to see ((stat & HSRX_RISC_INT) == 0) and ignore its interrupt,
which then causes problems like:

qla2xxx [0000:02:00.0]-d04c:6: MBX Command timeout for cmd 20,
  iocontrol=8 jiffies=1090c0300 mb[0-3]=[0x4000 0x0 0x40 0xda] mb7 0x500
  host_status 0x40000010 hccr 0x3f00
qla2xxx [0000:02:00.0]-101e:6: Mailbox cmd timeout occurred, cmd=0x20,
  mb[0]=0x20. Scheduling ISP abort
(the cmd varies; sometimes it is 0x20, 0x22, 0x54, 0x5a, 0x5d, or 0x6a)

This problem can be reproduced with a 16 or 32 Gbps HBA by loading
qla2xxx with qlini_mode=disabled and running a high IOPS test while
triggering frequent RSCN database change events.

While analyzing the problem I discovered that even with
disable_msix_handshake forced to 0, it is not necessary to clear the
RISC interrupt from qla2xxx_msix_rsp_q_hs() (more below).  So just
completely remove qla2xxx_msix_rsp_q_hs() and the logic for selecting
it, which also fixes the bug with qlini_mode=disabled.

The test below describes the justification for not needing
qla2xxx_msix_rsp_q_hs():

Force disable_msix_handshake to 0:
qla24xx_config_rings():
if (0 && (ha->fw_attributes & BIT_6) && (IS_MSIX_NACK_CAPABLE(ha)) &&
    (ha->flags.msix_enabled)) {

In qla24xx_msix_rsp_q() and qla2xxx_msix_rsp_q_hs(), check:
  (rd_reg_dword(&reg->host_status) & HSRX_RISC_INT)

Count the number of calls to each function with HSRX_RISC_INT set and
the number with HSRX_RISC_INT not set while performing some I/O.

If qla2xxx_msix_rsp_q_hs() clears the RISC interrupt (original code):
qla24xx_msix_rsp_q:    50% of calls have HSRX_RISC_INT set
qla2xxx_msix_rsp_q_hs:  5% of calls have HSRX_RISC_INT set
(# of qla2xxx_msix_rsp_q_hs interrupts) =
    (# of qla24xx_msix_rsp_q interrupts) * 3

If qla2xxx_msix_rsp_q_hs() does not clear the RISC interrupt (patched
code):
qla24xx_msix_rsp_q:    100% of calls have HSRX_RISC_INT set
qla2xxx_msix_rsp_q_hs:   9% of calls have HSRX_RISC_INT set
(# of qla2xxx_msix_rsp_q_hs interrupts) =
    (# of qla24xx_msix_rsp_q interrupts) * 3

In the case of the original code, qla24xx_msix_rsp_q() was seeing
HSRX_RISC_INT set only 50% of the time because qla2xxx_msix_rsp_q_hs()
was clearing it when it shouldn't have been.  In the patched code,
qla24xx_msix_rsp_q() sees HSRX_RISC_INT set 100% of the time, which
makes sense if that interrupt handler needs to clear the RISC interrupt
(which it does).  qla2xxx_msix_rsp_q_hs() sees HSRX_RISC_INT only 9% of
the time, which is just overlap from the other interrupt during the
high IOPS test.

Tested with SCST on:
QLE2742  FW:v9.08.02 (32 Gbps 2-port)
QLE2694L FW:v9.10.11 (16 Gbps 4-port)
QLE2694L FW:v9.08.02 (16 Gbps 4-port)
QLE2672  FW:v8.07.12 (16 Gbps 2-port)
both initiator and target mode

Signed-off-by: Tony Battersby <tonyb@cybernetics.com>
Link: https://patch.msgid.link/56d378eb-14ad-49c7-bae9-c649b6c7691e@cybernetics.com
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-11-12 18:07:50 -05:00
Tony Battersby
8f58fc64d5 scsi: qla2xxx: Fix initiator mode with qlini_mode=exclusive
When given the module parameter qlini_mode=exclusive, qla2xxx in
initiator mode is initially unable to successfully send SCSI commands to
devices it finds while scanning, resulting in an escalating series of
resets until an adapter reset clears the issue.  Fix by checking the
active mode instead of the module parameter.

Signed-off-by: Tony Battersby <tonyb@cybernetics.com>
Link: https://patch.msgid.link/1715ec14-ba9a-45dc-9cf2-d41aa6b81b5e@cybernetics.com
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-11-12 18:07:50 -05:00
Tony Battersby
b57fbc8871 scsi: Revert "scsi: qla2xxx: Perform lockless command completion in abort path"
This reverts commit 0367076b08.

The commit being reverted added code to __qla2x00_abort_all_cmds() to
call sp->done() without holding a spinlock.  But unlike the older code
below it, this new code failed to check sp->cmd_type and just assumed
TYPE_SRB, which results in a jump to an invalid pointer in target-mode
with TYPE_TGT_CMD:

qla2xxx [0000:65:00.0]-d034:8: qla24xx_do_nack_work create sess success
  0000000009f7a79b
qla2xxx [0000:65:00.0]-5003:8: ISP System Error - mbx1=1ff5h mbx2=10h
  mbx3=0h mbx4=0h mbx5=191h mbx6=0h mbx7=0h.
qla2xxx [0000:65:00.0]-d01e:8: -> fwdump no buffer
qla2xxx [0000:65:00.0]-f03a:8: qla_target(0): System error async event
  0x8002 occurred
qla2xxx [0000:65:00.0]-00af:8: Performing ISP error recovery -
  ha=0000000058183fda.
BUG: kernel NULL pointer dereference, address: 0000000000000000
PF: supervisor instruction fetch in kernel mode
PF: error_code(0x0010) - not-present page
PGD 0 P4D 0
Oops: 0010 [#1] SMP
CPU: 2 PID: 9446 Comm: qla2xxx_8_dpc Tainted: G           O       6.1.133 #1
Hardware name: Supermicro Super Server/X11SPL-F, BIOS 4.2 12/15/2023
RIP: 0010:0x0
Code: Unable to access opcode bytes at 0xffffffffffffffd6.
RSP: 0018:ffffc90001f93dc8 EFLAGS: 00010206
RAX: 0000000000000282 RBX: 0000000000000355 RCX: ffff88810d16a000
RDX: ffff88810dbadaa8 RSI: 0000000000080000 RDI: ffff888169dc38c0
RBP: ffff888169dc38c0 R08: 0000000000000001 R09: 0000000000000045
R10: ffffffffa034bdf0 R11: 0000000000000000 R12: ffff88810800bb40
R13: 0000000000001aa8 R14: ffff888100136610 R15: ffff8881070f7400
FS:  0000000000000000(0000) GS:ffff88bf80080000(0000) knlGS:0000000000000000
CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: ffffffffffffffd6 CR3: 000000010c8ff006 CR4: 00000000003706e0
DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
Call Trace:
 <TASK>
 ? __die+0x4d/0x8b
 ? page_fault_oops+0x91/0x180
 ? trace_buffer_unlock_commit_regs+0x38/0x1a0
 ? exc_page_fault+0x391/0x5e0
 ? asm_exc_page_fault+0x22/0x30
 __qla2x00_abort_all_cmds+0xcb/0x3e0 [qla2xxx_scst]
 qla2x00_abort_all_cmds+0x50/0x70 [qla2xxx_scst]
 qla2x00_abort_isp_cleanup+0x3b7/0x4b0 [qla2xxx_scst]
 qla2x00_abort_isp+0xfd/0x860 [qla2xxx_scst]
 qla2x00_do_dpc+0x581/0xa40 [qla2xxx_scst]
 kthread+0xa8/0xd0
 </TASK>

Then commit 4475afa264 ("scsi: qla2xxx: Complete command early within
lock") added the spinlock back, because not having the lock caused a
race and a crash.  But qla2x00_abort_srb() in the switch below already
checks for qla2x00_chip_is_down() and handles it the same way, so the
code above the switch is now redundant and still buggy in target-mode.
Remove it.

Cc: stable@vger.kernel.org
Signed-off-by: Tony Battersby <tonyb@cybernetics.com>
Link: https://patch.msgid.link/3a8022dc-bcfd-4b01-9f9b-7a9ec61fa2a3@cybernetics.com
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-11-12 18:07:50 -05:00
Bart Van Assche
08b12cda6c scsi: ufs: core: Switch to scsi_get_internal_cmd()
Instead of storing the tag of the reserved command in hba->reserved_slot,
use scsi_get_internal_cmd() and scsi_put_internal_cmd() to allocate the
tag for the reserved command dynamically. Add
ufshcd_queue_reserved_command() for submitting reserved commands. Add
support in ufshcd_abort() for device management commands. Use
blk_execute_rq() for submitting reserved commands. Remove the code and
data structures that became superfluous. This includes
ufshcd_wait_for_dev_cmd(), hba->reserved_slot and ufs_dev_cmd.complete.

Signed-off-by: Bart Van Assche <bvanassche@acm.org>
Link: https://patch.msgid.link/20251031204029.2883185-29-bvanassche@acm.org
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-11-12 17:02:34 -05:00
Bart Van Assche
a11c015c8a scsi: ufs: core: Move code out of ufshcd_wait_for_dev_cmd()
The ufshcd_dev_cmd_completion() call is useful for some but not for all
ufshcd_wait_for_dev_cmd() callers. Hence, remove the
ufshcd_dev_cmd_completion() call from ufshcd_wait_for_dev_cmd() and move
it past the ufshcd_issue_dev_cmd() calls where appropriate. This makes
it easier to detect timeout errors for UPIU frames submitted through the
BSG interface.

Reviewed-by: Avri Altman <avri.altman@sandisk.com>
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
Link: https://patch.msgid.link/20251031204029.2883185-28-bvanassche@acm.org
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-11-12 17:02:34 -05:00
Bart Van Assche
4b6c0d9cca scsi: ufs: core: Make blk_mq_tagset_busy_iter() skip reserved requests
A later patch will convert hba->reserved_slot into a reserved tag. Make
blk_mq_tagset_busy_iter() skip reserved requests such that device
management commands are skipped.

Signed-off-by: Bart Van Assche <bvanassche@acm.org>
Link: https://patch.msgid.link/20251031204029.2883185-27-bvanassche@acm.org
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-11-12 17:02:34 -05:00
Bart Van Assche
9a2c950092 scsi: ufs: core: Remove the ufshcd_lrb task_tag member
Remove the ufshcd_lrb task_tag member and use scsi_cmd_to_rq(cmd)->tag
instead. Use rq->tag instead of lrbp->task_tag. This patch reduces the
size of struct ufshcd_lrb.

Signed-off-by: Bart Van Assche <bvanassche@acm.org>
Link: https://patch.msgid.link/20251031204029.2883185-26-bvanassche@acm.org
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-11-12 17:02:34 -05:00
Bart Van Assche
176b93004c scsi: ufs: core: Pass a SCSI pointer instead of an LRB pointer
Pass a pointer to a SCSI command between functions instead of an LRB
pointer. This change prepares for removing the ufshcd_lrb task_tag
member.

Signed-off-by: Bart Van Assche <bvanassche@acm.org>
Link: https://patch.msgid.link/20251031204029.2883185-25-bvanassche@acm.org
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-11-12 17:02:34 -05:00
Bart Van Assche
22089c2180 scsi: ufs: core: Optimize the hot path
Set .cmd_size in the SCSI host template such that the SCSI core makes
struct scsi_cmnd and struct ufshcd_lrb adjacent. Convert the cmd->lrbp
and lrbp->cmd memory loads into pointer offset calculations. Remove the
data structure members that became superfluous, namely ufshcd_lrb.cmd
and ufs_hba.lrb. Since ufshcd_lrb.cmd is removed, this pointer cannot be
used anymore to test whether or not a command is a SCSI command.
Introduce a new function for this purpose, namely ufshcd_is_scsi_cmd().

Signed-off-by: Bart Van Assche <bvanassche@acm.org>
Link: https://patch.msgid.link/20251031204029.2883185-24-bvanassche@acm.org
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-11-12 17:02:34 -05:00
Bart Van Assche
e5f9cc2af9 scsi: ufs: core: Do not clear driver-private command data
Tell the SCSI core to skip the memset() call that clears driver-private
data because __ufshcd_setup_cmd() performs all necessary initialization.

Signed-off-by: Bart Van Assche <bvanassche@acm.org>
Link: https://patch.msgid.link/20251031204029.2883185-23-bvanassche@acm.org
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-11-12 17:02:33 -05:00
Bart Van Assche
1d0af94ffb scsi: ufs: core: Make the reserved slot a reserved request
Instead of letting the SCSI core allocate hba->nutrs - 1 commands, let
the SCSI core allocate hba->nutrs commands, set the number of reserved
tags to 1 and use the reserved tag for device management commands. This
patch changes the 'reserved slot' from hba->nutrs - 1 into 0 because the
block layer reserves the smallest tags for reserved commands.

Signed-off-by: Bart Van Assche <bvanassche@acm.org>
Link: https://patch.msgid.link/20251031204029.2883185-22-bvanassche@acm.org
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-11-12 17:02:33 -05:00
Bart Van Assche
d3fd0fd776 scsi: ufs: core: Use hba->reserved_slot
Use hba->reserved_slot instead of open-coding it. This patch prepares
for changing the value of hba->reserved_slot.

Signed-off-by: Bart Van Assche <bvanassche@acm.org>
Link: https://patch.msgid.link/20251031204029.2883185-21-bvanassche@acm.org
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-11-12 17:02:33 -05:00
Bart Van Assche
45e636ea12 scsi: ufs: core: Call ufshcd_init_lrb() later
Call ufshcd_init_lrb() from inside ufshcd_setup_dev_cmd() instead of
ufshcd_host_memory_configure(). This patch prepares for calling
ufshcd_host_memory_configure() before the information is available that
is required to call ufshcd_setup_dev_cmd().

Reviewed-by: Avri Altman <avri.altman@sandisk.com>
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
Link: https://patch.msgid.link/20251031204029.2883185-20-bvanassche@acm.org
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-11-12 17:02:33 -05:00
Bart Van Assche
f46b9a595f scsi: ufs: core: Allocate the SCSI host earlier
Call ufshcd_add_scsi_host() before any UPIU commands are sent to the UFS
device. This patch prepares for letting ufshcd_add_scsi_host() allocate
memory for both SCSI and UPIU commands.

Signed-off-by: Bart Van Assche <bvanassche@acm.org>
Link: https://patch.msgid.link/20251031204029.2883185-19-bvanassche@acm.org
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-11-12 17:02:33 -05:00
Bart Van Assche
e8ea985a83 scsi: ufs: core: Rework the SCSI host queue depth calculation code
Prepare for allocating the SCSI host earlier by making the SCSI host
queue depth independent of the queue depth supported by the UFS device.
This patch may increase the queue depth of the UFS SCSI host.

Signed-off-by: Bart Van Assche <bvanassche@acm.org>
Link: https://patch.msgid.link/20251031204029.2883185-18-bvanassche@acm.org
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-11-12 17:02:33 -05:00
Bart Van Assche
f18fac1e2b scsi: ufs: core: Rework ufshcd_eh_device_reset_handler()
Merge the MCQ mode and legacy mode loops into a single loop. This patch
prepares for optimizing the hot path by removing the direct hba->lrb[]
accesses from ufshcd_eh_device_reset_handler().

Reviewed-by: Avri Altman <avri.altman@sandisk.com>
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
Link: https://patch.msgid.link/20251031204029.2883185-17-bvanassche@acm.org
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-11-12 17:02:32 -05:00
Bart Van Assche
63a5b959c8 scsi: ufs: core: Rework ufshcd_mcq_compl_pending_transfer()
Replace a tag loop with blk_mq_tagset_busy_iter(). This patch prepares
for removing the hba->lrb[] array.

Reviewed-by: Avri Altman <avri.altman@sandisk.com>
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
Link: https://patch.msgid.link/20251031204029.2883185-16-bvanassche@acm.org
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-11-12 17:02:32 -05:00
Bart Van Assche
f59568f4e2 scsi: ufs: core: Change the monitor function argument types
Pass a SCSI command pointer instead of a struct ufshcd_lrb pointer. This
patch prepares for combining the SCSI command and ufshcd_lrb data
structures into a single data structure.

Reviewed-by: Avri Altman <avri.altman@sandisk.com>
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
Link: https://patch.msgid.link/20251031204029.2883185-15-bvanassche@acm.org
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-11-12 17:02:32 -05:00
Bart Van Assche
ae7bf255b1 scsi: ufs: core: Only call ufshcd_should_inform_monitor() for SCSI commands
ufshcd_should_inform_monitor() only returns 'true' for SCSI commands.
Instead of checking inside ufshcd_should_inform_monitor() whether its
second argument represents a SCSI command, only call this function for
SCSI commands. This patch prepares for removing the lrbp->cmd member.

Reviewed-by: Peter Wang <peter.wang@mediatek.com>
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
Link: https://patch.msgid.link/20251031204029.2883185-14-bvanassche@acm.org
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-11-12 17:02:32 -05:00
Bart Van Assche
3e7fff3fee scsi: ufs: core: Change the type of one ufshcd_send_command() argument
Change the 'task_tag' argument into an LRB pointer. This patch prepares
for the removal of the hba->lrb[] array.

Reviewed-by: Avri Altman <avri.altman@sandisk.com>
Reviewed-by: Peter Wang <peter.wang@mediatek.com>
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
Link: https://patch.msgid.link/20251031204029.2883185-13-bvanassche@acm.org
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-11-12 17:02:32 -05:00
Bart Van Assche
ffa5d8c153 scsi: ufs: core: Change the type of one ufshcd_add_command_trace() argument
Change the 'tag' argument into a SCSI command pointer. This patch
prepares for the removal of the hba->lrb[] array.

Reviewed-by: Avri Altman <avri.altman@sandisk.com>
Reviewed-by: Peter Wang <peter.wang@mediatek.com>
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
Link: https://patch.msgid.link/20251031204029.2883185-12-bvanassche@acm.org
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-11-12 17:02:32 -05:00
Bart Van Assche
60a1f6a8ad scsi: ufs: core: Only call ufshcd_add_command_trace() for SCSI commands
Instead of checking inside ufshcd_add_command_trace() whether 'cmd'
points at a SCSI command, let the caller perform that check. This patch
prepares for removing the lrbp->cmd pointer.

Reviewed-by: Avri Altman <avri.altman@sandisk.com>
Reviewed-by: Peter Wang <peter.wang@mediatek.com>
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
Link: https://patch.msgid.link/20251031204029.2883185-11-bvanassche@acm.org
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-11-12 17:02:32 -05:00
Bart Van Assche
9f8e09230f scsi: ufs: core: Change the type of one ufshcd_add_cmd_upiu_trace() argument
Change the 'tag' argument into an LRB pointer. This patch prepares for the
removal of the hba->lrb[] array.

Reviewed-by: Avri Altman <avri.altman@sandisk.com>
Reviewed-by: Peter Wang <peter.wang@mediatek.com>
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
Link: https://patch.msgid.link/20251031204029.2883185-10-bvanassche@acm.org
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-11-12 17:02:31 -05:00
Bart Van Assche
dd4299af9b scsi: ufs: core: Move an assignment in ufshcd_mcq_process_cqe()
Since 'tag' is only used inside the if-statement, move the 'tag'
assignment into the if-statement. This patch prepares for introducing a
WARN_ON_ONCE() call in ufshcd_mcq_get_tag() if the tag lookup fails.

Reviewed-by: Avri Altman <avri.altman@sandisk.com>
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
Link: https://patch.msgid.link/20251031204029.2883185-9-bvanassche@acm.org
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-11-12 17:02:31 -05:00
Bart Van Assche
581ca49035 scsi: scsi_debug: Abort SCSI commands via an internal command
Add a .queue_reserved_command() implementation and call it from the code
path that aborts SCSI commands. This ensures that the code for
allocating a pseudo SCSI device and also the code for allocating and
processing reserved commands gets triggered while running blktests.

Most of the code in this patch is a modified version of code from John
Garry. See also
https://lore.kernel.org/linux-scsi/75018e17-4dea-4e1b-8c92-7a224a1e13b9@oracle.com/

Reviewed-by: John Garry <john.g.garry@oracle.com>
Suggested-by: John Garry <john.g.garry@oracle.com>
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
Link: https://patch.msgid.link/20251031204029.2883185-8-bvanassche@acm.org
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-11-12 17:02:31 -05:00
Hannes Reinecke
a2ab4e3328 scsi: core: Add scsi_{get,put}_internal_cmd() helpers
Add helper functions to allow LLDDs to allocate and free internal commands.

[ bvanassche: changed the 'nowait' argument into a 'flags' argument. See also
  https://lore.kernel.org/linux-scsi/20211125151048.103910-3-hare@suse.de/ ]

Reviewed-by: John Garry <john.g.garry@oracle.com>
Signed-off-by: Hannes Reinecke <hare@suse.de>
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
Link: https://patch.msgid.link/20251031204029.2883185-7-bvanassche@acm.org
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-11-12 17:02:31 -05:00
John Garry
11ea1de3fc scsi: core: Introduce .queue_reserved_command()
Reserved commands will be used by SCSI LLDs for submitting internal
commands. Since the SCSI host, target and device limits do not apply to
the reserved command use cases, bypass the SCSI host limit checks for
reserved commands. Introduce the .queue_reserved_command() callback for
reserved commands. Additionally, do not activate the SCSI error handler
if a reserved command fails such that reserved commands can be submitted
from inside the SCSI error handler.

[ bvanassche: modified patch title and patch description. Renamed
  .reserved_queuecommand() into .queue_reserved_command(). Changed
  the second argument of __blk_mq_end_request() from 0 into error
  code in the completion path if cmd->result != 0. Rewrote the
  scsi_queue_rq() changes. See also
  https://lore.kernel.org/linux-scsi/1666693096-180008-5-git-send-email-john.garry@huawei.com/ ]

Cc: Hannes Reinecke <hare@suse.de>
Signed-off-by: John Garry <john.garry@huawei.com>
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
Reviewed-by: Hannes Reinecke <hare@suse.de>
Link: https://patch.msgid.link/20251031204029.2883185-6-bvanassche@acm.org
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-11-12 17:02:31 -05:00
Hannes Reinecke
d630fbf6fc scsi: core: Support allocating a pseudo SCSI device
Allocate a pseudo SCSI device if 'nr_reserved_cmds' has been set. Pseudo
SCSI devices have the SCSI ID <max_id>:U64_MAX so they won't clash with
any devices the LLD might create. Pseudo SCSI devices are excluded from
scanning and will not show up in sysfs. Additionally, pseudo SCSI
devices are skipped by shost_for_each_device(). This prevents that the
SCSI error handler tries to submit a reset to a non-existent logical
unit.

Do not allocate a budget map for pseudo SCSI devices since the
cmd_per_lun limit does not apply to pseudo SCSI devices.

Do not perform queue depth ramp up / ramp down for pseudo SCSI devices.

Pseudo SCSI devices will be used to send internal commands to a storage
device.

[ bvanassche: edited patch description / renamed host_sdev into
  pseudo_sdev / unexported scsi_get_host_dev() / modified error path in
  scsi_get_pseudo_dev() / skip pseudo devices in __scsi_iterate_devices()
  and also when calling sdev_init(), sdev_configure() and sdev_destroy().
  See also
  https://lore.kernel.org/linux-scsi/20211125151048.103910-2-hare@suse.de/ ]

Reviewed-by: John Garry <john.g.garry@oracle.com>
Signed-off-by: Hannes Reinecke <hare@suse.de>
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
Link: https://patch.msgid.link/20251031204029.2883185-5-bvanassche@acm.org
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-11-12 17:02:31 -05:00
Bart Van Assche
a47c7bef57 scsi: core: Make the budget map optional
Prepare for not allocating a budget map for pseudo SCSI devices by
checking whether a budget map has been allocated before using it.

Reviewed-by: Hannes Reinecke <hare@suse.de>
Cc: John Garry <john.g.garry@oracle.com>
Cc: Ming Lei <ming.lei@redhat.com>
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
Link: https://patch.msgid.link/20251031204029.2883185-4-bvanassche@acm.org
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-11-12 17:02:31 -05:00
Bart Van Assche
21008cabc5 scsi: core: Move two statements
Move two statements that will be needed for pseudo SCSI devices in front
of code that won't be needed for pseudo SCSI devices. No functionality
has been changed.

Reviewed-by: John Garry <john.g.garry@oracle.com>
Reviewed-by: Hannes Reinecke <hare@suse.de>
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
Link: https://patch.msgid.link/20251031204029.2883185-3-bvanassche@acm.org
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-11-12 17:02:30 -05:00
Hannes Reinecke
d604e1ec24 scsi: core: Support allocating reserved commands
Quite some drivers are using management commands internally. These
commands typically use the same tag pool as regular SCSI commands. Tags
for these management commands are set aside before allocating the
block-mq tag bitmap for regular SCSI commands. The block layer already
supports this via the reserved tag mechanism. Add a new field
'nr_reserved_cmds' to the SCSI host template to instruct the block layer
to set aside a tag space for these management commands by using reserved
tags. Exclude reserved commands from .can_queue because .can_queue is
visible in sysfs.

[ bvanassche: modified patch title and patch description. Left out the
  following statements: "if (sht->nr_reserved_cmds)" and also
  "if (sdev->host->nr_reserved_cmds) flags |= BLK_MQ_REQ_RESERVED;". Moved
  nr_reserved_cmds declarations and statements close to the
  corresponding can_queue declarations and statements. See also
  https://lore.kernel.org/linux-scsi/20210503150333.130310-11-hare@suse.de/ ]

Signed-off-by: Hannes Reinecke <hare@suse.de>
Reviewed-by: John Garry <john.g.garry@oracle.com>
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
Link: https://patch.msgid.link/20251031204029.2883185-2-bvanassche@acm.org
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-11-12 17:02:30 -05:00
Danilo Krummrich
ededb7bcdf rust: dma: use NonNull<T> instead of *mut T
In struct CoherentAllocation, use NonNull<T> instead of a raw *mut T for
the CPU address; the CPU address of a valid CoherentAllocation won't
ever be NULL.

Reviewed-by: Alice Ryhl <aliceryhl@google.com>
Link: https://patch.msgid.link/20251103190655.2326191-2-dakr@kernel.org
Signed-off-by: Danilo Krummrich <dakr@kernel.org>
2025-11-11 19:45:23 +11:00
Danilo Krummrich
f7afdc4737 rust: dma: make use of start_ptr() and start_ptr_mut()
Using start_ptr() and start_ptr_mut() has the advantage that we inherit
the requirements the a mutable or immutable reference from those
methods.

Hence, use them instead of self.cpu_addr.

Reviewed-by: Alice Ryhl <aliceryhl@google.com>
Link: https://patch.msgid.link/20251103190655.2326191-1-dakr@kernel.org
[ Keep using self.cpu_addr in item_from_index(). - Danilo ]
Signed-off-by: Danilo Krummrich <dakr@kernel.org>
2025-11-11 19:45:23 +11:00
Danilo Krummrich
d8407396f1 rust: pci: use "kernel vertical" style for imports
Convert all imports in the PCI Rust module to use "kernel vertical"
style.

With this subsequent patches neither introduce unrelated changes nor
leave an inconsistent import pattern.

While at it, drop unnecessary imports covered by prelude::*.

Link: https://docs.kernel.org/rust/coding-guidelines.html#imports
Reviewed-by: Zhi Wang <zhiw@nvidia.com>
Link: https://patch.msgid.link/20251105120352.77603-1-dakr@kernel.org
Signed-off-by: Danilo Krummrich <dakr@kernel.org>
2025-11-11 19:45:23 +11:00
Danilo Krummrich
9d39842f6a rust: io: cleanup imports and use "kernel vertical" style
Commit 46f045db5a ("rust: Add read_poll_timeout_atomic function")
initiated the first import change in the I/O module using the agreed
"kernel vertical" import style [1].

For consistency throughout the module, adjust all other imports
accordingly.

While at it, drop unnecessary imports covered by prelude::*.

Link: https://docs.kernel.org/rust/coding-guidelines.html#imports [1]
Reviewed-by: Zhi Wang <zhiw@nvidia.com>
Link: https://patch.msgid.link/20251104133301.59402-1-dakr@kernel.org
[ Use prelude::* in io/poll.rs. - Danilo ]
Signed-off-by: Danilo Krummrich <dakr@kernel.org>
2025-11-11 19:43:39 +11:00
Bean Huo
b06b8c4214 scsi: ufs: core: Add OP-TEE based RPMB driver for UFS devices
Add OP-TEE based RPMB support for UFS devices. This enables secure RPMB
operations on UFS devices through OP-TEE, providing the same
functionality available for eMMC devices and extending kernel-based
secure storage support to UFS-based systems.

Benefits of OP-TEE based RPMB implementation:

 - Eliminates dependency on userspace supplicant for RPMB access

 - Enables early boot secure storage access (e.g., fTPM, secure UEFI
   variables)

 - Provides kernel-level RPMB access as soon as UFS driver is
   initialized

 - Removes complex initramfs dependencies and boot ordering requirements

 - Ensures reliable and deterministic secure storage operations

 - Supports both built-in and modular fTPM configurations

[mkp: make this build as a module]

Co-developed-by: Can Guo <can.guo@oss.qualcomm.com>
Signed-off-by: Can Guo <can.guo@oss.qualcomm.com>
Reviewed-by: Avri Altman <avri.altman@sandisk.com>
Reviewed-by: Bart Van Assche <bvanassche@acm.org>
Signed-off-by: Bean Huo <beanhuo@micron.com>
Link: https://patch.msgid.link/20251107230518.4060231-4-beanhuo@iokpp.de
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-11-10 12:49:43 -05:00
Bean Huo
d794b499f9 scsi: ufs: core: fix incorrect buffer duplication in ufshcd_read_string_desc()
The function ufshcd_read_string_desc() was duplicating memory starting
from the beginning of struct uc_string_id, which included the length and
type fields. As a result, the allocated buffer contained unwanted
metadata in addition to the string itself.

The correct behavior is to duplicate only the Unicode character array in
the structure. Update the code so that only the actual string content is
copied into the new buffer.

Fixes: 5f57704dbc ("scsi: ufs: Use kmemdup in ufshcd_read_string_desc()")
Reviewed-by: Avri Altman <avri.altman@sandisk.com>
Reviewed-by: Bart Van Assche <bvanassche@acm.org>
Signed-off-by: Bean Huo <beanhuo@micron.com>
Link: https://patch.msgid.link/20251107230518.4060231-3-beanhuo@iokpp.de
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-11-10 12:36:19 -05:00
Bean Huo
0d9a7085ec scsi: ufs: core: Convert string descriptor format macros to enum
Convert SD_ASCII_STD and SD_RAW from boolean macros to enum values for
improved code readability. This makes ufshcd_read_string_desc() calls
self-documenting by using explicit enum values instead of true/false.

Move the ufshcd_read_string_desc() declaration from include/ufs/ufshcd.h
to drivers/ufs/core/ufshcd-priv.h since this function is not exported.

Co-developed-by: Bart Van Assche <bvanassche@acm.org>
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
Suggested-by: Avri Altman <Avri.Altman@sandisk.com>
Signed-off-by: Bean Huo <beanhuo@micron.com>
Link: https://patch.msgid.link/20251107230518.4060231-2-beanhuo@iokpp.de
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-11-10 12:36:19 -05:00
Martin K. Petersen
c53a741a7f Merge patch series "Support power resources defined in acpi on ata"
Markus Probst <markus.probst@posteo.de> says:

This series adds support for power resources defined in acpi on ata
ports/devices. A device can define a power resource in an ata port/device,
which then gets powered on right before the port is probed. This can be
useful for devices, which have sata power connectors that are:
  a: powered down by default
  b: can be individually powered on
like in some synology nas devices. If thats the case it will be assumed,
that the power resource won't survive reboots and therefore the disk will
be stopped.

Link: https://patch.msgid.link/20251104142413.322347-1-markus.probst@posteo.de
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-11-08 13:26:28 -05:00
Markus Probst
8c59fc1c90 scsi: ata: Stop disk on restart if ACPI power resources are found
Some embedded devices have the ability to control whether power is
provided to the disks via the SATA power connector or not. ACPI power
resources are usually off by default, thus making it unclear if the
specific power resource will retain its state after a restart. If power
resources are defined on ATA ports / devices in ACPI, we should stop the
disk on SYSTEM_RESTART, to ensure the disk will not lose power while
active.

Add a new function, ata_acpi_dev_manage_restart(), that will be used to
determine if a disk should be stopped before restarting the system. If a
usable ACPI power resource has been found, it is assumed that the disk
will lose power after a restart and should be stopped to avoid unclean
shutdown due to power loss.

Reviewed-by: Damien Le Moal <dlemoal@kernel.org>
Signed-off-by: Markus Probst <markus.probst@posteo.de>
Link: https://patch.msgid.link/20251104142413.322347-4-markus.probst@posteo.de
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-11-08 13:24:56 -05:00
Markus Probst
ce6d26b533 scsi: ata: Use ACPI methods to power on disks
Some embedded devices have the ability to control whether power is
provided to the disks via the SATA power connector or not. If power
resources are defined on ATA ports / devices in ACPI, we should try to
set the power state to D0 before probing the disk to ensure that any
power supply or power gate that may exist is providing power to the
disk.

An example for such devices would be newer synology NAS devices. Every
disk slot has its own SATA power connector. Whether the connector is
providing power is controlled via an gpio, which is *off by default*.
Also the disk loses power on reboots.

Add a new function, ata_acpi_port_power_on(), that will be used to power
on the SATA power connector if usable ACPI power resources on the
associated ATA port / device are found. It will be called right before
probing the port, therefore the disk will be powered on just in time.

Signed-off-by: Markus Probst <markus.probst@posteo.de>
Reviewed-by: Damien Le Moal <dlemoal@kernel.org>
Link: https://patch.msgid.link/20251104142413.322347-3-markus.probst@posteo.de
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-11-08 13:24:55 -05:00
Markus Probst
8fdfdb1488 scsi: sd: Add manage_restart device attribute to scsi_disk
In addition to the already existing manage_shutdown,
manage_system_start_stop and manage_runtime_start_stop device scsi_disk
attributes, add manage_restart, which allows the high-level device
driver (sd) to manage the device power state for SYSTEM_RESTART if set
to 1.

This attribute is necessary for the following commit "ata: stop disk on
restart if ACPI power resources are found" to avoid a potential disk
power failure in the case the SATA power connector does not retain the
power state after a restart.

Reviewed-by: Damien Le Moal <dlemoal@kernel.org>
Signed-off-by: Markus Probst <markus.probst@posteo.de>
Link: https://patch.msgid.link/20251104142413.322347-2-markus.probst@posteo.de
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-11-08 13:24:55 -05:00
Martin K. Petersen
5b5dedf007 Merge patch series "Update lpfc to revision 14.4.0.12"
Justin Tee <justin.tee@broadcom.com> says:

Update lpfc to revision 14.4.0.12

This patch set contains updates to log messaging, revision of outdated
comment descriptions, fixes to kref accounting, support for BB credit
recovery in point-to-point mode, and introduction of registering unique
platform name identifiers with fabrics.

The patches were cut against Martin's 6.19/scsi-queue tree.

Link: https://patch.msgid.link/20251106224639.139176-1-justintee8345@gmail.com
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-11-08 13:19:17 -05:00
Justin Tee
d45fdc6cdd scsi: lpfc: Update lpfc version to 14.4.0.12
Update lpfc version to 14.4.0.12

Signed-off-by: Justin Tee <justin.tee@broadcom.com>
Link: https://patch.msgid.link/20251106224639.139176-11-justintee8345@gmail.com
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-11-08 13:18:01 -05:00
Justin Tee
191da2c71b scsi: lpfc: Add capability to register Platform Name ID to fabric
FC-LS and FC-GS specifications outline fields for registering a platform
name identifier (PNI) to the fabric.  The PNI assists fabrics with
identifying the physical server source of frames in the fabric.

lpfc generates a PNI based partially on the uuid specific for the
system.  Initial attempts to extract a uuid are made from SMBIOS's
System Information 08h uuid entry.  If SMBIOS DMI does not exist, a PNI
is not generated and PNI registration with the fabric is skipped.

The PNI is submitted in FLOGI and FDISC frames.  After successful fabric
login, the RSPNI_PNI CT frame is submitted to the fabric to register the
OS host name tying it to the PNI.

Signed-off-by: Justin Tee <justin.tee@broadcom.com>
Link: https://patch.msgid.link/20251106224639.139176-10-justintee8345@gmail.com
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-11-08 13:18:01 -05:00
Justin Tee
683df5fc3e scsi: lpfc: Allow support for BB credit recovery in point-to-point topology
Currently, BB credit recovery is excluded to fabric topology mode.  This
patch allows setting of BB_SC_N in PLOGIs and PLOGI_ACCs when in
point-to-point mode so that BB credit recovery can operate in
point-to-point topology as well.

Signed-off-by: Justin Tee <justin.tee@broadcom.com>
Link: https://patch.msgid.link/20251106224639.139176-9-justintee8345@gmail.com
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-11-08 13:18:00 -05:00
Justin Tee
07caedc6a3 scsi: lpfc: Fix reusing an ndlp that is marked NLP_DROPPED during FLOGI
It's possible for an unstable link to repeatedly bounce allowing a FLOGI
retry, but then bounce again forcing an abort of the FLOGI.  Ensure that
the initial reference count on the FLOGI ndlp is restored in this faulty
link scenario.

Signed-off-by: Justin Tee <justin.tee@broadcom.com>
Link: https://patch.msgid.link/20251106224639.139176-8-justintee8345@gmail.com
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-11-08 13:18:00 -05:00
Justin Tee
0b8b15a0b7 scsi: lpfc: Modify kref handling for Fabric Controller ndlps
Currently, there is a kref put in the lpfc_cleanup() routine that takes
care of outstanding references on fabric controller ndlps in UNUSED
state.  While typically there is a state change from UNUSED -> REGLOGIN
when the ndlp successfully logs into the fabric, there may be cases when
FLOGI is unsuccessful and the ndlp will remain in UNUSED state without a
registered rpi, yet the ndlp incorrectly has a kref count of one.

To address this, handling of Fabric Controller ndlps are moved into the
routines: lpfc_issue_els_scr(), lpfc_issue_els_rdf(),
lpfc_cmpl_els_disc_cmd().

In both lpfc_issue_els_scr() and lpfc_issue_els_rdf(), if there does not
exist a previously created fabric controller ndlp, an ndlp will be
created.  Otherwise, we can reuse the pre-existing ndlp object.

In lpfc_cmpl_els_disc_cmd(), if the SCR or RDF are not successfully
issued, the initial reference on the ndlp that is not registered with
upper layers will be decremented with a kref_put().

Signed-off-by: Justin Tee <justin.tee@broadcom.com>
Link: https://patch.msgid.link/20251106224639.139176-7-justintee8345@gmail.com
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-11-08 13:18:00 -05:00
Justin Tee
23f4906729 scsi: lpfc: Fix leaked ndlp krefs when in point-to-point topology
In point-to-point topology, the driver sometimes defers the unsolicited
FLOGI LS_ACC until it sends its FLOGI to the remote port.  When this
happens, lpfc neglects to release the ndlp allocated for the unsolicited
FLOGI.  This patch adds code to release the ndlp for the deferred
unsolicited FLOGI LS_ACC.

An NLP_FLOGI_DFR_ACC flag is introduced to facilitate identifying an
ndlp with an expected deferred FLOGI LS_ACC completion.  When
lpfc_cmpl_els_rsp() detects the correct qualifiers, it releases the
initial reference on the ndlp object.  And when lpfc_cmpl_els_rsp()
exits, the remaining put for the deferred action is executed and the
ndlp is released.

Signed-off-by: Justin Tee <justin.tee@broadcom.com>
Link: https://patch.msgid.link/20251106224639.139176-6-justintee8345@gmail.com
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-11-08 13:18:00 -05:00
Justin Tee
6f81582b7a scsi: lpfc: Ensure unregistration of rpis for received PLOGIs
Unregistration of an rpi object should be done when a PLOGI is received
as PLOGI receipt implies an implicit LOGO.  Previously, the driver would
continue using the same, already registered, rpi and ACC the received
PLOGI.

Replace the ACC and early return statement with break to execute the
rest of the lpfc_rcv_plogi logic outside the switch case statement.
This ensures unregistration and reregistration of an rpi after PLOGI_ACC
completion.

Signed-off-by: Justin Tee <justin.tee@broadcom.com>
Link: https://patch.msgid.link/20251106224639.139176-5-justintee8345@gmail.com
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-11-08 13:18:00 -05:00
Justin Tee
3c228061c8 scsi: lpfc: Remove redundant NULL ptr assignment in lpfc_els_free_iocb()
Remove redundant cmd_dmabuf and bpl_dmabuf NULL ptr assignment as they
are already initialized to NULL when handling a new unsolicited event.

Signed-off-by: Justin Tee <justin.tee@broadcom.com>
Link: https://patch.msgid.link/20251106224639.139176-4-justintee8345@gmail.com
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-11-08 13:18:00 -05:00
Justin Tee
f7a302e475 scsi: lpfc: Revise discovery related function headers and comments
Correcting discovery related function headers, return status
information, and comment descriptions.  There are no functional changes.

Signed-off-by: Justin Tee <justin.tee@broadcom.com>
Link: https://patch.msgid.link/20251106224639.139176-3-justintee8345@gmail.com
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-11-08 13:18:00 -05:00
Justin Tee
051d4b65e8 scsi: lpfc: Update various NPIV diagnostic log messaging
Update PRLI status log message to automatically warn when CQE status is
non-zero.

When issuing an RSCN, log ndlp's kref count to the debugfs trace buffer.

Add the NPIV virtual port index to the FDMI registration log message
with the fabric.

Signed-off-by: Justin Tee <justin.tee@broadcom.com>
Link: https://patch.msgid.link/20251106224639.139176-2-justintee8345@gmail.com
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-11-08 13:17:59 -05:00
Martin K. Petersen
e15710242e Merge patch series "smartpqi updates"
Don Brace <don.brace@microchip.com> says:

These patches are based on Martin Petersen's 6.19/scsi-queue tree
  https://git.kernel.org/pub/scm/linux/kernel/git/mkp/scsi.git
  6.19/scsi-queue

This patch series includes four patches, with two main functional changes:

1. smartpqi-Add-timeout-value-to-RAID-path-requests-to-physical-devices

   Sets a timeout value for requests sent to physical devices via the
   RAID path. This prevents the controller firmware from waiting
   indefinitely and allows it to time out requests a few seconds before
   the OS issues Target Management Function (TMF) commands.

   The timeout value sent to the firmware is set to 3 seconds less than
   the OS timeout, which significantly reduces TMF invocations.

2. smartpqi-fix-Device-resources-accessed-after-device-removal
   Fixes a race condition during device removal by:
     * Checking for device removal in the reset handler and canceling any
       pending reset work if the device is no longer present.
     * Canceling outstanding TMF work items in the .sdev_destroy handler.

   Together, these changes eliminate races between reset operations
   and device removal.

The other two patches:
3. smartpqi-add-new-Hurray-Data-pci-device
   Adds support for new Hurray Data PCI device.
   No functional changes.
4. smartpqi-update-driver-version-to-2.1.36-026
   Updates the driver version string.
   No functional changes.

Link: https://patch.msgid.link/20251106163823.786828-1-don.brace@microchip.com
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-11-08 13:09:49 -05:00
Don Brace
4cec99e83d scsi: smartpqi: Update version to 2.1.36-026
Update driver version to 2.1.36-026

Reviewed-by: Scott Benesh <scott.benesh@microchip.com>
Reviewed-by: Scott Teel <scott.teel@microchip.com>
Reviewed-by: Gerry Morong <gerry.morong@microchip.com>
Signed-off-by: Don Brace <don.brace@microchip.com>
Link: https://patch.msgid.link/20251106163823.786828-5-don.brace@microchip.com
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-11-08 13:08:31 -05:00
David Strahan
48e6b7e708 scsi: smartpqi: Add support for Hurray Data new controller PCI device
Add support for new Hurray Data controller.

All entries are in HEX.

Add PCI IDs for Hurray Data controllers:
                                         VID  / DID  / SVID / SDID
                                         ----   ----   ----   ----
                                         9005   028f   207d   4840

Reviewed-by: Scott Benesh <scott.benesh@microchip.com>
Reviewed-by: Scott Teel <scott.teel@microchip.com>
Reviewed-by: Mike McGowen <mike.mcgowen@microchip.com>
Signed-off-by: David Strahan <David.Strahan@microchip.com>
Signed-off-by: Don Brace <don.brace@microchip.com>
Link: https://patch.msgid.link/20251106163823.786828-4-don.brace@microchip.com
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-11-08 13:08:31 -05:00
Mike McGowen
b518e86d1a scsi: smartpqi: Fix device resources accessed after device removal
Correct possible race conditions during device removal.

Previously, a scheduled work item to reset a LUN could still execute
after the device was removed, leading to use-after-free and other
resource access issues.

This race condition occurs because the abort handler may schedule a LUN
reset concurrently with device removal via sdev_destroy(), leading to
use-after-free and improper access to freed resources.

  - Check in the device reset handler if the device is still present in
    the controller's SCSI device list before running; if not, the reset
    is skipped.

  - Cancel any pending TMF work that has not started in sdev_destroy().

  - Ensure device freeing in sdev_destroy() is done while holding the
    LUN reset mutex to avoid races with ongoing resets.

Fixes: 2d80f4054f ("scsi: smartpqi: Update deleting a LUN via sysfs")
Reviewed-by: Scott Teel <scott.teel@microchip.com>
Reviewed-by: Scott Benesh <scott.benesh@microchip.com>
Signed-off-by: Mike McGowen <mike.mcgowen@microchip.com>
Signed-off-by: Don Brace <don.brace@microchip.com>
Link: https://patch.msgid.link/20251106163823.786828-3-don.brace@microchip.com
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-11-08 13:08:31 -05:00
Mike McGowen
f3ecbba1aa scsi: smartpqi: Add timeout value to RAID path requests to physical devices
Add a timeout value to requests sent to physical devices via the RAID
path.

A timeout value of zero means wait indefinitely, which may cause the OS
to issue Target Management Function (TMF) commands if the device does
not respond.

For input timeouts of 8 seconds or greater, the value sent to firmware
is reduced by 3 seconds to provide an earlier firmware timeout and allow
the OS additional time before timing out.

This change improves timeout handling between the driver, firmware, and
OS, helping to better manage device responsiveness and avoid indefinite
waits.

Reviewed-by: David Strahan <david.strahan@microchip.com>
Reviewed-by: Scott Benesh <scott.benesh@microchip.com>
Reviewed-by: Scott Teel <scott.teel@microchip.com>
Signed-off-by: Mike McGowen <Mike.McGowen@microchip.com>
Signed-off-by: Don Brace <don.brace@microchip.com>
Link: https://patch.msgid.link/20251106163823.786828-2-don.brace@microchip.com
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-11-08 13:08:31 -05:00
Thomas Richard (TI.com)
02880c083c scsi: ufs: ti-j721e: Add suspend-resume support
Restore the ctrl register to resume the TI UFS wrapper.

Signed-off-by: Thomas Richard (TI.com) <thomas.richard@bootlin.com>
Link: https://patch.msgid.link/20251106-scsi-ufs-ti-j721e-suspend-resume-support-v1-1-6f395f51219e@bootlin.com
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-11-08 12:58:07 -05:00
Marco Crivellari
57565f97b0 scsi: fcoe: Add WQ_PERCPU to alloc_workqueue() users
Currently if a user enqueues a work item using schedule_delayed_work()
the used wq is "system_wq" (per-cpu wq) while queue_delayed_work() uses
WORK_CPU_UNBOUND (used when a CPU is not specified). The same applies to
schedule_work() that is using system_wq and queue_work(), that makes use
again of WORK_CPU_UNBOUND.  This lack of consistentcy cannot be
addressed without refactoring the API.

alloc_workqueue() treats all queues as per-CPU by default, while unbound
workqueues must opt-in via WQ_UNBOUND.

This default is suboptimal: most workloads benefit from unbound queues,
allowing the scheduler to place worker threads where they’re needed and
reducing noise when CPUs are isolated.

Continue the effort to refactor workqueue APIs, which has begun with the
change introducing new workqueues and a new alloc_workqueue flag:

commit 128ea9f6cc ("workqueue: Add system_percpu_wq and system_dfl_wq")
commit 930c2ea566 ("workqueue: Add new WQ_PERCPU flag")

Adds a new WQ_PERCPU flag to explicitly request alloc_workqueue() to be
per-CPU when WQ_UNBOUND has not been specified.

With the introduction of the WQ_PERCPU flag (equivalent to !WQ_UNBOUND),
any alloc_workqueue() caller that doesn’t explicitly specify WQ_UNBOUND
must now use WQ_PERCPU.

Once migration is complete, WQ_UNBOUND can be removed and unbound will
become the implicit default.

Suggested-by: Tejun Heo <tj@kernel.org>
Signed-off-by: Marco Crivellari <marco.crivellari@suse.com>
Reviewed-by: Hannes Reinecke <hare@suse.de>
Link: https://patch.msgid.link/20251105150336.244079-1-marco.crivellari@suse.com
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-11-08 12:28:11 -05:00
David Jeffery
d27418aaf8 scsi: st: Skip buffer flush for information ioctls
With commit 9604eea5bd ("scsi: st: Add third party poweron reset
handling") some customer tape applications fail from being unable to
complete ioctls to verify ID information for the device when there has
been any type of reset event to their tape devices.

The st driver currently will fail all standard SCSI ioctls if a call to
flush_buffer() fails in st_ioctl(). This causes ioctls which otherwise
have no effect on tape state to succeed or fail based on events
unrelated to the requested ioctl.

This makes SCSI information ioctls unreliable after a reset even if no
buffering is in use. With a reset setting the pos_unknown field,
flush_buffer() will report failure and fail all ioctls. So any
application expecting to use ioctls to check the identify the device
will be unable to do so in such a state.

For SCSI information ioctls, avoid the need for a buffer flush and allow
the ioctls to execute regardless of buffer state.

Signed-off-by: David Jeffery <djeffery@redhat.com>
Tested-by: Laurence Oberman <loberman@redhat.com>
Acked-by: Kai Mäkisara <kai.makisara@kolumbus.fi>
Reviewed-by: John Meneghini <jmeneghi@redhat.com>
Tested-by: John Meneghini <jmeneghi@redhat.com>
Link: https://patch.msgid.link/20251104154709.6436-2-djeffery@redhat.com
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-11-08 12:21:10 -05:00
David Jeffery
b37d70c0df scsi: st: Separate st-unique ioctl handling from SCSI common ioctl handling
The st ioctl function currently interleaves code for handling various st
specific ioctls with parts of code needed for handling ioctls common to
all SCSI devices. Separate out st's code for the common ioctls into a
more manageable, separate function.

Signed-off-by: David Jeffery <djeffery@redhat.com>
Tested-by: Laurence Oberman <loberman@redhat.com>
Acked-by: Kai Mäkisara <kai.makisara@kolumbus.fi>
Reviewed-by: John Meneghini <jmeneghi@redhat.com>
Tested-by: John Meneghini <jmeneghi@redhat.com>
Link: https://patch.msgid.link/20251104154709.6436-1-djeffery@redhat.com
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-11-08 12:21:10 -05:00
Peter Wang
ad4716ad48 scsi: dt-bindings: phy: mediatek,ufs-phy: Update maintainer information in mediatek,ufs-phy.yaml
Replace Stanley Chu with me and Chaotian in the maintainers field, since
his email address is no longer active.

Signed-off-by: Peter Wang <peter.wang@mediatek.com>
Acked-by: Conor Dooley <conor.dooley@microchip.com>
Link: https://patch.msgid.link/20251103115808.3771214-1-peter.wang@mediatek.com
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-11-08 12:14:53 -05:00
Haotian Zhang
20da637eb5 scsi: stex: Fix reboot_notifier leak in probe error path
In stex_probe(), register_reboot_notifier() is called at the beginning,
but if any subsequent initialization step fails, the function returns
without unregistering the notifier, resulting in a resource leak.

Add unregister_reboot_notifier() in the out_disable error path to ensure
proper cleanup on all failure paths.

Fixes: 61b745fa63 ("scsi: stex: Add S6 support")
Signed-off-by: Haotian Zhang <vulab@iscas.ac.cn>
Link: https://patch.msgid.link/20251104094847.270-1-vulab@iscas.ac.cn
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-11-08 12:11:06 -05:00
Danilo Krummrich
0bc605713f rust: debugfs: Implement BinaryReader for Mutex<T> only when T is Unpin
Commit da123f0ee4 ("rust: lock: guard: Add T: Unpin bound to
DerefMut") from tip/master adds an Unpin bound to T for Mutex<T>, hence
also restrict the implementation of BinaryReader for Mutex<T>
accordingly.

Reported-by: Stephen Rothwell <sfr@canb.auug.org.au>
Closes: https://lore.kernel.org/all/20251107134144.117905bd@canb.auug.org.au/
Reviewed-by: Alice Ryhl <aliceryhl@google.com>
Link: https://patch.msgid.link/20251107091612.2557480-1-dakr@kernel.org
Signed-off-by: Danilo Krummrich <dakr@kernel.org>
2025-11-07 22:53:11 +01:00
Danilo Krummrich
b892ed360d rust: platform: get rid of redundant Result in IRQ methods
Currently request_irq_by_index() returns

        Result<impl PinInit<irq::Registration<T>, Error> + 'a>

which may carry an error in the Result or the initializer; the same is
true for the other IRQ methods.

Use pin_init::pin_init_scope() to get rid of this redundancy.

Reviewed-by: Alice Ryhl <aliceryhl@google.com>
Link: https://patch.msgid.link/20251103203053.2348783-2-dakr@kernel.org
Signed-off-by: Danilo Krummrich <dakr@kernel.org>
2025-11-06 10:19:36 +01:00
Danilo Krummrich
1f7b01661f rust: pci: get rid of redundant Result in IRQ methods
Currently request_irq() returns

	Result<impl PinInit<irq::Registration<T>, Error> + 'a>

which may carry an error in the Result or the initializer; the same is
true for request_threaded_irq().

Use pin_init::pin_init_scope() to get rid of this redundancy.

Reviewed-by: Alice Ryhl <aliceryhl@google.com>
Link: https://patch.msgid.link/20251103203053.2348783-1-dakr@kernel.org
Signed-off-by: Danilo Krummrich <dakr@kernel.org>
2025-11-06 10:19:36 +01:00
Danilo Krummrich
1bf5b90cd2 rust: auxiliary: fix false positive warning for missing a safety comment
Some older (yet supported) versions of clippy throw a false positive
warning for missing a safety comment when the safety comment is on a
multiline statement.

warning: unsafe block missing a safety comment
   --> rust/kernel/auxiliary.rs:351:22
    |
351 |                 Self(unsafe { NonNull::new_unchecked(adev) }),
    |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = help: consider adding a safety comment on the preceding line
    = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#undocumented_unsafe_blocks
    = note: requested on the command line with `-W clippy::undocumented-unsafe-blocks`

warning: 1 warning emitted

Fix this by placing the safety comment right on top of the same line
introducing the unsafe block.

Fixes: e4e679c860 ("rust: auxiliary: unregister on parent device unbind")
Reviewed-by: Alice Ryhl <aliceryhl@google.com>
Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Link: https://patch.msgid.link/20251103203932.2361660-1-dakr@kernel.org
Signed-off-by: Danilo Krummrich <dakr@kernel.org>
2025-11-05 01:26:51 +01:00
Danilo Krummrich
f656279afd samples: rust: debugfs_scoped: add example for blobs
Extend the rust_debugfs_scoped sample to demonstrate how to export a
large binary object through a ScopedDir.

Reviewed-by: Alice Ryhl <aliceryhl@google.com>
Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Reviewed-by: Matthew Maurer <mmaurer@google.com>
Signed-off-by: Danilo Krummrich <dakr@kernel.org>
2025-11-05 00:35:40 +01:00
Danilo Krummrich
35bd14d929 rust: debugfs: support binary large objects for ScopedDir
Add support for creating binary debugfs files via ScopedDir. This
mirrors the existing functionality for Dir, but without producing an
owning handle -- files are automatically removed when the associated
Scope is dropped.

Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Reviewed-by: Matthew Maurer <mmaurer@google.com>
Reviewed-by: Alice Ryhl <aliceryhl@google.com>
Signed-off-by: Danilo Krummrich <dakr@kernel.org>
2025-11-05 00:35:40 +01:00
Danilo Krummrich
52af0c3796 samples: rust: debugfs: add example for blobs
Extend the Rust debugfs sample to demonstrate usage of binary file
support. The example now shows how to expose both fixed-size arrays
and dynamically sized vectors as binary blobs in debugfs.

Reviewed-by: Alice Ryhl <aliceryhl@google.com>
Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Reviewed-by: Matthew Maurer <mmaurer@google.com>
Signed-off-by: Danilo Krummrich <dakr@kernel.org>
2025-11-05 00:35:40 +01:00
Danilo Krummrich
a9fca8a7b2 rust: debugfs: support blobs from smart pointers
Extend Rust debugfs binary support to allow exposing data stored in
common smart pointers and heap-allocated collections.

- Implement BinaryWriter for Box<T>, Pin<Box<T>>, Arc<T>, and Vec<T>.
- Introduce BinaryReaderMut for mutable binary access with outer locks.
- Implement BinaryReaderMut for Box<T>, Vec<T>, and base types.
- Update BinaryReader to delegate to BinaryReaderMut for Mutex<T>,
  Box<T>, Pin<Box<T>> and Arc<T>.

This enables debugfs files to directly expose or update data stored
inside heap-allocated, reference-counted, or lock-protected containers
without manual dereferencing or locking.

Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Reviewed-by: Matthew Maurer <mmaurer@google.com>
Reviewed-by: Alice Ryhl <aliceryhl@google.com>
Signed-off-by: Danilo Krummrich <dakr@kernel.org>
2025-11-05 00:35:40 +01:00
Danilo Krummrich
9c804d9cf2 rust: debugfs: support for binary large objects
Introduce support for read-only, write-only, and read-write binary files
in Rust debugfs. This adds:

- BinaryWriter and BinaryReader traits for writing to and reading from
  user slices in binary form.
- New Dir methods: read_binary_file(), write_binary_file(),
  `read_write_binary_file`.
- Corresponding FileOps implementations: BinaryReadFile,
  BinaryWriteFile, BinaryReadWriteFile.

This allows kernel modules to expose arbitrary binary data through
debugfs, with proper support for offsets and partial reads/writes.

Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Reviewed-by: Matthew Maurer <mmaurer@google.com>
Reviewed-by: Alice Ryhl <aliceryhl@google.com>
Signed-off-by: Danilo Krummrich <dakr@kernel.org>
2025-11-05 00:35:40 +01:00
Danilo Krummrich
0ddceba270 rust: uaccess: add UserSliceWriter::write_slice_file()
Add UserSliceWriter::write_slice_file(), which is the same as
UserSliceWriter::write_slice_partial() but updates the given
file::Offset by the number of bytes written.

This is equivalent to C's `simple_read_from_buffer()` and useful when
dealing with file offsets from file operations.

Reviewed-by: Alice Ryhl <aliceryhl@google.com>
Acked-by: Miguel Ojeda <ojeda@kernel.org>
[ Replace saturating_add() with the raw operator and a corresponding
  OVERFLOW comment. - Danilo ]
Signed-off-by: Danilo Krummrich <dakr@kernel.org>
2025-11-05 00:35:37 +01:00
Danilo Krummrich
8615053347 rust: uaccess: add UserSliceWriter::write_slice_partial()
The existing write_slice() method is a wrapper around copy_to_user() and
expects the user buffer to be larger than the source buffer.

However, userspace may split up reads in multiple partial operations
providing an offset into the source buffer and a smaller user buffer.

In order to support this common case, provide a helper for partial
writes.

Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Reviewed-by: Matthew Maurer <mmaurer@google.com>
Reviewed-by: Alice Ryhl <aliceryhl@google.com>
Reviewed-by: Alexandre Courbot <acourbot@nvidia.com>
Acked-by: Miguel Ojeda <ojeda@kernel.org>
[ Replace map_or() with let-else; use saturating_add(). - Danilo ]
Signed-off-by: Danilo Krummrich <dakr@kernel.org>
2025-11-05 00:35:27 +01:00
Danilo Krummrich
5829e33048 rust: uaccess: add UserSliceReader::read_slice_file()
Add UserSliceReader::read_slice_file(), which is the same as
UserSliceReader::read_slice_partial() but updates the given file::Offset
by the number of bytes read.

This is equivalent to C's `simple_write_to_buffer()` and useful when
dealing with file offsets from file operations.

Reviewed-by: Alice Ryhl <aliceryhl@google.com>
Reviewed-by: Alexandre Courbot <acourbot@nvidia.com>
Acked-by: Miguel Ojeda <ojeda@kernel.org>
[ Replace saturating_add() with the raw operator and a corresponding
  OVERFLOW comment. - Danilo ]
Signed-off-by: Danilo Krummrich <dakr@kernel.org>
2025-11-05 00:35:25 +01:00
Danilo Krummrich
f2af7b01b0 rust: uaccess: add UserSliceReader::read_slice_partial()
The existing read_slice() method is a wrapper around copy_from_user()
and expects the user buffer to be larger than the destination buffer.

However, userspace may split up writes in multiple partial operations
providing an offset into the destination buffer and a smaller user
buffer.

In order to support this common case, provide a helper for partial
reads.

Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Reviewed-by: Matthew Maurer <mmaurer@google.com>
Reviewed-by: Alice Ryhl <aliceryhl@google.com>
Reviewed-by: Alexandre Courbot <acourbot@nvidia.com>
Acked-by: Miguel Ojeda <ojeda@kernel.org>
[ Replace map_or() with let-else; use saturating_add(). - Danilo ]
Signed-off-by: Danilo Krummrich <dakr@kernel.org>
2025-11-05 00:35:20 +01:00
Danilo Krummrich
db7bd1affa rust: fs: add file::Offset type alias
Add a type alias for file offsets, i.e. bindings::loff_t. Trying to
avoid using raw bindings types, this seems to be the better alternative
compared to just using i64.

Cc: Alexander Viro <viro@zeniv.linux.org.uk>
Cc: Christian Brauner <brauner@kernel.org>
Cc: Jan Kara <jack@suse.cz>
Reviewed-by: Alice Ryhl <aliceryhl@google.com>
Reviewed-by: Christian Brauner <brauner@kernel.org>
Link: https://patch.msgid.link/20251020222722.240473-2-dakr@kernel.org
Signed-off-by: Danilo Krummrich <dakr@kernel.org>
2025-11-05 00:05:38 +01:00
FUJITA Tomonori
46f045db5a rust: Add read_poll_timeout_atomic function
Add read_poll_timeout_atomic function which polls periodically until a
condition is met, an error occurs, or the attempt limit is reached.

The C's read_poll_timeout_atomic() is used for the similar purpose.
In atomic context the timekeeping infrastructure is unavailable, so
reliable time-based timeouts cannot be implemented. So instead, the
helper accepts a maximum number of attempts and busy-waits (udelay +
cpu_relax) between tries.

Reviewed-by: Alice Ryhl <aliceryhl@google.com>
Signed-off-by: FUJITA Tomonori <fujita.tomonori@gmail.com>
Link: https://patch.msgid.link/20251103112958.2961517-3-fujita.tomonori@gmail.com
[ Adjust imports to use "kernel vertical" style. - Danilo ]
Signed-off-by: Danilo Krummrich <dakr@kernel.org>
2025-11-04 14:06:47 +01:00
FUJITA Tomonori
ad68b55a9e rust: add udelay() function
Add udelay() function, inserts a delay based on microseconds with busy
waiting, in preparation for supporting read_poll_timeout_atomic().

Reviewed-by: Andreas Hindborg <a.hindborg@kernel.org>
Reviewed-by: Alice Ryhl <aliceryhl@google.com>
Signed-off-by: FUJITA Tomonori <fujita.tomonori@gmail.com>
Acked-by: Andreas Hindborg <a.hindborg@kernel.org>
Link: https://patch.msgid.link/20251103112958.2961517-2-fujita.tomonori@gmail.com
Signed-off-by: Danilo Krummrich <dakr@kernel.org>
2025-11-04 13:25:29 +01:00
Danilo Krummrich
fde40a558d rust: usb: fix broken call to T::disconnect()
A refactoring of Device::drvdata_obtain() broke T::disconnect() in the
USB abstractions.

"""
error[E0599]: no method named `data` found for struct `core::pin::Pin<kbox::Box<T, Kmalloc>>` in the current scope
  --> rust/kernel/usb.rs:92:34
   |
92 |         T::disconnect(intf, data.data());
   |                                  ^^^^ method not found in `core::pin::Pin<kbox::Box<T, Kmalloc>>`

error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0599`.
make[2]: *** [rust/Makefile:553: rust/kernel.o] Error 1
make[1]: *** [/builddir/build/BUILD/kernel-6.18.0-build/kernel-next-20251103/linux-6.18.0-0.0.next.20251103.436.vanilla.fc44.x86_64/Makefile:1316: prepare] Error 2
make: *** [Makefile:256: __sub-make] Error 2
"""

This slipped through, since the USB abstractions are globally disabled.
However, the USB tree recently enabled them, hence it showed up in
linux-next.

Reported-by: Thorsten Leemhuis <linux@leemhuis.info>
Closes: https://lore.kernel.org/all/1c8afbc0-e888-4702-9e4e-fa8aef0f97ae@leemhuis.info/
Fixes: 6bbaa93912 ("rust: device: narrow the generic of drvdata_obtain()")
Reviewed-by: Alice Ryhl <aliceryhl@google.com>
Tested-by: Thorsten Leemhuis <linux@leemhuis.info>
Link: https://patch.msgid.link/20251103110115.1925072-1-dakr@kernel.org
Signed-off-by: Danilo Krummrich <dakr@kernel.org>
2025-11-04 00:31:25 +01:00
Martin K. Petersen
bb8222b6f3 Merge patch series "target: RW/num_cmds stats improvements"
Mike Christie <michael.christie@oracle.com> says:

The following patches were made over Linus tree. They fix/improve the
stats used in the main IO path. The first patch fixes an issue where
I made some stats u32 when they should have stayed u64. The rest of
the patches improve the handling of RW/num_cmds stats to reduce code
duplication and improve performance.

Link: https://patch.msgid.link/20250917221338.14813-1-michael.christie@oracle.com
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-11-02 22:07:27 -05:00
Mike Christie
bbb4900531 scsi: target: Move LUN stats to per-CPU
The atomic use in the main I/O path is causing perf issues when using
higher performance backend devices and multiple queues (more than
10 when using vhost-scsi) like with this fio workload:

[global]
bs=4K
iodepth=128
direct=1
ioengine=libaio
group_reporting
time_based
runtime=120
name=standard-iops
rw=randread
numjobs=16
cpus_allowed=0-15

To fix this issue, move the LUN stats to per CPU.

Note: I forgot to include this patch with the delayed/ordered per CPU
tracking and per device/device entry per CPU stats. With this patch you
get the full 33% improvements when using fast backends, multiple queues
and multiple IO submiters.

Signed-off-by: Mike Christie <michael.christie@oracle.com>
Reviewed-by: Dmitry Bogdanov <d.bogdanov@yadro.com>
Link: https://patch.msgid.link/20250917221338.14813-4-michael.christie@oracle.com
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-11-02 22:06:12 -05:00
Mike Christie
ed6b97a795 scsi: target: Create and use macro helpers for per-CPU stats
Create some macros to reduce code duplication for when we handle per-CPU
stats. Convert the existing LUN and auth cases.

Note: This is similar to percpu_counters but they only support s64 since
they are also used for non-stat counters where you need to handle/prevent
rollover more gracefully. Our use is just for stats where the spec
defines u64 use plus we already have some files exporting u64 values so
it's not possible to directly use percpu_counters.

Signed-off-by: Mike Christie <michael.christie@oracle.com>
Reviewed-by: Dmitry Bogdanov <d.bogdanov@yadro.com>
Link: https://patch.msgid.link/20250917221338.14813-3-michael.christie@oracle.com
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-11-02 22:06:11 -05:00
Mike Christie
95aa2041c6 scsi: target: Fix LUN/device R/W and total command stats
In commit 9cf2317b79 ("scsi: target: Move I/O path stats to per CPU")
I saw we sometimes use %u and also misread the spec. As a result I
thought all the stats were supposed to be 32-bit only. However, for the
majority of cases we support currently, the spec specifies u64 bit
stats. This patch converts the stats changed in the commit above to u64.

Fixes: 9cf2317b79 ("scsi: target: Move I/O path stats to per CPU")
Signed-off-by: Mike Christie <michael.christie@oracle.com>
Reviewed-by: Dmitry Bogdanov <d.bogdanov@yadro.com>
Link: https://patch.msgid.link/20250917221338.14813-2-michael.christie@oracle.com
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-11-02 22:06:11 -05:00
Bart Van Assche
867e4b1bae scsi: core: Improve sdev_store_timeout()
Check whether or not the conversion of the argument to an integer
succeeded. Reject invalid timeout values.

Signed-off-by: Bart Van Assche <bvanassche@acm.org>
Link: https://patch.msgid.link/20251031221844.2921694-1-bvanassche@acm.org
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-11-02 21:56:22 -05:00
Bart Van Assche
61deab8a32 scsi: core: Remove unused code from scsi_sysfs.c
Remove unused code since we do not keep unused code in the Linux kernel.

Signed-off-by: Bart Van Assche <bvanassche@acm.org>
Link: https://patch.msgid.link/20251031220857.2917954-1-bvanassche@acm.org
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-11-02 21:54:40 -05:00
Peter Wang
480ca79546 scsi: ufs: dt-bindings: mediatek,ufs: Update maintainer information in mediatek,ufs.yaml
Replace Stanley Chu with me and Chaotian in the maintainers field since
Stanley's email address is no longer active.

Signed-off-by: Peter Wang <peter.wang@mediatek.com>
Acked-by: Conor Dooley <conor.dooley@microchip.com>
Link: https://patch.msgid.link/20251031122008.1517549-1-peter.wang@mediatek.com
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-11-02 21:51:22 -05:00
Peter Wang
b0b9c7ccc1 scsi: ufs: mediatek: Add the maintainer for MediaTek UFS hooks
Add Chaotian Jing as the maintainer of the MediaTek UFS hooks.

Signed-off-by: Peter Wang <peter.wang@mediatek.com>
Link: https://patch.msgid.link/20251031115356.1501765-1-peter.wang@mediatek.com
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-11-02 21:50:26 -05:00
Bart Van Assche
f010c39ae1 scsi: target: Simplify target_lu_gp_members_show()
Remove the stack buffer 'buf'. This patch does not modify the output
produced by target_lu_gp_members_show().

An example of the output that is produced with this patch applied:

$ cat /sys/kernel/config/target/core/alua/lu_gps/default_lu_gp/members
fileio_0/vdev0
fileio_1/vdev1
iblock_0/vdev2
$ od -c /sys/kernel/config/target/core/alua/lu_gps/default_lu_gp/members
0000000   f   i   l   e   i   o   _   0   /   v   d   e   v   0  \n   f
0000020   i   l   e   i   o   _   1   /   v   d   e   v   1  \n   i   b
0000040   l   o   c   k   _   0   /   v   d   e   v   2  \n
0000055

Signed-off-by: Bart Van Assche <bvanassche@acm.org>
Link: https://patch.msgid.link/20251027184639.3501254-3-bvanassche@acm.org
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-11-02 21:47:29 -05:00
Bart Van Assche
c03b55f235 scsi: target: Do not write NUL characters into ASCII configfs output
NUL characters are not allowed in ASCII configfs output. Hence this
patch.

Fixes: c66ac9db8d ("[SCSI] target: Add LIO target core v4.0.0-rc6")
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
Link: https://patch.msgid.link/20251027184639.3501254-2-bvanassche@acm.org
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-11-02 21:47:29 -05:00
Martin K. Petersen
5fb43e2f67 Merge patch series "scsi: target: Add WRITE_ATOMIC_16 support"
John Garry <john.g.garry@oracle.com> says:

This is a reposting of Mike's atomic writes support for the SCSI
target.

Again, we are now only supporting target_core_iblock. It's implemented
similar to UNMAP where we do not do any emulation and instead pass the
operation to the block layer.

Link: https://patch.msgid.link/20251020103820.2917593-1-john.g.garry@oracle.com
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-11-02 21:41:45 -05:00
Mike Christie
8e62d8f4b1 scsi: target: Add atomic support to target_core_iblock
Make target_core_iblock use the LIO helper function to translate its
block_device atomic settings to LIO settings. If we then get a write
that LIO has indicated is atomic via the SCF_ATOMIC flag, we use the
REQ_ATOMIC flag to tell the block layer to perform an atomic write.

Signed-off-by: Mike Christie <michael.christie@oracle.com>
Signed-off-by: John Garry <john.g.garry@oracle.com>
Reviewed-by: John Garry <john.g.garry@oracle.com>
Link: https://patch.msgid.link/20251020103820.2917593-8-john.g.garry@oracle.com
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-11-02 21:40:02 -05:00
Mike Christie
2d9668883b scsi: target: Add WRITE_ATOMIC_16 support to RSOC
Report if the device supports WRITE_ATOMIC_16 in the
REPORT_SUPPORTED_OPERATION_CODES command.

Signed-off-by: Mike Christie <michael.christie@oracle.com>
Signed-off-by: John Garry <john.g.garry@oracle.com>
Link: https://patch.msgid.link/20251020103820.2917593-7-john.g.garry@oracle.com
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-11-02 21:40:02 -05:00
Mike Christie
710ad826e3 scsi: target: Report atomic values in INQUIRY
Report the atomic values in the Block Limits VPD page.

Signed-off-by: Mike Christie <michael.christie@oracle.com>
jpg: handle not having atomic_supported attribute
Signed-off-by: John Garry <john.g.garry@oracle.com>
Link: https://patch.msgid.link/20251020103820.2917593-6-john.g.garry@oracle.com
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-11-02 21:40:02 -05:00
Mike Christie
5261457251 scsi: target: Add WRITE_ATOMIC_16 handler
Add the core LIO code to process the WRITE_ATOMIC_16 command.

Signed-off-by: Mike Christie <michael.christie@oracle.com>
jpg: fix return code from sbc_check_atomic, reformat
Signed-off-by: John Garry <john.g.garry@oracle.com>
Link: https://patch.msgid.link/20251020103820.2917593-5-john.g.garry@oracle.com
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-11-02 21:40:02 -05:00
Mike Christie
c486634fe2 scsi: target: Add helper to set up atomic values from block_device
Add a helper function that sets up the atomic value based on a
block_device similar to what we do for unmap.

Signed-off-by: Mike Christie <michael.christie@oracle.com>
jpg: Set atomic alignment, drop atomic_supported reference
Signed-off-by: John Garry <john.g.garry@oracle.com>
Link: https://patch.msgid.link/20251020103820.2917593-4-john.g.garry@oracle.com
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-11-02 21:40:01 -05:00
Mike Christie
d505447b8d scsi: target: Add atomic se_device fields
Add atomic fields to the se_device and export them in configfs.

Initially only target_core_iblock will be supported and we will inherit
all the settings from the block layer.

Signed-off-by: Mike Christie <michael.christie@oracle.com>
jpg: Stop being allowed to configure atomic write alignment,
Signed-off-by: John Garry <john.g.garry@oracle.com>
Link: https://patch.msgid.link/20251020103820.2917593-3-john.g.garry@oracle.com
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-11-02 21:40:01 -05:00
Mike Christie
3434be3920 scsi: target: Rename target_configure_unmap_from_queue()
Rename target_configure_unmap_from_queue() to
target_configure_unmap_from_bdev() since it now takes a bdev.

Signed-off-by: Mike Christie <michael.christie@oracle.com>
Signed-off-by: John Garry <john.g.garry@oracle.com>
Reviewed-by: John Garry <john.g.garry@oracle.com>
Link: https://patch.msgid.link/20251020103820.2917593-2-john.g.garry@oracle.com
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-11-02 21:40:01 -05:00
Krzysztof Kozlowski
525a411f9a scsi: ufs: dt-bindings: qcom: Drop redundant "reg" constraints
The "reg" in top-level has maxItems:2, thus repeating this in "if:then:"
blocks is redundant.  Similarly number of items cannot be less than 1.

Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
Acked-by: Rob Herring (Arm) <robh@kernel.org>
Link: https://patch.msgid.link/20251027113107.75835-2-krzysztof.kozlowski@linaro.org
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-10-29 23:23:01 -04:00
Martin K. Petersen
041ef13bd0 Merge patch series "ufs: Add support for AMD Versal Gen2 UFS"
Ajay Neeli <ajay.neeli@amd.com> says:

This patch series adds support for the UFS driver on the AMD Versal
Gen 2 SoC.  It includes:

 - Device tree bindings and driver implementation.

 - Secure read support for the secure retrieval of UFS calibration
   values.

The UFS host driver is based upon the Synopsis DesignWare (DWC) UFS
architecture, utilizing the existing UFSHCD_DWC and UFSHCD_PLATFORM
drivers.

Link: https://patch.msgid.link/20251021113003.13650-1-ajay.neeli@amd.com
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-10-29 23:03:15 -04:00
Sai Krishna Potthuri
769b8b2ffd scsi: ufs: amd-versal2: Add UFS support for AMD Versal Gen 2 SoC
Add support for the UFS host controller on the AMD Versal Gen 2 SoC,
built on the Synopsys DWC UFS architecture, using the UFSHCD DWC and
UFSHCD platform driver. This controller requires specific configurations
like M-PHY/RMMI/UniPro and vendor specific registers programming before
doing the UIC_LINKSTARTUP.

Signed-off-by: Sai Krishna Potthuri <sai.krishna.potthuri@amd.com>
Signed-off-by: Ajay Neeli <ajay.neeli@amd.com>
Acked-by: Bart Van Assche <bvanassche@acm.org>
Link: https://patch.msgid.link/20251021113003.13650-5-ajay.neeli@amd.com
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-10-29 23:00:49 -04:00
Ajay Neeli
0e4d26f79a scsi: firmware: xilinx: Add APIs for UFS PHY initialization
- Add APIs for UFS PHY initialization.

 - Verify M-PHY TX-RX configuration readiness.

 - Confirm SRAM initialization and Set SRAM bypass.

 - Retrieve UFS calibration values.

Signed-off-by: Ajay Neeli <ajay.neeli@amd.com>
Acked-by: Senthil Nathan Thangaraj <senthilnathan.thangaraj@amd.com>
Acked-by: Michal Simek <michal.simek@amd.com>
Acked-by: Bart Van Assche <bvanassche@acm.org>
Link: https://patch.msgid.link/20251021113003.13650-4-ajay.neeli@amd.com
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-10-29 23:00:48 -04:00
Izhar Ameer Shaikh
00b3e8480b scsi: firmware: xilinx: Add support for secure read/write ioctl interface
Add support for a generic ioctl read/write interface using which users
can request firmware to perform read/write operations on a protected and
secure address space.

The functionality is introduced through the means of two new IOCTL IDs
which extend the existing PM_IOCTL EEMI API:

 - IOCTL_READ_REG
 - IOCTL_MASK_WRITE_REG

The caller only passes the node id of the given device and an offset.
The base address is not exposed to the caller and internally retrieved
by the firmware. Firmware will enforce an access policy on the incoming
read/write request.

Signed-off-by: Izhar Ameer Shaikh <izhar.ameer.shaikh@amd.com>
Reviewed-by: Tanmay Shah <tanmay.shah@amd.com>
Signed-off-by: Radhey Shyam Pandey <radhey.shyam.pandey@amd.com>
Signed-off-by: Ajay Neeli <ajay.neeli@amd.com>
Acked-by: Senthil Nathan Thangaraj <senthilnathan.thangaraj@amd.com>
Acked-by: Michal Simek <michal.simek@amd.com>
Acked-by: Bart Van Assche <bvanassche@acm.org>
Link: https://patch.msgid.link/20251021113003.13650-3-ajay.neeli@amd.com
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-10-29 23:00:48 -04:00
Sai Krishna Potthuri
754c6f539e scsi: ufs: dt-bindings: amd-versal2: Add UFS Host Controller for AMD Versal Gen 2 SoC
Add devicetree document for UFS Host Controller on AMD Versal Gen 2 SoC.
This includes clocks and clock-names as mandated by UFS common bindings.

Signed-off-by: Sai Krishna Potthuri <sai.krishna.potthuri@amd.com>
Co-developed-by: Ajay Neeli <ajay.neeli@amd.com>
Signed-off-by: Ajay Neeli <ajay.neeli@amd.com>
Reviewed-by: Conor Dooley <conor.dooley@microchip.com>
Acked-by: Bart Van Assche <bvanassche@acm.org>
Link: https://patch.msgid.link/20251021113003.13650-2-ajay.neeli@amd.com
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-10-29 23:00:48 -04:00
Danilo Krummrich
b0b7301b00 samples: rust: auxiliary: illustrate driver interaction
Illustrate how a parent driver of an auxiliary driver can take advantage
of the device context guarantees given by the auxiliary bus and
subsequently safely derive its device private data.

Reviewed-by: Alice Ryhl <aliceryhl@google.com>
Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Danilo Krummrich <dakr@kernel.org>
2025-10-29 18:29:32 +01:00
Danilo Krummrich
710ac54688 samples: rust: auxiliary: misc cleanup of ParentDriver::connect()
In ParentDriver::connect() rename parent to dev, use it for the
dev_info!() call, call pdev.vendor_() directly in the print statement
and remove the unnecessary generic type of Result.

Reviewed-by: Alice Ryhl <aliceryhl@google.com>
Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Danilo Krummrich <dakr@kernel.org>
2025-10-29 18:29:32 +01:00
Danilo Krummrich
675e514edd rust: auxiliary: implement parent() for Device<Bound>
Take advantage of the fact that if the auxiliary device is bound the
parent is guaranteed to be bound as well and implement a separate
parent() method for auxiliary::Device<Bound>.

Reviewed-by: Alice Ryhl <aliceryhl@google.com>
Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Danilo Krummrich <dakr@kernel.org>
2025-10-29 18:29:32 +01:00
Danilo Krummrich
b69165a097 rust: auxiliary: move parent() to impl Device
Currently, the parent method is implemented for any Device<Ctx>, i.e.
any device context and returns a &device::Device<Normal>.

However, a subsequent patch will introduce

	impl Device<Bound> {
	    pub fn parent() -> device::Device<Bound> { ... }
	}

which takes advantage of the fact that if the auxiliary device is bound
the parent is guaranteed to be bound as well.

I.e. the behavior we want is that all device contexts that dereference
to Bound, will use the implementation above, whereas the old
implementation should only be implemented for Device<Normal>.

Hence, move the current implementation.

Reviewed-by: Alice Ryhl <aliceryhl@google.com>
Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Danilo Krummrich <dakr@kernel.org>
2025-10-29 18:29:32 +01:00
Danilo Krummrich
e4e679c860 rust: auxiliary: unregister on parent device unbind
Guarantee that an auxiliary driver will be unbound before its parent is
unbound; there is no point in operating an auxiliary device whose parent
has been unbound.

In practice, this guarantee allows us to assume that for a bound
auxiliary device, also the parent device is bound.

This is useful when an auxiliary driver calls into its parent, since it
allows the parent to directly access device resources and its device
private data due to the guaranteed bound device context.

Reviewed-by: Alice Ryhl <aliceryhl@google.com>
Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Danilo Krummrich <dakr@kernel.org>
2025-10-29 18:29:32 +01:00
Danilo Krummrich
589b061975 rust: auxiliary: consider auxiliary devices always have a parent
An auxiliary device is guaranteed to always have a parent device (both
in C and Rust), hence don't return an Option<&auxiliary::Device> in
auxiliary::Device::parent().

Reviewed-by: Alice Ryhl <aliceryhl@google.com>
Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Danilo Krummrich <dakr@kernel.org>
2025-10-29 18:29:32 +01:00
Danilo Krummrich
6f61a2637a rust: device: introduce Device::drvdata()
In C dev_get_drvdata() has specific requirements under which it is valid
to access the returned pointer. That is, drivers have to ensure that

  (1) for the duration the returned pointer is accessed the driver is
      bound and remains to be bound to the corresponding device,

  (2) the returned void * is treated according to the driver's private
      data type, i.e. according to what has been passed to
      dev_set_drvdata().

In Rust, (1) can be ensured by simply requiring the Bound device
context, i.e. provide the drvdata() method for Device<Bound> only.

For (2) we would usually make the device type generic over the driver
type, e.g. Device<T: Driver>, where <T as Driver>::Data is the type of
the driver's private data.

However, a device does not have a driver type known at compile time and
may be bound to multiple drivers throughout its lifetime.

Hence, in order to be able to provide a safe accessor for the driver's
device private data, we have to do the type check on runtime.

This is achieved by letting a driver assert the expected type, which is
then compared to a type hash stored in struct device_private when
dev_set_drvdata() is called.

Example:

	// `dev` is a `&Device<Bound>`.
	let data = dev.drvdata::<SampleDriver>()?;

There are two aspects to note:

  (1) Technically, the same check could be achieved by comparing the
      struct device_driver pointer of struct device with the struct
      device_driver pointer of the driver struct (e.g. struct
      pci_driver).

      However, this would - in addition the pointer comparison - require
      to tie back the private driver data type to the struct
      device_driver pointer of the driver struct to prove correctness.

      Besides that, accessing the driver struct (stored in the module
      structure) isn't trivial and would result into horrible code and
      API ergonomics.

  (2) Having a direct accessor to the driver's private data is not
      commonly required (at least in Rust): Bus callback methods already
      provide access to the driver's device private data through a &self
      argument, while other driver entry points such as IRQs,
      workqueues, timers, IOCTLs, etc. have their own private data with
      separate ownership and lifetime.

      In other words, a driver's device private data is only relevant
      for driver model contexts (such a file private is only relevant
      for file contexts).

Having that said, the motivation for accessing the driver's device
private data with Device<Bound>::drvdata() are interactions between
drivers. For instance, when an auxiliary driver calls back into its
parent, the parent has to be capable to derive its private data from the
corresponding device (i.e. the parent of the auxiliary device).

Reviewed-by: Alice Ryhl <aliceryhl@google.com>
Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
[ * Remove unnecessary `const _: ()` block,
  * rename type_id_{store,match}() to {set,match}_type_id(),
  * assert size_of::<bindings::driver_type>() >= size_of::<TypeId>(),
  * add missing check in case Device::drvdata() is called from probe().

  - Danilo ]
Signed-off-by: Danilo Krummrich <dakr@kernel.org>
2025-10-29 18:18:02 +01:00
Danilo Krummrich
6bbaa93912 rust: device: narrow the generic of drvdata_obtain()
Let T be the actual private driver data type without the surrounding
box, as it leaves less room for potential bugs.

Reviewed-by: Alice Ryhl <aliceryhl@google.com>
Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Danilo Krummrich <dakr@kernel.org>
2025-10-29 16:40:28 +01:00
Greg Kroah-Hartman
37022410f4 Merge 6.18-rc3 into driver-core-next
We need the driver core fixes in here as well to build on top of.

Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2025-10-27 08:02:50 +01:00
FUJITA Tomonori
aad1577ab9 rust: simplify read_poll_timeout's example code
- Drop unnecessary Result's '<()>'
- Use '?' instead of match

Signed-off-by: FUJITA Tomonori <fujita.tomonori@gmail.com>
Signed-off-by: Danilo Krummrich <dakr@kernel.org>
2025-10-26 17:56:14 +01:00
Alok Tiwari
e9ff858c9a scsi: qla4xxx: Use correct variable in memset for clarity
Both mbox_cmd and mbox_sts have the same size, so using sizeof(mbox_cmd)
when clearing mbox_sts did not cause any functional issue. However, it
is misleading and reduces code readability.

Update the memset() calls to use sizeof(mbox_sts) to make the intent
clear

Signed-off-by: Alok Tiwari <alok.a.tiwari@oracle.com>
Link: https://patch.msgid.link/20251021090354.1804327-1-alok.a.tiwari@oracle.com
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-10-23 23:02:15 -04:00
Bart Van Assche
e414748b7e scsi: aacraid: Improve code readability
aac_queuecommand() is a scsi_host_template.queuecommand()
implementation.  Any value returned by this function other than one of
the following values is translated into SCSI_MLQUEUE_HOST_BUSY:

* 0
* SCSI_MLQUEUE_HOST_BUSY
* SCSI_MLQUEUE_DEVICE_BUSY
* SCSI_MLQUEUE_EH_RETRY
* SCSI_MLQUEUE_TARGET_BUSY

Improve readability of aac_queuecommand() by returning
SCSI_MLQUEUE_HOST_BUSY instead of FAILED.

Cc: Gilbert Wu <gilbert.wu@microchip.com>
Cc: Sagar Biradar <Sagar.Biradar@microchip.com>
Cc: John Garry <john.g.garry@oracle.com>
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
Reviewed-by: John Garry <john.g.garry@oracle.com>
Link: https://patch.msgid.link/20251021201743.3539900-1-bvanassche@acm.org
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-10-23 23:01:00 -04:00
John Garry
bb798c1f43 scsi: advansys: Don't call asc_prt_scsi_host() -> scsi_host_busy()
The driver calls asc_prt_scsi_host() -> scsi_host_busy() prior to
calling scsi_add_host(). This should not be done, and has raised issues
for other drivers, like [0].

Function asc_prt_scsi_host() only has a single callsite, as above, where
the shost busy count would always be 0.

Avoid printing the shost busy count to avoid this problem.

[0] https://lore.kernel.org/linux-scsi/20251014200118.3390839-3-bvanassche@acm.org/

Reported-by: Bart Van Assche <bvanassche@acm.org>
Signed-off-by: John Garry <john.g.garry@oracle.com>
Reviewed-by: Bart Van Assche <bvanassche@acm.org>
Link: https://patch.msgid.link/20251023085451.3933666-1-john.g.garry@oracle.com
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-10-23 22:58:53 -04:00
John Garry
dcc98c1136 scsi: core: Minor comment fixes for scsi_host_busy()
I guess that the @shost comment on scsi_host_busy() was copied from
scsi_host_get() (as it is the same), however they do not do the same
thing.

Also drop reference to busy counter, which has been removed.

Signed-off-by: John Garry <john.g.garry@oracle.com>
Reviewed-by: Bart Van Assche <bvanassche@acm.org>
Link: https://patch.msgid.link/20251023082759.3927000-1-john.g.garry@oracle.com
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-10-23 22:56:18 -04:00
Martin K. Petersen
a7480fda0f Merge patch series "Eight small UFS patches"
Bart Van Assche <bvanassche@acm.org> says:

Hi Martin,

This patch series includes two bug fixes for this development cycle
and six small patches that are intended for the next merge window. If
applying the first two patches only during the current development
cycle would be inconvenient, postponing all patches until the next
merge window is fine with me.

Please consider including these patches in the upstream kernel.

Thanks,

Bart.

[mkp: Applied patches #1 and #2 to 6.18/scsi-fixes]

Link: https://patch.msgid.link/20251014200118.3390839-1-bvanassche@acm.org
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-10-23 22:20:44 -04:00
Bart Van Assche
bfe5f5dacf scsi: ufs: core: Simplify ufshcd_mcq_sq_cleanup() using guard()
Simplify ufshcd_mcq_sq_cleanup() by using guard(mutex)() instead of
explicit mutex_lock() and mutex_unlock() calls. No functionality has
been changed.

Signed-off-by: Bart Van Assche <bvanassche@acm.org>
Reviewed-by: Peter Wang <peter.wang@mediatek.com>
Link: https://patch.msgid.link/20251014200118.3390839-9-bvanassche@acm.org
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-10-23 22:18:12 -04:00
Bart Van Assche
047f190494 scsi: ufs: core: Remove a goto label from ufshcd_uic_cmd_compl()
Return directly instead of jumping to a return statement. No
functionality has been changed.

Signed-off-by: Bart Van Assche <bvanassche@acm.org>
Reviewed-by: Peter Wang <peter.wang@mediatek.com>
Link: https://patch.msgid.link/20251014200118.3390839-8-bvanassche@acm.org
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-10-23 22:18:12 -04:00
Bart Van Assche
b30006b5be scsi: ufs: core: Move the ufshcd_enable_intr() declaration
ufshcd_enable_intr() is not exported and hence should not be declared in
include/ufs/ufshcd.h.

Fixes: 2537577979 ("scsi: ufs: core: Change MCQ interrupt enable flow")
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
Reviewed-by: Peter Wang <peter.wang@mediatek.com>
Link: https://patch.msgid.link/20251014200118.3390839-7-bvanassche@acm.org
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-10-23 22:18:12 -04:00
Bart Van Assche
a332735a53 scsi: ufs: core: Remove UFS_DEV_COMP
Remove the UFS_DEV_COMP constant because it is not used.

Signed-off-by: Bart Van Assche <bvanassche@acm.org>
Reviewed-by: Peter Wang <peter.wang@mediatek.com>
Link: https://patch.msgid.link/20251014200118.3390839-6-bvanassche@acm.org
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-10-23 22:18:12 -04:00
Bart Van Assche
b3b0842bcb scsi: ufs: core: Change the type of uic_command::cmd_active
Since uic_command::cmd_active is used as a boolean variable, change its
type from 'int' into 'bool'. No functionality has been changed.

Signed-off-by: Bart Van Assche <bvanassche@acm.org>
Link: https://patch.msgid.link/20251014200118.3390839-5-bvanassche@acm.org
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-10-23 22:18:12 -04:00
Bart Van Assche
7b2c4224fa scsi: ufs: core: Improve documentation in include/ufs/ufshci.h
Make it easier to find the sections in the UFSHCI standard where these
constants come from.

Signed-off-by: Bart Van Assche <bvanassche@acm.org>
Link: https://patch.msgid.link/20251014200118.3390839-4-bvanassche@acm.org
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-10-23 22:18:12 -04:00
Peter Colberg
26c1a20bf7 rust: pci: normalise spelling of PCI BAR
Consistently refer to PCI base address register as PCI BAR.
Fix spelling mistake "Mapps" -> "Maps".

Link: https://lore.kernel.org/rust-for-linux/20251015225827.GA960157@bhelgaas/
Link: https://github.com/Rust-for-Linux/linux/issues/1196
Suggested-by: Bjorn Helgaas <helgaas@kernel.org>
Signed-off-by: Peter Colberg <pcolberg@redhat.com>
Signed-off-by: Danilo Krummrich <dakr@kernel.org>
2025-10-23 20:12:32 +02:00
Peter Colberg
c7f6d5380f rust: pci: refer to legacy as INTx interrupts
Consistently use INTx, as in the description of IrqType::Intx, to refer
to the four legacy PCI interrupts, INTA#, INTB#, INTC#, and INTD#.

Link: https://lore.kernel.org/rust-for-linux/20251015230209.GA960343@bhelgaas/
Link: https://github.com/Rust-for-Linux/linux/issues/1196
Suggested-by: Bjorn Helgaas <helgaas@kernel.org>
Signed-off-by: Peter Colberg <pcolberg@redhat.com>
Signed-off-by: Danilo Krummrich <dakr@kernel.org>
2025-10-23 20:12:32 +02:00
Yunhui Cui
6d0ef68955 arch_topology: move parse_acpi_topology() to common code
Currently, RISC-V lacks arch-specific registers for CPU topology
properties and must get them from ACPI. Thus, parse_acpi_topology()
is moved from arm64/ to drivers/ for RISC-V reuse.

Signed-off-by: Yunhui Cui <cuiyunhui@bytedance.com>
Reviewed-by: Sudeep Holla <sudeep.holla@arm.com>
Link: https://patch.msgid.link/20250923015409.15983-2-cuiyunhui@bytedance.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2025-10-22 08:10:57 +02:00
Pei Xiao
cebd22dd3a platform: Use IOMEM_ERR_PTR for ioremap error returns
Replace ERR_PTR() with IOMEM_ERR_PTR() in stubbed ioremap functions to
maintain type consistency. The functions return void __iomem * pointers
and IOMEM_ERR_PTR() provides proper type casting to avoid sparse warnings.

Reported-by: kernel test robot <lkp@intel.com>
Closes: https://lore.kernel.org/oe-kbuild-all/202509060307.JubgnLhc-lkp@intel.com/
Signed-off-by: Pei Xiao <xiaopei01@kylinos.cn>
Link: https://patch.msgid.link/320f2cc9ada5cb66845daa6bf259000b4cffd8b3.1758163939.git.xiaopei01@kylinos.cn
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2025-10-22 08:09:37 +02:00
Kaushlendra Kumar
b811e8a01d firmware_loader: Replace simple_strtol() with kstrtoint()
Replace deprecated simple_strtol() calls with kstrtoint() in
timeout_store() and firmware_loading_store() functions to
improve input validation and error handling. The simple_strtol()
function does not provide proper error checking for invalid input,
while kstrtoint() returns an error for malformed strings.

This change adds proper validation for user input from sysfs attributes,
returning -EINVAL for invalid numeric strings instead of silently accepting
potentially malformed input. The behavior for valid numeric input remains
unchanged.

The simple_strtol() function is deprecated in favor of kstrtoint() family
functions which provide better error handling and are recommended for new
code and replacements.

Signed-off-by: Kaushlendra Kumar <kaushlendra.kumar@intel.com>
Link: https://patch.msgid.link/20250925063812.2269501-1-kaushlendra.kumar@intel.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2025-10-22 08:09:25 +02:00
Kaushlendra Kumar
fe6193a318 firmware_loader: Only call cancel when upload is active
The cancel_store() function currently calls the firmware upload cancel
operation even when no upload is in progress (i.e., when progress is
FW_UPLOAD_PROG_IDLE).

Update cancel_store() to only invoke the cancel operation when an upload
is active. If the upload is idle, return -ENODEV without calling cancel.

This change improves safety and correctness by ensuring driver operations
are only called in valid states.

Signed-off-by: Kaushlendra Kumar <kaushlendra.kumar@intel.com>
Link: https://patch.msgid.link/20250925054129.2199157-1-kaushlendra.kumar@intel.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2025-10-22 08:09:23 +02:00
Magnus Lindholm
ea0e278a5c scsi: qla1280: Fix compiler warnings (DEBUG mode)
Building the qla1280 driver with DEBUG_QLA1280 set will emit compiler
warnings. Fix some print formatting strings to reflect the correct type
of printed variables as well as remove unused code. (static function
ql1280_dump_device) in order to avoid compiler warnings.

[mkp: fixed a few more checkpatch warnings]

Signed-off-by: Magnus Lindholm <linmag7@gmail.com>
Link: https://patch.msgid.link/20251002052604.24590-1-linmag7@gmail.com
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-10-21 22:06:22 -04:00
Martin K. Petersen
36e6daa543 Merge patch series "Enhance UFS Mediatek Driver"
Peter Wang <peter.wang@mediatek.com says>:

Improves the UFS Mediatek driver by correcting clock scaling with PM
QoS, and adjusting power management flows. It addresses
shutdown/suspend race conditions, and removes redundant
functions. Support for new platforms is added with the MMIO_OTSD_CTRL
register, and MT6991 performance is optimized with MRTT and random
improvements. These changes collectively enhance driver performance,
stability, and compatibility.

Changes since v1:

 1. Remove two patches that will be fixed in UFS core.
    - ufs: host: mediatek: Fix runtime suspend error deadlock
    - ufs: host: mediatek: Enable interrupts for MCQ mode
 2. Use hba->shutting_down instead of ufshcd_is_user_access_allowed

v1:
   https://patch.msgid.link/20250918104000.208856-1-peter.wang@mediatek.com

Link: https://patch.msgid.link/20250924094527.2992256-1-peter.wang@mediatek.com
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-10-21 21:37:57 -04:00
Naomi Chu
9ce37e94c3 scsi: ufs: host: mediatek: Support new features for MT6991
Add support for the MT6991 platform by enabling MRTT settings and random
performance improvements. These enhancements aim to optimize performance
and efficiency on the MT6991 hardware.

Enable multi-Round Trip Time (MRTT) for improved data handling.  Enable
random performance improvement features to boost overall system
responsiveness.

Signed-off-by: Naomi Chu <naomi.chu@mediatek.com>
Reviewed-by: Peter Wang <peter.wang@mediatek.com>
Acked-by: Chun-Hung Wu <chun-hung.wu@mediatek.com>
Signed-off-by: Peter Wang <peter.wang@mediatek.com>
Link: https://patch.msgid.link/20250924094527.2992256-9-peter.wang@mediatek.com
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-10-21 21:36:46 -04:00
Peter Wang
4fb4c835a9 scsi: ufs: host: mediatek: Add support for new platform with MMIO_OTSD_CTR
Introduce support for a new UFS Mediatek platform by adding the
REG_UFS_UFS_MMIO_OTSD_CTRL register. This update includes checks for
legacy platforms and uses the new register to replace debug selection
and handle specific operations.  The changes ensure compatibility across
different hardware versions and prevent potential issues with debug
usage on newer platforms.

Additional updates include error logging improvements during link setup
for newer and legacy platforms, ensuring proper event logging and
debugging.

Signed-off-by: Peter Wang <peter.wang@mediatek.com>
Acked-by: Chun-Hung Wu <chun-hung.wu@mediatek.com>
Link: https://patch.msgid.link/20250924094527.2992256-8-peter.wang@mediatek.com
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-10-21 21:36:46 -04:00
Peter Wang
9b2b03b361 scsi: ufs: host: mediatek: Remove duplicate function
Remove the duplicate ufs_mtk_us_to_ahit() function in the UFS Mediatek
driver and export the existing ufshcd_us_to_ahit() function for shared
use. This change reduces redundancy and maintains consistency across the
codebase.

Signed-off-by: Peter Wang <peter.wang@mediatek.com>
Reviewed-by: Bart Van Assche <bvanassche@acm.org>
Acked-by: Chun-Hung Wu <chun-hung.wu@mediatek.com>
Link: https://patch.msgid.link/20250924094527.2992256-7-peter.wang@mediatek.com
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-10-21 21:36:46 -04:00
Peter Wang
014de20bb3 scsi: ufs: host: mediatek: Fix shutdown/suspend race condition
Address a race condition between shutdown and suspend operations in the
UFS Mediatek driver. Before entering suspend, check if a shutdown is in
progress to prevent conflicts and ensure system stability.

Signed-off-by: Peter Wang <peter.wang@mediatek.com>
Acked-by: Chun-Hung Wu <chun-hung.wu@mediatek.com>
Link: https://patch.msgid.link/20250924094527.2992256-6-peter.wang@mediatek.com
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-10-21 21:36:46 -04:00
Peter Wang
1fd05367d5 scsi: ufs: host: mediatek: Adjust sync length for FASTAUTO mode
Set the sync length for FASTAUTO G1 mode in the UFS Mediatek
driver. This ensures the sync length meets minimum values for high-speed
gears, improving stability during power mode changes.

Signed-off-by: Peter Wang <peter.wang@mediatek.com>
Reviewed-by: Bart Van Assche <bvanassche@acm.org>
Acked-by: Chun-Hung Wu <chun-hung.wu@mediatek.com>
Link: https://patch.msgid.link/20250924094527.2992256-5-peter.wang@mediatek.com
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-10-21 21:36:45 -04:00
Peter Wang
16b42c4281 scsi: ufs: host: mediatek: Handle clock scaling for high gear in PM flow
Add clock scaling down for power management flow in the UFS Mediatek
driver. If clock scaling is disabled and fixed in high gear, ensure the
clock scales down during suspend and scales up again after resume to
support high gear.  This adjustment maintains proper power management.

Signed-off-by: Peter Wang <peter.wang@mediatek.com>
Acked-by: Chun-Hung Wu <chun-hung.wu@mediatek.com>
Link: https://patch.msgid.link/20250924094527.2992256-4-peter.wang@mediatek.com
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-10-21 21:36:45 -04:00
Peter Wang
55ce691dc7 scsi: ufs: host: mediatek: Adjust clock scaling for PM flow
Adjust clock scaling during suspend and resume in the UFS Mediatek
driver. Ensure that the clock scales down during suspend if it was
scaled up, and scales up again after resume.  This adjustment maintains
proper power management.

Signed-off-by: Peter Wang <peter.wang@mediatek.com>
Acked-by: Chun-Hung Wu <chun-hung.wu@mediatek.com>
Link: https://patch.msgid.link/20250924094527.2992256-3-peter.wang@mediatek.com
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-10-21 21:36:45 -04:00
Peter Wang
7162536410 scsi: ufs: host: mediatek: Correct clock scaling with PM QoS flow
Correct clock scaling with PM QoS during suspend and resume.  Ensure PM
QoS is released during suspend if scaling up and re-applied after
resume. This prevents performance issues and maintains proper power
management.

Signed-off-by: Peter Wang <peter.wang@mediatek.com>
Reviewed-by: Bart Van Assche <bvanassche@acm.org>
Acked-by: Chun-Hung Wu <chun-hung.wu@mediatek.com>
Link: https://patch.msgid.link/20250924094527.2992256-2-peter.wang@mediatek.com
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-10-21 21:36:45 -04:00
Martin K. Petersen
1c6279dc25 Merge patch series "Remove UFS_DEVICE_QUIRK_DELAY_AFTER_LPM quirk"
Bao D. Nguyen <quic_nguyenb@quicinc.com> says:

Multiple ufs device manufacturers request support for the
UFS_DEVICE_QUIRK_DELAY_AFTER_LPM quirk in the Qualcomm's platform
driver.  After checking further with the major UFS manufacturers
engineering teams such as Samsung, Kioxia, SK Hynix and Micron, all
the manufacturers require this quirk. Since the quirk is needed by all
the ufs device manufacturers, remove the quirk in the ufs core driver
and implement a universal delay for all the ufs devices.

In addition to verifying with the public device's datasheets, the ufs
device manufacturer's engineering teams confirmed the required vcc
power-off time for the devices is a minimum of 1ms before vcc can be
powered on again. The existing 5ms delay implemented in the ufs core
driver seems too conservative, so replace the hard coded 5ms delay
with a variable default to 2ms setting to improve the system resume
latency.  The platform drivers can override this setting as needed.

Link: https://patch.msgid.link/cover.1760383740.git.quic_nguyenb@quicinc.com
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-10-21 21:23:50 -04:00
Bao D. Nguyen
4760b639b4 scsi: ufs: core: Replace hard coded vcc-off delay with a variable
After the UFS device VCC is powered off, all the UFS device
manufacturers require a minimum of 1ms of power-off time before VCC can
be powered on again. This requirement has been verified with all the UFS
device manufacturer's datasheets.

Replace the hard coded 5ms delay with a variable with a default setting
of 2ms to improve the system resume latency. The platform drivers can
override this setting as needed.

Signed-off-by: Bao D. Nguyen <quic_nguyenb@quicinc.com>
Reviewed-by: Bart Van Assche <bvanassche@acm.org>
Reviewed-by: Peter Wang <peter.wang@mediatek.com>
Link: https://patch.msgid.link/72fa649406a0bf02271575b7d58f22c968aa5d7e.1760383740.git.quic_nguyenb@quicinc.com
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-10-21 21:22:17 -04:00
Bao D. Nguyen
f8e82ae65e scsi: ufs: core: Remove UFS_DEVICE_QUIRK_DELAY_AFTER_LPM quirk
After the UFS device VCC is turned off, all the UFS device manufacturers
require a period of power-off time before the VCC can be turned on
again. This requirement has been confirmed with all the UFS device
manufacturer's datasheets.

Remove the UFS_DEVICE_QUIRK_DELAY_AFTER_LPM quirk in the UFS core driver
and implement a universal delay that is required by all the UFS device
manufacturers. In addition, remove the support for this quirk in the
platform drivers.

Signed-off-by: Bao D. Nguyen <quic_nguyenb@quicinc.com>
Reviewed-by: Peter Wang <peter.wang@mediatek.com>
Reviewed-by: Bart Van Assche <bvanassche@acm.org>
Link: https://patch.msgid.link/25f134d5a42e8b8365be64d512d1bb5fc2bce6ff.1760383740.git.quic_nguyenb@quicinc.com
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-10-21 21:22:17 -04:00
Peter Wang
8627f322cb scsi: ufs: core: Support dumping CQ entry in MCQ Mode
Enhance the ufshcd_print_tr() function to support dumping completion
queue (CQ) entries in MCQ mode when an error occurs.  This addition
provides more detailed debugging information by including the CQ entry
data in the error logs, aiding in the diagnosis of issues in MCQ mode.

Signed-off-by: Peter Wang <peter.wang@mediatek.com>
Reviewed-by: Bart Van Assche <bvanassche@acm.org>
Link: https://patch.msgid.link/20251016023507.1000664-3-peter.wang@mediatek.com
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-10-21 21:16:04 -04:00
Peter Wang
bfe0d22f12 scsi: ufs: core: Update CQ Entry to UFS 4.1 format
Update the completion queue (CQ) entry format according to the UFS 4.1
specification. UFS 4.1 introduces new members in reserved record
DW5. Also refine DW4 with detailed members defined in UFS 4.0. Modify
the code to incorporate these changes by updating the overall_status in
the CQ entry structure.

Signed-off-by: Peter Wang <peter.wang@mediatek.com>
Reviewed-by: Bart Van Assche <bvanassche@acm.org>
Link: https://patch.msgid.link/20251016023507.1000664-2-peter.wang@mediatek.com
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-10-21 21:16:04 -04:00
Bart Van Assche
ce085ecdba scsi: core: Do not declare scsi_cmnd pointers const
This change allows removing multiple casts and hence improves type
checking by the compiler.

Cc: Hannes Reinecke <hare@suse.de>
Suggested-by: John Garry <john.g.garry@oracle.com>
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
Reviewed-by: John Garry <john.g.garry@oracle.com>
Link: https://patch.msgid.link/20251014220426.3690007-1-bvanassche@acm.org
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-10-21 21:11:35 -04:00
Danilo Krummrich
0242623384 rust: driver: let probe() return impl PinInit<Self, Error>
The driver model defines the lifetime of the private data stored in (and
owned by) a bus device to be valid from when the driver is bound to a
device (i.e. from successful probe()) until the driver is unbound from
the device.

This is already taken care of by the Rust implementation of the driver
model. However, we still ask drivers to return a Result<Pin<KBox<Self>>>
from probe().

Unlike in C, where we do not have the concept of initializers, but
rather deal with uninitialized memory, drivers can just return an
impl PinInit<Self, Error> instead.

This contributes to more clarity to the fact that a driver returns it's
device private data in probe() and the Rust driver model owns the data,
manages the lifetime and - considering the lifetime - provides (safe)
accessors for the driver.

Hence, let probe() functions return an impl PinInit<Self, Error> instead
of Result<Pin<KBox<Self>>>.

Reviewed-by: Alice Ryhl <aliceryhl@google.com>
Acked-by: Viresh Kumar <viresh.kumar@linaro.org>
Reviewed-by: Alexandre Courbot <acourbot@nvidia.com>
Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Danilo Krummrich <dakr@kernel.org>
2025-10-21 18:40:48 +02:00
Benno Lossin
fc2b38de4c add [pin_]init_scope to execute code before creating an initializer
In more complex cases, initializers need to run arbitrary code before
assigning initializers to fields. While this is possible using the
underscore codeblock feature (`_: {}`), values returned by such
functions cannot be used from later field initializers.

The two new functions `[pin_]init_scope` allow users to first run some
fallible code and then return an initializer which the function turns
into a single initializer. This permits using the same value multiple
times by different fields.

Reviewed-by: Gary Guo <gary@garyguo.net>
Reviewed-by: Danilo Krummrich <dakr@kernel.org>
Signed-off-by: Benno Lossin <lossin@kernel.org>
Reviewed-by: Alice Ryhl <aliceryhl@google.com>
[ Fix typo in commit message: s/functinos/functions/. - Danilo ]
Signed-off-by: Danilo Krummrich <dakr@kernel.org>
2025-10-21 00:40:12 +02:00
Qiang Liu
3d0d1c7a5c scsi: fnic: Self-assignment of intr_time_type has no effect
Remove the self-assignment statement of the intr_time_type variable.

Signed-off-by: Qiang Liu <liuqiang@kylinos.cn>
Reviewed-by: Karan Tilak Kumar <kartilak@cisco.com>
Link: https://patch.msgid.link/20251017075504.143491-1-liuqiangneo@163.com
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-10-20 12:43:07 -04:00
André Draszik
79a2287c1d scsi: ufs: dt-bindings: exynos: Add power-domains
The UFS controller can be part of a power domain, so we need to allow
the relevant property 'power-domains'.

Signed-off-by: André Draszik <andre.draszik@linaro.org>
Reviewed-by: Peter Griffin <peter.griffin@linaro.org>
Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
Reviewed-by: Alim Akhtar <alim.akhtar@samsung.com>
Link: https://patch.msgid.link/20251007-power-domains-scsi-ufs-dt-bindings-exynos-v1-1-1acfa81a887a@linaro.org
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-10-20 12:03:14 -04:00
Bhanu Seshu Kumar Valluri
05e66c18e3 scsi: smartpqi: Prefer kmalloc_array() over kmalloc()
As a best practice use kmalloc_array() to safely calculate dynamic
object sizes without overflow.

[mkp: line exceeding 100 chars, added newline]

Acked-by: Don Brace <don.brace@microchip.com>
Signed-off-by: Bhanu Seshu Kumar Valluri <bhanuseshukumar@gmail.com>
Link: https://patch.msgid.link/20251007065345.8853-1-bhanuseshukumar@gmail.com
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-10-20 12:01:20 -04:00
Gustavo A. R. Silva
81cb6c228f scsi: megaraid_sas: Avoid a couple -Wflex-array-member-not-at-end warnings
-Wflex-array-member-not-at-end was introduced in GCC-14, and we are
getting ready to enable it, globally.

Use the new TRAILING_OVERLAP() helper to fix the following warnings:

drivers/scsi/megaraid/megaraid_sas_fusion.h:1153:31: warning: structure containing a flexible array member is not at the end of another structure [-Wflex-array-member-not-at-end]
drivers/scsi/megaraid/megaraid_sas_fusion.h:1198:32: warning: structure containing a flexible array member is not at the end of another structure [-Wflex-array-member-not-at-end]

This helper creates a union between a flexible-array member (FAM) and a
set of MEMBERS that would otherwise follow it --in this case 'struct
MR_LD_SPAN_MAP ldSpanMap[MAX_LOGICAL_DRIVES_DYN]' and 'struct
MR_LD_SPAN_MAP ldSpanMap[MAX_LOGICAL_DRIVES]' in the corresponding
structures.

This overlays the trailing members onto the FAM (struct MR_LD_SPAN_MAP
ldSpanMap[];) while keeping the FAM and the start of MEMBERS aligned.

The static_assert() ensures this alignment remains, and it's
intentionally placed inmediately after the corresponding structures --no
blank line in between.

Signed-off-by: Gustavo A. R. Silva <gustavoars@kernel.org>
Link: https://patch.msgid.link/aM1E7Xa8qYdZ598N@kspp
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-10-20 12:00:42 -04:00
Gustavo A. R. Silva
11956e4b91 scsi: isci: Avoid -Wflex-array-member-not-at-end warning
-Wflex-array-member-not-at-end was introduced in GCC-14, and we are
getting ready to enable it, globally.

Move the conflicting declaration (which happens to be in a union, so
we're moving the entire union) to the end of the corresponding
structure. Notice that `struct ssp_response_iu` is a flexible structure,
this is a structure that contains a flexible-array member.

With these changes fix the following warning:

drivers/scsi/isci/task.h:92:11: warning: structure containing a flexible
array member is not at the end of another structure
[-Wflex-array-member-not-at-end]

Signed-off-by: Gustavo A. R. Silva <gustavoars@kernel.org>
Link: https://patch.msgid.link/aM09bpl1xj9KZSZl@kspp
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
2025-10-20 12:00:11 -04:00
Danilo Krummrich
e6901808a3 rust: pci: move IRQ infrastructure to separate file
Move the PCI interrupt infrastructure to a separate sub-module in order
to keep things organized.

Signed-off-by: Danilo Krummrich <dakr@kernel.org>
2025-10-20 12:03:23 +02:00
Danilo Krummrich
3c2e31d717 rust: pci: move I/O infrastructure to separate file
Move the PCI I/O infrastructure to a separate sub-module in order to
keep things organized.

Signed-off-by: Danilo Krummrich <dakr@kernel.org>
2025-10-20 12:03:23 +02:00
Danilo Krummrich
651692d32c rust: pci: implement TryInto<IrqRequest<'a>> for IrqVector<'a>
Implement TryInto<IrqRequest<'a>> for IrqVector<'a> to directly convert
a pci::IrqVector into a generic IrqRequest, instead of taking the
indirection via an unrelated pci::Device method.

Reviewed-by: Alice Ryhl <aliceryhl@google.com>
Reviewed-by: Joel Fernandes <joelagnelf@nvidia.com>
Signed-off-by: Danilo Krummrich <dakr@kernel.org>
2025-10-20 12:03:23 +02:00
Joel Fernandes
340ccc9735 rust: pci: Allocate and manage PCI interrupt vectors
Add support to PCI rust module to allocate, free and manage IRQ vectors.
Integrate with devres for managing the allocated resources.

Signed-off-by: Joel Fernandes <joelagnelf@nvidia.com>
[ Add links in doc-comments; add missing invariant comment; re-format
  multiple safety requirements as list and fix missing backticks;
  refactor the example of alloc_irq_vectors() to compile. - Danilo ]
Signed-off-by: Danilo Krummrich <dakr@kernel.org>
2025-10-15 14:19:53 +02:00
Binbin Zhou
35bcedc1a7 MAINTAINERS: Add entry on Loongson-2K IPMI driver
When merging the Loongson-2K BMC driver, temporarily removed the
addition of the IPMI driver entry in MAINTAINERS to avoid conflicts.
This needs to be fixed as soon as possible.

Now, adding myself as maintainer for the Loongson-2K IPMI driver.

Signed-off-by: Binbin Zhou <zhoubinbin@loongson.cn>
Message-ID: <20251015095556.3736330-1-zhoubinbin@loongson.cn>
Signed-off-by: Corey Minyard <corey@minyard.net>
2025-10-15 06:37:22 -05:00
Rob Herring (Arm)
d27fea27a3 dt-bindings: ipmi: Convert aspeed,ast2400-ibt-bmc to DT schema
Convert the aspeed,ast2400-ibt-bmc binding to DT schema format. It's a
straight-forward conversion.

Signed-off-by: Rob Herring (Arm) <robh@kernel.org>
Message-ID: <20251014152948.3782738-1-robh@kernel.org>
Reviewed-by: Andrew Jeffery <andrew@codeconstruct.com.au>
Signed-off-by: Corey Minyard <corey@minyard.net>
2025-10-14 18:20:01 -05:00
Rob Herring (Arm)
1986798af7 dt-bindings: ipmi: Convert nuvoton,npcm750-kcs-bmc to DT schema
Convert the nuvoton,npcm750-kcs-bmc binding to DT schema format. It's a
straight-forward conversion.

Signed-off-by: Rob Herring (Arm) <robh@kernel.org>
Message-ID: <20251014152935.3782463-1-robh@kernel.org>
Signed-off-by: Corey Minyard <corey@minyard.net>
2025-10-14 18:19:24 -05:00
Jinhui Guo
1c35d80275 ipmi: Skip channel scan if channels are already marked ready
Channels remain static unless the BMC firmware changes.
Therefore, rescanning is unnecessary while they are marked
ready and no BMC update has occurred.

Signed-off-by: Jinhui Guo <guojinhui.liam@bytedance.com>
Message-ID: <20250930074239.2353-4-guojinhui.liam@bytedance.com>
Signed-off-by: Corey Minyard <corey@minyard.net>
2025-10-14 15:52:58 -05:00
Jinhui Guo
6bd30d8fc5 ipmi: Fix __scan_channels() failing to rescan channels
channel_handler() sets intf->channels_ready to true but never
clears it, so __scan_channels() skips any rescan. When the BMC
firmware changes a rescan is required. Allow it by clearing
the flag before starting a new scan.

Signed-off-by: Jinhui Guo <guojinhui.liam@bytedance.com>
Message-ID: <20250930074239.2353-3-guojinhui.liam@bytedance.com>
Signed-off-by: Corey Minyard <corey@minyard.net>
2025-10-14 15:52:58 -05:00
Jinhui Guo
936750fdba ipmi: Fix the race between __scan_channels() and deliver_response()
The race window between __scan_channels() and deliver_response() causes
the parameters of some channels to be set to 0.

1.[CPUA] __scan_channels() issues an IPMI request and waits with
         wait_event() until all channels have been scanned.
         wait_event() internally calls might_sleep(), which might
         yield the CPU. (Moreover, an interrupt can preempt
         wait_event() and force the task to yield the CPU.)
2.[CPUB] deliver_response() is invoked when the CPU receives the
         IPMI response. After processing a IPMI response,
         deliver_response() directly assigns intf->wchannels to
         intf->channel_list and sets intf->channels_ready to true.
         However, not all channels are actually ready for use.
3.[CPUA] Since intf->channels_ready is already true, wait_event()
         never enters __wait_event(). __scan_channels() immediately
         clears intf->null_user_handler and exits.
4.[CPUB] Once intf->null_user_handler is set to NULL, deliver_response()
         ignores further IPMI responses, leaving the remaining
	 channels zero-initialized and unusable.

CPUA                             CPUB
-------------------------------  -----------------------------
__scan_channels()
 intf->null_user_handler
       = channel_handler;
 send_channel_info_cmd(intf,
       0);
 wait_event(intf->waitq,
       intf->channels_ready);
  do {
   might_sleep();
                                 deliver_response()
                                  channel_handler()
                                   intf->channel_list =
				         intf->wchannels + set;
                                   intf->channels_ready = true;
                                   send_channel_info_cmd(intf,
                                         intf->curr_channel);
   if (condition)
    break;
   __wait_event(wq_head,
          condition);
  } while(0)
 intf->null_user_handler
       = NULL;
                                 deliver_response()
                                  if (!msg->user)
                                   if (intf->null_user_handler)
                                    rv = -EINVAL;
                                  return rv;
-------------------------------  -----------------------------

Fix the race between __scan_channels() and deliver_response() by
deferring both the assignment intf->channel_list = intf->wchannels
and the flag intf->channels_ready = true until all channels have
been successfully scanned or until the IPMI request has failed.

Signed-off-by: Jinhui Guo <guojinhui.liam@bytedance.com>
Message-ID: <20250930074239.2353-2-guojinhui.liam@bytedance.com>
Signed-off-by: Corey Minyard <corey@minyard.net>
2025-10-14 15:52:58 -05:00
200 changed files with 8167 additions and 2370 deletions

View File

@@ -764,6 +764,17 @@ Description:
participate in load balancing. These CPUs are set by
boot parameter "isolcpus=".
What: /sys/devices/system/cpu/housekeeping
Date: Oct 2025
Contact: Linux kernel mailing list <linux-kernel@vger.kernel.org>
Description:
(RO) the list of logical CPUs that are designated by the kernel as
"housekeeping". Each CPU are responsible for handling essential
system-wide background tasks, including RCU callbacks, delayed
timer callbacks, and unbound workqueues, minimizing scheduling
jitter on low-latency, isolated CPUs. These CPUs are set when boot
parameter "isolcpus=nohz" or "nohz_full=" is specified.
What: /sys/devices/system/cpu/crash_hotplug
Date: Aug 2023
Contact: Linux kernel mailing list <linux-kernel@vger.kernel.org>

View File

@@ -1211,12 +1211,8 @@ Kernel parameters
debugfs= [KNL,EARLY] This parameter enables what is exposed to
userspace and debugfs internal clients.
Format: { on, no-mount, off }
Format: { on, off }
on: All functions are enabled.
no-mount:
Filesystem is not registered but kernel clients can
access APIs and a crashkernel can be used to read
its content. There is nothing to mount.
off: Filesystem is not registered and clients
get a -EPERM as result when trying to register files
or directories within debugfs.

View File

@@ -1,28 +0,0 @@
* Aspeed BT (Block Transfer) IPMI interface
The Aspeed SOCs (AST2400 and AST2500) are commonly used as BMCs
(BaseBoard Management Controllers) and the BT interface can be used to
perform in-band IPMI communication with their host.
Required properties:
- compatible : should be one of
"aspeed,ast2400-ibt-bmc"
"aspeed,ast2500-ibt-bmc"
"aspeed,ast2600-ibt-bmc"
- reg: physical address and size of the registers
- clocks: clock for the device
Optional properties:
- interrupts: interrupt generated by the BT interface. without an
interrupt, the driver will operate in poll mode.
Example:
ibt@1e789140 {
compatible = "aspeed,ast2400-ibt-bmc";
reg = <0x1e789140 0x18>;
interrupts = <8>;
clocks = <&syscon ASPEED_CLK_GATE_LCLK>;
};

View File

@@ -0,0 +1,44 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/ipmi/aspeed,ast2400-ibt-bmc.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Aspeed Block Transfer (BT) IPMI interface
maintainers:
- Joel Stanley <joel@jms.id.au>
properties:
compatible:
enum:
- aspeed,ast2400-ibt-bmc
- aspeed,ast2500-ibt-bmc
- aspeed,ast2600-ibt-bmc
reg:
maxItems: 1
clocks:
maxItems: 1
interrupts:
maxItems: 1
required:
- compatible
- reg
- clocks
additionalProperties: false
examples:
- |
#include <dt-bindings/clock/aspeed-clock.h>
bt@1e789140 {
compatible = "aspeed,ast2400-ibt-bmc";
reg = <0x1e789140 0x18>;
interrupts = <8>;
clocks = <&syscon ASPEED_CLK_GATE_LCLK>;
};

View File

@@ -1,40 +0,0 @@
* Nuvoton NPCM KCS (Keyboard Controller Style) IPMI interface
The Nuvoton SOCs (NPCM) are commonly used as BMCs
(Baseboard Management Controllers) and the KCS interface can be
used to perform in-band IPMI communication with their host.
Required properties:
- compatible : should be one of
"nuvoton,npcm750-kcs-bmc"
"nuvoton,npcm845-kcs-bmc", "nuvoton,npcm750-kcs-bmc"
- interrupts : interrupt generated by the controller
- kcs_chan : The KCS channel number in the controller
Example:
lpc_kcs: lpc_kcs@f0007000 {
compatible = "nuvoton,npcm750-lpc-kcs", "simple-mfd", "syscon";
reg = <0xf0007000 0x40>;
reg-io-width = <1>;
#address-cells = <1>;
#size-cells = <1>;
ranges = <0x0 0xf0007000 0x40>;
kcs1: kcs1@0 {
compatible = "nuvoton,npcm750-kcs-bmc";
reg = <0x0 0x40>;
interrupts = <0 9 4>;
kcs_chan = <1>;
status = "disabled";
};
kcs2: kcs2@0 {
compatible = "nuvoton,npcm750-kcs-bmc";
reg = <0x0 0x40>;
interrupts = <0 9 4>;
kcs_chan = <2>;
status = "disabled";
};
};

View File

@@ -0,0 +1,55 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/ipmi/nuvoton,npcm750-kcs-bmc.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Nuvoton NPCM KCS BMC
maintainers:
- Avi Fishman <avifishman70@gmail.com>
- Tomer Maimon <tmaimon77@gmail.com>
- Tali Perry <tali.perry1@gmail.com>
description:
The Nuvoton SOCs (NPCM) are commonly used as BMCs (Baseboard Management
Controllers) and the KCS interface can be used to perform in-band IPMI
communication with their host.
properties:
compatible:
oneOf:
- const: nuvoton,npcm750-kcs-bmc
- items:
- enum:
- nuvoton,npcm845-kcs-bmc
- const: nuvoton,npcm750-kcs-bmc
reg:
maxItems: 1
interrupts:
maxItems: 1
kcs_chan:
description: The KCS channel number in the controller
$ref: /schemas/types.yaml#/definitions/uint32
minimum: 1
maximum: 3
required:
- compatible
- reg
- interrupts
- kcs_chan
additionalProperties: false
examples:
- |
kcs@0 {
compatible = "nuvoton,npcm750-kcs-bmc";
reg = <0x0 0x40>;
interrupts = <9 4>;
kcs_chan = <1>;
};

View File

@@ -8,8 +8,9 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
title: MediaTek Universal Flash Storage (UFS) M-PHY
maintainers:
- Stanley Chu <stanley.chu@mediatek.com>
- Chunfeng Yun <chunfeng.yun@mediatek.com>
- Peter Wang <peter.wang@mediatek.com>
- Chaotian Jing <chaotian.jing@mediatek.com>
description: |
UFS M-PHY nodes are defined to describe on-chip UFS M-PHY hardware macro.

View File

@@ -0,0 +1,61 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/ufs/amd,versal2-ufs.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: AMD Versal Gen 2 UFS Host Controller
maintainers:
- Sai Krishna Potthuri <sai.krishna.potthuri@amd.com>
allOf:
- $ref: ufs-common.yaml
properties:
compatible:
const: amd,versal2-ufs
reg:
maxItems: 1
clocks:
maxItems: 1
clock-names:
items:
- const: core
power-domains:
maxItems: 1
resets:
maxItems: 2
reset-names:
items:
- const: host
- const: phy
required:
- reg
- clocks
- clock-names
- resets
- reset-names
unevaluatedProperties: false
examples:
- |
#include <dt-bindings/interrupt-controller/arm-gic.h>
ufs@f10b0000 {
compatible = "amd,versal2-ufs";
reg = <0xf10b0000 0x1000>;
clocks = <&ufs_core_clk>;
clock-names = "core";
resets = <&scmi_reset 4>, <&scmi_reset 35>;
reset-names = "host", "phy";
interrupts = <GIC_SPI 234 IRQ_TYPE_LEVEL_HIGH>;
freq-table-hz = <0 0>;
};

View File

@@ -7,7 +7,8 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
title: Mediatek Universal Flash Storage (UFS) Controller
maintainers:
- Stanley Chu <stanley.chu@mediatek.com>
- Peter Wang <peter.wang@mediatek.com>
- Chaotian Jing <chaotian.jing@mediatek.com>
properties:
compatible:

View File

@@ -88,7 +88,6 @@ allOf:
- const: ice_core_clk
reg:
minItems: 2
maxItems: 2
reg-names:
minItems: 2
required:
@@ -117,7 +116,6 @@ allOf:
- const: tx_lane0_sync_clk
- const: rx_lane0_sync_clk
reg:
minItems: 1
maxItems: 1
reg-names:
maxItems: 1
@@ -147,7 +145,6 @@ allOf:
- const: ice_core_clk
reg:
minItems: 2
maxItems: 2
reg-names:
minItems: 2
required:

View File

@@ -61,6 +61,9 @@ properties:
phy-names:
const: ufs-phy
power-domains:
maxItems: 1
samsung,sysreg:
$ref: /schemas/types.yaml#/definitions/phandle-array
items:

View File

@@ -383,7 +383,6 @@ NET
PER-CPU MEM
devm_alloc_percpu()
devm_free_percpu()
PCI
devm_pci_alloc_host_bridge() : managed PCI host bridge allocation

View File

@@ -11821,6 +11821,16 @@ F: include/linux/i2c.h
F: include/uapi/linux/i2c-*.h
F: include/uapi/linux/i2c.h
I2C SUBSYSTEM [RUST]
M: Igor Korotin <igor.korotin.linux@gmail.com>
R: Danilo Krummrich <dakr@kernel.org>
R: Daniel Almeida <daniel.almeida@collabora.com>
L: rust-for-linux@vger.kernel.org
S: Maintained
F: rust/kernel/i2c.rs
F: samples/rust/rust_driver_i2c.rs
F: samples/rust/rust_i2c_client.rs
I2C SUBSYSTEM HOST DRIVERS
M: Andi Shyti <andi.shyti@kernel.org>
L: linux-i2c@vger.kernel.org
@@ -14767,6 +14777,7 @@ LOONGSON-2K Board Management Controller (BMC) DRIVER
M: Binbin Zhou <zhoubinbin@loongson.cn>
M: Chong Qiao <qiaochong@loongson.cn>
S: Maintained
F: drivers/char/ipmi/ipmi_si_ls2k.c
F: drivers/mfd/ls2k-bmc-core.c
LOONGSON EDAC DRIVER
@@ -23313,6 +23324,7 @@ F: drivers/scsi/
F: drivers/ufs/
F: include/scsi/
F: include/uapi/scsi/
F: include/ufs/
SCSI TAPE DRIVER
M: Kai Mäkisara <Kai.Makisara@kolumbus.fi>
@@ -26628,6 +26640,14 @@ S: Supported
F: Documentation/devicetree/bindings/ufs/
F: Documentation/scsi/ufs.rst
F: drivers/ufs/core/
F: include/ufs/
UNIVERSAL FLASH STORAGE HOST CONTROLLER DRIVER AMD VERSAL2
M: Sai Krishna Potthuri <sai.krishna.potthuri@amd.com>
M: Ajay Neeli <ajay.neeli@amd.com>
S: Maintained
F: Documentation/devicetree/bindings/ufs/amd,versal2-ufs.yaml
F: drivers/ufs/host/ufs-amd-versal2.c
UNIVERSAL FLASH STORAGE HOST CONTROLLER DRIVER DWC HOOKS
M: Pedro Sousa <pedrom.sousa@synopsys.com>
@@ -26645,6 +26665,7 @@ F: drivers/ufs/host/ufs-exynos*
UNIVERSAL FLASH STORAGE HOST CONTROLLER DRIVER MEDIATEK HOOKS
M: Peter Wang <peter.wang@mediatek.com>
M: Chaotian Jing <chaotian.jing@mediatek.com>
R: Stanley Jhu <chu.stanley@gmail.com>
L: linux-scsi@vger.kernel.org
L: linux-mediatek@lists.infradead.org (moderated for non-subscribers)

View File

@@ -36,6 +36,9 @@ void update_freq_counters_refs(void);
#define arch_scale_hw_pressure topology_get_hw_pressure
#define arch_update_hw_pressure topology_update_hw_pressure
#undef arch_cpu_is_threaded
#define arch_cpu_is_threaded() (read_cpuid_mpidr() & MPIDR_MT_BITMASK)
#include <asm-generic/topology.h>
#endif /* _ASM_ARM_TOPOLOGY_H */

View File

@@ -25,107 +25,6 @@
#include <asm/cputype.h>
#include <asm/topology.h>
#ifdef CONFIG_ACPI
static bool __init acpi_cpu_is_threaded(int cpu)
{
int is_threaded = acpi_pptt_cpu_is_thread(cpu);
/*
* if the PPTT doesn't have thread information, assume a homogeneous
* machine and return the current CPU's thread state.
*/
if (is_threaded < 0)
is_threaded = read_cpuid_mpidr() & MPIDR_MT_BITMASK;
return !!is_threaded;
}
struct cpu_smt_info {
unsigned int thread_num;
int core_id;
};
/*
* Propagate the topology information of the processor_topology_node tree to the
* cpu_topology array.
*/
int __init parse_acpi_topology(void)
{
unsigned int max_smt_thread_num = 1;
struct cpu_smt_info *entry;
struct xarray hetero_cpu;
unsigned long hetero_id;
int cpu, topology_id;
if (acpi_disabled)
return 0;
xa_init(&hetero_cpu);
for_each_possible_cpu(cpu) {
topology_id = find_acpi_cpu_topology(cpu, 0);
if (topology_id < 0)
return topology_id;
if (acpi_cpu_is_threaded(cpu)) {
cpu_topology[cpu].thread_id = topology_id;
topology_id = find_acpi_cpu_topology(cpu, 1);
cpu_topology[cpu].core_id = topology_id;
/*
* In the PPTT, CPUs below a node with the 'identical
* implementation' flag have the same number of threads.
* Count the number of threads for only one CPU (i.e.
* one core_id) among those with the same hetero_id.
* See the comment of find_acpi_cpu_topology_hetero_id()
* for more details.
*
* One entry is created for each node having:
* - the 'identical implementation' flag
* - its parent not having the flag
*/
hetero_id = find_acpi_cpu_topology_hetero_id(cpu);
entry = xa_load(&hetero_cpu, hetero_id);
if (!entry) {
entry = kzalloc(sizeof(*entry), GFP_KERNEL);
WARN_ON_ONCE(!entry);
if (entry) {
entry->core_id = topology_id;
entry->thread_num = 1;
xa_store(&hetero_cpu, hetero_id,
entry, GFP_KERNEL);
}
} else if (entry->core_id == topology_id) {
entry->thread_num++;
}
} else {
cpu_topology[cpu].thread_id = -1;
cpu_topology[cpu].core_id = topology_id;
}
topology_id = find_acpi_cpu_topology_cluster(cpu);
cpu_topology[cpu].cluster_id = topology_id;
topology_id = find_acpi_cpu_topology_package(cpu);
cpu_topology[cpu].package_id = topology_id;
}
/*
* This is a short loop since the number of XArray elements is the
* number of heterogeneous CPU clusters. On a homogeneous system
* there's only one entry in the XArray.
*/
xa_for_each(&hetero_cpu, hetero_id, entry) {
max_smt_thread_num = max(max_smt_thread_num, entry->thread_num);
xa_erase(&hetero_cpu, hetero_id);
kfree(entry);
}
cpu_smt_set_num_threads(max_smt_thread_num, max_smt_thread_num);
xa_destroy(&hetero_cpu);
return 0;
}
#endif
#ifdef CONFIG_ARM64_AMU_EXTN
#define read_corecnt() read_sysreg_s(SYS_AMEVCNTR0_CORE_EL0)
#define read_constcnt() read_sysreg_s(SYS_AMEVCNTR0_CONST_EL0)

View File

@@ -245,6 +245,73 @@ void ata_acpi_bind_dev(struct ata_device *dev)
ata_acpi_dev_uevent);
}
/**
* ata_acpi_dev_manage_restart - if the disk should be stopped (spun down) on
* system restart.
* @dev: target ATA device
*
* RETURNS:
* true if the disk should be stopped, otherwise false.
*/
bool ata_acpi_dev_manage_restart(struct ata_device *dev)
{
struct device *tdev;
/*
* If ATA_FLAG_ACPI_SATA is set, the acpi fwnode is attached to the
* ata_device instead of the ata_port.
*/
if (dev->link->ap->flags & ATA_FLAG_ACPI_SATA)
tdev = &dev->tdev;
else
tdev = &dev->link->ap->tdev;
if (!is_acpi_device_node(tdev->fwnode))
return false;
return acpi_bus_power_manageable(ACPI_HANDLE(tdev));
}
/**
* ata_acpi_port_power_on - set the power state of the ata port to D0
* @ap: target ATA port
*
* This function is called at the beginning of ata_port_probe().
*/
void ata_acpi_port_power_on(struct ata_port *ap)
{
acpi_handle handle;
int i;
/*
* If ATA_FLAG_ACPI_SATA is set, the acpi fwnode is attached to the
* ata_device instead of the ata_port.
*/
if (ap->flags & ATA_FLAG_ACPI_SATA) {
for (i = 0; i < ATA_MAX_DEVICES; i++) {
struct ata_device *dev = &ap->link.device[i];
if (!is_acpi_device_node(dev->tdev.fwnode))
continue;
handle = ACPI_HANDLE(&dev->tdev);
if (!acpi_bus_power_manageable(handle))
continue;
if (acpi_bus_set_power(handle, ACPI_STATE_D0))
ata_dev_err(dev,
"acpi: failed to set power state to D0\n");
}
return;
}
if (!is_acpi_device_node(ap->tdev.fwnode))
return;
handle = ACPI_HANDLE(&ap->tdev);
if (!acpi_bus_power_manageable(handle))
return;
if (acpi_bus_set_power(handle, ACPI_STATE_D0))
ata_port_err(ap, "acpi: failed to set power state to D0\n");
}
/**
* ata_acpi_dissociate - dissociate ATA host from ACPI objects
* @host: target ATA host

View File

@@ -3146,6 +3146,10 @@ int ata_dev_configure(struct ata_device *dev)
dev->max_sectors = min_t(unsigned int, ATA_MAX_SECTORS_1024,
dev->max_sectors);
if (dev->quirks & ATA_QUIRK_MAX_SEC_8191)
dev->max_sectors = min_t(unsigned int, ATA_MAX_SECTORS_8191,
dev->max_sectors);
if (dev->quirks & ATA_QUIRK_MAX_SEC_LBA48)
dev->max_sectors = ATA_MAX_SECTORS_LBA48;
@@ -3998,6 +4002,7 @@ static const char * const ata_quirk_names[] = {
[__ATA_QUIRK_NO_DMA_LOG] = "nodmalog",
[__ATA_QUIRK_NOTRIM] = "notrim",
[__ATA_QUIRK_MAX_SEC_1024] = "maxsec1024",
[__ATA_QUIRK_MAX_SEC_8191] = "maxsec8191",
[__ATA_QUIRK_MAX_TRIM_128M] = "maxtrim128m",
[__ATA_QUIRK_NO_NCQ_ON_ATI] = "noncqonati",
[__ATA_QUIRK_NO_LPM_ON_ATI] = "nolpmonati",
@@ -4104,6 +4109,12 @@ static const struct ata_dev_quirks_entry __ata_dev_quirks[] = {
{ "LITEON CX1-JB*-HP", NULL, ATA_QUIRK_MAX_SEC_1024 },
{ "LITEON EP1-*", NULL, ATA_QUIRK_MAX_SEC_1024 },
/*
* These devices time out with higher max sects.
* https://bugzilla.kernel.org/show_bug.cgi?id=220693
*/
{ "DELLBOSS VD", "MV.R00-0", ATA_QUIRK_MAX_SEC_8191 },
/* Devices we expect to fail diagnostics */
/* Devices where NCQ should be avoided */
@@ -5915,6 +5926,8 @@ void ata_port_probe(struct ata_port *ap)
struct ata_eh_info *ehi = &ap->link.eh_info;
unsigned long flags;
ata_acpi_port_power_on(ap);
/* kick EH for boot probing */
spin_lock_irqsave(ap->lock, flags);

View File

@@ -1102,6 +1102,7 @@ int ata_scsi_dev_config(struct scsi_device *sdev, struct queue_limits *lim,
*/
sdev->manage_runtime_start_stop = 1;
sdev->manage_shutdown = 1;
sdev->manage_restart = ata_acpi_dev_manage_restart(dev);
sdev->force_runtime_start_on_system_start = 1;
}

View File

@@ -130,6 +130,8 @@ extern void ata_acpi_on_disable(struct ata_device *dev);
extern void ata_acpi_set_state(struct ata_port *ap, pm_message_t state);
extern void ata_acpi_bind_port(struct ata_port *ap);
extern void ata_acpi_bind_dev(struct ata_device *dev);
extern void ata_acpi_port_power_on(struct ata_port *ap);
extern bool ata_acpi_dev_manage_restart(struct ata_device *dev);
extern acpi_handle ata_dev_acpi_handle(struct ata_device *dev);
#else
static inline void ata_acpi_dissociate(struct ata_host *host) { }
@@ -140,6 +142,8 @@ static inline void ata_acpi_set_state(struct ata_port *ap,
pm_message_t state) { }
static inline void ata_acpi_bind_port(struct ata_port *ap) {}
static inline void ata_acpi_bind_dev(struct ata_device *dev) {}
static inline void ata_acpi_port_power_on(struct ata_port *ap) {}
static inline bool ata_acpi_dev_manage_restart(struct ata_device *dev) { return 0; }
#endif
/* libata-scsi.c */

View File

@@ -823,12 +823,106 @@ void remove_cpu_topology(unsigned int cpu)
clear_cpu_topology(cpu);
}
#if defined(CONFIG_ARM64) || defined(CONFIG_RISCV)
struct cpu_smt_info {
unsigned int thread_num;
int core_id;
};
static bool __init acpi_cpu_is_threaded(int cpu)
{
int is_threaded = acpi_pptt_cpu_is_thread(cpu);
/*
* if the PPTT doesn't have thread information, check for architecture
* specific fallback if available
*/
if (is_threaded < 0)
is_threaded = arch_cpu_is_threaded();
return !!is_threaded;
}
/*
* Propagate the topology information of the processor_topology_node tree to the
* cpu_topology array.
*/
__weak int __init parse_acpi_topology(void)
{
unsigned int max_smt_thread_num = 1;
struct cpu_smt_info *entry;
struct xarray hetero_cpu;
unsigned long hetero_id;
int cpu, topology_id;
if (acpi_disabled)
return 0;
xa_init(&hetero_cpu);
for_each_possible_cpu(cpu) {
topology_id = find_acpi_cpu_topology(cpu, 0);
if (topology_id < 0)
return topology_id;
if (acpi_cpu_is_threaded(cpu)) {
cpu_topology[cpu].thread_id = topology_id;
topology_id = find_acpi_cpu_topology(cpu, 1);
cpu_topology[cpu].core_id = topology_id;
/*
* In the PPTT, CPUs below a node with the 'identical
* implementation' flag have the same number of threads.
* Count the number of threads for only one CPU (i.e.
* one core_id) among those with the same hetero_id.
* See the comment of find_acpi_cpu_topology_hetero_id()
* for more details.
*
* One entry is created for each node having:
* - the 'identical implementation' flag
* - its parent not having the flag
*/
hetero_id = find_acpi_cpu_topology_hetero_id(cpu);
entry = xa_load(&hetero_cpu, hetero_id);
if (!entry) {
entry = kzalloc(sizeof(*entry), GFP_KERNEL);
WARN_ON_ONCE(!entry);
if (entry) {
entry->core_id = topology_id;
entry->thread_num = 1;
xa_store(&hetero_cpu, hetero_id,
entry, GFP_KERNEL);
}
} else if (entry->core_id == topology_id) {
entry->thread_num++;
}
} else {
cpu_topology[cpu].thread_id = -1;
cpu_topology[cpu].core_id = topology_id;
}
topology_id = find_acpi_cpu_topology_cluster(cpu);
cpu_topology[cpu].cluster_id = topology_id;
topology_id = find_acpi_cpu_topology_package(cpu);
cpu_topology[cpu].package_id = topology_id;
}
/*
* This is a short loop since the number of XArray elements is the
* number of heterogeneous CPU clusters. On a homogeneous system
* there's only one entry in the XArray.
*/
xa_for_each(&hetero_cpu, hetero_id, entry) {
max_smt_thread_num = max(max_smt_thread_num, entry->thread_num);
xa_erase(&hetero_cpu, hetero_id);
kfree(entry);
}
cpu_smt_set_num_threads(max_smt_thread_num, max_smt_thread_num);
xa_destroy(&hetero_cpu);
return 0;
}
#if defined(CONFIG_ARM64) || defined(CONFIG_RISCV)
void __init init_cpu_topology(void)
{
int cpu, ret;

View File

@@ -85,6 +85,18 @@ struct driver_private {
};
#define to_driver(obj) container_of(obj, struct driver_private, kobj)
#ifdef CONFIG_RUST
/**
* struct driver_type - Representation of a Rust driver type.
*/
struct driver_type {
/**
* @id: Representation of core::any::TypeId.
*/
u8 id[16];
} __packed;
#endif
/**
* struct device_private - structure to hold the private to the driver core portions of the device structure.
*
@@ -100,6 +112,7 @@ struct driver_private {
* @async_driver - pointer to device driver awaiting probe via async_probe
* @device - pointer back to the struct device that this structure is
* associated with.
* @driver_type - The type of the bound Rust driver.
* @dead - This device is currently either in the process of or has been
* removed from the system. Any asynchronous events scheduled for this
* device should exit without taking any action.
@@ -116,6 +129,9 @@ struct device_private {
const struct device_driver *async_driver;
char *deferred_probe_reason;
struct device *device;
#ifdef CONFIG_RUST
struct driver_type driver_type;
#endif
u8 dead:1;
};
#define to_device_private_parent(obj) \

View File

@@ -533,8 +533,7 @@ void bus_probe_device(struct device *dev)
if (!sp)
return;
if (sp->drivers_autoprobe)
device_initial_probe(dev);
device_initial_probe(dev);
mutex_lock(&sp->mutex);
list_for_each_entry(sif, &sp->interfaces, node)

View File

@@ -4138,7 +4138,7 @@ int __init devices_init(void)
sysfs_dev_char_kobj = kobject_create_and_add("char", dev_kobj);
if (!sysfs_dev_char_kobj)
goto char_kobj_err;
device_link_wq = alloc_workqueue("device_link_wq", 0, 0);
device_link_wq = alloc_workqueue("device_link_wq", WQ_PERCPU, 0);
if (!device_link_wq)
goto wq_err;

View File

@@ -300,13 +300,30 @@ static ssize_t print_cpus_isolated(struct device *dev,
}
static DEVICE_ATTR(isolated, 0444, print_cpus_isolated, NULL);
#ifdef CONFIG_NO_HZ_FULL
static ssize_t print_cpus_nohz_full(struct device *dev,
struct device_attribute *attr, char *buf)
static ssize_t housekeeping_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
return sysfs_emit(buf, "%*pbl\n", cpumask_pr_args(tick_nohz_full_mask));
const struct cpumask *hk_mask;
hk_mask = housekeeping_cpumask(HK_TYPE_KERNEL_NOISE);
if (housekeeping_enabled(HK_TYPE_KERNEL_NOISE))
return sysfs_emit(buf, "%*pbl\n", cpumask_pr_args(hk_mask));
return sysfs_emit(buf, "\n");
}
static DEVICE_ATTR(nohz_full, 0444, print_cpus_nohz_full, NULL);
static DEVICE_ATTR_RO(housekeeping);
#ifdef CONFIG_NO_HZ_FULL
static ssize_t nohz_full_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
if (cpumask_available(tick_nohz_full_mask))
return sysfs_emit(buf, "%*pbl\n",
cpumask_pr_args(tick_nohz_full_mask));
return sysfs_emit(buf, "\n");
}
static DEVICE_ATTR_RO(nohz_full);
#endif
#ifdef CONFIG_CRASH_HOTPLUG
@@ -505,6 +522,7 @@ static struct attribute *cpu_root_attrs[] = {
&dev_attr_offline.attr,
&dev_attr_enabled.attr,
&dev_attr_isolated.attr,
&dev_attr_housekeeping.attr,
#ifdef CONFIG_NO_HZ_FULL
&dev_attr_nohz_full.attr,
#endif

View File

@@ -193,7 +193,7 @@ void driver_deferred_probe_trigger(void)
* Kick the re-probe thread. It may already be scheduled, but it is
* safe to kick it again.
*/
queue_work(system_unbound_wq, &deferred_probe_work);
queue_work(system_dfl_wq, &deferred_probe_work);
}
/**
@@ -1077,7 +1077,15 @@ EXPORT_SYMBOL_GPL(device_attach);
void device_initial_probe(struct device *dev)
{
__device_attach(dev, true);
struct subsys_private *sp = bus_to_subsys(dev->bus);
if (!sp)
return;
if (sp->drivers_autoprobe)
__device_attach(dev, true);
subsys_put(sp);
}
/*

View File

@@ -1222,13 +1222,6 @@ static void devm_percpu_release(struct device *dev, void *pdata)
free_percpu(p);
}
static int devm_percpu_match(struct device *dev, void *data, void *p)
{
struct devres *devr = container_of(data, struct devres, data);
return *(void **)devr->data == p;
}
/**
* __devm_alloc_percpu - Resource-managed alloc_percpu
* @dev: Device to allocate per-cpu memory for
@@ -1264,21 +1257,3 @@ void __percpu *__devm_alloc_percpu(struct device *dev, size_t size,
return pcpu;
}
EXPORT_SYMBOL_GPL(__devm_alloc_percpu);
/**
* devm_free_percpu - Resource-managed free_percpu
* @dev: Device this memory belongs to
* @pdata: Per-cpu memory to free
*
* Free memory allocated with devm_alloc_percpu().
*/
void devm_free_percpu(struct device *dev, void __percpu *pdata)
{
/*
* Use devres_release() to prevent memory leakage as
* devm_free_pages() does.
*/
WARN_ON(devres_release(dev, devm_percpu_release, devm_percpu_match,
(void *)(__force unsigned long)pdata));
}
EXPORT_SYMBOL_GPL(devm_free_percpu);

View File

@@ -47,7 +47,10 @@ static ssize_t timeout_show(const struct class *class, const struct class_attrib
static ssize_t timeout_store(const struct class *class, const struct class_attribute *attr,
const char *buf, size_t count)
{
int tmp_loading_timeout = simple_strtol(buf, NULL, 10);
int tmp_loading_timeout;
if (kstrtoint(buf, 10, &tmp_loading_timeout))
return -EINVAL;
if (tmp_loading_timeout < 0)
tmp_loading_timeout = 0;
@@ -157,7 +160,10 @@ static ssize_t firmware_loading_store(struct device *dev,
struct fw_sysfs *fw_sysfs = to_fw_sysfs(dev);
struct fw_priv *fw_priv;
ssize_t written = count;
int loading = simple_strtol(buf, NULL, 10);
int loading;
if (kstrtoint(buf, 10, &loading))
return -EINVAL;
mutex_lock(&fw_lock);
fw_priv = fw_sysfs->fw_priv;

View File

@@ -100,8 +100,10 @@ static ssize_t cancel_store(struct device *dev, struct device_attribute *attr,
return -EINVAL;
mutex_lock(&fwlp->lock);
if (fwlp->progress == FW_UPLOAD_PROG_IDLE)
ret = -ENODEV;
if (fwlp->progress == FW_UPLOAD_PROG_IDLE) {
mutex_unlock(&fwlp->lock);
return -ENODEV;
}
fwlp->ops->cancel(fwlp->fw_upload);
mutex_unlock(&fwlp->lock);

View File

@@ -599,7 +599,8 @@ static void __ipmi_bmc_unregister(struct ipmi_smi *intf);
static int __ipmi_bmc_register(struct ipmi_smi *intf,
struct ipmi_device_id *id,
bool guid_set, guid_t *guid, int intf_num);
static int __scan_channels(struct ipmi_smi *intf, struct ipmi_device_id *id);
static int __scan_channels(struct ipmi_smi *intf,
struct ipmi_device_id *id, bool rescan);
static void free_ipmi_user(struct kref *ref)
{
@@ -2668,7 +2669,7 @@ retry_bmc_lock:
if (__ipmi_bmc_register(intf, &id, guid_set, &guid, intf_num))
need_waiter(intf); /* Retry later on an error. */
else
__scan_channels(intf, &id);
__scan_channels(intf, &id, false);
if (!intf_set) {
@@ -2688,7 +2689,7 @@ retry_bmc_lock:
goto out_noprocessing;
} else if (memcmp(&bmc->fetch_id, &bmc->id, sizeof(bmc->id)))
/* Version info changes, scan the channels again. */
__scan_channels(intf, &bmc->fetch_id);
__scan_channels(intf, &bmc->fetch_id, true);
bmc->dyn_id_expiry = jiffies + IPMI_DYN_DEV_ID_EXPIRY;
@@ -3417,8 +3418,6 @@ channel_handler(struct ipmi_smi *intf, struct ipmi_recv_msg *msg)
intf->channels_ready = true;
wake_up(&intf->waitq);
} else {
intf->channel_list = intf->wchannels + set;
intf->channels_ready = true;
rv = send_channel_info_cmd(intf, intf->curr_channel);
}
@@ -3440,10 +3439,21 @@ channel_handler(struct ipmi_smi *intf, struct ipmi_recv_msg *msg)
/*
* Must be holding intf->bmc_reg_mutex to call this.
*/
static int __scan_channels(struct ipmi_smi *intf, struct ipmi_device_id *id)
static int __scan_channels(struct ipmi_smi *intf,
struct ipmi_device_id *id,
bool rescan)
{
int rv;
if (rescan) {
/* Clear channels_ready to force channels rescan. */
intf->channels_ready = false;
}
/* Skip channel scan if channels are already marked ready */
if (intf->channels_ready)
return 0;
if (ipmi_version_major(id) > 1
|| (ipmi_version_major(id) == 1
&& ipmi_version_minor(id) >= 5)) {
@@ -3658,7 +3668,7 @@ int ipmi_add_smi(struct module *owner,
}
mutex_lock(&intf->bmc_reg_mutex);
rv = __scan_channels(intf, &id);
rv = __scan_channels(intf, &id, false);
mutex_unlock(&intf->bmc_reg_mutex);
if (rv)
goto out_err_bmc_reg;

View File

@@ -11,8 +11,11 @@
* used by the kernel internally.
*/
#include "linux/dev_printk.h"
#include "linux/tpm.h"
#include "tpm.h"
#include <crypto/hash_info.h>
#include <linux/unaligned.h>
static bool disable_pcr_integrity;
module_param(disable_pcr_integrity, bool, 0444);
@@ -199,11 +202,15 @@ int tpm2_pcr_extend(struct tpm_chip *chip, u32 pcr_idx,
}
if (!disable_pcr_integrity) {
tpm_buf_append_name(chip, &buf, pcr_idx, NULL);
rc = tpm_buf_append_name(chip, &buf, pcr_idx, NULL);
if (rc) {
tpm_buf_destroy(&buf);
return rc;
}
tpm_buf_append_hmac_session(chip, &buf, 0, NULL, 0);
} else {
tpm_buf_append_handle(chip, &buf, pcr_idx);
tpm_buf_append_auth(chip, &buf, 0, NULL, 0);
tpm_buf_append_auth(chip, &buf, NULL, 0);
}
tpm_buf_append_u32(&buf, chip->nr_allocated_banks);
@@ -214,8 +221,14 @@ int tpm2_pcr_extend(struct tpm_chip *chip, u32 pcr_idx,
chip->allocated_banks[i].digest_size);
}
if (!disable_pcr_integrity)
tpm_buf_fill_hmac_session(chip, &buf);
if (!disable_pcr_integrity) {
rc = tpm_buf_fill_hmac_session(chip, &buf);
if (rc) {
tpm_buf_destroy(&buf);
return rc;
}
}
rc = tpm_transmit_cmd(chip, &buf, 0, "attempting extend a PCR value");
if (!disable_pcr_integrity)
rc = tpm_buf_check_hmac_response(chip, &buf, rc);
@@ -269,11 +282,24 @@ int tpm2_get_random(struct tpm_chip *chip, u8 *dest, size_t max)
do {
tpm_buf_reset(&buf, TPM2_ST_SESSIONS, TPM2_CC_GET_RANDOM);
tpm_buf_append_hmac_session_opt(chip, &buf, TPM2_SA_ENCRYPT
| TPM2_SA_CONTINUE_SESSION,
NULL, 0);
if (tpm2_chip_auth(chip)) {
tpm_buf_append_hmac_session(chip, &buf,
TPM2_SA_ENCRYPT |
TPM2_SA_CONTINUE_SESSION,
NULL, 0);
} else {
offset = buf.handles * 4 + TPM_HEADER_SIZE;
head = (struct tpm_header *)buf.data;
if (tpm_buf_length(&buf) == offset)
head->tag = cpu_to_be16(TPM2_ST_NO_SESSIONS);
}
tpm_buf_append_u16(&buf, num_bytes);
tpm_buf_fill_hmac_session(chip, &buf);
err = tpm_buf_fill_hmac_session(chip, &buf);
if (err) {
tpm_buf_destroy(&buf);
return err;
}
err = tpm_transmit_cmd(chip, &buf,
offsetof(struct tpm2_get_random_out,
buffer),

View File

@@ -144,59 +144,80 @@ struct tpm2_auth {
/*
* Name Size based on TPM algorithm (assumes no hash bigger than 255)
*/
static u8 name_size(const u8 *name)
static int name_size(const u8 *name)
{
static u8 size_map[] = {
[TPM_ALG_SHA1] = SHA1_DIGEST_SIZE,
[TPM_ALG_SHA256] = SHA256_DIGEST_SIZE,
[TPM_ALG_SHA384] = SHA384_DIGEST_SIZE,
[TPM_ALG_SHA512] = SHA512_DIGEST_SIZE,
};
u16 alg = get_unaligned_be16(name);
return size_map[alg] + 2;
u16 hash_alg = get_unaligned_be16(name);
switch (hash_alg) {
case TPM_ALG_SHA1:
return SHA1_DIGEST_SIZE + 2;
case TPM_ALG_SHA256:
return SHA256_DIGEST_SIZE + 2;
case TPM_ALG_SHA384:
return SHA384_DIGEST_SIZE + 2;
case TPM_ALG_SHA512:
return SHA512_DIGEST_SIZE + 2;
default:
pr_warn("tpm: unsupported name algorithm: 0x%04x\n", hash_alg);
return -EINVAL;
}
}
static int tpm2_parse_read_public(char *name, struct tpm_buf *buf)
static int tpm2_read_public(struct tpm_chip *chip, u32 handle, void *name)
{
struct tpm_header *head = (struct tpm_header *)buf->data;
u32 mso = tpm2_handle_mso(handle);
off_t offset = TPM_HEADER_SIZE;
u32 tot_len = be32_to_cpu(head->length);
u32 val;
/* we're starting after the header so adjust the length */
tot_len -= TPM_HEADER_SIZE;
/* skip public */
val = tpm_buf_read_u16(buf, &offset);
if (val > tot_len)
return -EINVAL;
offset += val;
/* name */
val = tpm_buf_read_u16(buf, &offset);
if (val != name_size(&buf->data[offset]))
return -EINVAL;
memcpy(name, &buf->data[offset], val);
/* forget the rest */
return 0;
}
static int tpm2_read_public(struct tpm_chip *chip, u32 handle, char *name)
{
int rc, name_size_alg;
struct tpm_buf buf;
int rc;
if (mso != TPM2_MSO_PERSISTENT && mso != TPM2_MSO_VOLATILE &&
mso != TPM2_MSO_NVRAM) {
memcpy(name, &handle, sizeof(u32));
return sizeof(u32);
}
rc = tpm_buf_init(&buf, TPM2_ST_NO_SESSIONS, TPM2_CC_READ_PUBLIC);
if (rc)
return rc;
tpm_buf_append_u32(&buf, handle);
rc = tpm_transmit_cmd(chip, &buf, 0, "read public");
if (rc == TPM2_RC_SUCCESS)
rc = tpm2_parse_read_public(name, &buf);
tpm_buf_destroy(&buf);
rc = tpm_transmit_cmd(chip, &buf, 0, "TPM2_ReadPublic");
if (rc) {
tpm_buf_destroy(&buf);
return tpm_ret_to_err(rc);
}
return rc;
/* Skip TPMT_PUBLIC: */
offset += tpm_buf_read_u16(&buf, &offset);
/*
* Ensure space for the length field of TPM2B_NAME and hashAlg field of
* TPMT_HA (the extra four bytes).
*/
if (offset + 4 > tpm_buf_length(&buf)) {
tpm_buf_destroy(&buf);
return -EIO;
}
rc = tpm_buf_read_u16(&buf, &offset);
name_size_alg = name_size(&buf.data[offset]);
if (name_size_alg < 0)
return name_size_alg;
if (rc != name_size_alg) {
tpm_buf_destroy(&buf);
return -EIO;
}
if (offset + rc > tpm_buf_length(&buf)) {
tpm_buf_destroy(&buf);
return -EIO;
}
memcpy(name, &buf.data[offset], rc);
return name_size_alg;
}
#endif /* CONFIG_TCG_TPM2_HMAC */
@@ -221,52 +242,76 @@ static int tpm2_read_public(struct tpm_chip *chip, u32 handle, char *name)
* As with most tpm_buf operations, success is assumed because failure
* will be caused by an incorrect programming model and indicated by a
* kernel message.
*
* Ends the authorization session on failure.
*/
void tpm_buf_append_name(struct tpm_chip *chip, struct tpm_buf *buf,
u32 handle, u8 *name)
int tpm_buf_append_name(struct tpm_chip *chip, struct tpm_buf *buf,
u32 handle, u8 *name)
{
#ifdef CONFIG_TCG_TPM2_HMAC
enum tpm2_mso_type mso = tpm2_handle_mso(handle);
struct tpm2_auth *auth;
u16 name_size_alg;
int slot;
int ret;
#endif
if (!tpm2_chip_auth(chip)) {
tpm_buf_append_handle(chip, buf, handle);
return;
return 0;
}
#ifdef CONFIG_TCG_TPM2_HMAC
slot = (tpm_buf_length(buf) - TPM_HEADER_SIZE) / 4;
if (slot >= AUTH_MAX_NAMES) {
dev_err(&chip->dev, "TPM: too many handles\n");
return;
dev_err(&chip->dev, "too many handles\n");
ret = -EIO;
goto err;
}
auth = chip->auth;
WARN(auth->session != tpm_buf_length(buf),
"name added in wrong place\n");
if (auth->session != tpm_buf_length(buf)) {
dev_err(&chip->dev, "session state malformed");
ret = -EIO;
goto err;
}
tpm_buf_append_u32(buf, handle);
auth->session += 4;
if (mso == TPM2_MSO_PERSISTENT ||
mso == TPM2_MSO_VOLATILE ||
mso == TPM2_MSO_NVRAM) {
if (!name)
tpm2_read_public(chip, handle, auth->name[slot]);
if (!name) {
ret = tpm2_read_public(chip, handle, auth->name[slot]);
if (ret < 0)
goto err;
name_size_alg = ret;
}
} else {
if (name)
dev_err(&chip->dev, "TPM: Handle does not require name but one is specified\n");
if (name) {
dev_err(&chip->dev, "handle 0x%08x does not use a name\n",
handle);
ret = -EIO;
goto err;
}
}
auth->name_h[slot] = handle;
if (name)
memcpy(auth->name[slot], name, name_size(name));
memcpy(auth->name[slot], name, name_size_alg);
#endif
return 0;
#ifdef CONFIG_TCG_TPM2_HMAC
err:
tpm2_end_auth_session(chip);
return tpm_ret_to_err(ret);
#endif
}
EXPORT_SYMBOL_GPL(tpm_buf_append_name);
void tpm_buf_append_auth(struct tpm_chip *chip, struct tpm_buf *buf,
u8 attributes, u8 *passphrase, int passphrase_len)
u8 *passphrase, int passphrase_len)
{
/* offset tells us where the sessions area begins */
int offset = buf->handles * 4 + TPM_HEADER_SIZE;
@@ -327,8 +372,7 @@ void tpm_buf_append_hmac_session(struct tpm_chip *chip, struct tpm_buf *buf,
#endif
if (!tpm2_chip_auth(chip)) {
tpm_buf_append_auth(chip, buf, attributes, passphrase,
passphrase_len);
tpm_buf_append_auth(chip, buf, passphrase, passphrase_len);
return;
}
@@ -533,11 +577,9 @@ static void tpm_buf_append_salt(struct tpm_buf *buf, struct tpm_chip *chip,
* encryption key and encrypts the first parameter of the command
* buffer with it.
*
* As with most tpm_buf operations, success is assumed because failure
* will be caused by an incorrect programming model and indicated by a
* kernel message.
* Ends the authorization session on failure.
*/
void tpm_buf_fill_hmac_session(struct tpm_chip *chip, struct tpm_buf *buf)
int tpm_buf_fill_hmac_session(struct tpm_chip *chip, struct tpm_buf *buf)
{
u32 cc, handles, val;
struct tpm2_auth *auth = chip->auth;
@@ -549,9 +591,12 @@ void tpm_buf_fill_hmac_session(struct tpm_chip *chip, struct tpm_buf *buf)
u8 cphash[SHA256_DIGEST_SIZE];
struct sha256_ctx sctx;
struct hmac_sha256_ctx hctx;
int ret;
if (!auth)
return;
if (!auth) {
ret = -EIO;
goto err;
}
/* save the command code in BE format */
auth->ordinal = head->ordinal;
@@ -560,9 +605,11 @@ void tpm_buf_fill_hmac_session(struct tpm_chip *chip, struct tpm_buf *buf)
i = tpm2_find_cc(chip, cc);
if (i < 0) {
dev_err(&chip->dev, "Command 0x%x not found in TPM\n", cc);
return;
dev_err(&chip->dev, "command 0x%08x not found\n", cc);
ret = -EIO;
goto err;
}
attrs = chip->cc_attrs_tbl[i];
handles = (attrs >> TPM2_CC_ATTR_CHANDLES) & GENMASK(2, 0);
@@ -576,9 +623,9 @@ void tpm_buf_fill_hmac_session(struct tpm_chip *chip, struct tpm_buf *buf)
u32 handle = tpm_buf_read_u32(buf, &offset_s);
if (auth->name_h[i] != handle) {
dev_err(&chip->dev, "TPM: handle %d wrong for name\n",
i);
return;
dev_err(&chip->dev, "invalid handle 0x%08x\n", handle);
ret = -EIO;
goto err;
}
}
/* point offset_s to the start of the sessions */
@@ -609,12 +656,14 @@ void tpm_buf_fill_hmac_session(struct tpm_chip *chip, struct tpm_buf *buf)
offset_s += len;
}
if (offset_s != offset_p) {
dev_err(&chip->dev, "TPM session length is incorrect\n");
return;
dev_err(&chip->dev, "session length is incorrect\n");
ret = -EIO;
goto err;
}
if (!hmac) {
dev_err(&chip->dev, "TPM could not find HMAC session\n");
return;
dev_err(&chip->dev, "could not find HMAC session\n");
ret = -EIO;
goto err;
}
/* encrypt before HMAC */
@@ -646,8 +695,11 @@ void tpm_buf_fill_hmac_session(struct tpm_chip *chip, struct tpm_buf *buf)
if (mso == TPM2_MSO_PERSISTENT ||
mso == TPM2_MSO_VOLATILE ||
mso == TPM2_MSO_NVRAM) {
sha256_update(&sctx, auth->name[i],
name_size(auth->name[i]));
ret = name_size(auth->name[i]);
if (ret < 0)
goto err;
sha256_update(&sctx, auth->name[i], ret);
} else {
__be32 h = cpu_to_be32(auth->name_h[i]);
@@ -668,6 +720,11 @@ void tpm_buf_fill_hmac_session(struct tpm_chip *chip, struct tpm_buf *buf)
hmac_sha256_update(&hctx, auth->tpm_nonce, sizeof(auth->tpm_nonce));
hmac_sha256_update(&hctx, &auth->attrs, 1);
hmac_sha256_final(&hctx, hmac);
return 0;
err:
tpm2_end_auth_session(chip);
return ret;
}
EXPORT_SYMBOL(tpm_buf_fill_hmac_session);

View File

@@ -207,9 +207,9 @@ impl platform::Driver for CPUFreqDTDriver {
fn probe(
pdev: &platform::Device<Core>,
_id_info: Option<&Self::IdInfo>,
) -> Result<Pin<KBox<Self>>> {
) -> impl PinInit<Self, Error> {
cpufreq::Registration::<CPUFreqDTDriver>::new_foreign_owned(pdev.as_ref())?;
Ok(KBox::new(Self {}, GFP_KERNEL)?.into())
Ok(Self {})
}
}

View File

@@ -1,5 +1,5 @@
# SPDX-License-Identifier: GPL-2.0
# Makefile for Xilinx firmwares
obj-$(CONFIG_ZYNQMP_FIRMWARE) += zynqmp.o
obj-$(CONFIG_ZYNQMP_FIRMWARE) += zynqmp.o zynqmp-ufs.o
obj-$(CONFIG_ZYNQMP_FIRMWARE_DEBUG) += zynqmp-debug.o

View File

@@ -0,0 +1,118 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Firmware Layer for UFS APIs
*
* Copyright (C) 2025 Advanced Micro Devices, Inc.
*/
#include <linux/firmware/xlnx-zynqmp.h>
#include <linux/module.h>
/* Register Node IDs */
#define PM_REGNODE_PMC_IOU_SLCR 0x30000002 /* PMC IOU SLCR */
#define PM_REGNODE_EFUSE_CACHE 0x30000003 /* EFUSE Cache */
/* Register Offsets for PMC IOU SLCR */
#define SRAM_CSR_OFFSET 0x104C /* SRAM Control and Status */
#define TXRX_CFGRDY_OFFSET 0x1054 /* M-PHY TX-RX Config ready */
/* Masks for SRAM Control and Status Register */
#define SRAM_CSR_INIT_DONE_MASK BIT(0) /* SRAM initialization done */
#define SRAM_CSR_EXT_LD_DONE_MASK BIT(1) /* SRAM External load done */
#define SRAM_CSR_BYPASS_MASK BIT(2) /* Bypass SRAM interface */
/* Mask to check M-PHY TX-RX configuration readiness */
#define TX_RX_CFG_RDY_MASK GENMASK(3, 0)
/* Register Offsets for EFUSE Cache */
#define UFS_CAL_1_OFFSET 0xBE8 /* UFS Calibration Value */
/**
* zynqmp_pm_is_mphy_tx_rx_config_ready - check M-PHY TX-RX config readiness
* @is_ready: Store output status (true/false)
*
* Return: Returns 0 on success or error value on failure.
*/
int zynqmp_pm_is_mphy_tx_rx_config_ready(bool *is_ready)
{
u32 regval;
int ret;
if (!is_ready)
return -EINVAL;
ret = zynqmp_pm_sec_read_reg(PM_REGNODE_PMC_IOU_SLCR, TXRX_CFGRDY_OFFSET, &regval);
if (ret)
return ret;
regval &= TX_RX_CFG_RDY_MASK;
if (regval)
*is_ready = true;
else
*is_ready = false;
return ret;
}
EXPORT_SYMBOL_GPL(zynqmp_pm_is_mphy_tx_rx_config_ready);
/**
* zynqmp_pm_is_sram_init_done - check SRAM initialization
* @is_done: Store output status (true/false)
*
* Return: Returns 0 on success or error value on failure.
*/
int zynqmp_pm_is_sram_init_done(bool *is_done)
{
u32 regval;
int ret;
if (!is_done)
return -EINVAL;
ret = zynqmp_pm_sec_read_reg(PM_REGNODE_PMC_IOU_SLCR, SRAM_CSR_OFFSET, &regval);
if (ret)
return ret;
regval &= SRAM_CSR_INIT_DONE_MASK;
if (regval)
*is_done = true;
else
*is_done = false;
return ret;
}
EXPORT_SYMBOL_GPL(zynqmp_pm_is_sram_init_done);
/**
* zynqmp_pm_set_sram_bypass - Set SRAM bypass Control
*
* Return: Returns 0 on success or error value on failure.
*/
int zynqmp_pm_set_sram_bypass(void)
{
u32 sram_csr;
int ret;
ret = zynqmp_pm_sec_read_reg(PM_REGNODE_PMC_IOU_SLCR, SRAM_CSR_OFFSET, &sram_csr);
if (ret)
return ret;
sram_csr &= ~SRAM_CSR_EXT_LD_DONE_MASK;
sram_csr |= SRAM_CSR_BYPASS_MASK;
return zynqmp_pm_sec_mask_write_reg(PM_REGNODE_PMC_IOU_SLCR, SRAM_CSR_OFFSET,
GENMASK(2, 1), sram_csr);
}
EXPORT_SYMBOL_GPL(zynqmp_pm_set_sram_bypass);
/**
* zynqmp_pm_get_ufs_calibration_values - Read UFS calibration values
* @val: Store the calibration value
*
* Return: Returns 0 on success or error value on failure.
*/
int zynqmp_pm_get_ufs_calibration_values(u32 *val)
{
return zynqmp_pm_sec_read_reg(PM_REGNODE_EFUSE_CACHE, UFS_CAL_1_OFFSET, val);
}
EXPORT_SYMBOL_GPL(zynqmp_pm_get_ufs_calibration_values);

View File

@@ -1653,6 +1653,52 @@ int zynqmp_pm_get_feature_config(enum pm_feature_config_id id,
return zynqmp_pm_invoke_fn(PM_IOCTL, payload, 3, 0, IOCTL_GET_FEATURE_CONFIG, id);
}
/**
* zynqmp_pm_sec_read_reg - PM call to securely read from given offset
* of the node
* @node_id: Node Id of the device
* @offset: Offset to be used (20-bit)
* @ret_value: Output data read from the given offset after
* firmware access policy is successfully enforced
*
* Return: Returns 0 on success or error value on failure
*/
int zynqmp_pm_sec_read_reg(u32 node_id, u32 offset, u32 *ret_value)
{
u32 ret_payload[PAYLOAD_ARG_CNT];
u32 count = 1;
int ret;
if (!ret_value)
return -EINVAL;
ret = zynqmp_pm_invoke_fn(PM_IOCTL, ret_payload, 4, node_id, IOCTL_READ_REG,
offset, count);
*ret_value = ret_payload[1];
return ret;
}
EXPORT_SYMBOL_GPL(zynqmp_pm_sec_read_reg);
/**
* zynqmp_pm_sec_mask_write_reg - PM call to securely write to given offset
* of the node
* @node_id: Node Id of the device
* @offset: Offset to be used (20-bit)
* @mask: Mask to be used
* @value: Value to be written
*
* Return: Returns 0 on success or error value on failure
*/
int zynqmp_pm_sec_mask_write_reg(const u32 node_id, const u32 offset, u32 mask,
u32 value)
{
return zynqmp_pm_invoke_fn(PM_IOCTL, NULL, 5, node_id, IOCTL_MASK_WRITE_REG,
offset, mask, value);
}
EXPORT_SYMBOL_GPL(zynqmp_pm_sec_mask_write_reg);
/**
* zynqmp_pm_set_sd_config - PM call to set value of SD config registers
* @node: SD node ID

View File

@@ -45,13 +45,13 @@ impl auxiliary::Driver for NovaDriver {
type IdInfo = ();
const ID_TABLE: auxiliary::IdTable<Self::IdInfo> = &AUX_TABLE;
fn probe(adev: &auxiliary::Device<Core>, _info: &Self::IdInfo) -> Result<Pin<KBox<Self>>> {
fn probe(adev: &auxiliary::Device<Core>, _info: &Self::IdInfo) -> impl PinInit<Self, Error> {
let data = try_pin_init!(NovaData { adev: adev.into() });
let drm = drm::Device::<Self>::new(adev.as_ref(), data)?;
drm::Registration::new_foreign_owned(&drm, adev.as_ref(), 0)?;
Ok(KBox::new(Self { drm }, GFP_KERNEL)?.into())
Ok(Self { drm })
}
}

View File

@@ -28,7 +28,7 @@ impl File {
_file: &drm::File<File>,
) -> Result<u32> {
let adev = &dev.adev;
let parent = adev.parent().ok_or(ENOENT)?;
let parent = adev.parent();
let pdev: &pci::Device = parent.try_into()?;
let value = match getparam.param as u32 {

View File

@@ -103,7 +103,7 @@ impl platform::Driver for TyrDriver {
fn probe(
pdev: &platform::Device<Core>,
_info: Option<&Self::IdInfo>,
) -> Result<Pin<KBox<Self>>> {
) -> impl PinInit<Self, Error> {
let core_clk = Clk::get(pdev.as_ref(), Some(c_str!("core")))?;
let stacks_clk = OptionalClk::get(pdev.as_ref(), Some(c_str!("stacks")))?;
let coregroup_clk = OptionalClk::get(pdev.as_ref(), Some(c_str!("coregroup")))?;
@@ -143,7 +143,7 @@ impl platform::Driver for TyrDriver {
let tdev: ARef<TyrDevice> = drm::Device::new(pdev.as_ref(), data)?;
drm::driver::Registration::new_foreign_owned(&tdev, pdev.as_ref(), 0)?;
let driver = KBox::pin_init(try_pin_init!(TyrDriver { device: tdev }), GFP_KERNEL)?;
let driver = TyrDriver { device: tdev };
// We need this to be dev_info!() because dev_dbg!() does not work at
// all in Rust for now, and we need to see whether probe succeeded.

View File

@@ -4,6 +4,7 @@ use kernel::{
auxiliary,
c_str,
device::Core,
devres::Devres,
dma::Device,
dma::DmaMask,
pci,
@@ -23,7 +24,8 @@ use crate::gpu::Gpu;
pub(crate) struct NovaCore {
#[pin]
pub(crate) gpu: Gpu,
_reg: auxiliary::Registration,
#[pin]
_reg: Devres<auxiliary::Registration>,
}
const BAR0_SIZE: usize = SZ_16M;
@@ -67,41 +69,33 @@ impl pci::Driver for NovaCore {
type IdInfo = ();
const ID_TABLE: pci::IdTable<Self::IdInfo> = &PCI_TABLE;
fn probe(pdev: &pci::Device<Core>, _info: &Self::IdInfo) -> Result<Pin<KBox<Self>>> {
dev_dbg!(pdev.as_ref(), "Probe Nova Core GPU driver.\n");
fn probe(pdev: &pci::Device<Core>, _info: &Self::IdInfo) -> impl PinInit<Self, Error> {
pin_init::pin_init_scope(move || {
dev_dbg!(pdev.as_ref(), "Probe Nova Core GPU driver.\n");
pdev.enable_device_mem()?;
pdev.set_master();
pdev.enable_device_mem()?;
pdev.set_master();
// SAFETY: No concurrent DMA allocations or mappings can be made because
// the device is still being probed and therefore isn't being used by
// other threads of execution.
unsafe { pdev.dma_set_mask_and_coherent(DmaMask::new::<GPU_DMA_BITS>())? };
// SAFETY: No concurrent DMA allocations or mappings can be made because
// the device is still being probed and therefore isn't being used by
// other threads of execution.
unsafe { pdev.dma_set_mask_and_coherent(DmaMask::new::<GPU_DMA_BITS>())? };
let devres_bar = Arc::pin_init(
pdev.iomap_region_sized::<BAR0_SIZE>(0, c_str!("nova-core/bar0")),
GFP_KERNEL,
)?;
let bar = Arc::pin_init(
pdev.iomap_region_sized::<BAR0_SIZE>(0, c_str!("nova-core/bar0")),
GFP_KERNEL,
)?;
// Used to provided a `&Bar0` to `Gpu::new` without tying it to the lifetime of
// `devres_bar`.
let bar_clone = Arc::clone(&devres_bar);
let bar = bar_clone.access(pdev.as_ref())?;
let this = KBox::pin_init(
try_pin_init!(Self {
gpu <- Gpu::new(pdev, devres_bar, bar),
_reg: auxiliary::Registration::new(
Ok(try_pin_init!(Self {
gpu <- Gpu::new(pdev, bar.clone(), bar.access(pdev.as_ref())?),
_reg <- auxiliary::Registration::new(
pdev.as_ref(),
c_str!("nova-drm"),
0, // TODO[XARR]: Once it lands, use XArray; for now we don't use the ID.
crate::MODULE_NAME
)?,
}),
GFP_KERNEL,
)?;
Ok(this)
),
}))
})
}
fn unbind(pdev: &pci::Device<Core>, this: Pin<&Self>) {

View File

@@ -1857,7 +1857,8 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id)
INIT_DELAYED_WORK(&ioc->fault_reset_work, mpt_fault_reset_work);
ioc->reset_work_q =
alloc_workqueue("mpt_poll_%d", WQ_MEM_RECLAIM, 0, ioc->id);
alloc_workqueue("mpt_poll_%d", WQ_MEM_RECLAIM | WQ_PERCPU, 0,
ioc->id);
if (!ioc->reset_work_q) {
printk(MYIOC_s_ERR_FMT "Insufficient memory to add adapter!\n",
ioc->name);
@@ -1984,7 +1985,9 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id)
INIT_LIST_HEAD(&ioc->fw_event_list);
spin_lock_init(&ioc->fw_event_lock);
ioc->fw_event_q = alloc_workqueue("mpt/%d", WQ_MEM_RECLAIM, 0, ioc->id);
ioc->fw_event_q = alloc_workqueue("mpt/%d",
WQ_MEM_RECLAIM | WQ_PERCPU, 0,
ioc->id);
if (!ioc->fw_event_q) {
printk(MYIOC_s_ERR_FMT "Insufficient memory to add adapter!\n",
ioc->name);

View File

@@ -106,7 +106,7 @@ config PHANTOM
config RPMB
tristate "RPMB partition interface"
depends on MMC
depends on MMC || SCSI_UFSHCD
help
Unified RPMB unit interface for RPMB capable devices such as eMMC and
UFS. Provides interface for in-kernel security controllers to access

View File

@@ -337,7 +337,7 @@ impl platform::Driver for Th1520PwmPlatformDriver {
fn probe(
pdev: &platform::Device<Core>,
_id_info: Option<&Self::IdInfo>,
) -> Result<Pin<KBox<Self>>> {
) -> impl PinInit<Self, Error> {
let dev = pdev.as_ref();
let request = pdev.io_request_by_index(0).ok_or(ENODEV)?;
@@ -374,7 +374,7 @@ impl platform::Driver for Th1520PwmPlatformDriver {
pwm::Registration::register(dev, chip)?;
Ok(KBox::new(Th1520PwmPlatformDriver, GFP_KERNEL)?.into())
Ok(Th1520PwmPlatformDriver)
}
}

View File

@@ -242,7 +242,7 @@ static int aac_queuecommand(struct Scsi_Host *shost,
{
aac_priv(cmd)->owner = AAC_OWNER_LOWLEVEL;
return aac_scsi_cmd(cmd) ? FAILED : 0;
return aac_scsi_cmd(cmd) ? SCSI_MLQUEUE_HOST_BUSY : 0;
}
/**

View File

@@ -2401,8 +2401,7 @@ static void asc_prt_scsi_host(struct Scsi_Host *s)
struct asc_board *boardp = shost_priv(s);
printk("Scsi_Host at addr 0x%p, device %s\n", s, dev_name(boardp->dev));
printk(" host_busy %d, host_no %d,\n",
scsi_host_busy(s), s->host_no);
printk(" host_no %d,\n", s->host_no);
printk(" base 0x%lx, io_port 0x%lx, irq %d,\n",
(ulong)s->base, (ulong)s->io_port, boardp->irq);

View File

@@ -882,6 +882,9 @@ static void asd_pci_remove(struct pci_dev *dev)
asd_disable_ints(asd_ha);
/* Ensure all scheduled tasklets complete before freeing resources */
tasklet_kill(&asd_ha->seq.dl_tasklet);
asd_remove_dev_attrs(asd_ha);
/* XXX more here as needed */

View File

@@ -5633,7 +5633,8 @@ static int beiscsi_dev_probe(struct pci_dev *pcidev,
phba->ctrl.mcc_alloc_index = phba->ctrl.mcc_free_index = 0;
phba->wq = alloc_workqueue("beiscsi_%02x_wq", WQ_MEM_RECLAIM, 1,
phba->wq = alloc_workqueue("beiscsi_%02x_wq",
WQ_MEM_RECLAIM | WQ_PERCPU, 1,
phba->shost->host_no);
if (!phba->wq) {
beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,

View File

@@ -2695,7 +2695,7 @@ static int __init bnx2fc_mod_init(void)
if (rc)
goto detach_ft;
bnx2fc_wq = alloc_workqueue("bnx2fc", 0, 0);
bnx2fc_wq = alloc_workqueue("bnx2fc", WQ_PERCPU, 0);
if (!bnx2fc_wq) {
rc = -ENOMEM;
goto release_bt;

View File

@@ -1300,7 +1300,7 @@ static int __init alua_init(void)
{
int r;
kaluad_wq = alloc_workqueue("kaluad", WQ_MEM_RECLAIM, 0);
kaluad_wq = alloc_workqueue("kaluad", WQ_MEM_RECLAIM | WQ_PERCPU, 0);
if (!kaluad_wq)
return -ENOMEM;

View File

@@ -2438,7 +2438,7 @@ static int __init fcoe_init(void)
unsigned int cpu;
int rc = 0;
fcoe_wq = alloc_workqueue("fcoe", 0, 0);
fcoe_wq = alloc_workqueue("fcoe", WQ_PERCPU, 0);
if (!fcoe_wq)
return -ENOMEM;

View File

@@ -134,7 +134,6 @@ int fnic_get_vnic_config(struct fnic *fnic)
c->luns_per_tgt));
c->intr_timer = min_t(u16, VNIC_INTR_TIMER_MAX, c->intr_timer);
c->intr_timer_type = c->intr_timer_type;
/* for older firmware, GET_CONFIG will not return anything */
if (c->wq_copy_count == 0)

View File

@@ -231,6 +231,12 @@ int scsi_add_host_with_dma(struct Scsi_Host *shost, struct device *dev,
goto fail;
}
if (shost->nr_reserved_cmds && !sht->queue_reserved_command) {
shost_printk(KERN_ERR, shost,
"nr_reserved_cmds set but no method to queue\n");
goto fail;
}
/* Use min_t(int, ...) in case shost->can_queue exceeds SHRT_MAX */
shost->cmd_per_lun = min_t(int, shost->cmd_per_lun,
shost->can_queue);
@@ -307,6 +313,14 @@ int scsi_add_host_with_dma(struct Scsi_Host *shost, struct device *dev,
if (error)
goto out_del_dev;
if (shost->nr_reserved_cmds) {
shost->pseudo_sdev = scsi_get_pseudo_sdev(shost);
if (!shost->pseudo_sdev) {
error = -ENOMEM;
goto out_del_dev;
}
}
scsi_proc_host_add(shost);
scsi_autopm_put_host(shost);
return error;
@@ -436,6 +450,7 @@ struct Scsi_Host *scsi_host_alloc(const struct scsi_host_template *sht, int priv
shost->hostt = sht;
shost->this_id = sht->this_id;
shost->can_queue = sht->can_queue;
shost->nr_reserved_cmds = sht->nr_reserved_cmds;
shost->sg_tablesize = sht->sg_tablesize;
shost->sg_prot_tablesize = sht->sg_prot_tablesize;
shost->cmd_per_lun = sht->cmd_per_lun;
@@ -604,8 +619,8 @@ static bool scsi_host_check_in_flight(struct request *rq, void *data)
}
/**
* scsi_host_busy - Return the host busy counter
* @shost: Pointer to Scsi_Host to inc.
* scsi_host_busy - Return the count of in-flight commands
* @shost: Pointer to Scsi_Host
**/
int scsi_host_busy(struct Scsi_Host *shost)
{

View File

@@ -3533,7 +3533,8 @@ static int ibmvscsis_probe(struct vio_dev *vdev,
init_completion(&vscsi->wait_idle);
init_completion(&vscsi->unconfig);
vscsi->work_q = alloc_workqueue("ibmvscsis%s", WQ_MEM_RECLAIM, 1,
vscsi->work_q = alloc_workqueue("ibmvscsis%s",
WQ_MEM_RECLAIM | WQ_PERCPU, 1,
dev_name(&vdev->dev));
if (!vscsi->work_q) {
rc = -ENOMEM;

View File

@@ -85,15 +85,17 @@ struct isci_tmf {
struct completion *complete;
enum sas_protocol proto;
unsigned char lun[8];
u16 io_tag;
enum isci_tmf_function_codes tmf_code;
int status;
/* Must be last --ends in a flexible-array member. */
union {
struct ssp_response_iu resp_iu;
struct dev_to_host_fis d2h_fis;
u8 rsp_buf[SSP_RESP_IU_MAX_SIZE];
} resp;
unsigned char lun[8];
u16 io_tag;
enum isci_tmf_function_codes tmf_code;
int status;
};
static inline void isci_print_tmf(struct isci_host *ihost, struct isci_tmf *tmf)

View File

@@ -311,7 +311,6 @@ struct lpfc_defer_flogi_acc {
u16 rx_id;
u16 ox_id;
struct lpfc_nodelist *ndlp;
};
#define LPFC_VMID_TIMER 300 /* timer interval in seconds */
@@ -634,6 +633,7 @@ struct lpfc_vport {
#define FC_CT_RSPN_ID 0x8 /* RSPN_ID accepted by switch */
#define FC_CT_RFT_ID 0x10 /* RFT_ID accepted by switch */
#define FC_CT_RPRT_DEFER 0x20 /* Defer issuing FDMI RPRT */
#define FC_CT_RSPNI_PNI 0x40 /* RSPNI_PNI accepted by switch */
struct list_head fc_nodes;
spinlock_t fc_nodes_list_lock; /* spinlock for fc_nodes list */
@@ -1078,6 +1078,8 @@ struct lpfc_hba {
uint32_t nport_event_cnt; /* timestamp for nlplist entry */
unsigned long pni; /* 64-bit Platform Name Identifier */
uint8_t wwnn[8];
uint8_t wwpn[8];
uint32_t RandomData[7];

View File

@@ -1742,6 +1742,28 @@ lpfc_cmpl_ct_cmd_rsnn_nn(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
return;
}
static void
lpfc_cmpl_ct_cmd_rspni_pni(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
struct lpfc_iocbq *rspiocb)
{
struct lpfc_vport *vport;
struct lpfc_dmabuf *outp;
struct lpfc_sli_ct_request *ctrsp;
u32 ulp_status;
vport = cmdiocb->vport;
ulp_status = get_job_ulpstatus(phba, rspiocb);
if (ulp_status == IOSTAT_SUCCESS) {
outp = cmdiocb->rsp_dmabuf;
ctrsp = (struct lpfc_sli_ct_request *)outp->virt;
if (be16_to_cpu(ctrsp->CommandResponse.bits.CmdRsp) ==
SLI_CT_RESPONSE_FS_ACC)
vport->ct_flags |= FC_CT_RSPNI_PNI;
}
lpfc_cmpl_ct(phba, cmdiocb, rspiocb);
}
static void
lpfc_cmpl_ct_cmd_da_id(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
struct lpfc_iocbq *rspiocb)
@@ -1956,6 +1978,8 @@ lpfc_ns_cmd(struct lpfc_vport *vport, int cmdcode,
bpl->tus.f.bdeSize = RSPN_REQUEST_SZ;
else if (cmdcode == SLI_CTNS_RSNN_NN)
bpl->tus.f.bdeSize = RSNN_REQUEST_SZ;
else if (cmdcode == SLI_CTNS_RSPNI_PNI)
bpl->tus.f.bdeSize = RSPNI_REQUEST_SZ;
else if (cmdcode == SLI_CTNS_DA_ID)
bpl->tus.f.bdeSize = DA_ID_REQUEST_SZ;
else if (cmdcode == SLI_CTNS_RFF_ID)
@@ -2077,6 +2101,18 @@ lpfc_ns_cmd(struct lpfc_vport *vport, int cmdcode,
CtReq->un.rsnn.symbname, size);
cmpl = lpfc_cmpl_ct_cmd_rsnn_nn;
break;
case SLI_CTNS_RSPNI_PNI:
vport->ct_flags &= ~FC_CT_RSPNI_PNI;
CtReq->CommandResponse.bits.CmdRsp =
cpu_to_be16(SLI_CTNS_RSPNI_PNI);
CtReq->un.rspni.pni = cpu_to_be64(phba->pni);
scnprintf(CtReq->un.rspni.symbname,
sizeof(CtReq->un.rspni.symbname), "OS Host Name::%s",
phba->os_host_name);
CtReq->un.rspni.len = strnlen(CtReq->un.rspni.symbname,
sizeof(CtReq->un.rspni.symbname));
cmpl = lpfc_cmpl_ct_cmd_rspni_pni;
break;
case SLI_CTNS_DA_ID:
/* Implement DA_ID Nameserver request */
CtReq->CommandResponse.bits.CmdRsp =

View File

@@ -1,7 +1,7 @@
/*******************************************************************
* This file is part of the Emulex Linux Device Driver for *
* Fibre Channel Host Bus Adapters. *
* Copyright (C) 2017-2024 Broadcom. All Rights Reserved. The term *
* Copyright (C) 2017-2025 Broadcom. All Rights Reserved. The term *
* Broadcom refers to Broadcom Inc. and/or its subsidiaries. *
* Copyright (C) 2004-2013 Emulex. All rights reserved. *
* EMULEX and SLI are trademarks of Emulex. *
@@ -208,6 +208,7 @@ enum lpfc_nlp_flag {
NPR list */
NLP_RM_DFLT_RPI = 26, /* need to remove leftover dflt RPI */
NLP_NODEV_REMOVE = 27, /* Defer removal till discovery ends */
NLP_FLOGI_DFR_ACC = 28, /* FLOGI LS_ACC was Deferred */
NLP_SC_REQ = 29, /* Target requires authentication */
NLP_FIRSTBURST = 30, /* Target supports FirstBurst */
NLP_RPI_REGISTERED = 31 /* nlp_rpi is valid */

View File

@@ -650,8 +650,6 @@ lpfc_cmpl_els_flogi_fabric(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
ndlp->nlp_class_sup |= FC_COS_CLASS2;
if (sp->cls3.classValid)
ndlp->nlp_class_sup |= FC_COS_CLASS3;
if (sp->cls4.classValid)
ndlp->nlp_class_sup |= FC_COS_CLASS4;
ndlp->nlp_maxframe = ((sp->cmn.bbRcvSizeMsb & 0x0F) << 8) |
sp->cmn.bbRcvSizeLsb;
@@ -934,10 +932,15 @@ lpfc_cmpl_els_flogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
/* Check to see if link went down during discovery */
if (lpfc_els_chk_latt(vport)) {
/* One additional decrement on node reference count to
* trigger the release of the node
* trigger the release of the node. Make sure the ndlp
* is marked NLP_DROPPED.
*/
if (!(ndlp->fc4_xpt_flags & SCSI_XPT_REGD))
if (!test_bit(NLP_IN_DEV_LOSS, &ndlp->nlp_flag) &&
!test_bit(NLP_DROPPED, &ndlp->nlp_flag) &&
!(ndlp->fc4_xpt_flags & SCSI_XPT_REGD)) {
set_bit(NLP_DROPPED, &ndlp->nlp_flag);
lpfc_nlp_put(ndlp);
}
goto out;
}
@@ -995,9 +998,10 @@ stop_rr_fcf_flogi:
IOERR_LOOP_OPEN_FAILURE)))
lpfc_vlog_msg(vport, KERN_WARNING, LOG_ELS,
"2858 FLOGI Status:x%x/x%x TMO"
":x%x Data x%lx x%x\n",
":x%x Data x%lx x%x x%lx x%x\n",
ulp_status, ulp_word4, tmo,
phba->hba_flag, phba->fcf.fcf_flag);
phba->hba_flag, phba->fcf.fcf_flag,
ndlp->nlp_flag, ndlp->fc4_xpt_flags);
/* Check for retry */
if (lpfc_els_retry(phba, cmdiocb, rspiocb)) {
@@ -1015,14 +1019,17 @@ stop_rr_fcf_flogi:
* reference to trigger node release.
*/
if (!test_bit(NLP_IN_DEV_LOSS, &ndlp->nlp_flag) &&
!(ndlp->fc4_xpt_flags & SCSI_XPT_REGD))
!test_bit(NLP_DROPPED, &ndlp->nlp_flag) &&
!(ndlp->fc4_xpt_flags & SCSI_XPT_REGD)) {
set_bit(NLP_DROPPED, &ndlp->nlp_flag);
lpfc_nlp_put(ndlp);
}
lpfc_printf_vlog(vport, KERN_WARNING, LOG_ELS,
"0150 FLOGI Status:x%x/x%x "
"xri x%x TMO:x%x refcnt %d\n",
"xri x%x iotag x%x TMO:x%x refcnt %d\n",
ulp_status, ulp_word4, cmdiocb->sli4_xritag,
tmo, kref_read(&ndlp->kref));
cmdiocb->iotag, tmo, kref_read(&ndlp->kref));
/* If this is not a loop open failure, bail out */
if (!(ulp_status == IOSTAT_LOCAL_REJECT &&
@@ -1279,6 +1286,19 @@ lpfc_issue_els_flogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
uint32_t tmo, did;
int rc;
/* It's possible for lpfc to reissue a FLOGI on an ndlp that is marked
* NLP_DROPPED. This happens when the FLOGI completed with the XB bit
* set causing lpfc to reference the ndlp until the XRI_ABORTED CQE is
* issued. The time window for the XRI_ABORTED CQE can be as much as
* 2*2*RA_TOV allowing for ndlp reuse of this type when the link is
* cycling quickly. When true, restore the initial reference and remove
* the NLP_DROPPED flag as lpfc is retrying.
*/
if (test_and_clear_bit(NLP_DROPPED, &ndlp->nlp_flag)) {
if (!lpfc_nlp_get(ndlp))
return 1;
}
cmdsize = (sizeof(uint32_t) + sizeof(struct serv_parm));
elsiocb = lpfc_prep_els_iocb(vport, 1, cmdsize, retry, ndlp,
ndlp->nlp_DID, ELS_CMD_FLOGI);
@@ -1334,6 +1354,14 @@ lpfc_issue_els_flogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
/* Can't do SLI4 class2 without support sequence coalescing */
sp->cls2.classValid = 0;
sp->cls2.seqDelivery = 0;
/* Fill out Auxiliary Parameter Data */
if (phba->pni) {
sp->aux.flags =
AUX_PARM_DATA_VALID | AUX_PARM_PNI_VALID;
sp->aux.pni = cpu_to_be64(phba->pni);
sp->aux.npiv_cnt = cpu_to_be16(phba->max_vpi - 1);
}
} else {
/* Historical, setting sequential-delivery bit for SLI3 */
sp->cls2.seqDelivery = (sp->cls2.classValid) ? 1 : 0;
@@ -1413,11 +1441,12 @@ lpfc_issue_els_flogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
phba->defer_flogi_acc.ox_id;
}
lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
"3354 Xmit deferred FLOGI ACC: rx_id: x%x,"
" ox_id: x%x, hba_flag x%lx\n",
phba->defer_flogi_acc.rx_id,
phba->defer_flogi_acc.ox_id, phba->hba_flag);
/* The LS_ACC completion needs to drop the initial reference.
* This is a special case for Pt2Pt because both FLOGIs need
* to complete and lpfc defers the LS_ACC when the remote
* FLOGI arrives before the driver's FLOGI.
*/
set_bit(NLP_FLOGI_DFR_ACC, &ndlp->nlp_flag);
/* Send deferred FLOGI ACC */
lpfc_els_rsp_acc(vport, ELS_CMD_FLOGI, &defer_flogi_acc,
@@ -1433,6 +1462,14 @@ lpfc_issue_els_flogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
phba->defer_flogi_acc.ndlp = NULL;
}
lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
"3354 Xmit deferred FLOGI ACC: rx_id: x%x,"
" ox_id: x%x, ndlp x%px hba_flag x%lx\n",
phba->defer_flogi_acc.rx_id,
phba->defer_flogi_acc.ox_id,
phba->defer_flogi_acc.ndlp,
phba->hba_flag);
vport->fc_myDID = did;
}
@@ -2248,7 +2285,8 @@ lpfc_issue_els_plogi(struct lpfc_vport *vport, uint32_t did, uint8_t retry)
sp->cmn.valid_vendor_ver_level = 0;
memset(sp->un.vendorVersion, 0, sizeof(sp->un.vendorVersion));
sp->cmn.bbRcvSizeMsb &= 0xF;
if (!test_bit(FC_PT2PT, &vport->fc_flag))
sp->cmn.bbRcvSizeMsb &= 0xF;
/* Check if the destination port supports VMID */
ndlp->vmid_support = 0;
@@ -2367,7 +2405,7 @@ lpfc_cmpl_els_prli(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
mode = KERN_INFO;
/* Warn PRLI status */
lpfc_printf_vlog(vport, mode, LOG_ELS,
lpfc_vlog_msg(vport, mode, LOG_ELS,
"2754 PRLI DID:%06X Status:x%x/x%x, "
"data: x%x x%x x%lx\n",
ndlp->nlp_DID, ulp_status,
@@ -3024,6 +3062,7 @@ lpfc_cmpl_els_logo(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
ndlp->nlp_DID, ulp_status,
ulp_word4);
/* Call NLP_EVT_DEVICE_RM if link is down or LOGO is aborted */
if (lpfc_error_lost_link(vport, ulp_status, ulp_word4))
skip_recovery = 1;
}
@@ -3262,7 +3301,7 @@ lpfc_reg_fab_ctrl_node(struct lpfc_vport *vport, struct lpfc_nodelist *fc_ndlp)
return -ENOMEM;
}
rc = lpfc_reg_rpi(phba, vport->vpi, fc_ndlp->nlp_DID,
(u8 *)&vport->fc_sparam, mbox, fc_ndlp->nlp_rpi);
(u8 *)&ns_ndlp->fc_sparam, mbox, fc_ndlp->nlp_rpi);
if (rc) {
rc = -EACCES;
goto out;
@@ -3306,7 +3345,8 @@ lpfc_reg_fab_ctrl_node(struct lpfc_vport *vport, struct lpfc_nodelist *fc_ndlp)
*
* This routine is a generic completion callback function for Discovery ELS cmd.
* Currently used by the ELS command issuing routines for the ELS State Change
* Request (SCR), lpfc_issue_els_scr() and the ELS RDF, lpfc_issue_els_rdf().
* Request (SCR), lpfc_issue_els_scr(), Exchange Diagnostic Capabilities (EDC),
* lpfc_issue_els_edc() and the ELS RDF, lpfc_issue_els_rdf().
* These commands will be retried once only for ELS timeout errors.
**/
static void
@@ -3379,11 +3419,21 @@ lpfc_cmpl_els_disc_cmd(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
lpfc_cmpl_els_edc(phba, cmdiocb, rspiocb);
return;
}
if (ulp_status) {
/* ELS discovery cmd completes with error */
lpfc_printf_vlog(vport, KERN_WARNING, LOG_ELS | LOG_CGN_MGMT,
"4203 ELS cmd x%x error: x%x x%X\n", cmd,
ulp_status, ulp_word4);
/* In the case where the ELS cmd completes with an error and
* the node does not have RPI registered, the node is
* outstanding and should put its initial reference.
*/
if ((cmd == ELS_CMD_SCR || cmd == ELS_CMD_RDF) &&
!(ndlp->fc4_xpt_flags & SCSI_XPT_REGD) &&
!test_and_set_bit(NLP_DROPPED, &ndlp->nlp_flag))
lpfc_nlp_put(ndlp);
goto out;
}
@@ -3452,6 +3502,7 @@ lpfc_issue_els_scr(struct lpfc_vport *vport, uint8_t retry)
uint8_t *pcmd;
uint16_t cmdsize;
struct lpfc_nodelist *ndlp;
bool node_created = false;
cmdsize = (sizeof(uint32_t) + sizeof(SCR));
@@ -3461,21 +3512,21 @@ lpfc_issue_els_scr(struct lpfc_vport *vport, uint8_t retry)
if (!ndlp)
return 1;
lpfc_enqueue_node(vport, ndlp);
node_created = true;
}
elsiocb = lpfc_prep_els_iocb(vport, 1, cmdsize, retry, ndlp,
ndlp->nlp_DID, ELS_CMD_SCR);
if (!elsiocb)
return 1;
goto out_node_created;
if (phba->sli_rev == LPFC_SLI_REV4) {
rc = lpfc_reg_fab_ctrl_node(vport, ndlp);
if (rc) {
lpfc_els_free_iocb(phba, elsiocb);
lpfc_printf_vlog(vport, KERN_ERR, LOG_NODE,
"0937 %s: Failed to reg fc node, rc %d\n",
__func__, rc);
return 1;
goto out_free_iocb;
}
}
pcmd = (uint8_t *)elsiocb->cmd_dmabuf->virt;
@@ -3494,23 +3545,27 @@ lpfc_issue_els_scr(struct lpfc_vport *vport, uint8_t retry)
phba->fc_stat.elsXmitSCR++;
elsiocb->cmd_cmpl = lpfc_cmpl_els_disc_cmd;
elsiocb->ndlp = lpfc_nlp_get(ndlp);
if (!elsiocb->ndlp) {
lpfc_els_free_iocb(phba, elsiocb);
return 1;
}
if (!elsiocb->ndlp)
goto out_free_iocb;
lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
"Issue SCR: did:x%x refcnt %d",
ndlp->nlp_DID, kref_read(&ndlp->kref), 0);
rc = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, elsiocb, 0);
if (rc == IOCB_ERROR) {
lpfc_els_free_iocb(phba, elsiocb);
lpfc_nlp_put(ndlp);
return 1;
}
if (rc == IOCB_ERROR)
goto out_iocb_error;
return 0;
out_iocb_error:
lpfc_nlp_put(ndlp);
out_free_iocb:
lpfc_els_free_iocb(phba, elsiocb);
out_node_created:
if (node_created)
lpfc_nlp_put(ndlp);
return 1;
}
/**
@@ -3597,8 +3652,8 @@ lpfc_issue_els_rscn(struct lpfc_vport *vport, uint8_t retry)
}
lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
"Issue RSCN: did:x%x",
ndlp->nlp_DID, 0, 0);
"Issue RSCN: did:x%x refcnt %d",
ndlp->nlp_DID, kref_read(&ndlp->kref), 0);
rc = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, elsiocb, 0);
if (rc == IOCB_ERROR) {
@@ -3705,10 +3760,7 @@ lpfc_issue_els_farpr(struct lpfc_vport *vport, uint32_t nportid, uint8_t retry)
lpfc_nlp_put(ndlp);
return 1;
}
/* This will cause the callback-function lpfc_cmpl_els_cmd to
* trigger the release of the node.
*/
/* Don't release reference count as RDF is likely outstanding */
return 0;
}
@@ -3726,7 +3778,12 @@ lpfc_issue_els_farpr(struct lpfc_vport *vport, uint32_t nportid, uint8_t retry)
*
* Return code
* 0 - Successfully issued rdf command
* 1 - Failed to issue rdf command
* < 0 - Failed to issue rdf command
* -EACCES - RDF not required for NPIV_PORT
* -ENODEV - No fabric controller device available
* -ENOMEM - No available memory
* -EIO - The mailbox failed to complete successfully.
*
**/
int
lpfc_issue_els_rdf(struct lpfc_vport *vport, uint8_t retry)
@@ -3737,25 +3794,30 @@ lpfc_issue_els_rdf(struct lpfc_vport *vport, uint8_t retry)
struct lpfc_nodelist *ndlp;
uint16_t cmdsize;
int rc;
bool node_created = false;
int err;
cmdsize = sizeof(*prdf);
/* RDF ELS is not required on an NPIV VN_Port. */
if (vport->port_type == LPFC_NPIV_PORT)
return -EACCES;
ndlp = lpfc_findnode_did(vport, Fabric_Cntl_DID);
if (!ndlp) {
ndlp = lpfc_nlp_init(vport, Fabric_Cntl_DID);
if (!ndlp)
return -ENODEV;
lpfc_enqueue_node(vport, ndlp);
node_created = true;
}
/* RDF ELS is not required on an NPIV VN_Port. */
if (vport->port_type == LPFC_NPIV_PORT)
return -EACCES;
elsiocb = lpfc_prep_els_iocb(vport, 1, cmdsize, retry, ndlp,
ndlp->nlp_DID, ELS_CMD_RDF);
if (!elsiocb)
return -ENOMEM;
if (!elsiocb) {
err = -ENOMEM;
goto out_node_created;
}
/* Configure the payload for the supported FPIN events. */
prdf = (struct lpfc_els_rdf_req *)elsiocb->cmd_dmabuf->virt;
@@ -3781,8 +3843,8 @@ lpfc_issue_els_rdf(struct lpfc_vport *vport, uint8_t retry)
elsiocb->cmd_cmpl = lpfc_cmpl_els_disc_cmd;
elsiocb->ndlp = lpfc_nlp_get(ndlp);
if (!elsiocb->ndlp) {
lpfc_els_free_iocb(phba, elsiocb);
return -EIO;
err = -EIO;
goto out_free_iocb;
}
lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
@@ -3791,11 +3853,19 @@ lpfc_issue_els_rdf(struct lpfc_vport *vport, uint8_t retry)
rc = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, elsiocb, 0);
if (rc == IOCB_ERROR) {
lpfc_els_free_iocb(phba, elsiocb);
lpfc_nlp_put(ndlp);
return -EIO;
err = -EIO;
goto out_iocb_error;
}
return 0;
out_iocb_error:
lpfc_nlp_put(ndlp);
out_free_iocb:
lpfc_els_free_iocb(phba, elsiocb);
out_node_created:
if (node_created)
lpfc_nlp_put(ndlp);
return err;
}
/**
@@ -3816,19 +3886,23 @@ static int
lpfc_els_rcv_rdf(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
struct lpfc_nodelist *ndlp)
{
int rc;
rc = lpfc_els_rsp_acc(vport, ELS_CMD_RDF, cmdiocb, ndlp, NULL);
/* Send LS_ACC */
if (lpfc_els_rsp_acc(vport, ELS_CMD_RDF, cmdiocb, ndlp, NULL)) {
if (rc) {
lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS | LOG_CGN_MGMT,
"1623 Failed to RDF_ACC from x%x for x%x\n",
ndlp->nlp_DID, vport->fc_myDID);
"1623 Failed to RDF_ACC from x%x for x%x Data: %d\n",
ndlp->nlp_DID, vport->fc_myDID, rc);
return -EIO;
}
rc = lpfc_issue_els_rdf(vport, 0);
/* Issue new RDF for reregistering */
if (lpfc_issue_els_rdf(vport, 0)) {
if (rc) {
lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS | LOG_CGN_MGMT,
"2623 Failed to re register RDF for x%x\n",
vport->fc_myDID);
"2623 Failed to re register RDF for x%x Data: %d\n",
vport->fc_myDID, rc);
return -EIO;
}
@@ -4299,7 +4373,7 @@ lpfc_issue_els_edc(struct lpfc_vport *vport, uint8_t retry)
rc = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, elsiocb, 0);
if (rc == IOCB_ERROR) {
/* The additional lpfc_nlp_put will cause the following
* lpfc_els_free_iocb routine to trigger the rlease of
* lpfc_els_free_iocb routine to trigger the release of
* the node.
*/
lpfc_els_free_iocb(phba, elsiocb);
@@ -5127,7 +5201,7 @@ lpfc_els_free_iocb(struct lpfc_hba *phba, struct lpfc_iocbq *elsiocb)
{
struct lpfc_dmabuf *buf_ptr, *buf_ptr1;
/* The I/O iocb is complete. Clear the node and first dmbuf */
/* The I/O iocb is complete. Clear the node and first dmabuf */
elsiocb->ndlp = NULL;
/* cmd_dmabuf = cmd, cmd_dmabuf->next = rsp, bpl_dmabuf = bpl */
@@ -5160,14 +5234,12 @@ lpfc_els_free_iocb(struct lpfc_hba *phba, struct lpfc_iocbq *elsiocb)
} else {
buf_ptr1 = elsiocb->cmd_dmabuf;
lpfc_els_free_data(phba, buf_ptr1);
elsiocb->cmd_dmabuf = NULL;
}
}
if (elsiocb->bpl_dmabuf) {
buf_ptr = elsiocb->bpl_dmabuf;
lpfc_els_free_bpl(phba, buf_ptr);
elsiocb->bpl_dmabuf = NULL;
}
lpfc_sli_release_iocbq(phba, elsiocb);
return 0;
@@ -5305,11 +5377,12 @@ lpfc_cmpl_els_rsp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
IOCB_t *irsp;
LPFC_MBOXQ_t *mbox = NULL;
u32 ulp_status, ulp_word4, tmo, did, iotag;
u32 cmd;
if (!vport) {
lpfc_printf_log(phba, KERN_WARNING, LOG_ELS,
"3177 null vport in ELS rsp\n");
goto out;
goto release;
}
if (cmdiocb->context_un.mbox)
mbox = cmdiocb->context_un.mbox;
@@ -5419,7 +5492,7 @@ out:
* these conditions because it doesn't need the login.
*/
if (phba->sli_rev == LPFC_SLI_REV4 &&
vport && vport->port_type == LPFC_NPIV_PORT &&
vport->port_type == LPFC_NPIV_PORT &&
!(ndlp->fc4_xpt_flags & SCSI_XPT_REGD)) {
if (ndlp->nlp_state != NLP_STE_PLOGI_ISSUE &&
ndlp->nlp_state != NLP_STE_REG_LOGIN_ISSUE &&
@@ -5435,6 +5508,27 @@ out:
}
}
/* The driver's unsolicited deferred FLOGI ACC in Pt2Pt needs to
* release the initial reference because the put after the free_iocb
* call removes only the reference from the defer logic. This FLOGI
* is never registered with the SCSI transport.
*/
if (test_bit(FC_PT2PT, &vport->fc_flag) &&
test_and_clear_bit(NLP_FLOGI_DFR_ACC, &ndlp->nlp_flag)) {
lpfc_printf_vlog(vport, KERN_INFO,
LOG_ELS | LOG_NODE | LOG_DISCOVERY,
"3357 Pt2Pt Defer FLOGI ACC ndlp x%px, "
"nflags x%lx, fc_flag x%lx\n",
ndlp, ndlp->nlp_flag,
vport->fc_flag);
cmd = *((u32 *)cmdiocb->cmd_dmabuf->virt);
if (cmd == ELS_CMD_ACC) {
if (!test_and_set_bit(NLP_DROPPED, &ndlp->nlp_flag))
lpfc_nlp_put(ndlp);
}
}
release:
/* Release the originating I/O reference. */
lpfc_els_free_iocb(phba, cmdiocb);
lpfc_nlp_put(ndlp);
@@ -5569,7 +5663,6 @@ lpfc_els_rsp_acc(struct lpfc_vport *vport, uint32_t flag,
sp->cls1.classValid = 0;
sp->cls2.classValid = 0;
sp->cls3.classValid = 0;
sp->cls4.classValid = 0;
/* Copy our worldwide names */
memcpy(&sp->portName, &vport->fc_sparam.portName,
@@ -5583,7 +5676,8 @@ lpfc_els_rsp_acc(struct lpfc_vport *vport, uint32_t flag,
sp->cmn.valid_vendor_ver_level = 0;
memset(sp->un.vendorVersion, 0,
sizeof(sp->un.vendorVersion));
sp->cmn.bbRcvSizeMsb &= 0xF;
if (!test_bit(FC_PT2PT, &vport->fc_flag))
sp->cmn.bbRcvSizeMsb &= 0xF;
/* If our firmware supports this feature, convey that
* info to the target using the vendor specific field.
@@ -8402,13 +8496,6 @@ lpfc_els_rcv_flogi(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
&wqe->xmit_els_rsp.wqe_com);
vport->fc_myDID = did;
lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
"3344 Deferring FLOGI ACC: rx_id: x%x,"
" ox_id: x%x, hba_flag x%lx\n",
phba->defer_flogi_acc.rx_id,
phba->defer_flogi_acc.ox_id, phba->hba_flag);
phba->defer_flogi_acc.flag = true;
/* This nlp_get is paired with nlp_puts that reset the
@@ -8417,6 +8504,14 @@ lpfc_els_rcv_flogi(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
* processed or cancelled.
*/
phba->defer_flogi_acc.ndlp = lpfc_nlp_get(ndlp);
lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
"3344 Deferring FLOGI ACC: rx_id: x%x,"
" ox_id: x%x, ndlp x%px, hba_flag x%lx\n",
phba->defer_flogi_acc.rx_id,
phba->defer_flogi_acc.ox_id,
phba->defer_flogi_acc.ndlp,
phba->hba_flag);
return 0;
}
@@ -8734,7 +8829,7 @@ reject_out:
* @cmdiocb: pointer to lpfc command iocb data structure.
* @ndlp: pointer to a node-list data structure.
*
* This routine processes Read Timout Value (RTV) IOCB received as an
* This routine processes Read Timeout Value (RTV) IOCB received as an
* ELS unsolicited event. It first checks the remote port state. If the
* remote port is not in NLP_STE_UNMAPPED_NODE state or NLP_STE_MAPPED_NODE
* state, it invokes the lpfc_els_rsl_reject() routine to send the reject
@@ -10357,11 +10452,8 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
* Do not process any unsolicited ELS commands
* if the ndlp is in DEV_LOSS
*/
if (test_bit(NLP_IN_DEV_LOSS, &ndlp->nlp_flag)) {
if (newnode)
lpfc_nlp_put(ndlp);
if (test_bit(NLP_IN_DEV_LOSS, &ndlp->nlp_flag))
goto dropit;
}
elsiocb->ndlp = lpfc_nlp_get(ndlp);
if (!elsiocb->ndlp)
@@ -10843,7 +10935,7 @@ lpfc_els_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
lpfc_els_unsol_buffer(phba, pring, vport, elsiocb);
/*
* The different unsolicited event handlers would tell us
* if they are done with "mp" by setting cmd_dmabuf to NULL.
* if they are done with "mp" by setting cmd_dmabuf/bpl_dmabuf to NULL.
*/
if (elsiocb->cmd_dmabuf) {
lpfc_in_buf_free(phba, elsiocb->cmd_dmabuf);
@@ -11423,6 +11515,13 @@ lpfc_issue_els_fdisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
sp->cls2.seqDelivery = 1;
sp->cls3.seqDelivery = 1;
/* Fill out Auxiliary Parameter Data */
if (phba->pni) {
sp->aux.flags =
AUX_PARM_DATA_VALID | AUX_PARM_PNI_VALID;
sp->aux.pni = cpu_to_be64(phba->pni);
}
pcmd += sizeof(uint32_t); /* CSP Word 2 */
pcmd += sizeof(uint32_t); /* CSP Word 3 */
pcmd += sizeof(uint32_t); /* CSP Word 4 */

View File

@@ -424,6 +424,7 @@ lpfc_check_nlp_post_devloss(struct lpfc_vport *vport,
struct lpfc_nodelist *ndlp)
{
if (test_and_clear_bit(NLP_IN_RECOV_POST_DEV_LOSS, &ndlp->save_flags)) {
clear_bit(NLP_DROPPED, &ndlp->nlp_flag);
lpfc_nlp_get(ndlp);
lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY | LOG_NODE,
"8438 Devloss timeout reversed on DID x%x "
@@ -566,7 +567,8 @@ lpfc_dev_loss_tmo_handler(struct lpfc_nodelist *ndlp)
return fcf_inuse;
}
lpfc_nlp_put(ndlp);
if (!test_and_set_bit(NLP_DROPPED, &ndlp->nlp_flag))
lpfc_nlp_put(ndlp);
return fcf_inuse;
}
@@ -4371,6 +4373,8 @@ out:
lpfc_ns_cmd(vport, SLI_CTNS_RNN_ID, 0, 0);
lpfc_ns_cmd(vport, SLI_CTNS_RSNN_NN, 0, 0);
lpfc_ns_cmd(vport, SLI_CTNS_RSPN_ID, 0, 0);
if (phba->pni)
lpfc_ns_cmd(vport, SLI_CTNS_RSPNI_PNI, 0, 0);
lpfc_ns_cmd(vport, SLI_CTNS_RFT_ID, 0, 0);
if ((vport->cfg_enable_fc4_type == LPFC_ENABLE_BOTH) ||

View File

@@ -168,6 +168,11 @@ struct lpfc_sli_ct_request {
uint8_t len;
uint8_t symbname[255];
} rspn;
struct rspni { /* For RSPNI_PNI requests */
__be64 pni;
u8 len;
u8 symbname[255];
} rspni;
struct gff {
uint32_t PortId;
} gff;
@@ -213,6 +218,8 @@ struct lpfc_sli_ct_request {
sizeof(struct da_id))
#define RSPN_REQUEST_SZ (offsetof(struct lpfc_sli_ct_request, un) + \
sizeof(struct rspn))
#define RSPNI_REQUEST_SZ (offsetof(struct lpfc_sli_ct_request, un) + \
sizeof(struct rspni))
/*
* FsType Definitions
@@ -309,6 +316,7 @@ struct lpfc_sli_ct_request {
#define SLI_CTNS_RIP_NN 0x0235
#define SLI_CTNS_RIPA_NN 0x0236
#define SLI_CTNS_RSNN_NN 0x0239
#define SLI_CTNS_RSPNI_PNI 0x0240
#define SLI_CTNS_DA_ID 0x0300
/*
@@ -512,6 +520,21 @@ struct class_parms {
uint8_t word3Reserved2; /* Fc Word 3, bit 0: 7 */
};
enum aux_parm_flags {
AUX_PARM_PNI_VALID = 0x20, /* FC Word 0, bit 29 */
AUX_PARM_DATA_VALID = 0x40, /* FC Word 0, bit 30 */
};
struct aux_parm {
u8 flags; /* FC Word 0, bit 31:24 */
u8 ext_feat[3]; /* FC Word 0, bit 23:0 */
__be64 pni; /* FC Word 1 and 2, platform name identifier */
__be16 rsvd; /* FC Word 3, bit 31:16 */
__be16 npiv_cnt; /* FC Word 3, bit 15:0 */
} __packed;
struct serv_parm { /* Structure is in Big Endian format */
struct csp cmn;
struct lpfc_name portName;
@@ -519,7 +542,7 @@ struct serv_parm { /* Structure is in Big Endian format */
struct class_parms cls1;
struct class_parms cls2;
struct class_parms cls3;
struct class_parms cls4;
struct aux_parm aux;
union {
uint8_t vendorVersion[16];
struct {

View File

@@ -3057,12 +3057,6 @@ lpfc_cleanup(struct lpfc_vport *vport)
lpfc_vmid_vport_cleanup(vport);
list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes, nlp_listp) {
if (ndlp->nlp_DID == Fabric_Cntl_DID &&
ndlp->nlp_state == NLP_STE_UNUSED_NODE) {
lpfc_nlp_put(ndlp);
continue;
}
/* Fabric Ports not in UNMAPPED state are cleaned up in the
* DEVICE_RM event.
*/
@@ -7950,7 +7944,7 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba)
/* Allocate all driver workqueues here */
/* The lpfc_wq workqueue for deferred irq use */
phba->wq = alloc_workqueue("lpfc_wq", WQ_MEM_RECLAIM, 0);
phba->wq = alloc_workqueue("lpfc_wq", WQ_MEM_RECLAIM | WQ_PERCPU, 0);
if (!phba->wq)
return -ENOMEM;
@@ -9082,9 +9076,9 @@ lpfc_setup_fdmi_mask(struct lpfc_vport *vport)
vport->fdmi_port_mask = LPFC_FDMI2_PORT_ATTR;
}
lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
"6077 Setup FDMI mask: hba x%x port x%x\n",
vport->fdmi_hba_mask, vport->fdmi_port_mask);
lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
"6077 Setup FDMI mask: hba x%x port x%x\n",
vport->fdmi_hba_mask, vport->fdmi_port_mask);
}
/**

View File

@@ -432,8 +432,6 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
ndlp->nlp_class_sup |= FC_COS_CLASS2;
if (sp->cls3.classValid)
ndlp->nlp_class_sup |= FC_COS_CLASS3;
if (sp->cls4.classValid)
ndlp->nlp_class_sup |= FC_COS_CLASS4;
ndlp->nlp_maxframe =
((sp->cmn.bbRcvSizeMsb & 0x0F) << 8) | sp->cmn.bbRcvSizeLsb;
/* if already logged in, do implicit logout */
@@ -452,18 +450,7 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
*/
if (!(ndlp->nlp_type & NLP_FABRIC) &&
!(phba->nvmet_support)) {
/* Clear ndlp info, since follow up PRLI may have
* updated ndlp information
*/
ndlp->nlp_type &= ~(NLP_FCP_TARGET | NLP_FCP_INITIATOR);
ndlp->nlp_type &= ~(NLP_NVME_TARGET | NLP_NVME_INITIATOR);
ndlp->nlp_fcp_info &= ~NLP_FCP_2_DEVICE;
ndlp->nlp_nvme_info &= ~NLP_NVME_NSLER;
clear_bit(NLP_FIRSTBURST, &ndlp->nlp_flag);
lpfc_els_rsp_acc(vport, ELS_CMD_PLOGI, cmdiocb,
ndlp, NULL);
return 1;
break;
}
if (nlp_portwwn != 0 &&
nlp_portwwn != wwn_to_u64(sp->portName.u.wwn))
@@ -485,7 +472,9 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
break;
}
/* Clear ndlp info, since follow up processes may have
* updated ndlp information
*/
ndlp->nlp_type &= ~(NLP_FCP_TARGET | NLP_FCP_INITIATOR);
ndlp->nlp_type &= ~(NLP_NVME_TARGET | NLP_NVME_INITIATOR);
ndlp->nlp_fcp_info &= ~NLP_FCP_2_DEVICE;
@@ -1426,8 +1415,6 @@ lpfc_cmpl_plogi_plogi_issue(struct lpfc_vport *vport,
ndlp->nlp_class_sup |= FC_COS_CLASS2;
if (sp->cls3.classValid)
ndlp->nlp_class_sup |= FC_COS_CLASS3;
if (sp->cls4.classValid)
ndlp->nlp_class_sup |= FC_COS_CLASS4;
ndlp->nlp_maxframe =
((sp->cmn.bbRcvSizeMsb & 0x0F) << 8) | sp->cmn.bbRcvSizeLsb;

View File

@@ -27,6 +27,8 @@
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/lockdep.h>
#include <linux/dmi.h>
#include <linux/of.h>
#include <scsi/scsi.h>
#include <scsi/scsi_cmnd.h>
@@ -8446,6 +8448,70 @@ lpfc_set_host_tm(struct lpfc_hba *phba)
return rc;
}
/**
* lpfc_get_platform_uuid - Attempts to extract a platform uuid
* @phba: pointer to lpfc hba data structure.
*
* This routine attempts to first read SMBIOS DMI data for the System
* Information structure offset 08h called System UUID. Else, no platform
* UUID will be advertised.
**/
static void
lpfc_get_platform_uuid(struct lpfc_hba *phba)
{
int rc;
const char *uuid;
char pni[17] = {0}; /* 16 characters + '\0' */
bool is_ff = true, is_00 = true;
u8 i;
/* First attempt SMBIOS DMI */
uuid = dmi_get_system_info(DMI_PRODUCT_UUID);
if (uuid) {
lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
"2088 SMBIOS UUID %s\n",
uuid);
} else {
lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
"2099 Could not extract UUID\n");
}
if (uuid && uuid_is_valid(uuid)) {
/* Generate PNI from UUID format.
*
* 1.) Extract lower 64 bits from UUID format.
* 2.) Set 3h for NAA Locally Assigned Name Identifier format.
*
* e.g. xxxxxxxx-xxxx-xxxx-yyyy-yyyyyyyyyyyy
*
* extract the yyyy-yyyyyyyyyyyy portion
* final PNI 3yyyyyyyyyyyyyyy
*/
scnprintf(pni, sizeof(pni), "3%c%c%c%s",
uuid[20], uuid[21], uuid[22], &uuid[24]);
/* Sanitize the converted PNI */
for (i = 1; i < 16 && (is_ff || is_00); i++) {
if (pni[i] != '0')
is_00 = false;
if (pni[i] != 'f' && pni[i] != 'F')
is_ff = false;
}
/* Convert from char* to unsigned long */
rc = kstrtoul(pni, 16, &phba->pni);
if (!rc && !is_ff && !is_00) {
lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
"2100 PNI 0x%016lx\n", phba->pni);
} else {
lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
"2101 PNI %s generation status %d\n",
pni, rc);
phba->pni = 0;
}
}
}
/**
* lpfc_sli4_hba_setup - SLI4 device initialization PCI function
* @phba: Pointer to HBA context object.
@@ -8529,6 +8595,10 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba)
clear_bit(HBA_FCOE_MODE, &phba->hba_flag);
}
/* Obtain platform UUID, only for SLI4 FC adapters */
if (!test_bit(HBA_FCOE_MODE, &phba->hba_flag))
lpfc_get_platform_uuid(phba);
if (bf_get(lpfc_mbx_rd_rev_cee_ver, &mqe->un.read_rev) ==
LPFC_DCBX_CEE_MODE)
set_bit(HBA_FIP_SUPPORT, &phba->hba_flag);
@@ -19858,13 +19928,15 @@ lpfc_sli4_remove_rpis(struct lpfc_hba *phba)
}
/**
* lpfc_sli4_resume_rpi - Remove the rpi bitmask region
* lpfc_sli4_resume_rpi - Resume traffic relative to an RPI
* @ndlp: pointer to lpfc nodelist data structure.
* @cmpl: completion call-back.
* @iocbq: data to load as mbox ctx_u information
*
* This routine is invoked to remove the memory region that
* provided rpi via a bitmask.
* Return codes
* 0 - successful
* -ENOMEM - No available memory
* -EIO - The mailbox failed to complete successfully.
**/
int
lpfc_sli4_resume_rpi(struct lpfc_nodelist *ndlp,
@@ -19894,7 +19966,6 @@ lpfc_sli4_resume_rpi(struct lpfc_nodelist *ndlp,
return -EIO;
}
/* Post all rpi memory regions to the port. */
lpfc_resume_rpi(mboxq, ndlp);
if (cmpl) {
mboxq->mbox_cmpl = cmpl;

View File

@@ -20,7 +20,7 @@
* included with this package. *
*******************************************************************/
#define LPFC_DRIVER_VERSION "14.4.0.11"
#define LPFC_DRIVER_VERSION "14.4.0.12"
#define LPFC_DRIVER_NAME "lpfc"
/* Used for SLI 2/3 */

View File

@@ -1150,9 +1150,13 @@ typedef struct LOG_BLOCK_SPAN_INFO {
} LD_SPAN_INFO, *PLD_SPAN_INFO;
struct MR_FW_RAID_MAP_ALL {
struct MR_FW_RAID_MAP raidMap;
struct MR_LD_SPAN_MAP ldSpanMap[MAX_LOGICAL_DRIVES];
/* Must be last --ends in a flexible-array member. */
TRAILING_OVERLAP(struct MR_FW_RAID_MAP, raidMap, ldSpanMap,
struct MR_LD_SPAN_MAP ldSpanMap[MAX_LOGICAL_DRIVES];
);
} __attribute__ ((packed));
static_assert(offsetof(struct MR_FW_RAID_MAP_ALL, raidMap.ldSpanMap) ==
offsetof(struct MR_FW_RAID_MAP_ALL, ldSpanMap));
struct MR_DRV_RAID_MAP {
/* total size of this structure, including this field.
@@ -1194,10 +1198,13 @@ struct MR_DRV_RAID_MAP {
* And it is mainly for code re-use purpose.
*/
struct MR_DRV_RAID_MAP_ALL {
struct MR_DRV_RAID_MAP raidMap;
struct MR_LD_SPAN_MAP ldSpanMap[MAX_LOGICAL_DRIVES_DYN];
/* Must be last --ends in a flexible-array member. */
TRAILING_OVERLAP(struct MR_DRV_RAID_MAP, raidMap, ldSpanMap,
struct MR_LD_SPAN_MAP ldSpanMap[MAX_LOGICAL_DRIVES_DYN];
);
} __packed;
static_assert(offsetof(struct MR_DRV_RAID_MAP_ALL, raidMap.ldSpanMap) ==
offsetof(struct MR_DRV_RAID_MAP_ALL, ldSpanMap));

View File

@@ -1534,7 +1534,7 @@ static int __init pm8001_init(void)
if (pm8001_use_tasklet && !pm8001_use_msix)
pm8001_use_tasklet = false;
pm8001_wq = alloc_workqueue("pm80xx", 0, 0);
pm8001_wq = alloc_workqueue("pm80xx", WQ_PERCPU, 0);
if (!pm8001_wq)
goto err;

View File

@@ -3374,7 +3374,8 @@ retry_probe:
QEDF_INFO(&(qedf->dbg_ctx), QEDF_LOG_INFO, "qedf->io_mempool=%p.\n",
qedf->io_mempool);
qedf->link_update_wq = alloc_workqueue("qedf_%u_link", WQ_MEM_RECLAIM,
qedf->link_update_wq = alloc_workqueue("qedf_%u_link",
WQ_MEM_RECLAIM | WQ_PERCPU,
1, qedf->lport->host->host_no);
INIT_DELAYED_WORK(&qedf->link_update, qedf_handle_link_update);
INIT_DELAYED_WORK(&qedf->link_recovery, qedf_link_recovery);
@@ -3585,7 +3586,8 @@ retry_probe:
ether_addr_copy(params.ll2_mac_address, qedf->mac);
/* Start LL2 processing thread */
qedf->ll2_recv_wq = alloc_workqueue("qedf_%d_ll2", WQ_MEM_RECLAIM, 1,
qedf->ll2_recv_wq = alloc_workqueue("qedf_%d_ll2",
WQ_MEM_RECLAIM | WQ_PERCPU, 1,
host->host_no);
if (!qedf->ll2_recv_wq) {
QEDF_ERR(&(qedf->dbg_ctx), "Failed to LL2 workqueue.\n");
@@ -3628,7 +3630,8 @@ retry_probe:
}
qedf->timer_work_queue = alloc_workqueue("qedf_%u_timer",
WQ_MEM_RECLAIM, 1, qedf->lport->host->host_no);
WQ_MEM_RECLAIM | WQ_PERCPU, 1,
qedf->lport->host->host_no);
if (!qedf->timer_work_queue) {
QEDF_ERR(&(qedf->dbg_ctx), "Failed to start timer "
"workqueue.\n");
@@ -3641,7 +3644,8 @@ retry_probe:
sprintf(host_buf, "qedf_%u_dpc",
qedf->lport->host->host_no);
qedf->dpc_wq =
alloc_workqueue("%s", WQ_MEM_RECLAIM, 1, host_buf);
alloc_workqueue("%s", WQ_MEM_RECLAIM | WQ_PERCPU, 1,
host_buf);
}
INIT_DELAYED_WORK(&qedf->recovery_work, qedf_recovery_handler);
@@ -4177,7 +4181,8 @@ static int __init qedf_init(void)
goto err3;
}
qedf_io_wq = alloc_workqueue("%s", WQ_MEM_RECLAIM, 1, "qedf_io_wq");
qedf_io_wq = alloc_workqueue("%s", WQ_MEM_RECLAIM | WQ_PERCPU, 1,
"qedf_io_wq");
if (!qedf_io_wq) {
QEDF_ERR(NULL, "Could not create qedf_io_wq.\n");
goto err4;

View File

@@ -2768,7 +2768,7 @@ retry_probe:
}
qedi->offload_thread = alloc_workqueue("qedi_ofld%d",
WQ_MEM_RECLAIM,
WQ_MEM_RECLAIM | WQ_PERCPU,
1, qedi->shost->host_no);
if (!qedi->offload_thread) {
QEDI_ERR(&qedi->dbg_ctx,

View File

@@ -2799,7 +2799,7 @@ qla1280_64bit_start_scsi(struct scsi_qla_host *ha, struct srb * sp)
dprintk(2, "start: cmd=%p sp=%p CDB=%xm, handle %lx\n", cmd, sp,
cmd->cmnd[0], (long)CMD_HANDLE(sp->cmd));
dprintk(2, " bus %i, target %i, lun %i\n",
dprintk(2, " bus %i, target %i, lun %llu\n",
SCSI_BUS_32(cmd), SCSI_TCN_32(cmd), SCSI_LUN_32(cmd));
qla1280_dump_buffer(2, cmd->cmnd, MAX_COMMAND_SIZE);
@@ -2871,7 +2871,7 @@ qla1280_64bit_start_scsi(struct scsi_qla_host *ha, struct srb * sp)
remseg--;
}
dprintk(5, "qla1280_64bit_start_scsi: Scatter/gather "
"command packet data - b %i, t %i, l %i \n",
"command packet data - b %i, t %i, l %llu\n",
SCSI_BUS_32(cmd), SCSI_TCN_32(cmd),
SCSI_LUN_32(cmd));
qla1280_dump_buffer(5, (char *)pkt,
@@ -2929,14 +2929,14 @@ qla1280_64bit_start_scsi(struct scsi_qla_host *ha, struct srb * sp)
remseg -= cnt;
dprintk(5, "qla1280_64bit_start_scsi: "
"continuation packet data - b %i, t "
"%i, l %i \n", SCSI_BUS_32(cmd),
"%i, l %llu\n", SCSI_BUS_32(cmd),
SCSI_TCN_32(cmd), SCSI_LUN_32(cmd));
qla1280_dump_buffer(5, (char *)pkt,
REQUEST_ENTRY_SIZE);
}
} else { /* No data transfer */
dprintk(5, "qla1280_64bit_start_scsi: No data, command "
"packet data - b %i, t %i, l %i \n",
"packet data - b %i, t %i, l %llu\n",
SCSI_BUS_32(cmd), SCSI_TCN_32(cmd), SCSI_LUN_32(cmd));
qla1280_dump_buffer(5, (char *)pkt, REQUEST_ENTRY_SIZE);
}
@@ -3655,7 +3655,7 @@ qla1280_status_entry(struct scsi_qla_host *ha, struct response *pkt,
dprintk(2, "qla1280_status_entry: Check "
"condition Sense data, b %i, t %i, "
"l %i\n", SCSI_BUS_32(cmd), SCSI_TCN_32(cmd),
"l %llu\n", SCSI_BUS_32(cmd), SCSI_TCN_32(cmd),
SCSI_LUN_32(cmd));
if (sense_sz)
qla1280_dump_buffer(2,
@@ -3955,7 +3955,7 @@ __qla1280_print_scsi_cmd(struct scsi_cmnd *cmd)
sp = scsi_cmd_priv(cmd);
printk("SCSI Command @= 0x%p, Handle=0x%p\n", cmd, CMD_HANDLE(cmd));
printk(" chan=%d, target = 0x%02x, lun = 0x%02x, cmd_len = 0x%02x\n",
printk(" chan=%d, target = 0x%02x, lun = 0x%02llx, cmd_len = 0x%02x\n",
SCSI_BUS_32(cmd), SCSI_TCN_32(cmd), SCSI_LUN_32(cmd),
CMD_CDBLEN(cmd));
printk(" CDB = ");
@@ -3976,29 +3976,6 @@ __qla1280_print_scsi_cmd(struct scsi_cmnd *cmd)
printk(" underflow size = 0x%x, direction=0x%x\n",
cmd->underflow, cmd->sc_data_direction);
}
/**************************************************************************
* ql1280_dump_device
*
**************************************************************************/
static void
ql1280_dump_device(struct scsi_qla_host *ha)
{
struct scsi_cmnd *cp;
struct srb *sp;
int i;
printk(KERN_DEBUG "Outstanding Commands on controller:\n");
for (i = 0; i < MAX_OUTSTANDING_COMMANDS; i++) {
if ((sp = ha->outstanding_cmds[i]) == NULL)
continue;
if ((cp = sp->cmd) == NULL)
continue;
qla1280_print_scsi_cmd(1, cp);
}
}
#endif

View File

@@ -54,10 +54,11 @@
* | Misc | 0xd303 | 0xd031-0xd0ff |
* | | | 0xd101-0xd1fe |
* | | | 0xd214-0xd2fe |
* | Target Mode | 0xe081 | |
* | Target Mode | 0xe089 | |
* | Target Mode Management | 0xf09b | 0xf002 |
* | | | 0xf046-0xf049 |
* | Target Mode Task Management | 0x1000d | |
* | Target Mode SRR | 0x11038 | |
* ----------------------------------------------------------------------
*/

View File

@@ -3503,7 +3503,6 @@ struct isp_operations {
#define QLA_MSIX_RSP_Q 0x01
#define QLA_ATIO_VECTOR 0x02
#define QLA_MSIX_QPAIR_MULTIQ_RSP_Q 0x03
#define QLA_MSIX_QPAIR_MULTIQ_RSP_Q_HS 0x04
#define QLA_MIDX_DEFAULT 0
#define QLA_MIDX_RSP_Q 1

View File

@@ -766,7 +766,7 @@ extern int qla2x00_dfs_remove(scsi_qla_host_t *);
/* Globa function prototypes for multi-q */
extern int qla25xx_request_irq(struct qla_hw_data *, struct qla_qpair *,
struct qla_msix_entry *, int);
struct qla_msix_entry *);
extern int qla25xx_init_req_que(struct scsi_qla_host *, struct req_que *);
extern int qla25xx_init_rsp_que(struct scsi_qla_host *, struct rsp_que *);
extern int qla25xx_create_req_que(struct qla_hw_data *, uint16_t, uint8_t,

View File

@@ -4369,6 +4369,7 @@ enable_82xx_npiv:
ha->max_npiv_vports =
MIN_MULTI_ID_FABRIC - 1;
}
qlt_config_nvram_with_fw_version(vha);
qla2x00_get_resource_cnts(vha);
qla_init_iocb_limit(vha);

View File

@@ -4467,32 +4467,6 @@ qla2xxx_msix_rsp_q(int irq, void *dev_id)
return IRQ_HANDLED;
}
irqreturn_t
qla2xxx_msix_rsp_q_hs(int irq, void *dev_id)
{
struct qla_hw_data *ha;
struct qla_qpair *qpair;
struct device_reg_24xx __iomem *reg;
unsigned long flags;
qpair = dev_id;
if (!qpair) {
ql_log(ql_log_info, NULL, 0x505b,
"%s: NULL response queue pointer.\n", __func__);
return IRQ_NONE;
}
ha = qpair->hw;
reg = &ha->iobase->isp24;
spin_lock_irqsave(&ha->hardware_lock, flags);
wrt_reg_dword(&reg->hccr, HCCRX_CLR_RISC_INT);
spin_unlock_irqrestore(&ha->hardware_lock, flags);
queue_work(ha->wq, &qpair->q_work);
return IRQ_HANDLED;
}
/* Interrupt handling helpers. */
struct qla_init_msix_entry {
@@ -4505,7 +4479,6 @@ static const struct qla_init_msix_entry msix_entries[] = {
{ "rsp_q", qla24xx_msix_rsp_q },
{ "atio_q", qla83xx_msix_atio_q },
{ "qpair_multiq", qla2xxx_msix_rsp_q },
{ "qpair_multiq_hs", qla2xxx_msix_rsp_q_hs },
};
static const struct qla_init_msix_entry qla82xx_msix_entries[] = {
@@ -4792,9 +4765,10 @@ free_irqs:
}
int qla25xx_request_irq(struct qla_hw_data *ha, struct qla_qpair *qpair,
struct qla_msix_entry *msix, int vector_type)
struct qla_msix_entry *msix)
{
const struct qla_init_msix_entry *intr = &msix_entries[vector_type];
const struct qla_init_msix_entry *intr =
&msix_entries[QLA_MSIX_QPAIR_MULTIQ_RSP_Q];
scsi_qla_host_t *vha = pci_get_drvdata(ha->pdev);
int ret;

View File

@@ -253,6 +253,7 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp)
/* Issue set host interrupt command to send cmd out. */
ha->flags.mbox_int = 0;
clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags);
reinit_completion(&ha->mbx_intr_comp);
/* Unlock mbx registers and wait for interrupt */
ql_dbg(ql_dbg_mbx, vha, 0x100f,
@@ -279,6 +280,7 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp)
"cmd=%x Timeout.\n", command);
spin_lock_irqsave(&ha->hardware_lock, flags);
clear_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags);
reinit_completion(&ha->mbx_intr_comp);
spin_unlock_irqrestore(&ha->hardware_lock, flags);
if (chip_reset != ha->chip_reset) {

View File

@@ -899,9 +899,7 @@ qla25xx_create_rsp_que(struct qla_hw_data *ha, uint16_t options,
rsp->options, rsp->id, rsp->rsp_q_in,
rsp->rsp_q_out);
ret = qla25xx_request_irq(ha, qpair, qpair->msix,
ha->flags.disable_msix_handshake ?
QLA_MSIX_QPAIR_MULTIQ_RSP_Q : QLA_MSIX_QPAIR_MULTIQ_RSP_Q_HS);
ret = qla25xx_request_irq(ha, qpair, qpair->msix);
if (ret)
goto que_failed;

View File

@@ -1292,7 +1292,7 @@ void qla2xxx_process_purls_iocb(void **pkt, struct rsp_que **rsp)
a.reason = FCNVME_RJT_RC_LOGIC;
a.explanation = FCNVME_RJT_EXP_NONE;
xmt_reject = true;
kfree(item);
qla24xx_free_purex_item(item);
goto out;
}

View File

@@ -1862,12 +1862,6 @@ __qla2x00_abort_all_cmds(struct qla_qpair *qp, int res)
for (cnt = 1; cnt < req->num_outstanding_cmds; cnt++) {
sp = req->outstanding_cmds[cnt];
if (sp) {
if (qla2x00_chip_is_down(vha)) {
req->outstanding_cmds[cnt] = NULL;
sp->done(sp, res);
continue;
}
switch (sp->cmd_type) {
case TYPE_SRB:
qla2x00_abort_srb(qp, sp, res, &flags);
@@ -1881,10 +1875,26 @@ __qla2x00_abort_all_cmds(struct qla_qpair *qp, int res)
continue;
}
cmd = (struct qla_tgt_cmd *)sp;
cmd->aborted = 1;
if (cmd->sg_mapped)
qlt_unmap_sg(vha, cmd);
if (cmd->state == QLA_TGT_STATE_NEED_DATA) {
cmd->aborted = 1;
cmd->write_data_transferred = 0;
cmd->state = QLA_TGT_STATE_DATA_IN;
ha->tgt.tgt_ops->handle_data(cmd);
} else {
ha->tgt.tgt_ops->free_cmd(cmd);
}
break;
case TYPE_TGT_TMCMD:
/* Skip task management functions. */
/*
* Currently, only ABTS response gets on the
* outstanding_cmds[]
*/
qlt_free_ul_mcmd(ha,
(struct qla_tgt_mgmt_cmd *) sp);
break;
default:
break;
@@ -3397,7 +3407,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
"req->req_q_in=%p req->req_q_out=%p rsp->rsp_q_in=%p rsp->rsp_q_out=%p.\n",
req->req_q_in, req->req_q_out, rsp->rsp_q_in, rsp->rsp_q_out);
ha->wq = alloc_workqueue("qla2xxx_wq", WQ_MEM_RECLAIM, 0);
ha->wq = alloc_workqueue("qla2xxx_wq", WQ_MEM_RECLAIM | WQ_PERCPU, 0);
if (unlikely(!ha->wq)) {
ret = -ENOMEM;
goto probe_failed;
@@ -3444,13 +3454,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
ha->mqenable = 0;
if (ha->mqenable) {
bool startit = false;
if (QLA_TGT_MODE_ENABLED())
startit = false;
if (ql2x_ini_mode == QLA2XXX_INI_MODE_ENABLED)
startit = true;
bool startit = !!(host->active_mode & MODE_INITIATOR);
/* Create start of day qpairs for Block MQ */
for (i = 0; i < ha->max_qpairs; i++)
@@ -5280,7 +5284,7 @@ void qla24xx_sched_upd_fcport(fc_port_t *fcport)
qla2x00_set_fcport_disc_state(fcport, DSC_UPD_FCPORT);
spin_unlock_irqrestore(&fcport->vha->work_lock, flags);
queue_work(system_unbound_wq, &fcport->reg_work);
queue_work(system_dfl_wq, &fcport->reg_work);
}
static
@@ -7244,6 +7248,7 @@ qla2xxx_wake_dpc(struct scsi_qla_host *vha)
if (!test_bit(UNLOADING, &vha->dpc_flags) && t)
wake_up_process(t);
}
EXPORT_SYMBOL(qla2xxx_wake_dpc);
/*
* qla2x00_rst_aen

File diff suppressed because it is too large Load Diff

View File

@@ -184,6 +184,7 @@ struct nack_to_isp {
#define NOTIFY_ACK_SRR_REJECT_REASON_UNABLE_TO_PERFORM 0x9
#define NOTIFY_ACK_SRR_FLAGS_REJECT_EXPL_NO_EXPL 0
#define NOTIFY_ACK_SRR_FLAGS_REJECT_EXPL_INVALID_OX_ID_RX_ID 0x17
#define NOTIFY_ACK_SRR_FLAGS_REJECT_EXPL_UNABLE_TO_SUPPLY_DATA 0x2a
#define NOTIFY_ACK_SUCCESS 0x01
@@ -686,6 +687,8 @@ struct qla_tgt_func_tmpl {
int (*handle_tmr)(struct qla_tgt_mgmt_cmd *, u64, uint16_t,
uint32_t);
struct qla_tgt_cmd *(*get_cmd)(struct fc_port *);
int (*get_cmd_ref)(struct qla_tgt_cmd *cmd);
void (*put_cmd_ref)(struct qla_tgt_cmd *cmd);
void (*rel_cmd)(struct qla_tgt_cmd *);
void (*free_cmd)(struct qla_tgt_cmd *);
void (*free_mcmd)(struct qla_tgt_mgmt_cmd *);
@@ -754,6 +757,7 @@ int qla2x00_wait_for_hba_online(struct scsi_qla_host *);
#define QLA_TGT_STATE_NEED_DATA 1 /* target needs data to continue */
#define QLA_TGT_STATE_DATA_IN 2 /* Data arrived + target processing */
#define QLA_TGT_STATE_PROCESSED 3 /* target done processing */
#define QLA_TGT_STATE_DONE 4 /* cmd being freed */
/* ATIO task_codes field */
#define ATIO_SIMPLE_QUEUE 0
@@ -822,18 +826,26 @@ struct qla_tgt {
int notify_ack_expected;
int abts_resp_expected;
int modify_lun_expected;
spinlock_t srr_lock;
struct list_head srr_list;
struct work_struct srr_work;
atomic_t tgt_global_resets_count;
struct list_head tgt_list_entry;
};
struct qla_tgt_sess_op {
struct scsi_qla_host *vha;
uint32_t chip_reset;
struct atio_from_isp atio;
struct work_struct work;
struct list_head cmd_list;
bool aborted;
struct rsp_que *rsp;
struct atio_from_isp atio;
/* DO NOT ADD ANYTHING ELSE HERE - atio must be last member */
};
enum trace_flags {
@@ -858,6 +870,7 @@ enum trace_flags {
TRC_DATA_IN = BIT_18,
TRC_ABORT = BIT_19,
TRC_DIF_ERR = BIT_20,
TRC_SRR_IMM = BIT_21,
};
struct qla_tgt_cmd {
@@ -876,25 +889,36 @@ struct qla_tgt_cmd {
/* Sense buffer that will be mapped into outgoing status */
unsigned char sense_buffer[TRANSPORT_SENSE_BUFFER];
spinlock_t cmd_lock;
/* to save extra sess dereferences */
unsigned int conf_compl_supported:1;
unsigned int sg_mapped:1;
/* Call qlt_free_sg() if set. */
unsigned int free_sg:1;
unsigned int write_data_transferred:1;
/* Set if the SCSI status was sent successfully. */
unsigned int rsp_sent:1;
unsigned int q_full:1;
unsigned int term_exchg:1;
unsigned int cmd_sent_to_fw:1;
unsigned int cmd_in_wq:1;
unsigned int edif:1;
/*
* This variable may be set from outside the LIO and I/O completion
* callback functions. Do not declare this member variable as a
* bitfield to avoid a read-modify-write operation when this variable
* is set.
*/
unsigned int aborted;
/* Set if a SRR was rejected. */
unsigned int srr_failed:1;
/* Set if the exchange has been terminated. */
unsigned int sent_term_exchg:1;
/*
* Set if sent_term_exchg is set, or if the cmd was aborted by a TMR,
* or if some other error prevents normal processing of the command.
*/
unsigned int aborted:1;
struct qla_tgt_srr *srr;
struct scatterlist *sg; /* cmd data buffer SG vector */
int sg_cnt; /* SG segments count */
int bufflen; /* cmd buffer length */
@@ -925,13 +949,23 @@ struct qla_tgt_cmd {
uint8_t scsi_status, sense_key, asc, ascq;
struct crc_context *ctx;
const uint8_t *cdb;
uint8_t *cdb;
uint64_t lba;
int cdb_len;
uint16_t a_guard, e_guard, a_app_tag, e_app_tag;
uint32_t a_ref_tag, e_ref_tag;
#define DIF_BUNDL_DMA_VALID 1
uint16_t prot_flags;
unsigned long jiffies_at_term_exchg;
/*
* jiffies64 when qlt_rdy_to_xfer() or qlt_xmit_response() first
* called, or 0 when not in those states. Used to limit the number of
* SRR retries.
*/
uint64_t jiffies_at_hw_st_entry;
uint64_t jiffies_at_alloc;
uint64_t jiffies_at_free;
@@ -965,6 +999,7 @@ struct qla_tgt_mgmt_cmd {
unsigned int flags;
#define QLA24XX_MGMT_SEND_NACK BIT_0
#define QLA24XX_MGMT_ABORT_IO_ATTR_VALID BIT_1
#define QLA24XX_MGMT_LLD_OWNED BIT_2
uint32_t reset_count;
struct work_struct work;
uint64_t unpacked_lun;
@@ -993,6 +1028,45 @@ struct qla_tgt_prm {
uint16_t tot_dsds;
};
/*
* SRR (Sequence Retransmission Request) - resend or re-receive some or all
* data or status to recover from a transient I/O error.
*/
struct qla_tgt_srr {
/*
* Copy of immediate notify SRR message received from hw; valid only if
* imm_ntfy_recvd is true.
*/
struct imm_ntfy_from_isp imm_ntfy;
struct list_head srr_list_entry;
/* The command affected by this SRR, or NULL if not yet determined. */
struct qla_tgt_cmd *cmd;
/* Used to detect if the HBA has been reset since receiving the SRR. */
uint32_t reset_count;
/*
* The hardware sends two messages for each SRR - an immediate notify
* and a CTIO with CTIO_SRR_RECEIVED status. These keep track of which
* messages have been received. The SRR can be processed once both of
* these are true.
*/
bool imm_ntfy_recvd;
bool ctio_recvd;
/*
* This is set to true if the affected command was aborted (cmd may be
* set to NULL), in which case the immediate notify exchange also needs
* to be aborted.
*/
bool aborted;
/* This is set to true to force the SRR to be rejected. */
bool reject;
};
/* Check for Switch reserved address */
#define IS_SW_RESV_ADDR(_s_id) \
((_s_id.b.domain == 0xff) && ((_s_id.b.area & 0xf0) == 0xf0))
@@ -1047,6 +1121,20 @@ static inline uint32_t sid_to_key(const be_id_t s_id)
s_id.al_pa;
}
/*
* Free the scatterlist allocated by qlt_set_data_offset(). Call this only if
* cmd->free_sg is set.
*/
static inline void qlt_free_sg(struct qla_tgt_cmd *cmd)
{
/*
* The scatterlist may be chained to the original scatterlist, but we
* only need to free the first segment here since that is the only part
* allocated by qlt_set_data_offset().
*/
kfree(cmd->sg);
}
/*
* Exported symbols from qla_target.c LLD logic used by qla2xxx code..
*/
@@ -1055,9 +1143,14 @@ extern void qlt_response_pkt_all_vps(struct scsi_qla_host *, struct rsp_que *,
extern int qlt_rdy_to_xfer(struct qla_tgt_cmd *);
extern int qlt_xmit_response(struct qla_tgt_cmd *, int, uint8_t);
extern int qlt_abort_cmd(struct qla_tgt_cmd *);
void qlt_srr_abort(struct qla_tgt_cmd *cmd, bool reject);
void qlt_send_term_exchange(struct qla_qpair *qpair,
struct qla_tgt_cmd *cmd, struct atio_from_isp *atio, int ha_locked);
extern void qlt_xmit_tm_rsp(struct qla_tgt_mgmt_cmd *);
void qlt_free_ul_mcmd(struct qla_hw_data *ha, struct qla_tgt_mgmt_cmd *mcmd);
extern void qlt_free_mcmd(struct qla_tgt_mgmt_cmd *);
extern void qlt_free_cmd(struct qla_tgt_cmd *cmd);
extern void qlt_unmap_sg(struct scsi_qla_host *vha, struct qla_tgt_cmd *cmd);
extern void qlt_async_event(uint16_t, struct scsi_qla_host *, uint16_t *);
extern void qlt_enable_vha(struct scsi_qla_host *);
extern void qlt_vport_create(struct scsi_qla_host *, struct qla_hw_data *);
@@ -1073,6 +1166,7 @@ extern void qlt_81xx_config_nvram_stage2(struct scsi_qla_host *,
struct init_cb_81xx *);
extern void qlt_81xx_config_nvram_stage1(struct scsi_qla_host *,
struct nvram_81xx *);
void qlt_config_nvram_with_fw_version(struct scsi_qla_host *vha);
extern void qlt_modify_vp_config(struct scsi_qla_host *,
struct vp_config_entry_24xx *);
extern void qlt_probe_one_stage1(struct scsi_qla_host *, struct qla_hw_data *);

View File

@@ -291,6 +291,16 @@ static struct qla_tgt_cmd *tcm_qla2xxx_get_cmd(struct fc_port *sess)
return cmd;
}
static int tcm_qla2xxx_get_cmd_ref(struct qla_tgt_cmd *cmd)
{
return target_get_sess_cmd(&cmd->se_cmd, true);
}
static void tcm_qla2xxx_put_cmd_ref(struct qla_tgt_cmd *cmd)
{
target_put_sess_cmd(&cmd->se_cmd);
}
static void tcm_qla2xxx_rel_cmd(struct qla_tgt_cmd *cmd)
{
target_free_tag(cmd->sess->se_sess, &cmd->se_cmd);
@@ -303,6 +313,8 @@ static void tcm_qla2xxx_rel_cmd(struct qla_tgt_cmd *cmd)
*/
static void tcm_qla2xxx_free_cmd(struct qla_tgt_cmd *cmd)
{
cmd->state = QLA_TGT_STATE_DONE;
cmd->qpair->tgt_counters.core_qla_free_cmd++;
cmd->cmd_in_wq = 1;
@@ -529,6 +541,9 @@ static void tcm_qla2xxx_handle_data_work(struct work_struct *work)
if (cmd->se_cmd.pi_err)
transport_generic_request_failure(&cmd->se_cmd,
cmd->se_cmd.pi_err);
else if (cmd->srr_failed)
transport_generic_request_failure(&cmd->se_cmd,
TCM_SNACK_REJECTED);
else
transport_generic_request_failure(&cmd->se_cmd,
TCM_CHECK_CONDITION_ABORT_CMD);
@@ -1524,6 +1539,8 @@ static const struct qla_tgt_func_tmpl tcm_qla2xxx_template = {
.handle_data = tcm_qla2xxx_handle_data,
.handle_tmr = tcm_qla2xxx_handle_tmr,
.get_cmd = tcm_qla2xxx_get_cmd,
.get_cmd_ref = tcm_qla2xxx_get_cmd_ref,
.put_cmd_ref = tcm_qla2xxx_put_cmd_ref,
.rel_cmd = tcm_qla2xxx_rel_cmd,
.free_cmd = tcm_qla2xxx_free_cmd,
.free_mcmd = tcm_qla2xxx_free_mcmd,

View File

@@ -1016,7 +1016,7 @@ void qla4xxx_get_crash_record(struct scsi_qla_host * ha)
uint32_t crash_record_size = 0;
memset(&mbox_cmd, 0, sizeof(mbox_cmd));
memset(&mbox_sts, 0, sizeof(mbox_cmd));
memset(&mbox_sts, 0, sizeof(mbox_sts));
/* Get size of crash record. */
mbox_cmd[0] = MBOX_CMD_GET_CRASH_RECORD;
@@ -1099,7 +1099,7 @@ void qla4xxx_get_conn_event_log(struct scsi_qla_host * ha)
/* Get Crash Record. */
memset(&mbox_cmd, 0, sizeof(mbox_cmd));
memset(&mbox_sts, 0, sizeof(mbox_cmd));
memset(&mbox_sts, 0, sizeof(mbox_sts));
mbox_cmd[0] = MBOX_CMD_GET_CONN_EVENT_LOG;
mbox_cmd[2] = LSDW(event_log_dma);

View File

@@ -216,6 +216,9 @@ int scsi_device_max_queue_depth(struct scsi_device *sdev)
*/
int scsi_change_queue_depth(struct scsi_device *sdev, int depth)
{
if (!sdev->budget_map.map)
return -EINVAL;
depth = min_t(int, depth, scsi_device_max_queue_depth(sdev));
if (depth > 0) {
@@ -255,6 +258,8 @@ EXPORT_SYMBOL(scsi_change_queue_depth);
*/
int scsi_track_queue_full(struct scsi_device *sdev, int depth)
{
if (!sdev->budget_map.map)
return 0;
/*
* Don't let QUEUE_FULLs on the same
@@ -826,8 +831,11 @@ struct scsi_device *__scsi_iterate_devices(struct Scsi_Host *shost,
spin_lock_irqsave(shost->host_lock, flags);
while (list->next != &shost->__devices) {
next = list_entry(list->next, struct scsi_device, siblings);
/* skip devices that we can't get a reference to */
if (!scsi_device_get(next))
/*
* Skip pseudo devices and also devices we can't get a
* reference to.
*/
if (!scsi_device_is_pseudo_dev(next) && !scsi_device_get(next))
break;
next = NULL;
list = list->next;

View File

@@ -230,6 +230,7 @@ struct tape_block {
#define SDEBUG_OPT_NO_CDB_NOISE 0x4000
#define SDEBUG_OPT_HOST_BUSY 0x8000
#define SDEBUG_OPT_CMD_ABORT 0x10000
#define SDEBUG_OPT_UNALIGNED_WRITE 0x20000
#define SDEBUG_OPT_ALL_NOISE (SDEBUG_OPT_NOISE | SDEBUG_OPT_Q_NOISE | \
SDEBUG_OPT_RESET_NOISE)
#define SDEBUG_OPT_ALL_INJECTING (SDEBUG_OPT_RECOVERED_ERR | \
@@ -237,7 +238,8 @@ struct tape_block {
SDEBUG_OPT_DIF_ERR | SDEBUG_OPT_DIX_ERR | \
SDEBUG_OPT_SHORT_TRANSFER | \
SDEBUG_OPT_HOST_BUSY | \
SDEBUG_OPT_CMD_ABORT)
SDEBUG_OPT_CMD_ABORT | \
SDEBUG_OPT_UNALIGNED_WRITE)
#define SDEBUG_OPT_RECOV_DIF_DIX (SDEBUG_OPT_RECOVERED_ERR | \
SDEBUG_OPT_DIF_ERR | SDEBUG_OPT_DIX_ERR)
@@ -2961,11 +2963,11 @@ static int resp_mode_sense(struct scsi_cmnd *scp,
int target_dev_id;
int target = scp->device->id;
unsigned char *ap;
unsigned char *arr __free(kfree);
unsigned char *cmd = scp->cmnd;
bool dbd, llbaa, msense_6, is_disk, is_zbc, is_tape;
arr = kzalloc(SDEBUG_MAX_MSENSE_SZ, GFP_ATOMIC);
unsigned char *arr __free(kfree) = kzalloc(SDEBUG_MAX_MSENSE_SZ, GFP_ATOMIC);
if (!arr)
return -ENOMEM;
dbd = !!(cmd[1] & 0x8); /* disable block descriptors */
@@ -4932,6 +4934,14 @@ static int resp_write_dt0(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
u8 *cmd = scp->cmnd;
bool meta_data_locked = false;
if (unlikely(sdebug_opts & SDEBUG_OPT_UNALIGNED_WRITE &&
atomic_read(&sdeb_inject_pending))) {
atomic_set(&sdeb_inject_pending, 0);
mk_sense_buffer(scp, ILLEGAL_REQUEST, LBA_OUT_OF_RANGE,
UNALIGNED_WRITE_ASCQ);
return check_condition_result;
}
switch (cmd[0]) {
case WRITE_16:
ei_lba = 0;
@@ -6752,20 +6762,59 @@ static bool scsi_debug_stop_cmnd(struct scsi_cmnd *cmnd)
return false;
}
struct sdebug_abort_cmd {
u32 unique_tag;
};
enum sdebug_internal_cmd_type {
SCSI_DEBUG_ABORT_CMD,
};
struct sdebug_internal_cmd {
enum sdebug_internal_cmd_type type;
union {
struct sdebug_abort_cmd abort_cmd;
};
};
union sdebug_priv {
struct sdebug_scsi_cmd cmd;
struct sdebug_internal_cmd internal_cmd;
};
/*
* Called from scsi_debug_abort() only, which is for timed-out cmd.
* Abort SCSI command @cmnd. Only called from scsi_debug_abort(). Although
* it would be possible to call scsi_debug_stop_cmnd() directly, an internal
* command is allocated and submitted to trigger the reserved command
* infrastructure.
*/
static bool scsi_debug_abort_cmnd(struct scsi_cmnd *cmnd)
{
struct sdebug_scsi_cmd *sdsc = scsi_cmd_priv(cmnd);
unsigned long flags;
bool res;
struct Scsi_Host *shost = cmnd->device->host;
struct request *rq = scsi_cmd_to_rq(cmnd);
u32 unique_tag = blk_mq_unique_tag(rq);
struct sdebug_internal_cmd *internal_cmd;
struct scsi_cmnd *abort_cmd;
struct request *abort_rq;
blk_status_t res;
spin_lock_irqsave(&sdsc->lock, flags);
res = scsi_debug_stop_cmnd(cmnd);
spin_unlock_irqrestore(&sdsc->lock, flags);
return res;
abort_cmd = scsi_get_internal_cmd(shost->pseudo_sdev, DMA_NONE,
BLK_MQ_REQ_RESERVED);
if (!abort_cmd)
return false;
internal_cmd = scsi_cmd_priv(abort_cmd);
*internal_cmd = (struct sdebug_internal_cmd) {
.type = SCSI_DEBUG_ABORT_CMD,
.abort_cmd = {
.unique_tag = unique_tag,
},
};
abort_rq = scsi_cmd_to_rq(abort_cmd);
abort_rq->timeout = secs_to_jiffies(3);
res = blk_execute_rq(abort_rq, true);
scsi_put_internal_cmd(abort_cmd);
return res == BLK_STS_OK;
}
/*
@@ -9220,6 +9269,56 @@ out_handle:
return ret;
}
/* Process @scp, a request to abort a SCSI command by tag. */
static void scsi_debug_abort_cmd(struct Scsi_Host *shost, struct scsi_cmnd *scp)
{
struct sdebug_internal_cmd *internal_cmd = scsi_cmd_priv(scp);
struct sdebug_abort_cmd *abort_cmd = &internal_cmd->abort_cmd;
const u32 unique_tag = abort_cmd->unique_tag;
struct scsi_cmnd *to_be_aborted_scmd =
scsi_host_find_tag(shost, unique_tag);
struct sdebug_scsi_cmd *to_be_aborted_sdsc =
scsi_cmd_priv(to_be_aborted_scmd);
bool res = false;
if (!to_be_aborted_scmd) {
pr_err("%s: command with tag %#x not found\n", __func__,
unique_tag);
return;
}
scoped_guard(spinlock_irqsave, &to_be_aborted_sdsc->lock)
res = scsi_debug_stop_cmnd(to_be_aborted_scmd);
if (res)
pr_info("%s: aborted command with tag %#x\n",
__func__, unique_tag);
else
pr_err("%s: failed to abort command with tag %#x\n",
__func__, unique_tag);
set_host_byte(scp, res ? DID_OK : DID_ERROR);
}
static int scsi_debug_process_reserved_command(struct Scsi_Host *shost,
struct scsi_cmnd *scp)
{
struct sdebug_internal_cmd *internal_cmd = scsi_cmd_priv(scp);
switch (internal_cmd->type) {
case SCSI_DEBUG_ABORT_CMD:
scsi_debug_abort_cmd(shost, scp);
break;
default:
WARN_ON_ONCE(true);
set_host_byte(scp, DID_ERROR);
break;
}
scsi_done(scp);
return 0;
}
static int scsi_debug_queuecommand(struct Scsi_Host *shost,
struct scsi_cmnd *scp)
{
@@ -9420,6 +9519,9 @@ static int sdebug_init_cmd_priv(struct Scsi_Host *shost, struct scsi_cmnd *cmd)
struct sdebug_scsi_cmd *sdsc = scsi_cmd_priv(cmd);
struct sdebug_defer *sd_dp = &sdsc->sd_dp;
if (blk_mq_is_reserved_rq(scsi_cmd_to_rq(cmd)))
return 0;
spin_lock_init(&sdsc->lock);
hrtimer_setup(&sd_dp->hrt, sdebug_q_cmd_hrt_complete, CLOCK_MONOTONIC,
HRTIMER_MODE_REL_PINNED);
@@ -9439,6 +9541,7 @@ static const struct scsi_host_template sdebug_driver_template = {
.sdev_destroy = scsi_debug_sdev_destroy,
.ioctl = scsi_debug_ioctl,
.queuecommand = scsi_debug_queuecommand,
.queue_reserved_command = scsi_debug_process_reserved_command,
.change_queue_depth = sdebug_change_qdepth,
.map_queues = sdebug_map_queues,
.mq_poll = sdebug_blk_mq_poll,
@@ -9448,6 +9551,7 @@ static const struct scsi_host_template sdebug_driver_template = {
.eh_bus_reset_handler = scsi_debug_bus_reset,
.eh_host_reset_handler = scsi_debug_host_reset,
.can_queue = SDEBUG_CANQUEUE,
.nr_reserved_cmds = 1,
.this_id = 7,
.sg_tablesize = SG_MAX_SEGMENTS,
.cmd_per_lun = DEF_CMD_PER_LUN,
@@ -9456,7 +9560,7 @@ static const struct scsi_host_template sdebug_driver_template = {
.module = THIS_MODULE,
.skip_settle_delay = 1,
.track_queue_depth = 1,
.cmd_size = sizeof(struct sdebug_scsi_cmd),
.cmd_size = sizeof(union sdebug_priv),
.init_cmd_priv = sdebug_init_cmd_priv,
.target_alloc = sdebug_target_alloc,
.target_destroy = sdebug_target_destroy,

View File

@@ -749,6 +749,9 @@ static void scsi_handle_queue_ramp_up(struct scsi_device *sdev)
const struct scsi_host_template *sht = sdev->host->hostt;
struct scsi_device *tmp_sdev;
if (!sdev->budget_map.map)
return;
if (!sht->track_queue_depth ||
sdev->queue_depth >= sdev->max_queue_depth)
return;

View File

@@ -396,7 +396,8 @@ void scsi_device_unbusy(struct scsi_device *sdev, struct scsi_cmnd *cmd)
if (starget->can_queue > 0)
atomic_dec(&starget->target_busy);
sbitmap_put(&sdev->budget_map, cmd->budget_token);
if (sdev->budget_map.map)
sbitmap_put(&sdev->budget_map, cmd->budget_token);
cmd->budget_token = -1;
}
@@ -1360,6 +1361,9 @@ static inline int scsi_dev_queue_ready(struct request_queue *q,
{
int token;
if (!sdev->budget_map.map)
return INT_MAX;
token = sbitmap_get(&sdev->budget_map);
if (token < 0)
return -1;
@@ -1530,6 +1534,14 @@ static void scsi_complete(struct request *rq)
struct scsi_cmnd *cmd = blk_mq_rq_to_pdu(rq);
enum scsi_disposition disposition;
if (blk_mq_is_reserved_rq(rq)) {
/* Only pass-through requests are supported in this code path. */
WARN_ON_ONCE(!blk_rq_is_passthrough(scsi_cmd_to_rq(cmd)));
scsi_mq_uninit_cmd(cmd);
__blk_mq_end_request(rq, scsi_result_to_blk_status(cmd->result));
return;
}
INIT_LIST_HEAD(&cmd->eh_entry);
atomic_inc(&cmd->device->iodone_cnt);
@@ -1749,7 +1761,8 @@ static void scsi_mq_put_budget(struct request_queue *q, int budget_token)
{
struct scsi_device *sdev = q->queuedata;
sbitmap_put(&sdev->budget_map, budget_token);
if (sdev->budget_map.map)
sbitmap_put(&sdev->budget_map, budget_token);
}
/*
@@ -1818,25 +1831,31 @@ static blk_status_t scsi_queue_rq(struct blk_mq_hw_ctx *hctx,
WARN_ON_ONCE(cmd->budget_token < 0);
/*
* If the device is not in running state we will reject some or all
* commands.
* Bypass the SCSI device, SCSI target and SCSI host checks for
* reserved commands.
*/
if (unlikely(sdev->sdev_state != SDEV_RUNNING)) {
ret = scsi_device_state_check(sdev, req);
if (ret != BLK_STS_OK)
goto out_put_budget;
}
if (!blk_mq_is_reserved_rq(req)) {
/*
* If the device is not in running state we will reject some or
* all commands.
*/
if (unlikely(sdev->sdev_state != SDEV_RUNNING)) {
ret = scsi_device_state_check(sdev, req);
if (ret != BLK_STS_OK)
goto out_put_budget;
}
ret = BLK_STS_RESOURCE;
if (!scsi_target_queue_ready(shost, sdev))
goto out_put_budget;
if (unlikely(scsi_host_in_recovery(shost))) {
if (cmd->flags & SCMD_FAIL_IF_RECOVERING)
ret = BLK_STS_OFFLINE;
goto out_dec_target_busy;
ret = BLK_STS_RESOURCE;
if (!scsi_target_queue_ready(shost, sdev))
goto out_put_budget;
if (unlikely(scsi_host_in_recovery(shost))) {
if (cmd->flags & SCMD_FAIL_IF_RECOVERING)
ret = BLK_STS_OFFLINE;
goto out_dec_target_busy;
}
if (!scsi_host_queue_ready(q, shost, sdev, cmd))
goto out_dec_target_busy;
}
if (!scsi_host_queue_ready(q, shost, sdev, cmd))
goto out_dec_target_busy;
/*
* Only clear the driver-private command data if the LLD does not supply
@@ -1865,6 +1884,14 @@ static blk_status_t scsi_queue_rq(struct blk_mq_hw_ctx *hctx,
cmd->submitter = SUBMITTED_BY_BLOCK_LAYER;
blk_mq_start_request(req);
if (blk_mq_is_reserved_rq(req)) {
reason = shost->hostt->queue_reserved_command(shost, cmd);
if (reason) {
ret = BLK_STS_RESOURCE;
goto out_put_budget;
}
return BLK_STS_OK;
}
reason = scsi_dispatch_cmd(cmd);
if (reason) {
scsi_set_blocked(cmd, reason);
@@ -2083,7 +2110,8 @@ int scsi_mq_setup_tags(struct Scsi_Host *shost)
tag_set->ops = &scsi_mq_ops_no_commit;
tag_set->nr_hw_queues = shost->nr_hw_queues ? : 1;
tag_set->nr_maps = shost->nr_maps ? : 1;
tag_set->queue_depth = shost->can_queue;
tag_set->queue_depth = shost->can_queue + shost->nr_reserved_cmds;
tag_set->reserved_tags = shost->nr_reserved_cmds;
tag_set->cmd_size = cmd_size;
tag_set->numa_node = dev_to_node(shost->dma_dev);
if (shost->hostt->tag_alloc_policy_rr)
@@ -2106,6 +2134,44 @@ void scsi_mq_free_tags(struct kref *kref)
complete(&shost->tagset_freed);
}
/**
* scsi_get_internal_cmd() - Allocate an internal SCSI command.
* @sdev: SCSI device from which to allocate the command
* @data_direction: Data direction for the allocated command
* @flags: request allocation flags, e.g. BLK_MQ_REQ_RESERVED or
* BLK_MQ_REQ_NOWAIT.
*
* Allocates a SCSI command for internal LLDD use.
*/
struct scsi_cmnd *scsi_get_internal_cmd(struct scsi_device *sdev,
enum dma_data_direction data_direction,
blk_mq_req_flags_t flags)
{
enum req_op op = data_direction == DMA_TO_DEVICE ? REQ_OP_DRV_OUT :
REQ_OP_DRV_IN;
struct scsi_cmnd *scmd;
struct request *rq;
rq = scsi_alloc_request(sdev->request_queue, op, flags);
if (IS_ERR(rq))
return NULL;
scmd = blk_mq_rq_to_pdu(rq);
scmd->device = sdev;
return scmd;
}
EXPORT_SYMBOL_GPL(scsi_get_internal_cmd);
/**
* scsi_put_internal_cmd() - Free an internal SCSI command.
* @scmd: SCSI command to be freed
*/
void scsi_put_internal_cmd(struct scsi_cmnd *scmd)
{
blk_mq_free_request(blk_mq_rq_from_pdu(scmd));
}
EXPORT_SYMBOL_GPL(scsi_put_internal_cmd);
/**
* scsi_device_from_queue - return sdev associated with a request_queue
* @q: The request queue to return the sdev from

View File

@@ -26,9 +26,9 @@ static void scsi_log_release_buffer(char *bufptr)
kfree(bufptr);
}
static inline const char *scmd_name(const struct scsi_cmnd *scmd)
static inline const char *scmd_name(struct scsi_cmnd *scmd)
{
struct request *rq = scsi_cmd_to_rq((struct scsi_cmnd *)scmd);
const struct request *rq = scsi_cmd_to_rq(scmd);
if (!rq->q || !rq->q->disk)
return NULL;
@@ -80,8 +80,8 @@ void sdev_prefix_printk(const char *level, const struct scsi_device *sdev,
}
EXPORT_SYMBOL(sdev_prefix_printk);
void scmd_printk(const char *level, const struct scsi_cmnd *scmd,
const char *fmt, ...)
void scmd_printk(const char *level, struct scsi_cmnd *scmd, const char *fmt,
...)
{
va_list args;
char *logbuf;
@@ -94,7 +94,7 @@ void scmd_printk(const char *level, const struct scsi_cmnd *scmd,
if (!logbuf)
return;
off = sdev_format_header(logbuf, logbuf_len, scmd_name(scmd),
scsi_cmd_to_rq((struct scsi_cmnd *)scmd)->tag);
scsi_cmd_to_rq(scmd)->tag);
if (off < logbuf_len) {
va_start(args, fmt);
off += vscnprintf(logbuf + off, logbuf_len - off, fmt, args);
@@ -371,16 +371,15 @@ void __scsi_print_sense(const struct scsi_device *sdev, const char *name,
EXPORT_SYMBOL(__scsi_print_sense);
/* Normalize and print sense buffer in SCSI command */
void scsi_print_sense(const struct scsi_cmnd *cmd)
void scsi_print_sense(struct scsi_cmnd *cmd)
{
scsi_log_print_sense(cmd->device, scmd_name(cmd),
scsi_cmd_to_rq((struct scsi_cmnd *)cmd)->tag,
cmd->sense_buffer, SCSI_SENSE_BUFFERSIZE);
scsi_cmd_to_rq(cmd)->tag, cmd->sense_buffer,
SCSI_SENSE_BUFFERSIZE);
}
EXPORT_SYMBOL(scsi_print_sense);
void scsi_print_result(const struct scsi_cmnd *cmd, const char *msg,
int disposition)
void scsi_print_result(struct scsi_cmnd *cmd, const char *msg, int disposition)
{
char *logbuf;
size_t off, logbuf_len;
@@ -393,7 +392,7 @@ void scsi_print_result(const struct scsi_cmnd *cmd, const char *msg,
return;
off = sdev_format_header(logbuf, logbuf_len, scmd_name(cmd),
scsi_cmd_to_rq((struct scsi_cmnd *)cmd)->tag);
scsi_cmd_to_rq(cmd)->tag);
if (off >= logbuf_len)
goto out_printk;

View File

@@ -205,7 +205,6 @@ static int scsi_runtime_idle(struct device *dev)
/* Insert hooks here for targets, hosts, and transport classes */
if (scsi_is_sdev_device(dev)) {
pm_runtime_mark_last_busy(dev);
pm_runtime_autosuspend(dev);
return -EBUSY;
}

View File

@@ -135,6 +135,7 @@ extern int scsi_complete_async_scans(void);
extern int scsi_scan_host_selected(struct Scsi_Host *, unsigned int,
unsigned int, u64, enum scsi_scan_mode);
extern void scsi_forget_host(struct Scsi_Host *);
struct scsi_device *scsi_get_pseudo_sdev(struct Scsi_Host *);
/* scsi_sysctl.c */
#ifdef CONFIG_SYSCTL

View File

@@ -347,6 +347,11 @@ static struct scsi_device *scsi_alloc_sdev(struct scsi_target *starget,
kref_get(&sdev->host->tagset_refcnt);
sdev->request_queue = q;
scsi_sysfs_device_initialize(sdev);
if (scsi_device_is_pseudo_dev(sdev))
return sdev;
depth = sdev->host->cmd_per_lun ?: 1;
/*
@@ -363,8 +368,6 @@ static struct scsi_device *scsi_alloc_sdev(struct scsi_target *starget,
scsi_change_queue_depth(sdev, depth);
scsi_sysfs_device_initialize(sdev);
if (shost->hostt->sdev_init) {
ret = shost->hostt->sdev_init(sdev);
if (ret) {
@@ -1068,6 +1071,11 @@ static int scsi_add_lun(struct scsi_device *sdev, unsigned char *inq_result,
transport_configure_device(&sdev->sdev_gendev);
sdev->sdev_bflags = *bflags;
if (scsi_device_is_pseudo_dev(sdev))
return SCSI_SCAN_LUN_PRESENT;
/*
* No need to freeze the queue as it isn't reachable to anyone else yet.
*/
@@ -1113,7 +1121,6 @@ static int scsi_add_lun(struct scsi_device *sdev, unsigned char *inq_result,
sdev->max_queue_depth = sdev->queue_depth;
WARN_ON_ONCE(sdev->max_queue_depth > sdev->budget_map.depth);
sdev->sdev_bflags = *bflags;
/*
* Ok, the device is now all set up, we can
@@ -1212,6 +1219,12 @@ static int scsi_probe_and_add_lun(struct scsi_target *starget,
if (!sdev)
goto out;
if (scsi_device_is_pseudo_dev(sdev)) {
if (bflagsp)
*bflagsp = BLIST_NOLUN;
return SCSI_SCAN_LUN_PRESENT;
}
result = kmalloc(result_len, GFP_KERNEL);
if (!result)
goto out_free_sdev;
@@ -2083,12 +2096,65 @@ void scsi_forget_host(struct Scsi_Host *shost)
restart:
spin_lock_irqsave(shost->host_lock, flags);
list_for_each_entry(sdev, &shost->__devices, siblings) {
if (sdev->sdev_state == SDEV_DEL)
if (scsi_device_is_pseudo_dev(sdev) ||
sdev->sdev_state == SDEV_DEL)
continue;
spin_unlock_irqrestore(shost->host_lock, flags);
__scsi_remove_device(sdev);
goto restart;
}
spin_unlock_irqrestore(shost->host_lock, flags);
/*
* Remove the pseudo device last since it may be needed during removal
* of other SCSI devices.
*/
if (shost->pseudo_sdev)
__scsi_remove_device(shost->pseudo_sdev);
}
/**
* scsi_get_pseudo_sdev() - Attach a pseudo SCSI device to a SCSI host
* @shost: Host that needs a pseudo SCSI device
*
* Lock status: None assumed.
*
* Returns: The scsi_device or NULL
*
* Notes:
* Attach a single scsi_device to the Scsi_Host. The primary aim for this
* device is to serve as a container from which SCSI commands can be
* allocated. Each SCSI command will carry a command tag allocated by the
* block layer. These SCSI commands can be used by the LLDD to send
* internal or passthrough commands without having to manage tag allocation
* inside the LLDD.
*/
struct scsi_device *scsi_get_pseudo_sdev(struct Scsi_Host *shost)
{
struct scsi_device *sdev = NULL;
struct scsi_target *starget;
guard(mutex)(&shost->scan_mutex);
if (!scsi_host_scan_allowed(shost))
goto out;
starget = scsi_alloc_target(&shost->shost_gendev, 0, shost->max_id);
if (!starget)
goto out;
sdev = scsi_alloc_sdev(starget, U64_MAX, NULL);
if (!sdev) {
scsi_target_reap(starget);
goto put_target;
}
sdev->borken = 0;
put_target:
/* See also the get_device(dev) call in scsi_alloc_target(). */
put_device(&starget->dev);
out:
return sdev;
}

View File

@@ -605,68 +605,6 @@ sdev_show_##field (struct device *dev, struct device_attribute *attr, \
sdev_show_function(field, format_string) \
static DEVICE_ATTR(field, S_IRUGO, sdev_show_##field, NULL);
/*
* sdev_rw_attr: create a function and attribute variable for a
* read/write field.
*/
#define sdev_rw_attr(field, format_string) \
sdev_show_function(field, format_string) \
\
static ssize_t \
sdev_store_##field (struct device *dev, struct device_attribute *attr, \
const char *buf, size_t count) \
{ \
struct scsi_device *sdev; \
sdev = to_scsi_device(dev); \
sscanf (buf, format_string, &sdev->field); \
return count; \
} \
static DEVICE_ATTR(field, S_IRUGO | S_IWUSR, sdev_show_##field, sdev_store_##field);
/* Currently we don't export bit fields, but we might in future,
* so leave this code in */
#if 0
/*
* sdev_rd_attr: create a function and attribute variable for a
* read/write bit field.
*/
#define sdev_rw_attr_bit(field) \
sdev_show_function(field, "%d\n") \
\
static ssize_t \
sdev_store_##field (struct device *dev, struct device_attribute *attr, \
const char *buf, size_t count) \
{ \
int ret; \
struct scsi_device *sdev; \
ret = scsi_sdev_check_buf_bit(buf); \
if (ret >= 0) { \
sdev = to_scsi_device(dev); \
sdev->field = ret; \
ret = count; \
} \
return ret; \
} \
static DEVICE_ATTR(field, S_IRUGO | S_IWUSR, sdev_show_##field, sdev_store_##field);
/*
* scsi_sdev_check_buf_bit: return 0 if buf is "0", return 1 if buf is "1",
* else return -EINVAL.
*/
static int scsi_sdev_check_buf_bit(const char *buf)
{
if ((buf[1] == '\0') || ((buf[1] == '\n') && (buf[2] == '\0'))) {
if (buf[0] == '1')
return 1;
else if (buf[0] == '0')
return 0;
else
return -EINVAL;
} else
return -EINVAL;
}
#endif
/*
* Create the actual show/store functions and data structures.
*/
@@ -710,10 +648,14 @@ static ssize_t
sdev_store_timeout (struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
struct scsi_device *sdev;
int timeout;
sdev = to_scsi_device(dev);
sscanf (buf, "%d\n", &timeout);
struct scsi_device *sdev = to_scsi_device(dev);
int ret, timeout;
ret = kstrtoint(buf, 0, &timeout);
if (ret)
return ret;
if (timeout <= 0)
return -EINVAL;
blk_queue_rq_timeout(sdev->request_queue, timeout * HZ);
return count;
}
@@ -1406,6 +1348,9 @@ int scsi_sysfs_add_sdev(struct scsi_device *sdev)
int error;
struct scsi_target *starget = sdev->sdev_target;
if (WARN_ON_ONCE(scsi_device_is_pseudo_dev(sdev)))
return -EINVAL;
error = scsi_target_add(starget);
if (error)
return error;
@@ -1513,7 +1458,7 @@ void __scsi_remove_device(struct scsi_device *sdev)
kref_put(&sdev->host->tagset_refcnt, scsi_mq_free_tags);
cancel_work_sync(&sdev->requeue_work);
if (sdev->host->hostt->sdev_destroy)
if (!scsi_device_is_pseudo_dev(sdev) && sdev->host->hostt->sdev_destroy)
sdev->host->hostt->sdev_destroy(sdev);
transport_destroy_device(dev);

View File

@@ -441,7 +441,8 @@ static int fc_host_setup(struct transport_container *tc, struct device *dev,
fc_host->next_vport_number = 0;
fc_host->npiv_vports_inuse = 0;
fc_host->work_q = alloc_workqueue("fc_wq_%d", 0, 0, shost->host_no);
fc_host->work_q = alloc_workqueue("fc_wq_%d", WQ_PERCPU, 0,
shost->host_no);
if (!fc_host->work_q)
return -ENOMEM;
@@ -3088,7 +3089,7 @@ fc_remote_port_create(struct Scsi_Host *shost, int channel,
spin_unlock_irqrestore(shost->host_lock, flags);
rport->devloss_work_q = alloc_workqueue("fc_dl_%d_%d", 0, 0,
rport->devloss_work_q = alloc_workqueue("fc_dl_%d_%d", WQ_PERCPU, 0,
shost->host_no, rport->number);
if (!rport->devloss_work_q) {
printk(KERN_ERR "FC Remote Port alloc_workqueue failed\n");

View File

@@ -3961,7 +3961,7 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, uint32_t *group)
list_del_init(&session->sess_list);
spin_unlock_irqrestore(&sesslock, flags);
queue_work(system_unbound_wq, &session->destroy_work);
queue_work(system_dfl_wq, &session->destroy_work);
}
break;
case ISCSI_UEVENT_UNBIND_SESSION:

View File

@@ -318,6 +318,35 @@ static ssize_t manage_shutdown_store(struct device *dev,
}
static DEVICE_ATTR_RW(manage_shutdown);
static ssize_t manage_restart_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct scsi_disk *sdkp = to_scsi_disk(dev);
struct scsi_device *sdp = sdkp->device;
return sysfs_emit(buf, "%u\n", sdp->manage_restart);
}
static ssize_t manage_restart_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
struct scsi_disk *sdkp = to_scsi_disk(dev);
struct scsi_device *sdp = sdkp->device;
bool v;
if (!capable(CAP_SYS_ADMIN))
return -EACCES;
if (kstrtobool(buf, &v))
return -EINVAL;
sdp->manage_restart = v;
return count;
}
static DEVICE_ATTR_RW(manage_restart);
static ssize_t
allow_restart_show(struct device *dev, struct device_attribute *attr, char *buf)
{
@@ -654,6 +683,7 @@ static struct attribute *sd_disk_attrs[] = {
&dev_attr_manage_system_start_stop.attr,
&dev_attr_manage_runtime_start_stop.attr,
&dev_attr_manage_shutdown.attr,
&dev_attr_manage_restart.attr,
&dev_attr_protection_type.attr,
&dev_attr_protection_mode.attr,
&dev_attr_app_tag_own.attr,
@@ -4177,7 +4207,9 @@ static void sd_shutdown(struct device *dev)
(system_state == SYSTEM_POWER_OFF &&
sdkp->device->manage_shutdown) ||
(system_state == SYSTEM_RUNNING &&
sdkp->device->manage_runtime_start_stop)) {
sdkp->device->manage_runtime_start_stop) ||
(system_state == SYSTEM_RESTART &&
sdkp->device->manage_restart)) {
sd_printk(KERN_NOTICE, sdkp, "Stopping disk\n");
sd_start_stop_device(sdkp, 0);
}

View File

@@ -133,6 +133,7 @@ static int sim710_probe_common(struct device *dev, unsigned long base_addr,
out_put_host:
scsi_host_put(host);
out_release:
ioport_unmap(hostdata->base);
release_region(base_addr, 64);
out_free:
kfree(hostdata);
@@ -148,6 +149,7 @@ static int sim710_device_remove(struct device *dev)
scsi_remove_host(host);
NCR_700_release(host);
ioport_unmap(hostdata->base);
kfree(hostdata);
free_irq(host->irq, host);
release_region(host->base, 64);

View File

@@ -34,11 +34,11 @@
#define BUILD_TIMESTAMP
#endif
#define DRIVER_VERSION "2.1.34-035"
#define DRIVER_VERSION "2.1.36-026"
#define DRIVER_MAJOR 2
#define DRIVER_MINOR 1
#define DRIVER_RELEASE 34
#define DRIVER_REVISION 35
#define DRIVER_RELEASE 36
#define DRIVER_REVISION 26
#define DRIVER_NAME "Microchip SmartPQI Driver (v" \
DRIVER_VERSION BUILD_TIMESTAMP ")"
@@ -5555,14 +5555,25 @@ static void pqi_raid_io_complete(struct pqi_io_request *io_request,
pqi_scsi_done(scmd);
}
/*
* Adjust the timeout value for physical devices sent to the firmware
* by subtracting 3 seconds for timeouts greater than or equal to 8 seconds.
*
* This provides the firmware with additional time to attempt early recovery
* before the OS-level timeout occurs.
*/
#define ADJUST_SECS_TIMEOUT_VALUE(tv) (((tv) >= 8) ? ((tv) - 3) : (tv))
static int pqi_raid_submit_io(struct pqi_ctrl_info *ctrl_info,
struct pqi_scsi_dev *device, struct scsi_cmnd *scmd,
struct pqi_queue_group *queue_group, bool io_high_prio)
{
int rc;
u32 timeout;
size_t cdb_length;
struct pqi_io_request *io_request;
struct pqi_raid_path_request *request;
struct request *rq;
io_request = pqi_alloc_io_request(ctrl_info, scmd);
if (!io_request)
@@ -5634,6 +5645,12 @@ static int pqi_raid_submit_io(struct pqi_ctrl_info *ctrl_info,
return SCSI_MLQUEUE_HOST_BUSY;
}
if (device->is_physical_device) {
rq = scsi_cmd_to_rq(scmd);
timeout = rq->timeout / HZ;
put_unaligned_le32(ADJUST_SECS_TIMEOUT_VALUE(timeout), &request->timeout);
}
pqi_start_io(ctrl_info, queue_group, RAID_PATH, io_request);
return 0;
@@ -6410,10 +6427,22 @@ static int pqi_device_reset(struct pqi_ctrl_info *ctrl_info, struct pqi_scsi_dev
static int pqi_device_reset_handler(struct pqi_ctrl_info *ctrl_info, struct pqi_scsi_dev *device, u8 lun, struct scsi_cmnd *scmd, u8 scsi_opcode)
{
unsigned long flags;
int rc;
mutex_lock(&ctrl_info->lun_reset_mutex);
spin_lock_irqsave(&ctrl_info->scsi_device_list_lock, flags);
if (pqi_find_scsi_dev(ctrl_info, device->bus, device->target, device->lun) == NULL) {
dev_warn(&ctrl_info->pci_dev->dev,
"skipping reset of scsi %d:%d:%d:%u, device has been removed\n",
ctrl_info->scsi_host->host_no, device->bus, device->target, device->lun);
spin_unlock_irqrestore(&ctrl_info->scsi_device_list_lock, flags);
mutex_unlock(&ctrl_info->lun_reset_mutex);
return 0;
}
spin_unlock_irqrestore(&ctrl_info->scsi_device_list_lock, flags);
dev_err(&ctrl_info->pci_dev->dev,
"resetting scsi %d:%d:%d:%u SCSI cmd at %p due to cmd opcode 0x%02x\n",
ctrl_info->scsi_host->host_no, device->bus, device->target, lun, scmd, scsi_opcode);
@@ -6594,7 +6623,9 @@ static void pqi_sdev_destroy(struct scsi_device *sdev)
{
struct pqi_ctrl_info *ctrl_info;
struct pqi_scsi_dev *device;
struct pqi_tmf_work *tmf_work;
int mutex_acquired;
unsigned int lun;
unsigned long flags;
ctrl_info = shost_to_hba(sdev->host);
@@ -6621,8 +6652,13 @@ static void pqi_sdev_destroy(struct scsi_device *sdev)
mutex_unlock(&ctrl_info->scan_mutex);
for (lun = 0, tmf_work = device->tmf_work; lun < PQI_MAX_LUNS_PER_DEVICE; lun++, tmf_work++)
cancel_work_sync(&tmf_work->work_struct);
mutex_lock(&ctrl_info->lun_reset_mutex);
pqi_dev_info(ctrl_info, "removed", device);
pqi_free_device(device);
mutex_unlock(&ctrl_info->lun_reset_mutex);
}
static int pqi_getpciinfo_ioctl(struct pqi_ctrl_info *ctrl_info, void __user *arg)
@@ -8936,7 +8972,8 @@ static int pqi_host_alloc_mem(struct pqi_ctrl_info *ctrl_info,
if (sg_count == 0 || sg_count > PQI_HOST_MAX_SG_DESCRIPTORS)
goto out;
host_memory_descriptor->host_chunk_virt_address = kmalloc(sg_count * sizeof(void *), GFP_KERNEL);
host_memory_descriptor->host_chunk_virt_address =
kmalloc_array(sg_count, sizeof(void *), GFP_KERNEL);
if (!host_memory_descriptor->host_chunk_virt_address)
goto out;
@@ -10108,6 +10145,10 @@ static const struct pci_device_id pqi_pci_id_table[] = {
PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f,
0x207d, 0x4240)
},
{
PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f,
0x207d, 0x4840)
},
{
PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f,
PCI_VENDOR_ID_ADVANTECH, 0x8312)

View File

@@ -3526,8 +3526,64 @@ static int partition_tape(struct scsi_tape *STp, int size)
out:
return result;
}
/*
* Handles any extra state needed for ioctls which are not st-specific.
* Called with the scsi_tape lock held, released before return
*/
static long st_common_ioctl(struct scsi_tape *STp, struct st_modedef *STm,
struct file *file, unsigned int cmd_in,
unsigned long arg)
{
int i, retval = 0;
if (!STm->defined) {
retval = -ENXIO;
goto out;
}
switch (cmd_in) {
case SCSI_IOCTL_GET_IDLUN:
case SCSI_IOCTL_GET_BUS_NUMBER:
case SCSI_IOCTL_GET_PCI:
break;
case SG_IO:
case SCSI_IOCTL_SEND_COMMAND:
case CDROM_SEND_PACKET:
if (!capable(CAP_SYS_RAWIO)) {
retval = -EPERM;
goto out;
}
fallthrough;
default:
if ((i = flush_buffer(STp, 0)) < 0) {
retval = i;
goto out;
} else { /* flush_buffer succeeds */
if (STp->can_partitions) {
i = switch_partition(STp);
if (i < 0) {
retval = i;
goto out;
}
}
}
}
mutex_unlock(&STp->lock);
retval = scsi_ioctl(STp->device, file->f_mode & FMODE_WRITE,
cmd_in, (void __user *)arg);
if (!retval && cmd_in == SCSI_IOCTL_STOP_UNIT) {
/* unload */
STp->rew_at_close = 0;
STp->ready = ST_NO_TAPE;
}
return retval;
out:
mutex_unlock(&STp->lock);
return retval;
}
/* The ioctl command */
static long st_ioctl(struct file *file, unsigned int cmd_in, unsigned long arg)
@@ -3565,6 +3621,15 @@ static long st_ioctl(struct file *file, unsigned int cmd_in, unsigned long arg)
if (retval)
goto out;
switch (cmd_in) {
case MTIOCPOS:
case MTIOCGET:
case MTIOCTOP:
break;
default:
return st_common_ioctl(STp, STm, file, cmd_in, arg);
}
cmd_type = _IOC_TYPE(cmd_in);
cmd_nr = _IOC_NR(cmd_in);
@@ -3876,29 +3941,7 @@ static long st_ioctl(struct file *file, unsigned int cmd_in, unsigned long arg)
}
mt_pos.mt_blkno = blk;
retval = put_user_mtpos(p, &mt_pos);
goto out;
}
mutex_unlock(&STp->lock);
switch (cmd_in) {
case SG_IO:
case SCSI_IOCTL_SEND_COMMAND:
case CDROM_SEND_PACKET:
if (!capable(CAP_SYS_RAWIO))
return -EPERM;
break;
default:
break;
}
retval = scsi_ioctl(STp->device, file->f_mode & FMODE_WRITE, cmd_in, p);
if (!retval && cmd_in == SCSI_IOCTL_STOP_UNIT) {
/* unload */
STp->rew_at_close = 0;
STp->ready = ST_NO_TAPE;
}
return retval;
out:
mutex_unlock(&STp->lock);
return retval;

View File

@@ -1844,6 +1844,7 @@ out_release_regions:
out_scsi_host_put:
scsi_host_put(host);
out_disable:
unregister_reboot_notifier(&stex_notifier);
pci_disable_device(pdev);
return err;

View File

@@ -730,7 +730,7 @@ static int tgt_agent_rw_orb_pointer(struct fw_card *card, int tcode, void *data,
pr_debug("tgt_agent ORB_POINTER write: 0x%llx\n",
agent->orb_pointer);
queue_work(system_unbound_wq, &agent->work);
queue_work(system_dfl_wq, &agent->work);
return RCODE_COMPLETE;
@@ -764,7 +764,7 @@ static int tgt_agent_rw_doorbell(struct fw_card *card, int tcode, void *data,
pr_debug("tgt_agent DOORBELL\n");
queue_work(system_unbound_wq, &agent->work);
queue_work(system_dfl_wq, &agent->work);
return RCODE_COMPLETE;
@@ -990,7 +990,7 @@ static void tgt_agent_fetch_work(struct work_struct *work)
if (tgt_agent_check_active(agent) && !doorbell) {
INIT_WORK(&req->work, tgt_agent_process_work);
queue_work(system_unbound_wq, &req->work);
queue_work(system_dfl_wq, &req->work);
} else {
/* don't process this request, just check next_ORB */
sbp_free_request(req);
@@ -1618,7 +1618,7 @@ static void sbp_mgt_agent_rw(struct fw_card *card,
agent->orb_offset = sbp2_pointer_to_addr(ptr);
agent->request = req;
queue_work(system_unbound_wq, &agent->work);
queue_work(system_dfl_wq, &agent->work);
rcode = RCODE_COMPLETE;
} else if (tcode == TCODE_READ_BLOCK_REQUEST) {
addr_to_sbp2_pointer(agent->orb_offset, ptr);

View File

@@ -578,6 +578,11 @@ DEF_CONFIGFS_ATTRIB_SHOW(unmap_zeroes_data);
DEF_CONFIGFS_ATTRIB_SHOW(max_write_same_len);
DEF_CONFIGFS_ATTRIB_SHOW(emulate_rsoc);
DEF_CONFIGFS_ATTRIB_SHOW(submit_type);
DEF_CONFIGFS_ATTRIB_SHOW(atomic_max_len);
DEF_CONFIGFS_ATTRIB_SHOW(atomic_alignment);
DEF_CONFIGFS_ATTRIB_SHOW(atomic_granularity);
DEF_CONFIGFS_ATTRIB_SHOW(atomic_max_with_boundary);
DEF_CONFIGFS_ATTRIB_SHOW(atomic_max_boundary);
#define DEF_CONFIGFS_ATTRIB_STORE_U32(_name) \
static ssize_t _name##_store(struct config_item *item, const char *page,\
@@ -1300,6 +1305,11 @@ CONFIGFS_ATTR(, max_write_same_len);
CONFIGFS_ATTR(, alua_support);
CONFIGFS_ATTR(, pgr_support);
CONFIGFS_ATTR(, submit_type);
CONFIGFS_ATTR_RO(, atomic_max_len);
CONFIGFS_ATTR_RO(, atomic_alignment);
CONFIGFS_ATTR_RO(, atomic_granularity);
CONFIGFS_ATTR_RO(, atomic_max_with_boundary);
CONFIGFS_ATTR_RO(, atomic_max_boundary);
/*
* dev_attrib attributes for devices using the target core SBC/SPC
@@ -1343,6 +1353,11 @@ struct configfs_attribute *sbc_attrib_attrs[] = {
&attr_pgr_support,
&attr_emulate_rsoc,
&attr_submit_type,
&attr_atomic_alignment,
&attr_atomic_max_len,
&attr_atomic_granularity,
&attr_atomic_max_with_boundary,
&attr_atomic_max_boundary,
NULL,
};
EXPORT_SYMBOL(sbc_attrib_attrs);
@@ -2758,33 +2773,24 @@ static ssize_t target_lu_gp_lu_gp_id_store(struct config_item *item,
static ssize_t target_lu_gp_members_show(struct config_item *item, char *page)
{
struct t10_alua_lu_gp *lu_gp = to_lu_gp(item);
struct se_device *dev;
struct se_hba *hba;
struct t10_alua_lu_gp_member *lu_gp_mem;
ssize_t len = 0, cur_len;
unsigned char buf[LU_GROUP_NAME_BUF] = { };
const char *const end = page + PAGE_SIZE;
char *cur = page;
spin_lock(&lu_gp->lu_gp_lock);
list_for_each_entry(lu_gp_mem, &lu_gp->lu_gp_mem_list, lu_gp_mem_list) {
dev = lu_gp_mem->lu_gp_mem_dev;
hba = dev->se_hba;
struct se_device *dev = lu_gp_mem->lu_gp_mem_dev;
struct se_hba *hba = dev->se_hba;
cur_len = snprintf(buf, LU_GROUP_NAME_BUF, "%s/%s\n",
cur += scnprintf(cur, end - cur, "%s/%s\n",
config_item_name(&hba->hba_group.cg_item),
config_item_name(&dev->dev_group.cg_item));
cur_len++; /* Extra byte for NULL terminator */
if ((cur_len + len) > PAGE_SIZE || cur_len > LU_GROUP_NAME_BUF) {
pr_warn("Ran out of lu_gp_show_attr"
"_members buffer\n");
if (WARN_ON_ONCE(cur >= end))
break;
}
memcpy(page+len, buf, cur_len);
len += cur_len;
}
spin_unlock(&lu_gp->lu_gp_lock);
return len;
return cur - page;
}
CONFIGFS_ATTR(target_lu_gp_, lu_gp_id);

View File

@@ -814,6 +814,7 @@ struct se_device *target_alloc_device(struct se_hba *hba, const char *name)
dev->dev_attrib.max_write_same_len = DA_MAX_WRITE_SAME_LEN;
dev->dev_attrib.submit_type = TARGET_FABRIC_DEFAULT_SUBMIT;
/* Skip allocating lun_stats since we can't export them. */
xcopy_lun = &dev->xcopy_lun;
rcu_assign_pointer(xcopy_lun->lun_se_dev, dev);
init_completion(&xcopy_lun->lun_shutdown_comp);
@@ -840,12 +841,29 @@ free_device:
return NULL;
}
void target_configure_write_atomic_from_bdev(struct se_dev_attrib *attrib,
struct block_device *bdev)
{
struct request_queue *q = bdev_get_queue(bdev);
int block_size = bdev_logical_block_size(bdev);
if (!bdev_can_atomic_write(bdev))
return;
attrib->atomic_max_len = queue_atomic_write_max_bytes(q) / block_size;
attrib->atomic_granularity = attrib->atomic_alignment =
queue_atomic_write_unit_min_bytes(q) / block_size;
attrib->atomic_max_with_boundary = 0;
attrib->atomic_max_boundary = 0;
}
EXPORT_SYMBOL_GPL(target_configure_write_atomic_from_bdev);
/*
* Check if the underlying struct block_device supports discard and if yes
* configure the UNMAP parameters.
*/
bool target_configure_unmap_from_queue(struct se_dev_attrib *attrib,
struct block_device *bdev)
bool target_configure_unmap_from_bdev(struct se_dev_attrib *attrib,
struct block_device *bdev)
{
int block_size = bdev_logical_block_size(bdev);
@@ -863,7 +881,7 @@ bool target_configure_unmap_from_queue(struct se_dev_attrib *attrib,
bdev_discard_alignment(bdev) / block_size;
return true;
}
EXPORT_SYMBOL(target_configure_unmap_from_queue);
EXPORT_SYMBOL(target_configure_unmap_from_bdev);
/*
* Convert from blocksize advertised to the initiator to the 512 byte

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