Commit 7efd0a74 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull ata fixes from Damien Le Moal:

 - Add the mask_port_map parameter to the ahci driver. This is a
   follow-up to the recent snafu with the ASMedia controller and its
   virtual port hidding port-multiplier devices. As ASMedia confirmed
   that there is no way to determine if these slow-to-probe virtual
   ports are actually representing the ports of a port-multiplier
   devices, this new parameter allow masking ports to significantly
   speed up probing during system boot, resulting in shorter boot times.

 - A fix for an incorrect handling of a port unlock in
   ata_scsi_dev_rescan().

 - Allow command duration limits to be detected for ACS-4 devices are
   there are such devices out in the field.

* tag 'ata-6.9-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/libata/linux:
  ata: libata-core: Allow command duration limits detection for ACS-4 drives
  ata: libata-scsi: Fix ata_scsi_dev_rescan() error path
  ata: ahci: Add mask_port_map module parameter
parents 76b0e9c4 c0297e7d
Loading
Loading
Loading
Loading
+85 −0
Original line number Diff line number Diff line
@@ -666,6 +666,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)
{
@@ -688,6 +769,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);
}

+1 −1
Original line number Diff line number Diff line
@@ -2539,7 +2539,7 @@ static void ata_dev_config_cdl(struct ata_device *dev)
	bool cdl_enabled;
	u64 val;

	if (ata_id_major_version(dev->id) < 12)
	if (ata_id_major_version(dev->id) < 11)
		goto not_supported;

	if (!ata_log_supported(dev, ATA_LOG_IDENTIFY_DEVICE) ||
+5 −4
Original line number Diff line number Diff line
@@ -4745,7 +4745,7 @@ void ata_scsi_dev_rescan(struct work_struct *work)
			 * bail out.
			 */
			if (ap->pflags & ATA_PFLAG_SUSPENDED)
				goto unlock;
				goto unlock_ap;

			if (!sdev)
				continue;
@@ -4758,7 +4758,7 @@ void ata_scsi_dev_rescan(struct work_struct *work)
			if (do_resume) {
				ret = scsi_resume_device(sdev);
				if (ret == -EWOULDBLOCK)
					goto unlock;
					goto unlock_scan;
				dev->flags &= ~ATA_DFLAG_RESUMING;
			}
			ret = scsi_rescan_device(sdev);
@@ -4766,12 +4766,13 @@ void ata_scsi_dev_rescan(struct work_struct *work)
			spin_lock_irqsave(ap->lock, flags);

			if (ret)
				goto unlock;
				goto unlock_ap;
		}
	}

unlock:
unlock_ap:
	spin_unlock_irqrestore(ap->lock, flags);
unlock_scan:
	mutex_unlock(&ap->scsi_scan_mutex);

	/* Reschedule with a delay if scsi_rescan_device() returned an error */