Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 43d8eb9c authored by James Bottomley's avatar James Bottomley Committed by James Bottomley
Browse files

[SCSI] ses: add support for enclosure component hot removal



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

Signed-off-by: default avatarJames Bottomley <James.Bottomley@HansenPartnership.com>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@suse.de>
parent 163f52b6
Loading
Loading
Loading
Loading
+14 −8
Original line number Original line Diff line number Diff line
@@ -332,20 +332,26 @@ EXPORT_SYMBOL_GPL(enclosure_add_device);
 * Returns zero on success or an error.
 * 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;
	struct enclosure_component *cdev;
	int i;


	if (!edev || component >= edev->components)
	if (!edev || !dev)
		return -EINVAL;
		return -EINVAL;


	cdev = &edev->component[component];
	for (i = 0; i < edev->components; i++) {

		cdev = &edev->component[i];
		if (cdev->dev == dev) {
			enclosure_remove_links(cdev);
			device_del(&cdev->cdev);
			device_del(&cdev->cdev);
	put_device(cdev->dev);
			put_device(dev);
			cdev->dev = NULL;
			cdev->dev = NULL;
			return device_add(&cdev->cdev);
			return device_add(&cdev->cdev);
		}
		}
	}
	return -ENODEV;
}
EXPORT_SYMBOL_GPL(enclosure_remove_device);
EXPORT_SYMBOL_GPL(enclosure_remove_device);


/*
/*
+26 −7
Original line number Original line Diff line number Diff line
@@ -616,18 +616,26 @@ static int ses_remove(struct device *dev)
	return 0;
	return 0;
}
}


static void ses_intf_remove(struct device *cdev,
static void ses_intf_remove_component(struct scsi_device *sdev)
			    struct class_interface *intf)
{
	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 enclosure_device *edev;
	struct ses_device *ses_dev;
	struct ses_device *ses_dev;


	if (!scsi_device_enclosure(sdev))
		return;

	/*  exact match to this enclosure */
	/*  exact match to this enclosure */
	edev = enclosure_find(cdev->parent, NULL);
	edev = enclosure_find(&sdev->sdev_gendev, NULL);
	if (!edev)
	if (!edev)
		return;
		return;


@@ -645,6 +653,17 @@ static void ses_intf_remove(struct device *cdev,
	enclosure_unregister(edev);
	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 = {
static struct class_interface ses_interface = {
	.add_dev	= ses_intf_add,
	.add_dev	= ses_intf_add,
	.remove_dev	= ses_intf_remove,
	.remove_dev	= ses_intf_remove,
+1 −1
Original line number Original line Diff line number Diff line
@@ -122,7 +122,7 @@ enclosure_component_register(struct enclosure_device *, unsigned int,
				 enum enclosure_component_type, const char *);
				 enum enclosure_component_type, const char *);
int enclosure_add_device(struct enclosure_device *enclosure, int component,
int enclosure_add_device(struct enclosure_device *enclosure, int component,
			 struct device *dev);
			 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 *enclosure_find(struct device *dev,
					struct enclosure_device *start);
					struct enclosure_device *start);
int enclosure_for_each_device(int (*fn)(struct enclosure_device *, void *),
int enclosure_for_each_device(int (*fn)(struct enclosure_device *, void *),