Commit aca7c377 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'ata-6.10-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/libata/linux

Pull ata fixes from Niklas Cassel:

 - Add NOLPM quirk for for all Crucial BX SSD1 models.

   Considering that we now have had bug reports for 3 different BX SSD1
   variants from Crucial with the same product name, make the quirk more
   inclusive, to catch more device models from the same generation.

 - Fix a trivial NULL pointer dereference in the error path for
   ata_host_release().

 - Create a ata_port_free(), so that we don't miss freeing ata_port
   struct members when freeing a struct ata_port.

 - Fix a trivial double free in the error path for ata_host_alloc().

 - Ensure that we remove the libata "remapped NVMe device count" sysfs
   entry on .probe() error.

* tag 'ata-6.10-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/libata/linux:
  ata: ahci: Clean up sysfs file on error
  ata: libata-core: Fix double free on error
  ata,scsi: libata-core: Do not leak memory for ata_port struct members
  ata: libata-core: Fix null pointer dereference on error
  ata: libata-core: Add ATA_HORKAGE_NOLPM for all Crucial BX SSD1 models
parents e0b668b0 eeb25a09
...@@ -1975,8 +1975,10 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -1975,8 +1975,10 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
n_ports = max(ahci_nr_ports(hpriv->cap), fls(hpriv->port_map)); n_ports = max(ahci_nr_ports(hpriv->cap), fls(hpriv->port_map));
host = ata_host_alloc_pinfo(&pdev->dev, ppi, n_ports); host = ata_host_alloc_pinfo(&pdev->dev, ppi, n_ports);
if (!host) if (!host) {
return -ENOMEM; rc = -ENOMEM;
goto err_rm_sysfs_file;
}
host->private_data = hpriv; host->private_data = hpriv;
if (ahci_init_msi(pdev, n_ports, hpriv) < 0) { if (ahci_init_msi(pdev, n_ports, hpriv) < 0) {
...@@ -2031,11 +2033,11 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -2031,11 +2033,11 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
/* initialize adapter */ /* initialize adapter */
rc = ahci_configure_dma_masks(pdev, hpriv); rc = ahci_configure_dma_masks(pdev, hpriv);
if (rc) if (rc)
return rc; goto err_rm_sysfs_file;
rc = ahci_pci_reset_controller(host); rc = ahci_pci_reset_controller(host);
if (rc) if (rc)
return rc; goto err_rm_sysfs_file;
ahci_pci_init_controller(host); ahci_pci_init_controller(host);
ahci_pci_print_info(host); ahci_pci_print_info(host);
...@@ -2044,10 +2046,15 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -2044,10 +2046,15 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
rc = ahci_host_activate(host, &ahci_sht); rc = ahci_host_activate(host, &ahci_sht);
if (rc) if (rc)
return rc; goto err_rm_sysfs_file;
pm_runtime_put_noidle(&pdev->dev); pm_runtime_put_noidle(&pdev->dev);
return 0; return 0;
err_rm_sysfs_file:
sysfs_remove_file_from_group(&pdev->dev.kobj,
&dev_attr_remapped_nvme.attr, NULL);
return rc;
} }
static void ahci_shutdown_one(struct pci_dev *pdev) static void ahci_shutdown_one(struct pci_dev *pdev)
......
...@@ -4137,8 +4137,7 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = { ...@@ -4137,8 +4137,7 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = {
{ "PIONEER BD-RW BDR-205", NULL, ATA_HORKAGE_NOLPM }, { "PIONEER BD-RW BDR-205", NULL, ATA_HORKAGE_NOLPM },
/* Crucial devices with broken LPM support */ /* Crucial devices with broken LPM support */
{ "CT500BX100SSD1", NULL, ATA_HORKAGE_NOLPM }, { "CT*0BX*00SSD1", NULL, ATA_HORKAGE_NOLPM },
{ "CT240BX500SSD1", NULL, ATA_HORKAGE_NOLPM },
/* 512GB MX100 with MU01 firmware has both queued TRIM and LPM issues */ /* 512GB MX100 with MU01 firmware has both queued TRIM and LPM issues */
{ "Crucial_CT512MX100*", "MU01", ATA_HORKAGE_NO_NCQ_TRIM | { "Crucial_CT512MX100*", "MU01", ATA_HORKAGE_NO_NCQ_TRIM |
...@@ -5490,6 +5489,18 @@ struct ata_port *ata_port_alloc(struct ata_host *host) ...@@ -5490,6 +5489,18 @@ struct ata_port *ata_port_alloc(struct ata_host *host)
return ap; return ap;
} }
void ata_port_free(struct ata_port *ap)
{
if (!ap)
return;
kfree(ap->pmp_link);
kfree(ap->slave_link);
kfree(ap->ncq_sense_buf);
kfree(ap);
}
EXPORT_SYMBOL_GPL(ata_port_free);
static void ata_devres_release(struct device *gendev, void *res) static void ata_devres_release(struct device *gendev, void *res)
{ {
struct ata_host *host = dev_get_drvdata(gendev); struct ata_host *host = dev_get_drvdata(gendev);
...@@ -5516,12 +5527,7 @@ static void ata_host_release(struct kref *kref) ...@@ -5516,12 +5527,7 @@ static void ata_host_release(struct kref *kref)
int i; int i;
for (i = 0; i < host->n_ports; i++) { for (i = 0; i < host->n_ports; i++) {
struct ata_port *ap = host->ports[i]; ata_port_free(host->ports[i]);
kfree(ap->pmp_link);
kfree(ap->slave_link);
kfree(ap->ncq_sense_buf);
kfree(ap);
host->ports[i] = NULL; host->ports[i] = NULL;
} }
kfree(host); kfree(host);
...@@ -5571,8 +5577,10 @@ struct ata_host *ata_host_alloc(struct device *dev, int max_ports) ...@@ -5571,8 +5577,10 @@ struct ata_host *ata_host_alloc(struct device *dev, int max_ports)
if (!host) if (!host)
return NULL; return NULL;
if (!devres_open_group(dev, NULL, GFP_KERNEL)) if (!devres_open_group(dev, NULL, GFP_KERNEL)) {
goto err_free; kfree(host);
return NULL;
}
dr = devres_alloc(ata_devres_release, 0, GFP_KERNEL); dr = devres_alloc(ata_devres_release, 0, GFP_KERNEL);
if (!dr) if (!dr)
...@@ -5604,8 +5612,6 @@ struct ata_host *ata_host_alloc(struct device *dev, int max_ports) ...@@ -5604,8 +5612,6 @@ struct ata_host *ata_host_alloc(struct device *dev, int max_ports)
err_out: err_out:
devres_release_group(dev, NULL); devres_release_group(dev, NULL);
err_free:
kfree(host);
return NULL; return NULL;
} }
EXPORT_SYMBOL_GPL(ata_host_alloc); EXPORT_SYMBOL_GPL(ata_host_alloc);
...@@ -5904,7 +5910,7 @@ int ata_host_register(struct ata_host *host, const struct scsi_host_template *sh ...@@ -5904,7 +5910,7 @@ int ata_host_register(struct ata_host *host, const struct scsi_host_template *sh
* allocation time. * allocation time.
*/ */
for (i = host->n_ports; host->ports[i]; i++) for (i = host->n_ports; host->ports[i]; i++)
kfree(host->ports[i]); ata_port_free(host->ports[i]);
/* give ports names and add SCSI hosts */ /* give ports names and add SCSI hosts */
for (i = 0; i < host->n_ports; i++) { for (i = 0; i < host->n_ports; i++) {
......
...@@ -610,15 +610,15 @@ int sas_ata_init(struct domain_device *found_dev) ...@@ -610,15 +610,15 @@ int sas_ata_init(struct domain_device *found_dev)
rc = ata_sas_tport_add(ata_host->dev, ap); rc = ata_sas_tport_add(ata_host->dev, ap);
if (rc) if (rc)
goto destroy_port; goto free_port;
found_dev->sata_dev.ata_host = ata_host; found_dev->sata_dev.ata_host = ata_host;
found_dev->sata_dev.ap = ap; found_dev->sata_dev.ap = ap;
return 0; return 0;
destroy_port: free_port:
kfree(ap); ata_port_free(ap);
free_host: free_host:
ata_host_put(ata_host); ata_host_put(ata_host);
return rc; return rc;
......
...@@ -301,7 +301,7 @@ void sas_free_device(struct kref *kref) ...@@ -301,7 +301,7 @@ void sas_free_device(struct kref *kref)
if (dev_is_sata(dev) && dev->sata_dev.ap) { if (dev_is_sata(dev) && dev->sata_dev.ap) {
ata_sas_tport_delete(dev->sata_dev.ap); ata_sas_tport_delete(dev->sata_dev.ap);
kfree(dev->sata_dev.ap); ata_port_free(dev->sata_dev.ap);
ata_host_put(dev->sata_dev.ata_host); ata_host_put(dev->sata_dev.ata_host);
dev->sata_dev.ata_host = NULL; dev->sata_dev.ata_host = NULL;
dev->sata_dev.ap = NULL; dev->sata_dev.ap = NULL;
......
...@@ -1249,6 +1249,7 @@ extern int ata_slave_link_init(struct ata_port *ap); ...@@ -1249,6 +1249,7 @@ extern int ata_slave_link_init(struct ata_port *ap);
extern struct ata_port *ata_sas_port_alloc(struct ata_host *, extern struct ata_port *ata_sas_port_alloc(struct ata_host *,
struct ata_port_info *, struct Scsi_Host *); struct ata_port_info *, struct Scsi_Host *);
extern void ata_port_probe(struct ata_port *ap); extern void ata_port_probe(struct ata_port *ap);
extern void ata_port_free(struct ata_port *ap);
extern int ata_sas_tport_add(struct device *parent, struct ata_port *ap); extern int ata_sas_tport_add(struct device *parent, struct ata_port *ap);
extern void ata_sas_tport_delete(struct ata_port *ap); extern void ata_sas_tport_delete(struct ata_port *ap);
int ata_sas_device_configure(struct scsi_device *sdev, struct queue_limits *lim, int ata_sas_device_configure(struct scsi_device *sdev, struct queue_limits *lim,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment