linux/drivers/scsi/device_handler/scsi_dh_rdac.c
<<
>>
Prefs
   1/*
   2 * Engenio/LSI RDAC SCSI Device Handler
   3 *
   4 * Copyright (C) 2005 Mike Christie. All rights reserved.
   5 * Copyright (C) Chandra Seetharaman, IBM Corp. 2007
   6 *
   7 * This program is free software; you can redistribute it and/or modify
   8 * it under the terms of the GNU General Public License as published by
   9 * the Free Software Foundation; either version 2 of the License, or
  10 * (at your option) any later version.
  11 *
  12 * This program is distributed in the hope that it will be useful,
  13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15 * GNU General Public License for more details.
  16 *
  17 * You should have received a copy of the GNU General Public License
  18 * along with this program; if not, write to the Free Software
  19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  20 *
  21 */
  22#include <scsi/scsi.h>
  23#include <scsi/scsi_eh.h>
  24#include <scsi/scsi_dh.h>
  25
  26#define RDAC_NAME "rdac"
  27
  28/*
  29 * LSI mode page stuff
  30 *
  31 * These struct definitions and the forming of the
  32 * mode page were taken from the LSI RDAC 2.4 GPL'd
  33 * driver, and then converted to Linux conventions.
  34 */
  35#define RDAC_QUIESCENCE_TIME 20;
  36/*
  37 * Page Codes
  38 */
  39#define RDAC_PAGE_CODE_REDUNDANT_CONTROLLER 0x2c
  40
  41/*
  42 * Controller modes definitions
  43 */
  44#define RDAC_MODE_TRANSFER_SPECIFIED_LUNS       0x02
  45
  46/*
  47 * RDAC Options field
  48 */
  49#define RDAC_FORCED_QUIESENCE 0x02
  50
  51#define RDAC_TIMEOUT    (60 * HZ)
  52#define RDAC_RETRIES    3
  53
  54struct rdac_mode_6_hdr {
  55        u8      data_len;
  56        u8      medium_type;
  57        u8      device_params;
  58        u8      block_desc_len;
  59};
  60
  61struct rdac_mode_10_hdr {
  62        u16     data_len;
  63        u8      medium_type;
  64        u8      device_params;
  65        u16     reserved;
  66        u16     block_desc_len;
  67};
  68
  69struct rdac_mode_common {
  70        u8      controller_serial[16];
  71        u8      alt_controller_serial[16];
  72        u8      rdac_mode[2];
  73        u8      alt_rdac_mode[2];
  74        u8      quiescence_timeout;
  75        u8      rdac_options;
  76};
  77
  78struct rdac_pg_legacy {
  79        struct rdac_mode_6_hdr hdr;
  80        u8      page_code;
  81        u8      page_len;
  82        struct rdac_mode_common common;
  83#define MODE6_MAX_LUN   32
  84        u8      lun_table[MODE6_MAX_LUN];
  85        u8      reserved2[32];
  86        u8      reserved3;
  87        u8      reserved4;
  88};
  89
  90struct rdac_pg_expanded {
  91        struct rdac_mode_10_hdr hdr;
  92        u8      page_code;
  93        u8      subpage_code;
  94        u8      page_len[2];
  95        struct rdac_mode_common common;
  96        u8      lun_table[256];
  97        u8      reserved3;
  98        u8      reserved4;
  99};
 100
 101struct c9_inquiry {
 102        u8      peripheral_info;
 103        u8      page_code;      /* 0xC9 */
 104        u8      reserved1;
 105        u8      page_len;
 106        u8      page_id[4];     /* "vace" */
 107        u8      avte_cvp;
 108        u8      path_prio;
 109        u8      reserved2[38];
 110};
 111
 112#define SUBSYS_ID_LEN   16
 113#define SLOT_ID_LEN     2
 114
 115struct c4_inquiry {
 116        u8      peripheral_info;
 117        u8      page_code;      /* 0xC4 */
 118        u8      reserved1;
 119        u8      page_len;
 120        u8      page_id[4];     /* "subs" */
 121        u8      subsys_id[SUBSYS_ID_LEN];
 122        u8      revision[4];
 123        u8      slot_id[SLOT_ID_LEN];
 124        u8      reserved[2];
 125};
 126
 127struct rdac_controller {
 128        u8                      subsys_id[SUBSYS_ID_LEN];
 129        u8                      slot_id[SLOT_ID_LEN];
 130        int                     use_ms10;
 131        struct kref             kref;
 132        struct list_head        node; /* list of all controllers */
 133        union                   {
 134                struct rdac_pg_legacy legacy;
 135                struct rdac_pg_expanded expanded;
 136        } mode_select;
 137};
 138struct c8_inquiry {
 139        u8      peripheral_info;
 140        u8      page_code; /* 0xC8 */
 141        u8      reserved1;
 142        u8      page_len;
 143        u8      page_id[4]; /* "edid" */
 144        u8      reserved2[3];
 145        u8      vol_uniq_id_len;
 146        u8      vol_uniq_id[16];
 147        u8      vol_user_label_len;
 148        u8      vol_user_label[60];
 149        u8      array_uniq_id_len;
 150        u8      array_unique_id[16];
 151        u8      array_user_label_len;
 152        u8      array_user_label[60];
 153        u8      lun[8];
 154};
 155
 156struct c2_inquiry {
 157        u8      peripheral_info;
 158        u8      page_code;      /* 0xC2 */
 159        u8      reserved1;
 160        u8      page_len;
 161        u8      page_id[4];     /* "swr4" */
 162        u8      sw_version[3];
 163        u8      sw_date[3];
 164        u8      features_enabled;
 165        u8      max_lun_supported;
 166        u8      partitions[239]; /* Total allocation length should be 0xFF */
 167};
 168
 169struct rdac_dh_data {
 170        struct rdac_controller  *ctlr;
 171#define UNINITIALIZED_LUN       (1 << 8)
 172        unsigned                lun;
 173#define RDAC_STATE_ACTIVE       0
 174#define RDAC_STATE_PASSIVE      1
 175        unsigned char           state;
 176
 177#define RDAC_LUN_UNOWNED        0
 178#define RDAC_LUN_OWNED          1
 179#define RDAC_LUN_AVT            2
 180        char                    lun_state;
 181        unsigned char           sense[SCSI_SENSE_BUFFERSIZE];
 182        union                   {
 183                struct c2_inquiry c2;
 184                struct c4_inquiry c4;
 185                struct c8_inquiry c8;
 186                struct c9_inquiry c9;
 187        } inq;
 188};
 189
 190static const char *lun_state[] =
 191{
 192        "unowned",
 193        "owned",
 194        "owned (AVT mode)",
 195};
 196
 197static LIST_HEAD(ctlr_list);
 198static DEFINE_SPINLOCK(list_lock);
 199
 200static inline struct rdac_dh_data *get_rdac_data(struct scsi_device *sdev)
 201{
 202        struct scsi_dh_data *scsi_dh_data = sdev->scsi_dh_data;
 203        BUG_ON(scsi_dh_data == NULL);
 204        return ((struct rdac_dh_data *) scsi_dh_data->buf);
 205}
 206
 207static struct request *get_rdac_req(struct scsi_device *sdev,
 208                        void *buffer, unsigned buflen, int rw)
 209{
 210        struct request *rq;
 211        struct request_queue *q = sdev->request_queue;
 212
 213        rq = blk_get_request(q, rw, GFP_NOIO);
 214
 215        if (!rq) {
 216                sdev_printk(KERN_INFO, sdev,
 217                                "get_rdac_req: blk_get_request failed.\n");
 218                return NULL;
 219        }
 220
 221        if (buflen && blk_rq_map_kern(q, rq, buffer, buflen, GFP_NOIO)) {
 222                blk_put_request(rq);
 223                sdev_printk(KERN_INFO, sdev,
 224                                "get_rdac_req: blk_rq_map_kern failed.\n");
 225                return NULL;
 226        }
 227
 228        memset(rq->cmd, 0, BLK_MAX_CDB);
 229
 230        rq->cmd_type = REQ_TYPE_BLOCK_PC;
 231        rq->cmd_flags |= REQ_FAILFAST | REQ_NOMERGE;
 232        rq->retries = RDAC_RETRIES;
 233        rq->timeout = RDAC_TIMEOUT;
 234
 235        return rq;
 236}
 237
 238static struct request *rdac_failover_get(struct scsi_device *sdev,
 239                                         struct rdac_dh_data *h)
 240{
 241        struct request *rq;
 242        struct rdac_mode_common *common;
 243        unsigned data_size;
 244
 245        if (h->ctlr->use_ms10) {
 246                struct rdac_pg_expanded *rdac_pg;
 247
 248                data_size = sizeof(struct rdac_pg_expanded);
 249                rdac_pg = &h->ctlr->mode_select.expanded;
 250                memset(rdac_pg, 0, data_size);
 251                common = &rdac_pg->common;
 252                rdac_pg->page_code = RDAC_PAGE_CODE_REDUNDANT_CONTROLLER + 0x40;
 253                rdac_pg->subpage_code = 0x1;
 254                rdac_pg->page_len[0] = 0x01;
 255                rdac_pg->page_len[1] = 0x28;
 256                rdac_pg->lun_table[h->lun] = 0x81;
 257        } else {
 258                struct rdac_pg_legacy *rdac_pg;
 259
 260                data_size = sizeof(struct rdac_pg_legacy);
 261                rdac_pg = &h->ctlr->mode_select.legacy;
 262                memset(rdac_pg, 0, data_size);
 263                common = &rdac_pg->common;
 264                rdac_pg->page_code = RDAC_PAGE_CODE_REDUNDANT_CONTROLLER;
 265                rdac_pg->page_len = 0x68;
 266                rdac_pg->lun_table[h->lun] = 0x81;
 267        }
 268        common->rdac_mode[1] = RDAC_MODE_TRANSFER_SPECIFIED_LUNS;
 269        common->quiescence_timeout = RDAC_QUIESCENCE_TIME;
 270        common->rdac_options = RDAC_FORCED_QUIESENCE;
 271
 272        /* get request for block layer packet command */
 273        rq = get_rdac_req(sdev, &h->ctlr->mode_select, data_size, WRITE);
 274        if (!rq)
 275                return NULL;
 276
 277        /* Prepare the command. */
 278        if (h->ctlr->use_ms10) {
 279                rq->cmd[0] = MODE_SELECT_10;
 280                rq->cmd[7] = data_size >> 8;
 281                rq->cmd[8] = data_size & 0xff;
 282        } else {
 283                rq->cmd[0] = MODE_SELECT;
 284                rq->cmd[4] = data_size;
 285        }
 286        rq->cmd_len = COMMAND_SIZE(rq->cmd[0]);
 287
 288        rq->sense = h->sense;
 289        memset(rq->sense, 0, SCSI_SENSE_BUFFERSIZE);
 290        rq->sense_len = 0;
 291
 292        return rq;
 293}
 294
 295static void release_controller(struct kref *kref)
 296{
 297        struct rdac_controller *ctlr;
 298        ctlr = container_of(kref, struct rdac_controller, kref);
 299
 300        spin_lock(&list_lock);
 301        list_del(&ctlr->node);
 302        spin_unlock(&list_lock);
 303        kfree(ctlr);
 304}
 305
 306static struct rdac_controller *get_controller(u8 *subsys_id, u8 *slot_id)
 307{
 308        struct rdac_controller *ctlr, *tmp;
 309
 310        spin_lock(&list_lock);
 311
 312        list_for_each_entry(tmp, &ctlr_list, node) {
 313                if ((memcmp(tmp->subsys_id, subsys_id, SUBSYS_ID_LEN) == 0) &&
 314                          (memcmp(tmp->slot_id, slot_id, SLOT_ID_LEN) == 0)) {
 315                        kref_get(&tmp->kref);
 316                        spin_unlock(&list_lock);
 317                        return tmp;
 318                }
 319        }
 320        ctlr = kmalloc(sizeof(*ctlr), GFP_ATOMIC);
 321        if (!ctlr)
 322                goto done;
 323
 324        /* initialize fields of controller */
 325        memcpy(ctlr->subsys_id, subsys_id, SUBSYS_ID_LEN);
 326        memcpy(ctlr->slot_id, slot_id, SLOT_ID_LEN);
 327        kref_init(&ctlr->kref);
 328        ctlr->use_ms10 = -1;
 329        list_add(&ctlr->node, &ctlr_list);
 330done:
 331        spin_unlock(&list_lock);
 332        return ctlr;
 333}
 334
 335static int submit_inquiry(struct scsi_device *sdev, int page_code,
 336                          unsigned int len, struct rdac_dh_data *h)
 337{
 338        struct request *rq;
 339        struct request_queue *q = sdev->request_queue;
 340        int err = SCSI_DH_RES_TEMP_UNAVAIL;
 341
 342        rq = get_rdac_req(sdev, &h->inq, len, READ);
 343        if (!rq)
 344                goto done;
 345
 346        /* Prepare the command. */
 347        rq->cmd[0] = INQUIRY;
 348        rq->cmd[1] = 1;
 349        rq->cmd[2] = page_code;
 350        rq->cmd[4] = len;
 351        rq->cmd_len = COMMAND_SIZE(INQUIRY);
 352
 353        rq->sense = h->sense;
 354        memset(rq->sense, 0, SCSI_SENSE_BUFFERSIZE);
 355        rq->sense_len = 0;
 356
 357        err = blk_execute_rq(q, NULL, rq, 1);
 358        if (err == -EIO)
 359                err = SCSI_DH_IO;
 360
 361        blk_put_request(rq);
 362done:
 363        return err;
 364}
 365
 366static int get_lun(struct scsi_device *sdev, struct rdac_dh_data *h)
 367{
 368        int err;
 369        struct c8_inquiry *inqp;
 370
 371        err = submit_inquiry(sdev, 0xC8, sizeof(struct c8_inquiry), h);
 372        if (err == SCSI_DH_OK) {
 373                inqp = &h->inq.c8;
 374                if (inqp->page_code != 0xc8)
 375                        return SCSI_DH_NOSYS;
 376                if (inqp->page_id[0] != 'e' || inqp->page_id[1] != 'd' ||
 377                    inqp->page_id[2] != 'i' || inqp->page_id[3] != 'd')
 378                        return SCSI_DH_NOSYS;
 379                h->lun = inqp->lun[7]; /* Uses only the last byte */
 380        }
 381        return err;
 382}
 383
 384static int check_ownership(struct scsi_device *sdev, struct rdac_dh_data *h)
 385{
 386        int err;
 387        struct c9_inquiry *inqp;
 388
 389        h->lun_state = RDAC_LUN_UNOWNED;
 390        err = submit_inquiry(sdev, 0xC9, sizeof(struct c9_inquiry), h);
 391        if (err == SCSI_DH_OK) {
 392                inqp = &h->inq.c9;
 393                if ((inqp->avte_cvp >> 7) == 0x1) {
 394                        /* LUN in AVT mode */
 395                        sdev_printk(KERN_NOTICE, sdev,
 396                                    "%s: AVT mode detected\n",
 397                                    RDAC_NAME);
 398                        h->lun_state = RDAC_LUN_AVT;
 399                } else if ((inqp->avte_cvp & 0x1) != 0) {
 400                        /* LUN was owned by the controller */
 401                        h->lun_state = RDAC_LUN_OWNED;
 402                }
 403        }
 404
 405        return err;
 406}
 407
 408static int initialize_controller(struct scsi_device *sdev,
 409                                 struct rdac_dh_data *h)
 410{
 411        int err;
 412        struct c4_inquiry *inqp;
 413
 414        err = submit_inquiry(sdev, 0xC4, sizeof(struct c4_inquiry), h);
 415        if (err == SCSI_DH_OK) {
 416                inqp = &h->inq.c4;
 417                h->ctlr = get_controller(inqp->subsys_id, inqp->slot_id);
 418                if (!h->ctlr)
 419                        err = SCSI_DH_RES_TEMP_UNAVAIL;
 420        }
 421        return err;
 422}
 423
 424static int set_mode_select(struct scsi_device *sdev, struct rdac_dh_data *h)
 425{
 426        int err;
 427        struct c2_inquiry *inqp;
 428
 429        err = submit_inquiry(sdev, 0xC2, sizeof(struct c2_inquiry), h);
 430        if (err == SCSI_DH_OK) {
 431                inqp = &h->inq.c2;
 432                /*
 433                 * If more than MODE6_MAX_LUN luns are supported, use
 434                 * mode select 10
 435                 */
 436                if (inqp->max_lun_supported >= MODE6_MAX_LUN)
 437                        h->ctlr->use_ms10 = 1;
 438                else
 439                        h->ctlr->use_ms10 = 0;
 440        }
 441        return err;
 442}
 443
 444static int mode_select_handle_sense(struct scsi_device *sdev,
 445                                    unsigned char *sensebuf)
 446{
 447        struct scsi_sense_hdr sense_hdr;
 448        int sense, err = SCSI_DH_IO, ret;
 449
 450        ret = scsi_normalize_sense(sensebuf, SCSI_SENSE_BUFFERSIZE, &sense_hdr);
 451        if (!ret)
 452                goto done;
 453
 454        err = SCSI_DH_OK;
 455        sense = (sense_hdr.sense_key << 16) | (sense_hdr.asc << 8) |
 456                        sense_hdr.ascq;
 457        /* If it is retryable failure, submit the c9 inquiry again */
 458        if (sense == 0x59136 || sense == 0x68b02 || sense == 0xb8b02 ||
 459                            sense == 0x62900) {
 460                /* 0x59136    - Command lock contention
 461                 * 0x[6b]8b02 - Quiesense in progress or achieved
 462                 * 0x62900    - Power On, Reset, or Bus Device Reset
 463                 */
 464                err = SCSI_DH_RETRY;
 465        }
 466
 467        if (sense)
 468                sdev_printk(KERN_INFO, sdev,
 469                        "MODE_SELECT failed with sense 0x%x.\n", sense);
 470done:
 471        return err;
 472}
 473
 474static int send_mode_select(struct scsi_device *sdev, struct rdac_dh_data *h)
 475{
 476        struct request *rq;
 477        struct request_queue *q = sdev->request_queue;
 478        int err = SCSI_DH_RES_TEMP_UNAVAIL;
 479
 480        rq = rdac_failover_get(sdev, h);
 481        if (!rq)
 482                goto done;
 483
 484        sdev_printk(KERN_INFO, sdev, "queueing MODE_SELECT command.\n");
 485
 486        err = blk_execute_rq(q, NULL, rq, 1);
 487        if (err != SCSI_DH_OK)
 488                err = mode_select_handle_sense(sdev, h->sense);
 489        if (err == SCSI_DH_OK)
 490                h->state = RDAC_STATE_ACTIVE;
 491
 492        blk_put_request(rq);
 493done:
 494        return err;
 495}
 496
 497static int rdac_activate(struct scsi_device *sdev)
 498{
 499        struct rdac_dh_data *h = get_rdac_data(sdev);
 500        int err = SCSI_DH_OK;
 501
 502        err = check_ownership(sdev, h);
 503        if (err != SCSI_DH_OK)
 504                goto done;
 505
 506        if (!h->ctlr) {
 507                err = initialize_controller(sdev, h);
 508                if (err != SCSI_DH_OK)
 509                        goto done;
 510        }
 511
 512        if (h->ctlr->use_ms10 == -1) {
 513                err = set_mode_select(sdev, h);
 514                if (err != SCSI_DH_OK)
 515                        goto done;
 516        }
 517        if (h->lun_state == RDAC_LUN_UNOWNED)
 518                err = send_mode_select(sdev, h);
 519done:
 520        return err;
 521}
 522
 523static int rdac_prep_fn(struct scsi_device *sdev, struct request *req)
 524{
 525        struct rdac_dh_data *h = get_rdac_data(sdev);
 526        int ret = BLKPREP_OK;
 527
 528        if (h->state != RDAC_STATE_ACTIVE) {
 529                ret = BLKPREP_KILL;
 530                req->cmd_flags |= REQ_QUIET;
 531        }
 532        return ret;
 533
 534}
 535
 536static int rdac_check_sense(struct scsi_device *sdev,
 537                                struct scsi_sense_hdr *sense_hdr)
 538{
 539        struct rdac_dh_data *h = get_rdac_data(sdev);
 540        switch (sense_hdr->sense_key) {
 541        case NOT_READY:
 542                if (sense_hdr->asc == 0x04 && sense_hdr->ascq == 0x81)
 543                        /* LUN Not Ready - Storage firmware incompatible
 544                         * Manual code synchonisation required.
 545                         *
 546                         * Nothing we can do here. Try to bypass the path.
 547                         */
 548                        return SUCCESS;
 549                if (sense_hdr->asc == 0x04 && sense_hdr->ascq == 0xA1)
 550                        /* LUN Not Ready - Quiescense in progress
 551                         *
 552                         * Just retry and wait.
 553                         */
 554                        return ADD_TO_MLQUEUE;
 555                break;
 556        case ILLEGAL_REQUEST:
 557                if (sense_hdr->asc == 0x94 && sense_hdr->ascq == 0x01) {
 558                        /* Invalid Request - Current Logical Unit Ownership.
 559                         * Controller is not the current owner of the LUN,
 560                         * Fail the path, so that the other path be used.
 561                         */
 562                        h->state = RDAC_STATE_PASSIVE;
 563                        return SUCCESS;
 564                }
 565                break;
 566        case UNIT_ATTENTION:
 567                if (sense_hdr->asc == 0x29 && sense_hdr->ascq == 0x00)
 568                        /*
 569                         * Power On, Reset, or Bus Device Reset, just retry.
 570                         */
 571                        return ADD_TO_MLQUEUE;
 572                break;
 573        }
 574        /* success just means we do not care what scsi-ml does */
 575        return SCSI_RETURN_NOT_HANDLED;
 576}
 577
 578static const struct scsi_dh_devlist rdac_dev_list[] = {
 579        {"IBM", "1722"},
 580        {"IBM", "1724"},
 581        {"IBM", "1726"},
 582        {"IBM", "1742"},
 583        {"IBM", "1814"},
 584        {"IBM", "1815"},
 585        {"IBM", "1818"},
 586        {"IBM", "3526"},
 587        {"SGI", "TP9400"},
 588        {"SGI", "TP9500"},
 589        {"SGI", "IS"},
 590        {"STK", "OPENstorage D280"},
 591        {"SUN", "CSM200_R"},
 592        {"SUN", "LCSM100_F"},
 593        {"DELL", "MD3000"},
 594        {"DELL", "MD3000i"},
 595        {NULL, NULL},
 596};
 597
 598static int rdac_bus_attach(struct scsi_device *sdev);
 599static void rdac_bus_detach(struct scsi_device *sdev);
 600
 601static struct scsi_device_handler rdac_dh = {
 602        .name = RDAC_NAME,
 603        .module = THIS_MODULE,
 604        .devlist = rdac_dev_list,
 605        .prep_fn = rdac_prep_fn,
 606        .check_sense = rdac_check_sense,
 607        .attach = rdac_bus_attach,
 608        .detach = rdac_bus_detach,
 609        .activate = rdac_activate,
 610};
 611
 612static int rdac_bus_attach(struct scsi_device *sdev)
 613{
 614        struct scsi_dh_data *scsi_dh_data;
 615        struct rdac_dh_data *h;
 616        unsigned long flags;
 617        int err;
 618
 619        scsi_dh_data = kzalloc(sizeof(struct scsi_device_handler *)
 620                               + sizeof(*h) , GFP_KERNEL);
 621        if (!scsi_dh_data) {
 622                sdev_printk(KERN_ERR, sdev, "%s: Attach failed\n",
 623                            RDAC_NAME);
 624                return 0;
 625        }
 626
 627        scsi_dh_data->scsi_dh = &rdac_dh;
 628        h = (struct rdac_dh_data *) scsi_dh_data->buf;
 629        h->lun = UNINITIALIZED_LUN;
 630        h->state = RDAC_STATE_ACTIVE;
 631
 632        err = get_lun(sdev, h);
 633        if (err != SCSI_DH_OK)
 634                goto failed;
 635
 636        err = check_ownership(sdev, h);
 637        if (err != SCSI_DH_OK)
 638                goto failed;
 639
 640        if (!try_module_get(THIS_MODULE))
 641                goto failed;
 642
 643        spin_lock_irqsave(sdev->request_queue->queue_lock, flags);
 644        sdev->scsi_dh_data = scsi_dh_data;
 645        spin_unlock_irqrestore(sdev->request_queue->queue_lock, flags);
 646
 647        sdev_printk(KERN_NOTICE, sdev,
 648                    "%s: LUN %d (%s)\n",
 649                    RDAC_NAME, h->lun, lun_state[(int)h->lun_state]);
 650
 651        return 0;
 652
 653failed:
 654        kfree(scsi_dh_data);
 655        sdev_printk(KERN_ERR, sdev, "%s: not attached\n",
 656                    RDAC_NAME);
 657        return -EINVAL;
 658}
 659
 660static void rdac_bus_detach( struct scsi_device *sdev )
 661{
 662        struct scsi_dh_data *scsi_dh_data;
 663        struct rdac_dh_data *h;
 664        unsigned long flags;
 665
 666        spin_lock_irqsave(sdev->request_queue->queue_lock, flags);
 667        scsi_dh_data = sdev->scsi_dh_data;
 668        sdev->scsi_dh_data = NULL;
 669        spin_unlock_irqrestore(sdev->request_queue->queue_lock, flags);
 670
 671        h = (struct rdac_dh_data *) scsi_dh_data->buf;
 672        if (h->ctlr)
 673                kref_put(&h->ctlr->kref, release_controller);
 674        kfree(scsi_dh_data);
 675        module_put(THIS_MODULE);
 676        sdev_printk(KERN_NOTICE, sdev, "%s: Detached\n", RDAC_NAME);
 677}
 678
 679
 680
 681static int __init rdac_init(void)
 682{
 683        int r;
 684
 685        r = scsi_register_device_handler(&rdac_dh);
 686        if (r != 0)
 687                printk(KERN_ERR "Failed to register scsi device handler.");
 688        return r;
 689}
 690
 691static void __exit rdac_exit(void)
 692{
 693        scsi_unregister_device_handler(&rdac_dh);
 694}
 695
 696module_init(rdac_init);
 697module_exit(rdac_exit);
 698
 699MODULE_DESCRIPTION("Multipath LSI/Engenio RDAC driver");
 700MODULE_AUTHOR("Mike Christie, Chandra Seetharaman");
 701MODULE_LICENSE("GPL");
 702
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.