ata fixes for 6.9-rc4
- 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. -----BEGIN PGP SIGNATURE----- iHUEABYKAB0WIQSRPv8tYSvhwAzJdzjdoc3SxdoYdgUCZho+/AAKCRDdoc3SxdoY dhm2AP49p/aAmpTGKYQjXwiQWH4JMR/ey9rZgdw0jjGtMYkdRQEA+aCLtWFKnENr 1E+lnTO+ef01BhJlk/FCK2VyOqCNxwM= =pDw+ -----END PGP SIGNATURE----- Merge tag 'ata-6.9-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/libata/linux 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
This commit is contained in:
commit
7efd0a7403
|
@ -666,6 +666,87 @@ static int mobile_lpm_policy = -1;
|
||||||
module_param(mobile_lpm_policy, int, 0644);
|
module_param(mobile_lpm_policy, int, 0644);
|
||||||
MODULE_PARM_DESC(mobile_lpm_policy, "Default LPM policy for mobile chipsets");
|
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,
|
static void ahci_pci_save_initial_config(struct pci_dev *pdev,
|
||||||
struct ahci_host_priv *hpriv)
|
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");
|
"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);
|
ahci_save_initial_config(&pdev->dev, hpriv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2539,7 +2539,7 @@ static void ata_dev_config_cdl(struct ata_device *dev)
|
||||||
bool cdl_enabled;
|
bool cdl_enabled;
|
||||||
u64 val;
|
u64 val;
|
||||||
|
|
||||||
if (ata_id_major_version(dev->id) < 12)
|
if (ata_id_major_version(dev->id) < 11)
|
||||||
goto not_supported;
|
goto not_supported;
|
||||||
|
|
||||||
if (!ata_log_supported(dev, ATA_LOG_IDENTIFY_DEVICE) ||
|
if (!ata_log_supported(dev, ATA_LOG_IDENTIFY_DEVICE) ||
|
||||||
|
|
|
@ -4745,7 +4745,7 @@ void ata_scsi_dev_rescan(struct work_struct *work)
|
||||||
* bail out.
|
* bail out.
|
||||||
*/
|
*/
|
||||||
if (ap->pflags & ATA_PFLAG_SUSPENDED)
|
if (ap->pflags & ATA_PFLAG_SUSPENDED)
|
||||||
goto unlock;
|
goto unlock_ap;
|
||||||
|
|
||||||
if (!sdev)
|
if (!sdev)
|
||||||
continue;
|
continue;
|
||||||
|
@ -4758,7 +4758,7 @@ void ata_scsi_dev_rescan(struct work_struct *work)
|
||||||
if (do_resume) {
|
if (do_resume) {
|
||||||
ret = scsi_resume_device(sdev);
|
ret = scsi_resume_device(sdev);
|
||||||
if (ret == -EWOULDBLOCK)
|
if (ret == -EWOULDBLOCK)
|
||||||
goto unlock;
|
goto unlock_scan;
|
||||||
dev->flags &= ~ATA_DFLAG_RESUMING;
|
dev->flags &= ~ATA_DFLAG_RESUMING;
|
||||||
}
|
}
|
||||||
ret = scsi_rescan_device(sdev);
|
ret = scsi_rescan_device(sdev);
|
||||||
|
@ -4766,12 +4766,13 @@ void ata_scsi_dev_rescan(struct work_struct *work)
|
||||||
spin_lock_irqsave(ap->lock, flags);
|
spin_lock_irqsave(ap->lock, flags);
|
||||||
|
|
||||||
if (ret)
|
if (ret)
|
||||||
goto unlock;
|
goto unlock_ap;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unlock:
|
unlock_ap:
|
||||||
spin_unlock_irqrestore(ap->lock, flags);
|
spin_unlock_irqrestore(ap->lock, flags);
|
||||||
|
unlock_scan:
|
||||||
mutex_unlock(&ap->scsi_scan_mutex);
|
mutex_unlock(&ap->scsi_scan_mutex);
|
||||||
|
|
||||||
/* Reschedule with a delay if scsi_rescan_device() returned an error */
|
/* Reschedule with a delay if scsi_rescan_device() returned an error */
|
||||||
|
|
Loading…
Reference in New Issue