[SCSI] scsi_dh: Implement match callback function
[deliverable/linux.git] / drivers / scsi / device_handler / scsi_dh.c
index 0119b814779744ccfc448bceddcaac3a7e195fcc..3ac71cf6b7f0e9427cacbf16a8fec4872fa80016 100644 (file)
@@ -59,6 +59,46 @@ static struct scsi_device_handler *get_device_handler_by_idx(int idx)
        return found;
 }
 
+/*
+ * device_handler_match_function - Match a device handler to a device
+ * @sdev - SCSI device to be tested
+ *
+ * Tests @sdev against the match function of all registered device_handler.
+ * Returns the found device handler or NULL if not found.
+ */
+static struct scsi_device_handler *
+device_handler_match_function(struct scsi_device *sdev)
+{
+       struct scsi_device_handler *tmp_dh, *found_dh = NULL;
+
+       spin_lock(&list_lock);
+       list_for_each_entry(tmp_dh, &scsi_dh_list, list) {
+               if (tmp_dh->match && tmp_dh->match(sdev)) {
+                       found_dh = tmp_dh;
+                       break;
+               }
+       }
+       spin_unlock(&list_lock);
+       return found_dh;
+}
+
+/*
+ * device_handler_match_devlist - Match a device handler to a device
+ * @sdev - SCSI device to be tested
+ *
+ * Tests @sdev against all device_handler registered in the devlist.
+ * Returns the found device handler or NULL if not found.
+ */
+static struct scsi_device_handler *
+device_handler_match_devlist(struct scsi_device *sdev)
+{
+       int idx;
+
+       idx = scsi_get_device_flags_keyed(sdev, sdev->vendor, sdev->model,
+                                         SCSI_DEVINFO_DH);
+       return get_device_handler_by_idx(idx);
+}
+
 /*
  * device_handler_match - Attach a device handler to a device
  * @scsi_dh - The device handler to match against or NULL
@@ -72,12 +112,11 @@ static struct scsi_device_handler *
 device_handler_match(struct scsi_device_handler *scsi_dh,
                     struct scsi_device *sdev)
 {
-       struct scsi_device_handler *found_dh = NULL;
-       int idx;
+       struct scsi_device_handler *found_dh;
 
-       idx = scsi_get_device_flags_keyed(sdev, sdev->vendor, sdev->model,
-                                         SCSI_DEVINFO_DH);
-       found_dh = get_device_handler_by_idx(idx);
+       found_dh = device_handler_match_function(sdev);
+       if (!found_dh)
+               found_dh = device_handler_match_devlist(sdev);
 
        if (scsi_dh && found_dh != scsi_dh)
                found_dh = NULL;
@@ -327,7 +366,7 @@ int scsi_register_device_handler(struct scsi_device_handler *scsi_dh)
        list_add(&scsi_dh->list, &scsi_dh_list);
        spin_unlock(&list_lock);
 
-       for (i = 0; scsi_dh->devlist[i].vendor; i++) {
+       for (i = 0; scsi_dh->devlist && scsi_dh->devlist[i].vendor; i++) {
                scsi_dev_info_list_add_keyed(0,
                                        scsi_dh->devlist[i].vendor,
                                        scsi_dh->devlist[i].model,
@@ -360,7 +399,7 @@ int scsi_unregister_device_handler(struct scsi_device_handler *scsi_dh)
        bus_for_each_dev(&scsi_bus_type, NULL, scsi_dh,
                         scsi_dh_notifier_remove);
 
-       for (i = 0; scsi_dh->devlist[i].vendor; i++) {
+       for (i = 0; scsi_dh->devlist && scsi_dh->devlist[i].vendor; i++) {
                scsi_dev_info_list_del_keyed(scsi_dh->devlist[i].vendor,
                                             scsi_dh->devlist[i].model,
                                             SCSI_DEVINFO_DH);
@@ -468,7 +507,7 @@ int scsi_dh_handler_exist(const char *name)
 EXPORT_SYMBOL_GPL(scsi_dh_handler_exist);
 
 /*
- * scsi_dh_handler_attach - Attach device handler
+ * scsi_dh_attach - Attach device handler
  * @sdev - sdev the handler should be attached to
  * @name - name of the handler to attach
  */
@@ -498,7 +537,7 @@ int scsi_dh_attach(struct request_queue *q, const char *name)
 EXPORT_SYMBOL_GPL(scsi_dh_attach);
 
 /*
- * scsi_dh_handler_detach - Detach device handler
+ * scsi_dh_detach - Detach device handler
  * @sdev - sdev the handler should be detached from
  *
  * This function will detach the device handler only
This page took 0.027975 seconds and 5 git commands to generate.