extern int scsi_scan_host_selected(struct Scsi_Host *, unsigned int,
unsigned int, unsigned int, int);
extern void scsi_forget_host(struct Scsi_Host *);
-extern void scsi_free_sdev(struct scsi_device *);
extern void scsi_rescan_device(struct device *);
/* scsi_sysctl.c */
#endif /* CONFIG_SYSCTL */
/* scsi_sysfs.c */
-extern int scsi_device_register(struct scsi_device *);
+extern void scsi_device_dev_release(struct device *);
+extern int scsi_sysfs_add_sdev(struct scsi_device *);
extern int scsi_sysfs_add_host(struct Scsi_Host *);
extern int scsi_sysfs_register(void);
extern void scsi_sysfs_unregister(void);
goto out_free_queue;
}
+ if (get_device(&sdev->host->shost_gendev)) {
+
+ device_initialize(&sdev->sdev_gendev);
+ sdev->sdev_gendev.parent = &sdev->host->shost_gendev;
+ sdev->sdev_gendev.bus = &scsi_bus_type;
+ sdev->sdev_gendev.release = scsi_device_dev_release;
+ sprintf(sdev->sdev_gendev.bus_id,"%d:%d:%d:%d",
+ sdev->host->host_no, sdev->channel, sdev->id,
+ sdev->lun);
+
+ class_device_initialize(&sdev->sdev_classdev);
+ sdev->sdev_classdev.dev = &sdev->sdev_gendev;
+ sdev->sdev_classdev.class = &sdev_class;
+ snprintf(sdev->sdev_classdev.class_id, BUS_ID_SIZE,
+ "%d:%d:%d:%d", sdev->host->host_no,
+ sdev->channel, sdev->id, sdev->lun);
+ } else
+ goto out_free_queue;
+
/*
* If there are any same target siblings, add this to the
* sibling list
return NULL;
}
-/**
- * scsi_free_sdev - cleanup and free a scsi_device
- * @sdev: cleanup and free this scsi_device
- *
- * Description:
- * Undo the actions in scsi_alloc_sdev, including removing @sdev from
- * the list, and freeing @sdev.
- **/
-void scsi_free_sdev(struct scsi_device *sdev)
-{
- unsigned long flags;
-
- spin_lock_irqsave(sdev->host->host_lock, flags);
- list_del(&sdev->siblings);
- list_del(&sdev->same_target_siblings);
- spin_unlock_irqrestore(sdev->host->host_lock, flags);
-
- if (sdev->request_queue)
- scsi_free_queue(sdev->request_queue);
-
- spin_lock_irqsave(sdev->host->host_lock, flags);
- list_del(&sdev->starved_entry);
- if (sdev->single_lun && --sdev->sdev_target->starget_refcnt == 0)
- kfree(sdev->sdev_target);
- spin_unlock_irqrestore(sdev->host->host_lock, flags);
-
- kfree(sdev->inquiry);
- kfree(sdev);
-}
-
/**
* scsi_probe_lun - probe a single LUN using a SCSI INQUIRY
* @sreq: used to send the INQUIRY
* register it and tell the rest of the kernel
* about it.
*/
- scsi_device_register(sdev);
+ scsi_sysfs_add_sdev(sdev);
return SCSI_SCAN_LUN_PRESENT;
}
if (res == SCSI_SCAN_LUN_PRESENT) {
if (sdevp)
*sdevp = sdev;
- } else
- scsi_free_sdev(sdev);
+ } else {
+ if (sdev->host->hostt->slave_destroy)
+ sdev->host->hostt->slave_destroy(sdev);
+ put_device(&sdev->sdev_gendev);
+ }
out:
return res;
}
void scsi_free_host_dev(struct scsi_device *sdev)
{
BUG_ON(sdev->id != sdev->host->this_id);
- scsi_free_sdev(sdev);
+
+ if (sdev->host->hostt->slave_destroy)
+ sdev->host->hostt->slave_destroy(sdev);
+ put_device(&sdev->sdev_gendev);
}
put_device(&sdev->sdev_gendev);
}
-static void scsi_device_dev_release(struct device *dev)
+void scsi_device_dev_release(struct device *dev)
{
struct scsi_device *sdev;
struct device *parent;
+ unsigned long flags;
parent = dev->parent;
sdev = to_scsi_device(dev);
- scsi_free_sdev(sdev);
+
+ spin_lock_irqsave(sdev->host->host_lock, flags);
+ list_del(&sdev->siblings);
+ list_del(&sdev->same_target_siblings);
+ list_del(&sdev->starved_entry);
+ if (sdev->single_lun && --sdev->sdev_target->starget_refcnt == 0)
+ kfree(sdev->sdev_target);
+ spin_unlock_irqrestore(sdev->host->host_lock, flags);
+
+ if (sdev->request_queue)
+ scsi_free_queue(sdev->request_queue);
+
+ kfree(sdev->inquiry);
+ kfree(sdev);
+
put_device(parent);
}
}
/**
- * scsi_device_register - register a scsi device with the scsi bus
- * @sdev: scsi_device to register
+ * scsi_sysfs_add_sdev - add scsi device to sysfs
+ * @sdev: scsi_device to add
*
* Return value:
* 0 on Success / non-zero on Failure
**/
-int scsi_device_register(struct scsi_device *sdev)
+int scsi_sysfs_add_sdev(struct scsi_device *sdev)
{
- int error = 0, i;
-
- set_bit(SDEV_ADD, &sdev->sdev_state);
- device_initialize(&sdev->sdev_gendev);
- sprintf(sdev->sdev_gendev.bus_id,"%d:%d:%d:%d",
- sdev->host->host_no, sdev->channel, sdev->id, sdev->lun);
- sdev->sdev_gendev.parent = &sdev->host->shost_gendev;
- sdev->sdev_gendev.bus = &scsi_bus_type;
- sdev->sdev_gendev.release = scsi_device_dev_release;
-
- class_device_initialize(&sdev->sdev_classdev);
- sdev->sdev_classdev.dev = &sdev->sdev_gendev;
- sdev->sdev_classdev.class = &sdev_class;
- snprintf(sdev->sdev_classdev.class_id, BUS_ID_SIZE, "%d:%d:%d:%d",
- sdev->host->host_no, sdev->channel, sdev->id, sdev->lun);
+ int error = -EINVAL, i;
+
+ if (test_and_set_bit(SDEV_ADD, &sdev->sdev_state))
+ return error;
error = device_add(&sdev->sdev_gendev);
if (error) {
return error;
}
- get_device(sdev->sdev_gendev.parent);
-
error = class_device_add(&sdev->sdev_classdev);
if (error) {
printk(KERN_INFO "error 2\n");
**/
void scsi_remove_device(struct scsi_device *sdev)
{
- class_device_unregister(&sdev->sdev_classdev);
- set_bit(SDEV_DEL, &sdev->sdev_state);
- if (sdev->host->hostt->slave_destroy)
- sdev->host->hostt->slave_destroy(sdev);
- device_del(&sdev->sdev_gendev);
- put_device(&sdev->sdev_gendev);
+ if (test_and_clear_bit(SDEV_ADD, &sdev->sdev_state)) {
+ set_bit(SDEV_DEL, &sdev->sdev_state);
+ class_device_unregister(&sdev->sdev_classdev);
+ device_del(&sdev->sdev_gendev);
+ if (sdev->host->hostt->slave_destroy)
+ sdev->host->hostt->slave_destroy(sdev);
+ put_device(&sdev->sdev_gendev);
+ }
}
int scsi_register_driver(struct device_driver *drv)