summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin K. Petersen <martin.petersen@oracle.com>2026-01-12 05:33:19 +0300
committerMartin K. Petersen <martin.petersen@oracle.com>2026-01-12 05:33:19 +0300
commit3a8a4ee99cb603aa889de18dd4d1cadb7de331a5 (patch)
treed1457719c653e7757fd6c933fbb8caaabe59664b
parentae62d62b1c740f7a5ea72082dc28f30ebf6b134d (diff)
parent44859905375ff4d739cca2113408336a90ed227d (diff)
downloadlinux-3a8a4ee99cb603aa889de18dd4d1cadb7de331a5.tar.xz
Merge patch series "scsi: Make use of bus callbacks"
Uwe Kleine-König <u.kleine-koenig@baylibre.com> says: Hello, this is v2 of the series to make the scsi subsystem stop using the callbacks .probe(), .remove() and .shutdown() of struct device_driver. Instead use their designated alternatives in struct bus_type. The eventual goal is to drop the callbacks from struct device_driver. The 2nd patch introduces some legacy handling for drivers still using the device_driver callbacks. This results in a runtime warning (in driver_register()). The following patches convert all in-tree drivers (and thus fix the warnings one after another). Conceptually this legacy handling could be dropped at the end of the series, but I think this is a bad idea because this silently breaks out-of-tree drivers (which also covers drivers that are currently prepared for mainline submission) and in-tree drivers I might have missed (though I'm convinced I catched them all). That convinces me that keeping the legacy handling for at least one development cycle is the right choice. I'll care for that at the latest when I remove the callbacks from struct device_driver. Link: https://patch.msgid.link/cover.1766133330.git.u.kleine-koenig@baylibre.com Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
-rw-r--r--drivers/scsi/ch.c18
-rw-r--r--drivers/scsi/scsi_sysfs.c77
-rw-r--r--drivers/scsi/sd.c29
-rw-r--r--drivers/scsi/ses.c15
-rw-r--r--drivers/scsi/sr.c21
-rw-r--r--drivers/scsi/st.c22
-rw-r--r--drivers/ufs/core/ufshcd.c22
-rw-r--r--include/scsi/scsi_driver.h7
8 files changed, 139 insertions, 72 deletions
diff --git a/drivers/scsi/ch.c b/drivers/scsi/ch.c
index fa07a6f54003..b6ca23a29ef5 100644
--- a/drivers/scsi/ch.c
+++ b/drivers/scsi/ch.c
@@ -894,9 +894,9 @@ static long ch_ioctl(struct file *file,
/* ------------------------------------------------------------------------ */
-static int ch_probe(struct device *dev)
+static int ch_probe(struct scsi_device *sd)
{
- struct scsi_device *sd = to_scsi_device(dev);
+ struct device *dev = &sd->sdev_gendev;
struct device *class_dev;
int ret;
scsi_changer *ch;
@@ -967,8 +967,9 @@ free_ch:
return ret;
}
-static int ch_remove(struct device *dev)
+static void ch_remove(struct scsi_device *sd)
{
+ struct device *dev = &sd->sdev_gendev;
scsi_changer *ch = dev_get_drvdata(dev);
spin_lock(&ch_index_lock);
@@ -979,15 +980,14 @@ static int ch_remove(struct device *dev)
device_destroy(&ch_sysfs_class, MKDEV(SCSI_CHANGER_MAJOR, ch->minor));
scsi_device_put(ch->device);
kref_put(&ch->ref, ch_destroy);
- return 0;
}
static struct scsi_driver ch_template = {
- .gendrv = {
+ .probe = ch_probe,
+ .remove = ch_remove,
+ .gendrv = {
.name = "ch",
.owner = THIS_MODULE,
- .probe = ch_probe,
- .remove = ch_remove,
},
};
@@ -1014,7 +1014,7 @@ static int __init init_ch_module(void)
SCSI_CHANGER_MAJOR);
goto fail1;
}
- rc = scsi_register_driver(&ch_template.gendrv);
+ rc = scsi_register_driver(&ch_template);
if (rc < 0)
goto fail2;
return 0;
@@ -1028,7 +1028,7 @@ static int __init init_ch_module(void)
static void __exit exit_ch_module(void)
{
- scsi_unregister_driver(&ch_template.gendrv);
+ scsi_unregister_driver(&ch_template);
unregister_chrdev(SCSI_CHANGER_MAJOR, "ch");
class_unregister(&ch_sysfs_class);
idr_destroy(&ch_index_idr);
diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c
index 99eb0a30df61..6b8c5c05f294 100644
--- a/drivers/scsi/scsi_sysfs.c
+++ b/drivers/scsi/scsi_sysfs.c
@@ -554,10 +554,48 @@ static int scsi_bus_uevent(const struct device *dev, struct kobj_uevent_env *env
return 0;
}
+static int scsi_bus_probe(struct device *dev)
+{
+ struct scsi_device *sdp = to_scsi_device(dev);
+ struct scsi_driver *drv = to_scsi_driver(dev->driver);
+
+ if (drv->probe)
+ return drv->probe(sdp);
+ else
+ return 0;
+}
+
+static void scsi_bus_remove(struct device *dev)
+{
+ struct scsi_device *sdp = to_scsi_device(dev);
+ struct scsi_driver *drv = to_scsi_driver(dev->driver);
+
+ if (drv->remove)
+ drv->remove(sdp);
+}
+
+static void scsi_bus_shutdown(struct device *dev)
+{
+ struct scsi_device *sdp = to_scsi_device(dev);
+ struct scsi_driver *drv;
+
+ if (!dev->driver)
+ return;
+
+ drv = to_scsi_driver(dev->driver);
+
+ if (drv->shutdown)
+ drv->shutdown(sdp);
+}
+
+
const struct bus_type scsi_bus_type = {
- .name = "scsi",
- .match = scsi_bus_match,
+ .name = "scsi",
+ .match = scsi_bus_match,
.uevent = scsi_bus_uevent,
+ .probe = scsi_bus_probe,
+ .remove = scsi_bus_remove,
+ .shutdown = scsi_bus_shutdown,
#ifdef CONFIG_PM
.pm = &scsi_bus_pm_ops,
#endif
@@ -1554,11 +1592,44 @@ restart:
}
EXPORT_SYMBOL(scsi_remove_target);
-int __scsi_register_driver(struct device_driver *drv, struct module *owner)
+static int scsi_legacy_probe(struct scsi_device *sdp)
+{
+ struct device *dev = &sdp->sdev_gendev;
+ struct device_driver *driver = dev->driver;
+
+ return driver->probe(dev);
+}
+
+static void scsi_legacy_remove(struct scsi_device *sdp)
+{
+ struct device *dev = &sdp->sdev_gendev;
+ struct device_driver *driver = dev->driver;
+
+ driver->remove(dev);
+}
+
+static void scsi_legacy_shutdown(struct scsi_device *sdp)
+{
+ struct device *dev = &sdp->sdev_gendev;
+ struct device_driver *driver = dev->driver;
+
+ driver->shutdown(dev);
+}
+
+int __scsi_register_driver(struct scsi_driver *sdrv, struct module *owner)
{
+ struct device_driver *drv = &sdrv->gendrv;
+
drv->bus = &scsi_bus_type;
drv->owner = owner;
+ if (!sdrv->probe && drv->probe)
+ sdrv->probe = scsi_legacy_probe;
+ if (!sdrv->remove && drv->remove)
+ sdrv->remove = scsi_legacy_remove;
+ if (!sdrv->shutdown && drv->shutdown)
+ sdrv->shutdown = scsi_legacy_shutdown;
+
return driver_register(drv);
}
EXPORT_SYMBOL(__scsi_register_driver);
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index f50b92e63201..dc7eac6211bc 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -108,7 +108,7 @@ static void sd_config_write_same(struct scsi_disk *sdkp,
struct queue_limits *lim);
static void sd_revalidate_disk(struct gendisk *);
static void sd_unlock_native_capacity(struct gendisk *disk);
-static void sd_shutdown(struct device *);
+static void sd_shutdown(struct scsi_device *);
static void scsi_disk_release(struct device *cdev);
static DEFINE_IDA(sd_index_ida);
@@ -3935,7 +3935,7 @@ static int sd_format_disk_name(char *prefix, int index, char *buf, int buflen)
* sd_probe - called during driver initialization and whenever a
* new scsi device is attached to the system. It is called once
* for each scsi device (not just disks) present.
- * @dev: pointer to device object
+ * @sdp: pointer to device object
*
* Returns 0 if successful (or not interested in this scsi device
* (e.g. scanner)); 1 when there is an error.
@@ -3949,9 +3949,9 @@ static int sd_format_disk_name(char *prefix, int index, char *buf, int buflen)
* Assume sd_probe is not re-entrant (for time being)
* Also think about sd_probe() and sd_remove() running coincidentally.
**/
-static int sd_probe(struct device *dev)
+static int sd_probe(struct scsi_device *sdp)
{
- struct scsi_device *sdp = to_scsi_device(dev);
+ struct device *dev = &sdp->sdev_gendev;
struct scsi_disk *sdkp;
struct gendisk *gd;
int index;
@@ -4091,15 +4091,16 @@ static int sd_probe(struct device *dev)
* sd_remove - called whenever a scsi disk (previously recognized by
* sd_probe) is detached from the system. It is called (potentially
* multiple times) during sd module unload.
- * @dev: pointer to device object
+ * @sdp: pointer to device object
*
* Note: this function is invoked from the scsi mid-level.
* This function potentially frees up a device name (e.g. /dev/sdc)
* that could be re-used by a subsequent sd_probe().
* This function is not called when the built-in sd driver is "exit-ed".
**/
-static int sd_remove(struct device *dev)
+static void sd_remove(struct scsi_device *sdp)
{
+ struct device *dev = &sdp->sdev_gendev;
struct scsi_disk *sdkp = dev_get_drvdata(dev);
scsi_autopm_get_device(sdkp->device);
@@ -4107,10 +4108,9 @@ static int sd_remove(struct device *dev)
device_del(&sdkp->disk_dev);
del_gendisk(sdkp->disk);
if (!sdkp->suspended)
- sd_shutdown(dev);
+ sd_shutdown(sdp);
put_disk(sdkp->disk);
- return 0;
}
static void scsi_disk_release(struct device *dev)
@@ -4197,8 +4197,9 @@ static int sd_start_stop_device(struct scsi_disk *sdkp, int start)
* the normal SCSI command structure. Wait for the command to
* complete.
*/
-static void sd_shutdown(struct device *dev)
+static void sd_shutdown(struct scsi_device *sdp)
{
+ struct device *dev = &sdp->sdev_gendev;
struct scsi_disk *sdkp = dev_get_drvdata(dev);
if (!sdkp)
@@ -4368,12 +4369,12 @@ static const struct dev_pm_ops sd_pm_ops = {
};
static struct scsi_driver sd_template = {
+ .probe = sd_probe,
+ .remove = sd_remove,
+ .shutdown = sd_shutdown,
.gendrv = {
.name = "sd",
- .probe = sd_probe,
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
- .remove = sd_remove,
- .shutdown = sd_shutdown,
.pm = &sd_pm_ops,
},
.rescan = sd_rescan,
@@ -4417,7 +4418,7 @@ static int __init init_sd(void)
goto err_out_class;
}
- err = scsi_register_driver(&sd_template.gendrv);
+ err = scsi_register_driver(&sd_template);
if (err)
goto err_out_driver;
@@ -4444,7 +4445,7 @@ static void __exit exit_sd(void)
SCSI_LOG_HLQUEUE(3, printk("exit_sd: exiting sd driver\n"));
- scsi_unregister_driver(&sd_template.gendrv);
+ scsi_unregister_driver(&sd_template);
mempool_destroy(sd_page_pool);
class_unregister(&sd_disk_class);
diff --git a/drivers/scsi/ses.c b/drivers/scsi/ses.c
index 2c61624cb4b0..789b170da652 100644
--- a/drivers/scsi/ses.c
+++ b/drivers/scsi/ses.c
@@ -42,9 +42,8 @@ static bool ses_page2_supported(struct enclosure_device *edev)
return (ses_dev->page2 != NULL);
}
-static int ses_probe(struct device *dev)
+static int ses_probe(struct scsi_device *sdev)
{
- struct scsi_device *sdev = to_scsi_device(dev);
int err = -ENODEV;
if (sdev->type != TYPE_ENCLOSURE)
@@ -847,11 +846,6 @@ page2_not_supported:
return err;
}
-static int ses_remove(struct device *dev)
-{
- return 0;
-}
-
static void ses_intf_remove_component(struct scsi_device *sdev)
{
struct enclosure_device *edev, *prev = NULL;
@@ -906,10 +900,9 @@ static struct class_interface ses_interface = {
};
static struct scsi_driver ses_template = {
+ .probe = ses_probe,
.gendrv = {
.name = "ses",
- .probe = ses_probe,
- .remove = ses_remove,
},
};
@@ -921,7 +914,7 @@ static int __init ses_init(void)
if (err)
return err;
- err = scsi_register_driver(&ses_template.gendrv);
+ err = scsi_register_driver(&ses_template);
if (err)
goto out_unreg;
@@ -934,7 +927,7 @@ static int __init ses_init(void)
static void __exit ses_exit(void)
{
- scsi_unregister_driver(&ses_template.gendrv);
+ scsi_unregister_driver(&ses_template);
scsi_unregister_interface(&ses_interface);
}
diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c
index add13e306898..1fb85f548955 100644
--- a/drivers/scsi/sr.c
+++ b/drivers/scsi/sr.c
@@ -82,8 +82,8 @@ MODULE_ALIAS_SCSI_DEVICE(TYPE_WORM);
CDC_CD_R|CDC_CD_RW|CDC_DVD|CDC_DVD_R|CDC_DVD_RAM|CDC_GENERIC_PACKET| \
CDC_MRW|CDC_MRW_W|CDC_RAM)
-static int sr_probe(struct device *);
-static int sr_remove(struct device *);
+static int sr_probe(struct scsi_device *);
+static void sr_remove(struct scsi_device *);
static blk_status_t sr_init_command(struct scsi_cmnd *SCpnt);
static int sr_done(struct scsi_cmnd *);
static int sr_runtime_suspend(struct device *dev);
@@ -93,10 +93,10 @@ static const struct dev_pm_ops sr_pm_ops = {
};
static struct scsi_driver sr_template = {
+ .probe = sr_probe,
+ .remove = sr_remove,
.gendrv = {
.name = "sr",
- .probe = sr_probe,
- .remove = sr_remove,
.pm = &sr_pm_ops,
},
.init_command = sr_init_command,
@@ -616,9 +616,9 @@ static void sr_release(struct cdrom_device_info *cdi)
{
}
-static int sr_probe(struct device *dev)
+static int sr_probe(struct scsi_device *sdev)
{
- struct scsi_device *sdev = to_scsi_device(dev);
+ struct device *dev = &sdev->sdev_gendev;
struct gendisk *disk;
struct scsi_cd *cd;
int minor, error;
@@ -982,16 +982,15 @@ out_put_request:
return ret;
}
-static int sr_remove(struct device *dev)
+static void sr_remove(struct scsi_device *sdev)
{
+ struct device *dev = &sdev->sdev_gendev;
struct scsi_cd *cd = dev_get_drvdata(dev);
scsi_autopm_get_device(cd->device);
del_gendisk(cd->disk);
put_disk(cd->disk);
-
- return 0;
}
static int __init init_sr(void)
@@ -1001,7 +1000,7 @@ static int __init init_sr(void)
rc = register_blkdev(SCSI_CDROM_MAJOR, "sr");
if (rc)
return rc;
- rc = scsi_register_driver(&sr_template.gendrv);
+ rc = scsi_register_driver(&sr_template);
if (rc)
unregister_blkdev(SCSI_CDROM_MAJOR, "sr");
@@ -1010,7 +1009,7 @@ static int __init init_sr(void)
static void __exit exit_sr(void)
{
- scsi_unregister_driver(&sr_template.gendrv);
+ scsi_unregister_driver(&sr_template);
unregister_blkdev(SCSI_CDROM_MAJOR, "sr");
}
diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c
index 168f25e4aaa3..40d88bbb4388 100644
--- a/drivers/scsi/st.c
+++ b/drivers/scsi/st.c
@@ -202,14 +202,14 @@ static int sgl_map_user_pages(struct st_buffer *, const unsigned int,
unsigned long, size_t, int);
static int sgl_unmap_user_pages(struct st_buffer *, const unsigned int, int);
-static int st_probe(struct device *);
-static int st_remove(struct device *);
+static int st_probe(struct scsi_device *);
+static void st_remove(struct scsi_device *);
static struct scsi_driver st_template = {
+ .probe = st_probe,
+ .remove = st_remove,
.gendrv = {
.name = "st",
- .probe = st_probe,
- .remove = st_remove,
.groups = st_drv_groups,
},
};
@@ -4342,9 +4342,9 @@ static void remove_cdevs(struct scsi_tape *tape)
}
}
-static int st_probe(struct device *dev)
+static int st_probe(struct scsi_device *SDp)
{
- struct scsi_device *SDp = to_scsi_device(dev);
+ struct device *dev = &SDp->sdev_gendev;
struct scsi_tape *tpnt = NULL;
struct st_modedef *STm;
struct st_partstat *STps;
@@ -4499,12 +4499,13 @@ out:
};
-static int st_remove(struct device *dev)
+static void st_remove(struct scsi_device *SDp)
{
+ struct device *dev = &SDp->sdev_gendev;
struct scsi_tape *tpnt = dev_get_drvdata(dev);
int index = tpnt->index;
- scsi_autopm_get_device(to_scsi_device(dev));
+ scsi_autopm_get_device(SDp);
remove_cdevs(tpnt);
mutex_lock(&st_ref_mutex);
@@ -4513,7 +4514,6 @@ static int st_remove(struct device *dev)
spin_lock(&st_index_lock);
idr_remove(&st_index_idr, index);
spin_unlock(&st_index_lock);
- return 0;
}
/**
@@ -4576,7 +4576,7 @@ static int __init init_st(void)
goto err_class;
}
- err = scsi_register_driver(&st_template.gendrv);
+ err = scsi_register_driver(&st_template);
if (err)
goto err_chrdev;
@@ -4592,7 +4592,7 @@ err_class:
static void __exit exit_st(void)
{
- scsi_unregister_driver(&st_template.gendrv);
+ scsi_unregister_driver(&st_template);
unregister_chrdev_region(MKDEV(SCSI_TAPE_MAJOR, 0),
ST_MAX_TAPE_ENTRIES);
class_unregister(&st_sysfs_class);
diff --git a/drivers/ufs/core/ufshcd.c b/drivers/ufs/core/ufshcd.c
index 80c0b49f30b0..78669c205568 100644
--- a/drivers/ufs/core/ufshcd.c
+++ b/drivers/ufs/core/ufshcd.c
@@ -10525,9 +10525,8 @@ int ufshcd_runtime_resume(struct device *dev)
EXPORT_SYMBOL(ufshcd_runtime_resume);
#endif /* CONFIG_PM */
-static void ufshcd_wl_shutdown(struct device *dev)
+static void ufshcd_wl_shutdown(struct scsi_device *sdev)
{
- struct scsi_device *sdev = to_scsi_device(dev);
struct ufs_hba *hba = shost_priv(sdev->host);
down(&hba->host_sem);
@@ -11133,9 +11132,9 @@ static int ufshcd_wl_poweroff(struct device *dev)
}
#endif
-static int ufshcd_wl_probe(struct device *dev)
+static int ufshcd_wl_probe(struct scsi_device *sdev)
{
- struct scsi_device *sdev = to_scsi_device(dev);
+ struct device *dev = &sdev->sdev_gendev;
if (!is_device_wlun(sdev))
return -ENODEV;
@@ -11147,10 +11146,11 @@ static int ufshcd_wl_probe(struct device *dev)
return 0;
}
-static int ufshcd_wl_remove(struct device *dev)
+static void ufshcd_wl_remove(struct scsi_device *sdev)
{
+ struct device *dev = &sdev->sdev_gendev;
+
pm_runtime_forbid(dev);
- return 0;
}
static const struct dev_pm_ops ufshcd_wl_pm_ops = {
@@ -11223,12 +11223,12 @@ static void ufshcd_check_header_layout(void)
* Hence register a scsi driver for ufs wluns only.
*/
static struct scsi_driver ufs_dev_wlun_template = {
+ .probe = ufshcd_wl_probe,
+ .remove = ufshcd_wl_remove,
+ .shutdown = ufshcd_wl_shutdown,
.gendrv = {
.name = "ufs_device_wlun",
- .probe = ufshcd_wl_probe,
- .remove = ufshcd_wl_remove,
.pm = &ufshcd_wl_pm_ops,
- .shutdown = ufshcd_wl_shutdown,
},
};
@@ -11240,7 +11240,7 @@ static int __init ufshcd_core_init(void)
ufs_debugfs_init();
- ret = scsi_register_driver(&ufs_dev_wlun_template.gendrv);
+ ret = scsi_register_driver(&ufs_dev_wlun_template);
if (ret)
ufs_debugfs_exit();
return ret;
@@ -11249,7 +11249,7 @@ static int __init ufshcd_core_init(void)
static void __exit ufshcd_core_exit(void)
{
ufs_debugfs_exit();
- scsi_unregister_driver(&ufs_dev_wlun_template.gendrv);
+ scsi_unregister_driver(&ufs_dev_wlun_template);
}
module_init(ufshcd_core_init);
diff --git a/include/scsi/scsi_driver.h b/include/scsi/scsi_driver.h
index c0e89996bdb3..249cea724abd 100644
--- a/include/scsi/scsi_driver.h
+++ b/include/scsi/scsi_driver.h
@@ -12,6 +12,9 @@ struct request;
struct scsi_driver {
struct device_driver gendrv;
+ int (*probe)(struct scsi_device *);
+ void (*remove)(struct scsi_device *);
+ void (*shutdown)(struct scsi_device *);
int (*resume)(struct device *);
void (*rescan)(struct device *);
blk_status_t (*init_command)(struct scsi_cmnd *);
@@ -25,9 +28,9 @@ struct scsi_driver {
#define scsi_register_driver(drv) \
__scsi_register_driver(drv, THIS_MODULE)
-int __scsi_register_driver(struct device_driver *, struct module *);
+int __scsi_register_driver(struct scsi_driver *, struct module *);
#define scsi_unregister_driver(drv) \
- driver_unregister(drv);
+ driver_unregister(&(drv)->gendrv);
extern int scsi_register_interface(struct class_interface *);
#define scsi_unregister_interface(intf) \