forked from mirrors/linux
		
	[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,20 +332,26 @@ 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]; | ||||
| 
 | ||||
| 	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(cdev->dev); | ||||
| 			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
	
	 James Bottomley
						James Bottomley