mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 02:30:34 +02:00 
			
		
		
		
	[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: James Bottomley <James.Bottomley@HansenPartnership.com> Signed-off-by: James Bottomley <James.Bottomley@suse.de>
This commit is contained in:
		
							parent
							
								
									163f52b6cf
								
							
						
					
					
						commit
						43d8eb9cfd
					
				
					 3 changed files with 41 additions and 16 deletions
				
			
		| 
						 | 
				
			
			@ -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);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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 *),
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue