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>
This commit is contained in:
Martin K. Petersen
2026-01-11 21:33:19 -05:00
8 changed files with 139 additions and 72 deletions

View File

@@ -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 @@ static int ch_probe(struct device *dev)
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);

View File

@@ -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 @@ void scsi_remove_target(struct device *dev)
}
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);

View File

@@ -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);

View File

@@ -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 @@ static int ses_intf_add(struct device *cdev)
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);
}

View File

@@ -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 @@ static int sr_read_cdda_bpc(struct cdrom_device_info *cdi, void __user *ubuf,
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");
}

View File

@@ -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 @@ static int st_probe(struct device *dev)
};
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 @@ static int __init init_st(void)
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);

View File

@@ -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);

View File

@@ -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) \