@@ -129,6 +129,17 @@ Supported Cards/Chipsets
People
======
+Sagar Biradar <Sagar.Biradar@microchip.com>
+
+ - Added support for CPU offlining and updated the driver to support MultiQ.
+ - Introduced the option CONFIG_SCSI_AACRAID_MULTIQ to control this feature.
+
+By default, MultiQ support is disabled to provide optimal I/O performance.
+
+Enable CONFIG_SCSI_AACRAID_MULTIQ only if CPU offlining support is required,
+as enabling it may result in reduced performance in some configurations.
+Note : Disabling MultiQ while still offlining CPUs may lead to I/O hangs.
+
Alan Cox <alan@lxorguk.ukuu.org.uk>
Christoph Hellwig <hch@infradead.org>
@@ -184,6 +184,7 @@ L: linux-scsi@vger.kernel.org
S: Supported
W: http://www.adaptec.com/
F: Documentation/scsi/aacraid.rst
+F: drivers/scsi/aacraid/Kconfig
F: drivers/scsi/aacraid/
AAEON UPBOARD FPGA MFD DRIVER
@@ -456,7 +456,7 @@ config SCSI_AACRAID
To compile this driver as a module, choose M here: the module
will be called aacraid.
-
+source "drivers/scsi/aacraid/Kconfig"
source "drivers/scsi/aic7xxx/Kconfig.aic7xxx"
source "drivers/scsi/aic7xxx/Kconfig.aic79xx"
source "drivers/scsi/aic94xx/Kconfig"
new file mode 100644
@@ -0,0 +1,20 @@
+# SPDX-License-Identifier: GPL-2.0-only
+#
+# Kernel configuration file for the aacraid driver.
+#
+# Copyright (c) 2025 Microchip Technology Inc. and its subsidiaries
+# (mailto:storagedev@microchip.com)
+#
+config SCSI_AACRAID_MULTIQ
+ bool "AACRAID Multiq support"
+ depends on SCSI_AACRAID
+ default n
+ help
+ This option enables MultiQ support in the aacraid driver.
+
+ Enabling MultiQ allows the driver to safely handle CPU offlining.
+ However, it may cause a performance drop in certain configurations.
+
+ Enable this option only if your system requires CPU offlining support.
+
+ If unsure, say N.
@@ -328,7 +328,6 @@ MODULE_PARM_DESC(wwn, "Select a WWN type for the arrays:\n"
"\t1 - Array Meta Data Signature (default)\n"
"\t2 - Adapter Serial Number");
-
static inline int aac_valid_context(struct scsi_cmnd *scsicmd,
struct fib *fibptr) {
struct scsi_device *device;
@@ -1672,6 +1672,9 @@ struct aac_dev
u32 handle_pci_error;
bool init_reset;
u8 soft_reset_support;
+#ifdef CONFIG_SCSI_AACRAID_MULTIQ
+ u8 use_map_queue;
+#endif
};
#define aac_adapter_interrupt(dev) \
@@ -215,8 +215,17 @@ int aac_fib_setup(struct aac_dev * dev)
struct fib *aac_fib_alloc_tag(struct aac_dev *dev, struct scsi_cmnd *scmd)
{
struct fib *fibptr;
+#ifdef CONFIG_SCSI_AACRAID_MULTIQ
+ u32 blk_tag;
+ int i;
+ blk_tag = blk_mq_unique_tag(scsi_cmd_to_rq(scmd));
+ i = blk_mq_unique_tag_to_tag(blk_tag);
+ fibptr = &dev->fibs[i];
+#else
fibptr = &dev->fibs[scsi_cmd_to_rq(scmd)->tag];
+#endif
+
/*
* Null out fields that depend on being zero at the start of
* each I/O
@@ -242,14 +251,17 @@ struct fib *aac_fib_alloc(struct aac_dev *dev)
{
struct fib * fibptr;
unsigned long flags;
+
spin_lock_irqsave(&dev->fib_lock, flags);
+ /* Management FIB allocation: use free list within reserved range */
fibptr = dev->free_fib;
- if(!fibptr){
+ if (!fibptr) {
spin_unlock_irqrestore(&dev->fib_lock, flags);
- return fibptr;
+ return NULL;
}
dev->free_fib = fibptr->next;
spin_unlock_irqrestore(&dev->fib_lock, flags);
+
/*
* Set the proper node type code and node byte size
*/
@@ -506,6 +506,17 @@ static int aac_sdev_configure(struct scsi_device *sdev,
return 0;
}
+#ifdef CONFIG_SCSI_AACRAID_MULTIQ
+static void aac_map_queues(struct Scsi_Host *shost)
+{
+ struct aac_dev *aac = (struct aac_dev *)shost->hostdata;
+ struct blk_mq_queue_map *qmap = &shost->tag_set.map[HCTX_TYPE_DEFAULT];
+
+ blk_mq_map_hw_queues(qmap, &aac->pdev->dev, 0);
+ aac->use_map_queue = true;
+}
+#endif
+
/**
* aac_change_queue_depth - alter queue depths
* @sdev: SCSI device we are considering
@@ -1490,6 +1501,9 @@ static const struct scsi_host_template aac_driver_template = {
.bios_param = aac_biosparm,
.shost_groups = aac_host_groups,
.sdev_configure = aac_sdev_configure,
+#ifdef CONFIG_SCSI_AACRAID_MULTIQ
+ .map_queues = aac_map_queues,
+#endif
.change_queue_depth = aac_change_queue_depth,
.sdev_groups = aac_dev_groups,
.eh_abort_handler = aac_eh_abort,
@@ -1777,7 +1791,11 @@ static int aac_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
shost->max_lun = AAC_MAX_LUN;
pci_set_drvdata(pdev, shost);
-
+#ifdef CONFIG_SCSI_AACRAID_MULTIQ
+ shost->nr_hw_queues = aac->max_msix;
+ shost->can_queue = min_t(int, aac->vector_cap, shost->can_queue);
+ shost->host_tagset = 1;
+#endif
error = scsi_add_host(shost, &pdev->dev);
if (error)
goto out_deinit;
@@ -1908,6 +1926,9 @@ static void aac_remove_one(struct pci_dev *pdev)
struct aac_dev *aac = (struct aac_dev *)shost->hostdata;
aac_cancel_rescan_worker(aac);
+#ifdef CONFIG_SCSI_AACRAID_MULTIQ
+ aac->use_map_queue = false;
+#endif
scsi_remove_host(shost);
__aac_shutdown(aac);
@@ -493,6 +493,12 @@ static int aac_src_deliver_message(struct fib *fib)
#endif
u16 vector_no;
+#ifdef CONFIG_SCSI_AACRAID_MULTIQ
+ struct scsi_cmnd *scmd;
+ u32 blk_tag;
+ struct Scsi_Host *shost = dev->scsi_host_ptr;
+ struct blk_mq_queue_map *qmap;
+#endif
atomic_inc(&q->numpending);
@@ -505,8 +511,28 @@ static int aac_src_deliver_message(struct fib *fib)
if ((dev->comm_interface == AAC_COMM_MESSAGE_TYPE3)
&& dev->sa_firmware)
vector_no = aac_get_vector(dev);
- else
+ else {
+#ifdef CONFIG_SCSI_AACRAID_MULTIQ
+ if (!fib->vector_no || !fib->callback_data) {
+ if (shost && dev->use_map_queue) {
+ qmap = &shost->tag_set.map[HCTX_TYPE_DEFAULT];
+ vector_no = qmap->mq_map[raw_smp_processor_id()];
+ }
+ /*
+ * We hardcode the vector_no for reserved commands
+ * as a valid shost is absent during the init.
+ */
+ else
+ vector_no = 0;
+ } else {
+ scmd = (struct scsi_cmnd *)fib->callback_data;
+ blk_tag = blk_mq_unique_tag(scsi_cmd_to_rq(scmd));
+ vector_no = blk_mq_unique_tag_to_hwq(blk_tag);
+ }
+#else
vector_no = fib->vector_no;
+#endif
+ }
if (native_hba) {
if (fib->flags & FIB_CONTEXT_FLAG_NATIVE_HBA_TMF) {