Patch "ata: ahci: Add mask_port_map module parameter" has been added to the 6.6-stable tree

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This is a note to let you know that I've just added the patch titled

    ata: ahci: Add mask_port_map module parameter

to the 6.6-stable tree which can be found at:
    http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
     ata-ahci-add-mask_port_map-module-parameter.patch
and it can be found in the queue-6.6 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree,
please let <stable@xxxxxxxxxxxxxxx> know about it.



commit a7467ebcdf3913b503bede80332003221d10fa1d
Author: Damien Le Moal <dlemoal@xxxxxxxxxx>
Date:   Thu Apr 4 18:30:14 2024 +0900

    ata: ahci: Add mask_port_map module parameter
    
    [ Upstream commit 24cfd86433c920188ac3f02df8aba6bc4c792f4b ]
    
    Commits 0077a504e1a4 ("ahci: asm1166: correct count of reported ports")
    and 9815e3961754 ("ahci: asm1064: correct count of reported ports")
    attempted to limit the ports of the ASM1166 and ASM1064 AHCI controllers
    to avoid long boot times caused by the fact that these adapters report
    a port map larger than the number of physical ports. The excess ports
    are "virtual" to hide port multiplier devices and probing these ports
    takes time. However, these commits caused a regression for users that do
    use PMP devices, as the ATA devices connected to the PMP cannot be
    scanned. These commits have thus been reverted by commit 6cd8adc3e18
    ("ahci: asm1064: asm1166: don't limit reported ports") to allow the
    discovery of devices connected through a port multiplier. But this
    revert re-introduced the long boot times for users that do not use a
    port multiplier setup.
    
    This patch adds the mask_port_map ahci module parameter to allow users
    to manually specify port map masks for controllers. In the case of the
    ASMedia 1166 and 1064 controllers, users that do not have port
    multiplier devices can mask the excess virtual ports exposed by the
    controller to speedup port scanning, thus reducing boot time.
    
    The mask_port_map parameter accepts 2 different formats:
     - mask_port_map=<mask>
       This applies the same mask to all AHCI controllers
       present in the system. This format is convenient for small systems
       that have only a single AHCI controller.
     - mask_port_map=<pci_dev>=<mask>,<pci_dev>=mask,...
       This applies the specified masks only to the PCI device listed. The
       <pci_dev> field is a regular PCI device ID (domain:bus:dev.func).
       This ID can be seen following "ahci" in the kernel messages. E.g.
       for "ahci 0000:01:00.0: 2/2 ports implemented (port mask 0x3)", the
       <pci_dev> field is "0000:01:00.0".
    
    When used, the function ahci_save_initial_config() indicates that a
    port map mask was applied with the message "masking port_map ...".
    E.g.: without a mask:
    modprobe ahci
    dmesg | grep ahci
    ...
    ahci 0000:00:17.0: AHCI vers 0001.0301, 32 command slots, 6 Gbps, SATA mode
    ahci 0000:00:17.0: (0000:00:17.0) 8/8 ports implemented (port mask 0xff)
    
    With a mask:
    modprobe ahci mask_port_map=0000:00:17.0=0x1
    dmesg | grep ahci
    ...
    ahci 0000:00:17.0: masking port_map 0xff -> 0x1
    ahci 0000:00:17.0: AHCI vers 0001.0301, 32 command slots, 6 Gbps, SATA mode
    ahci 0000:00:17.0: (0000:00:17.0) 1/8 ports implemented (port mask 0x1)
    
    Signed-off-by: Damien Le Moal <dlemoal@xxxxxxxxxx>
    Reviewed-by: Niklas Cassel <cassel@xxxxxxxxxx>
    Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx>

diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
index 0a6aea36cd975..6e76780fb4308 100644
--- a/drivers/ata/ahci.c
+++ b/drivers/ata/ahci.c
@@ -667,6 +667,87 @@ static int mobile_lpm_policy = -1;
 module_param(mobile_lpm_policy, int, 0644);
 MODULE_PARM_DESC(mobile_lpm_policy, "Default LPM policy for mobile chipsets");
 
+static char *ahci_mask_port_map;
+module_param_named(mask_port_map, ahci_mask_port_map, charp, 0444);
+MODULE_PARM_DESC(mask_port_map,
+		 "32-bits port map masks to ignore controllers ports. "
+		 "Valid values are: "
+		 "\"<mask>\" to apply the same mask to all AHCI controller "
+		 "devices, and \"<pci_dev>=<mask>,<pci_dev>=<mask>,...\" to "
+		 "specify different masks for the controllers specified, "
+		 "where <pci_dev> is the PCI ID of an AHCI controller in the "
+		 "form \"domain:bus:dev.func\"");
+
+static void ahci_apply_port_map_mask(struct device *dev,
+				     struct ahci_host_priv *hpriv, char *mask_s)
+{
+	unsigned int mask;
+
+	if (kstrtouint(mask_s, 0, &mask)) {
+		dev_err(dev, "Invalid port map mask\n");
+		return;
+	}
+
+	hpriv->mask_port_map = mask;
+}
+
+static void ahci_get_port_map_mask(struct device *dev,
+				   struct ahci_host_priv *hpriv)
+{
+	char *param, *end, *str, *mask_s;
+	char *name;
+
+	if (!strlen(ahci_mask_port_map))
+		return;
+
+	str = kstrdup(ahci_mask_port_map, GFP_KERNEL);
+	if (!str)
+		return;
+
+	/* Handle single mask case */
+	if (!strchr(str, '=')) {
+		ahci_apply_port_map_mask(dev, hpriv, str);
+		goto free;
+	}
+
+	/*
+	 * Mask list case: parse the parameter to apply the mask only if
+	 * the device name matches.
+	 */
+	param = str;
+	end = param + strlen(param);
+	while (param && param < end && *param) {
+		name = param;
+		param = strchr(name, '=');
+		if (!param)
+			break;
+
+		*param = '\0';
+		param++;
+		if (param >= end)
+			break;
+
+		if (strcmp(dev_name(dev), name) != 0) {
+			param = strchr(param, ',');
+			if (param)
+				param++;
+			continue;
+		}
+
+		mask_s = param;
+		param = strchr(mask_s, ',');
+		if (param) {
+			*param = '\0';
+			param++;
+		}
+
+		ahci_apply_port_map_mask(dev, hpriv, mask_s);
+	}
+
+free:
+	kfree(str);
+}
+
 static void ahci_pci_save_initial_config(struct pci_dev *pdev,
 					 struct ahci_host_priv *hpriv)
 {
@@ -689,6 +770,10 @@ static void ahci_pci_save_initial_config(struct pci_dev *pdev,
 			  "Disabling your PATA port. Use the boot option 'ahci.marvell_enable=0' to avoid this.\n");
 	}
 
+	/* Handle port map masks passed as module parameter. */
+	if (ahci_mask_port_map)
+		ahci_get_port_map_mask(&pdev->dev, hpriv);
+
 	ahci_save_initial_config(&pdev->dev, hpriv);
 }
 




[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux