Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ata: ahci_platform: fix owner module reference mismatch for scsi host

The owner module reference of the ahci platform's scsi_host is
initialized to libahci_platform's one, because these drivers use a
scsi_host_template defined in libahci_platform. So these drivers can
be unloaded even if the scsi device is being accessed.

This fixes it by pushing the scsi_host_template from libahci_platform
to all leaf drivers. The scsi_host_template is passed through a new
argument of ahci_platform_init_host().

Signed-off-by: Akinobu Mita <akinobu.mita@gmail.com>
Signed-off-by: Tejun Heo <tj@kernel.org>
Cc: Hans de Goede <hdegoede@redhat.com>
Cc: Christoph Hellwig <hch@lst.de>
Cc: "James E.J. Bottomley" <JBottomley@parallels.com>
Cc: linux-ide@vger.kernel.org
Cc: linux-scsi@vger.kernel.org

authored by

Akinobu Mita and committed by
Tejun Heo
018d5ef2 cedda4c3

+89 -23
+4
drivers/ata/ahci.h
··· 354 354 extern struct device_attribute *ahci_shost_attrs[]; 355 355 extern struct device_attribute *ahci_sdev_attrs[]; 356 356 357 + /* 358 + * This must be instantiated by the edge drivers. Read the comments 359 + * for ATA_BASE_SHT 360 + */ 357 361 #define AHCI_SHT(drv_name) \ 358 362 ATA_NCQ_SHT(drv_name), \ 359 363 .can_queue = AHCI_MAX_CMDS - 1, \
+9 -2
drivers/ata/ahci_da850.c
··· 16 16 #include <linux/ahci_platform.h> 17 17 #include "ahci.h" 18 18 19 + #define DRV_NAME "ahci_da850" 20 + 19 21 /* SATA PHY Control Register offset from AHCI base */ 20 22 #define SATA_P0PHYCR_REG 0x178 21 23 ··· 61 59 .port_ops = &ahci_platform_ops, 62 60 }; 63 61 62 + static struct scsi_host_template ahci_platform_sht = { 63 + AHCI_SHT(DRV_NAME), 64 + }; 65 + 64 66 static int ahci_da850_probe(struct platform_device *pdev) 65 67 { 66 68 struct device *dev = &pdev->dev; ··· 91 85 92 86 da850_sata_init(dev, pwrdn_reg, hpriv->mmio); 93 87 94 - rc = ahci_platform_init_host(pdev, hpriv, &ahci_da850_port_info); 88 + rc = ahci_platform_init_host(pdev, hpriv, &ahci_da850_port_info, 89 + &ahci_platform_sht); 95 90 if (rc) 96 91 goto disable_resources; 97 92 ··· 109 102 .probe = ahci_da850_probe, 110 103 .remove = ata_platform_remove_one, 111 104 .driver = { 112 - .name = "ahci_da850", 105 + .name = DRV_NAME, 113 106 .pm = &ahci_da850_pm_ops, 114 107 }, 115 108 };
+9 -2
drivers/ata/ahci_imx.c
··· 28 28 #include <linux/libata.h> 29 29 #include "ahci.h" 30 30 31 + #define DRV_NAME "ahci-imx" 32 + 31 33 enum { 32 34 /* Timer 1-ms Register */ 33 35 IMX_TIMER1MS = 0x00e0, ··· 522 520 return reg_value; 523 521 } 524 522 523 + static struct scsi_host_template ahci_platform_sht = { 524 + AHCI_SHT(DRV_NAME), 525 + }; 526 + 525 527 static int imx_ahci_probe(struct platform_device *pdev) 526 528 { 527 529 struct device *dev = &pdev->dev; ··· 622 616 reg_val = clk_get_rate(imxpriv->ahb_clk) / 1000; 623 617 writel(reg_val, hpriv->mmio + IMX_TIMER1MS); 624 618 625 - ret = ahci_platform_init_host(pdev, hpriv, &ahci_imx_port_info); 619 + ret = ahci_platform_init_host(pdev, hpriv, &ahci_imx_port_info, 620 + &ahci_platform_sht); 626 621 if (ret) 627 622 goto disable_sata; 628 623 ··· 681 674 .probe = imx_ahci_probe, 682 675 .remove = ata_platform_remove_one, 683 676 .driver = { 684 - .name = "ahci-imx", 677 + .name = DRV_NAME, 685 678 .of_match_table = imx_ahci_of_match, 686 679 .pm = &ahci_imx_pm_ops, 687 680 },
+9 -2
drivers/ata/ahci_mvebu.c
··· 19 19 #include <linux/platform_device.h> 20 20 #include "ahci.h" 21 21 22 + #define DRV_NAME "ahci-mvebu" 23 + 22 24 #define AHCI_VENDOR_SPECIFIC_0_ADDR 0xa0 23 25 #define AHCI_VENDOR_SPECIFIC_0_DATA 0xa4 24 26 ··· 69 67 .port_ops = &ahci_platform_ops, 70 68 }; 71 69 70 + static struct scsi_host_template ahci_platform_sht = { 71 + AHCI_SHT(DRV_NAME), 72 + }; 73 + 72 74 static int ahci_mvebu_probe(struct platform_device *pdev) 73 75 { 74 76 struct ahci_host_priv *hpriv; ··· 94 88 ahci_mvebu_mbus_config(hpriv, dram); 95 89 ahci_mvebu_regret_option(hpriv); 96 90 97 - rc = ahci_platform_init_host(pdev, hpriv, &ahci_mvebu_port_info); 91 + rc = ahci_platform_init_host(pdev, hpriv, &ahci_mvebu_port_info, 92 + &ahci_platform_sht); 98 93 if (rc) 99 94 goto disable_resources; 100 95 ··· 121 114 .probe = ahci_mvebu_probe, 122 115 .remove = ata_platform_remove_one, 123 116 .driver = { 124 - .name = "ahci-mvebu", 117 + .name = DRV_NAME, 125 118 .of_match_table = ahci_mvebu_of_match, 126 119 }, 127 120 };
+9 -2
drivers/ata/ahci_platform.c
··· 22 22 #include <linux/ahci_platform.h> 23 23 #include "ahci.h" 24 24 25 + #define DRV_NAME "ahci" 26 + 25 27 static const struct ata_port_info ahci_port_info = { 26 28 .flags = AHCI_FLAG_COMMON, 27 29 .pio_mask = ATA_PIO4, 28 30 .udma_mask = ATA_UDMA6, 29 31 .port_ops = &ahci_platform_ops, 32 + }; 33 + 34 + static struct scsi_host_template ahci_platform_sht = { 35 + AHCI_SHT(DRV_NAME), 30 36 }; 31 37 32 38 static int ahci_probe(struct platform_device *pdev) ··· 52 46 if (of_device_is_compatible(dev->of_node, "hisilicon,hisi-ahci")) 53 47 hpriv->flags |= AHCI_HFLAG_NO_FBS | AHCI_HFLAG_NO_NCQ; 54 48 55 - rc = ahci_platform_init_host(pdev, hpriv, &ahci_port_info); 49 + rc = ahci_platform_init_host(pdev, hpriv, &ahci_port_info, 50 + &ahci_platform_sht); 56 51 if (rc) 57 52 goto disable_resources; 58 53 ··· 82 75 .probe = ahci_probe, 83 76 .remove = ata_platform_remove_one, 84 77 .driver = { 85 - .name = "ahci", 78 + .name = DRV_NAME, 86 79 .of_match_table = ahci_of_match, 87 80 .pm = &ahci_pm_ops, 88 81 },
+9 -2
drivers/ata/ahci_st.c
··· 23 23 24 24 #include "ahci.h" 25 25 26 + #define DRV_NAME "st_ahci" 27 + 26 28 #define ST_AHCI_OOBR 0xbc 27 29 #define ST_AHCI_OOBR_WE BIT(31) 28 30 #define ST_AHCI_OOBR_CWMIN_SHIFT 24 ··· 142 140 .port_ops = &st_ahci_port_ops, 143 141 }; 144 142 143 + static struct scsi_host_template ahci_platform_sht = { 144 + AHCI_SHT(DRV_NAME), 145 + }; 146 + 145 147 static int st_ahci_probe(struct platform_device *pdev) 146 148 { 147 149 struct st_ahci_drv_data *drv_data; ··· 172 166 if (err) 173 167 return err; 174 168 175 - err = ahci_platform_init_host(pdev, hpriv, &st_ahci_port_info); 169 + err = ahci_platform_init_host(pdev, hpriv, &st_ahci_port_info, 170 + &ahci_platform_sht); 176 171 if (err) { 177 172 ahci_platform_disable_resources(hpriv); 178 173 return err; ··· 236 229 237 230 static struct platform_driver st_ahci_driver = { 238 231 .driver = { 239 - .name = "st_ahci", 232 + .name = DRV_NAME, 240 233 .pm = &st_ahci_pm_ops, 241 234 .of_match_table = of_match_ptr(st_ahci_match), 242 235 },
+9 -2
drivers/ata/ahci_sunxi.c
··· 27 27 #include <linux/regulator/consumer.h> 28 28 #include "ahci.h" 29 29 30 + #define DRV_NAME "ahci-sunxi" 31 + 30 32 /* Insmod parameters */ 31 33 static bool enable_pmp; 32 34 module_param(enable_pmp, bool, 0); ··· 171 169 .port_ops = &ahci_platform_ops, 172 170 }; 173 171 172 + static struct scsi_host_template ahci_platform_sht = { 173 + AHCI_SHT(DRV_NAME), 174 + }; 175 + 174 176 static int ahci_sunxi_probe(struct platform_device *pdev) 175 177 { 176 178 struct device *dev = &pdev->dev; ··· 206 200 if (!enable_pmp) 207 201 hpriv->flags |= AHCI_HFLAG_NO_PMP; 208 202 209 - rc = ahci_platform_init_host(pdev, hpriv, &ahci_sunxi_port_info); 203 + rc = ahci_platform_init_host(pdev, hpriv, &ahci_sunxi_port_info, 204 + &ahci_platform_sht); 210 205 if (rc) 211 206 goto disable_resources; 212 207 ··· 258 251 .probe = ahci_sunxi_probe, 259 252 .remove = ata_platform_remove_one, 260 253 .driver = { 261 - .name = "ahci-sunxi", 254 + .name = DRV_NAME, 262 255 .of_match_table = ahci_sunxi_of_match, 263 256 .pm = &ahci_sunxi_pm_ops, 264 257 },
+9 -2
drivers/ata/ahci_tegra.c
··· 31 31 32 32 #include "ahci.h" 33 33 34 + #define DRV_NAME "tegra-ahci" 35 + 34 36 #define SATA_CONFIGURATION_0 0x180 35 37 #define SATA_CONFIGURATION_EN_FPCI BIT(0) 36 38 ··· 291 289 }; 292 290 MODULE_DEVICE_TABLE(of, tegra_ahci_of_match); 293 291 292 + static struct scsi_host_template ahci_platform_sht = { 293 + AHCI_SHT(DRV_NAME), 294 + }; 295 + 294 296 static int tegra_ahci_probe(struct platform_device *pdev) 295 297 { 296 298 struct ahci_host_priv *hpriv; ··· 360 354 if (ret) 361 355 return ret; 362 356 363 - ret = ahci_platform_init_host(pdev, hpriv, &ahci_tegra_port_info); 357 + ret = ahci_platform_init_host(pdev, hpriv, &ahci_tegra_port_info, 358 + &ahci_platform_sht); 364 359 if (ret) 365 360 goto deinit_controller; 366 361 ··· 377 370 .probe = tegra_ahci_probe, 378 371 .remove = ata_platform_remove_one, 379 372 .driver = { 380 - .name = "tegra-ahci", 373 + .name = DRV_NAME, 381 374 .of_match_table = tegra_ahci_of_match, 382 375 }, 383 376 /* LP0 suspend support not implemented */
+9 -2
drivers/ata/ahci_xgene.c
··· 30 30 #include <linux/phy/phy.h> 31 31 #include "ahci.h" 32 32 33 + #define DRV_NAME "xgene-ahci" 34 + 33 35 /* Max # of disk per a controller */ 34 36 #define MAX_AHCI_CHN_PERCTR 2 35 37 ··· 623 621 return val & CFG_SATA_ENET_SELECT_MASK ? -1 : 0; 624 622 } 625 623 624 + static struct scsi_host_template ahci_platform_sht = { 625 + AHCI_SHT(DRV_NAME), 626 + }; 627 + 626 628 static int xgene_ahci_probe(struct platform_device *pdev) 627 629 { 628 630 struct device *dev = &pdev->dev; ··· 704 698 skip_clk_phy: 705 699 hpriv->flags = AHCI_HFLAG_NO_PMP | AHCI_HFLAG_NO_NCQ; 706 700 707 - rc = ahci_platform_init_host(pdev, hpriv, &xgene_ahci_port_info); 701 + rc = ahci_platform_init_host(pdev, hpriv, &xgene_ahci_port_info, 702 + &ahci_platform_sht); 708 703 if (rc) 709 704 goto disable_resources; 710 705 ··· 727 720 .probe = xgene_ahci_probe, 728 721 .remove = ata_platform_remove_one, 729 722 .driver = { 730 - .name = "xgene-ahci", 723 + .name = DRV_NAME, 731 724 .of_match_table = xgene_ahci_of_match, 732 725 }, 733 726 };
+4 -6
drivers/ata/libahci_platform.c
··· 35 35 }; 36 36 EXPORT_SYMBOL_GPL(ahci_platform_ops); 37 37 38 - static struct scsi_host_template ahci_platform_sht = { 39 - AHCI_SHT("ahci_platform"), 40 - }; 41 - 42 38 /** 43 39 * ahci_platform_enable_phys - Enable PHYs 44 40 * @hpriv: host private area to store config values ··· 490 494 * @pdev: platform device pointer for the host 491 495 * @hpriv: ahci-host private data for the host 492 496 * @pi_template: template for the ata_port_info to use 497 + * @sht: scsi_host_template to use when registering 493 498 * 494 499 * This function does all the usual steps needed to bring up an 495 500 * ahci-platform host, note any necessary resources (ie clks, phys, etc.) ··· 501 504 */ 502 505 int ahci_platform_init_host(struct platform_device *pdev, 503 506 struct ahci_host_priv *hpriv, 504 - const struct ata_port_info *pi_template) 507 + const struct ata_port_info *pi_template, 508 + struct scsi_host_template *sht) 505 509 { 506 510 struct device *dev = &pdev->dev; 507 511 struct ata_port_info pi = *pi_template; ··· 586 588 ahci_init_controller(host); 587 589 ahci_print_info(host, "platform"); 588 590 589 - return ahci_host_activate(host, irq, &ahci_platform_sht); 591 + return ahci_host_activate(host, irq, sht); 590 592 } 591 593 EXPORT_SYMBOL_GPL(ahci_platform_init_host); 592 594
+3 -1
include/linux/ahci_platform.h
··· 21 21 struct ata_port_info; 22 22 struct ahci_host_priv; 23 23 struct platform_device; 24 + struct scsi_host_template; 24 25 25 26 int ahci_platform_enable_clks(struct ahci_host_priv *hpriv); 26 27 void ahci_platform_disable_clks(struct ahci_host_priv *hpriv); ··· 33 32 struct platform_device *pdev); 34 33 int ahci_platform_init_host(struct platform_device *pdev, 35 34 struct ahci_host_priv *hpriv, 36 - const struct ata_port_info *pi_template); 35 + const struct ata_port_info *pi_template, 36 + struct scsi_host_template *sht); 37 37 38 38 int ahci_platform_suspend_host(struct device *dev); 39 39 int ahci_platform_resume_host(struct device *dev);
+6
include/linux/libata.h
··· 1338 1338 extern const struct ata_port_operations sata_port_ops; 1339 1339 extern struct device_attribute *ata_common_sdev_attrs[]; 1340 1340 1341 + /* 1342 + * All sht initializers (BASE, PIO, BMDMA, NCQ) must be instantiated 1343 + * by the edge drivers. Because the 'module' field of sht must be the 1344 + * edge driver's module reference, otherwise the driver can be unloaded 1345 + * even if the scsi_device is being accessed. 1346 + */ 1341 1347 #define ATA_BASE_SHT(drv_name) \ 1342 1348 .module = THIS_MODULE, \ 1343 1349 .name = drv_name, \