diff --git a/drivers/scsi/device_handler/scsi_dh_rdac.c b/drivers/scsi/device_handler/scsi_dh_rdac.c index 0bd33ee..d163cd8 100644 --- a/drivers/scsi/device_handler/scsi_dh_rdac.c +++ b/drivers/scsi/device_handler/scsi_dh_rdac.c @@ -42,6 +42,7 @@ /* * Controller modes definitions */ +#define RDAC_MODE_TRANSFER_ALL_VISIBLE_LUNS 0x01 #define RDAC_MODE_TRANSFER_SPECIFIED_LUNS 0x02 /* @@ -178,6 +179,7 @@ struct rdac_dh_data { #define RDAC_LUN_UNOWNED 0 #define RDAC_LUN_OWNED 1 #define RDAC_LUN_AVT 2 +#define RDAC_LUN_PREF 4 char lun_state; unsigned char sense[SCSI_SENSE_BUFFERSIZE]; union { @@ -192,7 +194,12 @@ static const char *lun_state[] = { "unowned", "owned", - "owned (AVT mode)", + "unowned (AVT)", + "owned (AVT)", + "unowned (preferred)", + "owned (preferred)", + "unowned (preferred,AVT)", + "owned (preferred,AVT)", }; static LIST_HEAD(ctlr_list); @@ -253,7 +260,8 @@ static struct request *rdac_failover_get(struct scsi_device *sdev, rdac_pg->subpage_code = 0x1; rdac_pg->page_len[0] = 0x01; rdac_pg->page_len[1] = 0x28; - rdac_pg->lun_table[h->lun] = 0x81; + if (h->lun->state & RDAC_LUN_PREF) + rdac_pg->lun_table[h->lun] = 0x81; } else { struct rdac_pg_legacy *rdac_pg; @@ -263,9 +271,16 @@ static struct request *rdac_failover_get(struct scsi_device *sdev, common = &rdac_pg->common; rdac_pg->page_code = RDAC_PAGE_CODE_REDUNDANT_CONTROLLER; rdac_pg->page_len = 0x68; - rdac_pg->lun_table[h->lun] = 0x81; + if (h->lun_state & RDAC_LUN_PREF) + rdac_pg->lun_table[h->lun] = 0x81; } - common->rdac_mode[1] = RDAC_MODE_TRANSFER_SPECIFIED_LUNS; + if (h->lun_state & RDAC_LUN_PREF) + /* Failback mode; swith this LUN only */ + common->rdac_mode[1] = RDAC_MODE_TRANSFER_SPECIFIED_LUNS; + else + /* Failover mode; switch all LUNs */ + common->rdac_mode[1] = RDAC_MODE_TRANSFER_ALL_VISIBLE_LUNS; + common->quiescence_timeout = RDAC_QUIESCENCE_TIME; common->rdac_options = RDAC_FORCED_QUIESENCE; @@ -326,6 +341,7 @@ static struct rdac_controller *get_controller(u8 *subsys_id, u8 *slot_id) memcpy(ctlr->slot_id, slot_id, SLOT_ID_LEN); kref_init(&ctlr->kref); ctlr->use_ms10 = -1; + ctlr->transfer_all_luns = 1; list_add(&ctlr->node, &ctlr_list); done: spin_unlock(&list_lock); @@ -391,19 +407,24 @@ static int check_ownership(struct scsi_device *sdev, struct rdac_dh_data *h) err = submit_inquiry(sdev, 0xC9, sizeof(struct c9_inquiry), h); if (err == SCSI_DH_OK) { inqp = &h->inq.c9; + if ((inqp->avte_cvp & 0x1) != 0) { + /* LUN was owned by the controller */ + h->lun_state = RDAC_LUN_OWNED; + } if ((inqp->avte_cvp >> 7) == 0x1) { /* LUN in AVT mode */ sdev_printk(KERN_NOTICE, sdev, "%s: AVT mode detected\n", RDAC_NAME); - h->lun_state = RDAC_LUN_AVT; - } else if ((inqp->avte_cvp & 0x1) != 0) { - /* LUN was owned by the controller */ - h->lun_state = RDAC_LUN_OWNED; + h->lun_state |= RDAC_LUN_AVT; + } + if ((inqp->path_prio && 0xf) == 0x1) { + /* LUN access through preferred path */ + h->lun_state |= RDAC_LUN_PREF; } } - if (h->lun_state == RDAC_LUN_UNOWNED) + if ((h->lun_state & RDAC_LUN_OWNED) == 0) h->state = RDAC_STATE_PASSIVE; return err; @@ -537,7 +558,8 @@ static int rdac_activate(struct scsi_device *sdev) if (err != SCSI_DH_OK) goto done; } - if (h->lun_state == RDAC_LUN_UNOWNED) + if ((h->lun_state & RDAC_LUN_OWNED) == 0 && + (h->lun_state & RDAC_LUN_AVT) == 0 ) err = send_mode_select(sdev, h); done: return err;