From 228beab6e6d8effd262145ede94762a3b81c663c Mon Sep 17 00:00:00 2001 From: Ben Collins Date: Sat, 21 Feb 2004 00:47:03 -0500 Subject: [PATCH] IEEE1394(r1146): Make the probe callback return an error if problems, and unbind drivers on failure. --- drivers/ieee1394/eth1394.c | 8 +++++--- drivers/ieee1394/nodemgr.c | 7 +++++-- drivers/ieee1394/nodemgr.h | 6 ++++-- drivers/ieee1394/sbp2.c | 20 ++++++++++++-------- drivers/ieee1394/sbp2.h | 6 ------ 5 files changed, 26 insertions(+), 21 deletions(-) diff --git a/drivers/ieee1394/eth1394.c b/drivers/ieee1394/eth1394.c index 06714fa4b39a3..4b6c36c69b5fb 100644 --- a/drivers/ieee1394/eth1394.c +++ b/drivers/ieee1394/eth1394.c @@ -411,7 +411,7 @@ static int eth1394_remove(struct device *dev) return 0; } -static void eth1394_update(struct unit_directory *ud) +static int eth1394_update(struct unit_directory *ud) { struct eth1394_host_info *hi; struct eth1394_priv *priv; @@ -420,7 +420,7 @@ static void eth1394_update(struct unit_directory *ud) hi = hpsb_get_hostinfo(ð1394_highlevel, ud->ne->host); if (!hi) - return; + return -ENOENT; priv = (struct eth1394_priv *)hi->dev->priv; @@ -430,7 +430,7 @@ static void eth1394_update(struct unit_directory *ud) node = kmalloc(sizeof(struct eth1394_node_ref), in_interrupt() ? GFP_ATOMIC : GFP_KERNEL); if (!node) - return; + return -ENOMEM; node_info = kmalloc(sizeof(struct eth1394_node_info), @@ -446,6 +446,8 @@ static void eth1394_update(struct unit_directory *ud) priv = (struct eth1394_priv *)hi->dev->priv; list_add_tail(&node->list, &priv->ip_node_list); } + + return 0; } diff --git a/drivers/ieee1394/nodemgr.c b/drivers/ieee1394/nodemgr.c index 3c595e87e77f9..03d45d374bdee 100644 --- a/drivers/ieee1394/nodemgr.c +++ b/drivers/ieee1394/nodemgr.c @@ -1364,8 +1364,11 @@ static void nodemgr_ud_update_pdrv(struct unit_directory *ud) if (ud->device.driver) { pdrv = container_of(ud->device.driver, struct hpsb_protocol_driver, driver); - if (pdrv->update) - pdrv->update(ud); + if (pdrv->update && pdrv->update(ud)) { + down_write(&ud->device.bus->subsys.rwsem); + device_release_driver(&ud->device); + up_write(&ud->device.bus->subsys.rwsem); + } } put_device(&ud->device); diff --git a/drivers/ieee1394/nodemgr.h b/drivers/ieee1394/nodemgr.h index 80da876ac263d..c3dfa380fca73 100644 --- a/drivers/ieee1394/nodemgr.h +++ b/drivers/ieee1394/nodemgr.h @@ -128,9 +128,11 @@ struct hpsb_protocol_driver { * The update function is called when the node has just * survived a bus reset, i.e. it is still present on the bus. * However, it may be necessary to reestablish the connection - * or login into the node again, depending on the protocol. + * or login into the node again, depending on the protocol. If the + * probe fails (returns non-zero), we unbind the driver from this + * device. */ - void (*update)(struct unit_directory *ud); + int (*update)(struct unit_directory *ud); /* Our LDM structure */ struct device_driver driver; diff --git a/drivers/ieee1394/sbp2.c b/drivers/ieee1394/sbp2.c index 45c4239f18663..f9c0170b6d660 100644 --- a/drivers/ieee1394/sbp2.c +++ b/drivers/ieee1394/sbp2.c @@ -234,6 +234,10 @@ const u8 sbp2_speedto_max_payload[] = { 0x7, 0x8, 0x9, 0xA, 0xB, 0xC }; static void sbp2_remove_host(struct hpsb_host *host); static void sbp2_host_reset(struct hpsb_host *host); +static int sbp2_probe(struct device *dev); +static int sbp2_remove(struct device *dev); +static int sbp2_update(struct unit_directory *ud); + static struct hpsb_highlevel sbp2_highlevel = { .name = SBP2_DEVICE_NAME, .remove_host = sbp2_remove_host, @@ -638,28 +642,26 @@ static int sbp2_remove(struct device *dev) return 0; } -static void sbp2_update(struct unit_directory *ud) +static int sbp2_update(struct unit_directory *ud) { struct scsi_id_instance_data *scsi_id = ud->device.driver_data; - struct sbp2scsi_host_info *hi = scsi_id->hi; SBP2_DEBUG("sbp2_update"); - hi = scsi_id->hi; - if (sbp2_reconnect_device(scsi_id)) { /* * Ok, reconnect has failed. Perhaps we didn't - * reconnect fast enough. Try doing a regular login. + * reconnect fast enough. Try doing a regular login, but + * first do a logout just in case of any weirdness. */ sbp2_logout_device(scsi_id); if (sbp2_login_device(scsi_id)) { - /* Login failed too, just remove the device. */ + /* Login failed too, just fail, and the backend + * will call our sbp2_remove for us */ SBP2_ERR("sbp2_reconnect_device failed!"); - sbp2_remove_device(scsi_id); - return; + return -EBUSY; } } @@ -676,6 +678,8 @@ static void sbp2_update(struct unit_directory *ud) * retried) and remove them from our queue */ sbp2scsi_complete_all_commands(scsi_id, DID_BUS_BUSY); + + return 0; } /* This functions is called by the sbp2_probe, for each new device. We now diff --git a/drivers/ieee1394/sbp2.h b/drivers/ieee1394/sbp2.h index 37a706dbd499c..360f63767833f 100644 --- a/drivers/ieee1394/sbp2.h +++ b/drivers/ieee1394/sbp2.h @@ -439,12 +439,6 @@ static struct sbp2_command_info *sbp2util_allocate_command_orb(struct scsi_id_in static void sbp2util_mark_command_completed(struct scsi_id_instance_data *scsi_id, struct sbp2_command_info *command); -/* - * IEEE-1394 core driver related prototypes - */ -static int sbp2_probe(struct device *dev); -static int sbp2_remove(struct device *dev); -static void sbp2_update(struct unit_directory *ud); static int sbp2_start_device(struct scsi_id_instance_data *scsi_id); static void sbp2_remove_device(struct scsi_id_instance_data *scsi_id); -- 2.53.0