2  * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
 
   4  * This file is released under the GPL.
 
   6  * Multipath hardware handler registration.
 
  10 #include "dm-hw-handler.h"
 
  12 #include <linux/slab.h>
 
  15         struct hw_handler_type hwht;
 
  17         struct list_head list;
 
  21 #define hwht_to_hwhi(__hwht) container_of((__hwht), struct hwh_internal, hwht)
 
  23 static LIST_HEAD(_hw_handlers);
 
  24 static DECLARE_RWSEM(_hwh_lock);
 
  26 static struct hwh_internal *__find_hw_handler_type(const char *name)
 
  28         struct hwh_internal *hwhi;
 
  30         list_for_each_entry(hwhi, &_hw_handlers, list) {
 
  31                 if (!strcmp(name, hwhi->hwht.name))
 
  38 static struct hwh_internal *get_hw_handler(const char *name)
 
  40         struct hwh_internal *hwhi;
 
  42         down_read(&_hwh_lock);
 
  43         hwhi = __find_hw_handler_type(name);
 
  45                 if ((hwhi->use == 0) && !try_module_get(hwhi->hwht.module))
 
  55 struct hw_handler_type *dm_get_hw_handler(const char *name)
 
  57         struct hwh_internal *hwhi;
 
  62         hwhi = get_hw_handler(name);
 
  64                 request_module("dm-%s", name);
 
  65                 hwhi = get_hw_handler(name);
 
  68         return hwhi ? &hwhi->hwht : NULL;
 
  71 void dm_put_hw_handler(struct hw_handler_type *hwht)
 
  73         struct hwh_internal *hwhi;
 
  78         down_read(&_hwh_lock);
 
  79         hwhi = __find_hw_handler_type(hwht->name);
 
  84                 module_put(hwhi->hwht.module);
 
  93 static struct hwh_internal *_alloc_hw_handler(struct hw_handler_type *hwht)
 
  95         struct hwh_internal *hwhi = kmalloc(sizeof(*hwhi), GFP_KERNEL);
 
  98                 memset(hwhi, 0, sizeof(*hwhi));
 
 105 int dm_register_hw_handler(struct hw_handler_type *hwht)
 
 108         struct hwh_internal *hwhi = _alloc_hw_handler(hwht);
 
 113         down_write(&_hwh_lock);
 
 115         if (__find_hw_handler_type(hwht->name)) {
 
 119                 list_add(&hwhi->list, &_hw_handlers);
 
 121         up_write(&_hwh_lock);
 
 126 int dm_unregister_hw_handler(struct hw_handler_type *hwht)
 
 128         struct hwh_internal *hwhi;
 
 130         down_write(&_hwh_lock);
 
 132         hwhi = __find_hw_handler_type(hwht->name);
 
 134                 up_write(&_hwh_lock);
 
 139                 up_write(&_hwh_lock);
 
 143         list_del(&hwhi->list);
 
 145         up_write(&_hwh_lock);
 
 152 unsigned dm_scsi_err_handler(struct hw_handler *hwh, struct bio *bio)
 
 155         int sense_key, asc, ascq;
 
 157         if (bio->bi_error & BIO_SENSE) {
 
 158                 /* FIXME: This is just an initial guess. */
 
 159                 /* key / asc / ascq */
 
 160                 sense_key = (bio->bi_error >> 16) & 0xff;
 
 161                 asc = (bio->bi_error >> 8) & 0xff;
 
 162                 ascq = bio->bi_error & 0xff;
 
 165                         /* This block as a whole comes from the device.
 
 166                          * So no point retrying on another path. */
 
 167                 case 0x03:      /* Medium error */
 
 168                 case 0x05:      /* Illegal request */
 
 169                 case 0x07:      /* Data protect */
 
 170                 case 0x08:      /* Blank check */
 
 171                 case 0x0a:      /* copy aborted */
 
 172                 case 0x0c:      /* obsolete - no clue ;-) */
 
 173                 case 0x0d:      /* volume overflow */
 
 174                 case 0x0e:      /* data miscompare */
 
 175                 case 0x0f:      /* reserved - no idea either. */
 
 178                         /* For these errors it's unclear whether they
 
 179                          * come from the device or the controller.
 
 180                          * So just lets try a different path, and if
 
 181                          * it eventually succeeds, user-space will clear
 
 182                          * the paths again... */
 
 183                 case 0x02:      /* Not ready */
 
 184                 case 0x04:      /* Hardware error */
 
 185                 case 0x09:      /* vendor specific */
 
 186                 case 0x0b:      /* Aborted command */
 
 189                 case 0x06:      /* Unit attention - might want to decode */
 
 190                         if (asc == 0x04 && ascq == 0x01)
 
 191                                 /* "Unit in the process of
 
 196                         /* FIXME: For Unit Not Ready we may want
 
 197                          * to have a generic pg activation
 
 198                          * feature (START_UNIT). */
 
 200                         /* Should these two ever end up in the
 
 201                          * error path? I don't think so. */
 
 202                 case 0x00:      /* No sense */
 
 203                 case 0x01:      /* Recovered error */
 
 209         /* We got no idea how to decode the other kinds of errors ->
 
 210          * assume generic error condition. */
 
 214 EXPORT_SYMBOL_GPL(dm_register_hw_handler);
 
 215 EXPORT_SYMBOL_GPL(dm_unregister_hw_handler);
 
 216 EXPORT_SYMBOL_GPL(dm_scsi_err_handler);