From: James Bottomley <James.Bottomley@HansenPartnership.com>
To: Chris Ptacek <chris.ptacek@arrisi.com>
Cc: dave.romrell@arrisi.com,
Michael Galassi <michael.galassi@arrisi.com>,
linux-scsi <linux-scsi@vger.kernel.org>
Subject: [PATCH 2/3] ses: add support for enclosure component hot removal
Date: Sat, 01 Aug 2009 00:41:22 +0000 [thread overview]
Message-ID: <1249087282.3922.515.camel@mulgrave.site> (raw)
In-Reply-To: <1249087023.3922.503.camel@mulgrave.site>
Right at the moment, hot removal of a device within an enclosure does
nothing (because the intf_remove only copes with enclosure removal not
with component removal). Fix this by adding a function to remove the
component. Also needed to fix the prototype of
enclosure_remove_device, since we know the device we've removed but
not the internal component number
---
drivers/misc/enclosure.c | 22 ++++++++++++++--------
drivers/scsi/ses.c | 33 ++++++++++++++++++++++++++-------
include/linux/enclosure.h | 2 +-
3 files changed, 41 insertions(+), 16 deletions(-)
diff --git a/drivers/misc/enclosure.c b/drivers/misc/enclosure.c
index 789d121..850706a 100644
--- a/drivers/misc/enclosure.c
+++ b/drivers/misc/enclosure.c
@@ -332,19 +332,25 @@ EXPORT_SYMBOL_GPL(enclosure_add_device);
* Returns zero on success or an error.
*
*/
-int enclosure_remove_device(struct enclosure_device *edev, int component)
+int enclosure_remove_device(struct enclosure_device *edev, struct device *dev)
{
struct enclosure_component *cdev;
+ int i;
- if (!edev || component >= edev->components)
+ if (!edev || !dev)
return -EINVAL;
- cdev = &edev->component[component];
-
- device_del(&cdev->cdev);
- put_device(cdev->dev);
- cdev->dev = NULL;
- return device_add(&cdev->cdev);
+ for (i = 0; i < edev->components; i++) {
+ cdev = &edev->component[i];
+ if (cdev->dev == dev) {
+ enclosure_remove_links(cdev);
+ device_del(&cdev->cdev);
+ put_device(dev);
+ cdev->dev = NULL;
+ return device_add(&cdev->cdev);
+ }
+ }
+ return -ENODEV;
}
EXPORT_SYMBOL_GPL(enclosure_remove_device);
diff --git a/drivers/scsi/ses.c b/drivers/scsi/ses.c
index e1b8c82..be593c8 100644
--- a/drivers/scsi/ses.c
+++ b/drivers/scsi/ses.c
@@ -616,18 +616,26 @@ static int ses_remove(struct device *dev)
return 0;
}
-static void ses_intf_remove(struct device *cdev,
- struct class_interface *intf)
+static void ses_intf_remove_component(struct scsi_device *sdev)
+{
+ struct enclosure_device *edev, *prev = NULL;
+
+ while ((edev = enclosure_find(&sdev->host->shost_gendev, prev)) != NULL) {
+ prev = edev;
+ if (!enclosure_remove_device(edev, &sdev->sdev_gendev))
+ break;
+ }
+ if (edev)
+ put_device(&edev->edev);
+}
+
+static void ses_intf_remove_enclosure(struct scsi_device *sdev)
{
- struct scsi_device *sdev = to_scsi_device(cdev->parent);
struct enclosure_device *edev;
struct ses_device *ses_dev;
- if (!scsi_device_enclosure(sdev))
- return;
-
/* exact match to this enclosure */
- edev = enclosure_find(cdev->parent, NULL);
+ edev = enclosure_find(&sdev->sdev_gendev, NULL);
if (!edev)
return;
@@ -645,6 +653,17 @@ static void ses_intf_remove(struct device *cdev,
enclosure_unregister(edev);
}
+static void ses_intf_remove(struct device *cdev,
+ struct class_interface *intf)
+{
+ struct scsi_device *sdev = to_scsi_device(cdev->parent);
+
+ if (!scsi_device_enclosure(sdev))
+ ses_intf_remove_component(sdev);
+ else
+ ses_intf_remove_enclosure(sdev);
+}
+
static struct class_interface ses_interface = {
.add_dev = ses_intf_add,
.remove_dev = ses_intf_remove,
diff --git a/include/linux/enclosure.h b/include/linux/enclosure.h
index d77811e..90d1c21 100644
--- a/include/linux/enclosure.h
+++ b/include/linux/enclosure.h
@@ -122,7 +122,7 @@ enclosure_component_register(struct enclosure_device *, unsigned int,
enum enclosure_component_type, const char *);
int enclosure_add_device(struct enclosure_device *enclosure, int component,
struct device *dev);
-int enclosure_remove_device(struct enclosure_device *enclosure, int component);
+int enclosure_remove_device(struct enclosure_device *, struct device *);
struct enclosure_device *enclosure_find(struct device *dev,
struct enclosure_device *start);
int enclosure_for_each_device(int (*fn)(struct enclosure_device *, void *),
--
1.6.3.3
next prev parent reply other threads:[~2009-08-01 0:41 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <4A71F4DF.1060600@arrisi.com>
2009-07-30 20:05 ` Linux enclosure services, hot swap issues James Bottomley
2009-08-01 0:37 ` James Bottomley
2009-08-01 0:39 ` [PATCH 1/3] ses: fix hotplug with multiple devices and expanders James Bottomley
2009-08-01 0:41 ` James Bottomley [this message]
2009-08-01 0:43 ` ses: update enclosure data on hot add James Bottomley
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1249087282.3922.515.camel@mulgrave.site \
--to=james.bottomley@hansenpartnership.com \
--cc=chris.ptacek@arrisi.com \
--cc=dave.romrell@arrisi.com \
--cc=linux-scsi@vger.kernel.org \
--cc=michael.galassi@arrisi.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox