aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/device_handler/scsi_dh_rdac.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/device_handler/scsi_dh_rdac.c')
-rw-r--r--drivers/scsi/device_handler/scsi_dh_rdac.c72
1 files changed, 55 insertions, 17 deletions
diff --git a/drivers/scsi/device_handler/scsi_dh_rdac.c b/drivers/scsi/device_handler/scsi_dh_rdac.c
index 293c183dfe6d..e7fc70d6b478 100644
--- a/drivers/scsi/device_handler/scsi_dh_rdac.c
+++ b/drivers/scsi/device_handler/scsi_dh_rdac.c
@@ -182,14 +182,24 @@ struct rdac_dh_data {
struct rdac_controller *ctlr;
#define UNINITIALIZED_LUN (1 << 8)
unsigned lun;
+
+#define RDAC_MODE 0
+#define RDAC_MODE_AVT 1
+#define RDAC_MODE_IOSHIP 2
+ unsigned char mode;
+
#define RDAC_STATE_ACTIVE 0
#define RDAC_STATE_PASSIVE 1
unsigned char state;
#define RDAC_LUN_UNOWNED 0
#define RDAC_LUN_OWNED 1
-#define RDAC_LUN_AVT 2
char lun_state;
+
+#define RDAC_PREFERRED 0
+#define RDAC_NON_PREFERRED 1
+ char preferred;
+
unsigned char sense[SCSI_SENSE_BUFFERSIZE];
union {
struct c2_inquiry c2;
@@ -199,11 +209,15 @@ struct rdac_dh_data {
} inq;
};
+static const char *mode[] = {
+ "RDAC",
+ "AVT",
+ "IOSHIP",
+};
static const char *lun_state[] =
{
"unowned",
"owned",
- "owned (AVT mode)",
};
struct rdac_queue_data {
@@ -458,25 +472,33 @@ static int check_ownership(struct scsi_device *sdev, struct rdac_dh_data *h)
int err;
struct c9_inquiry *inqp;
- h->lun_state = RDAC_LUN_UNOWNED;
h->state = RDAC_STATE_ACTIVE;
err = submit_inquiry(sdev, 0xC9, sizeof(struct c9_inquiry), h);
if (err == SCSI_DH_OK) {
inqp = &h->inq.c9;
- 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 */
+ /* detect the operating mode */
+ if ((inqp->avte_cvp >> 5) & 0x1)
+ h->mode = RDAC_MODE_IOSHIP; /* LUN in IOSHIP mode */
+ else if (inqp->avte_cvp >> 7)
+ h->mode = RDAC_MODE_AVT; /* LUN in AVT mode */
+ else
+ h->mode = RDAC_MODE; /* LUN in RDAC mode */
+
+ /* Update ownership */
+ if (inqp->avte_cvp & 0x1)
h->lun_state = RDAC_LUN_OWNED;
+ else {
+ h->lun_state = RDAC_LUN_UNOWNED;
+ if (h->mode == RDAC_MODE)
+ h->state = RDAC_STATE_PASSIVE;
}
- }
- if (h->lun_state == RDAC_LUN_UNOWNED)
- h->state = RDAC_STATE_PASSIVE;
+ /* Update path prio*/
+ if (inqp->path_prio & 0x1)
+ h->preferred = RDAC_PREFERRED;
+ else
+ h->preferred = RDAC_NON_PREFERRED;
+ }
return err;
}
@@ -648,12 +670,27 @@ static int rdac_activate(struct scsi_device *sdev,
{
struct rdac_dh_data *h = get_rdac_data(sdev);
int err = SCSI_DH_OK;
+ int act = 0;
err = check_ownership(sdev, h);
if (err != SCSI_DH_OK)
goto done;
- if (h->lun_state == RDAC_LUN_UNOWNED) {
+ switch (h->mode) {
+ case RDAC_MODE:
+ if (h->lun_state == RDAC_LUN_UNOWNED)
+ act = 1;
+ break;
+ case RDAC_MODE_IOSHIP:
+ if ((h->lun_state == RDAC_LUN_UNOWNED) &&
+ (h->preferred == RDAC_PREFERRED))
+ act = 1;
+ break;
+ default:
+ break;
+ }
+
+ if (act) {
err = queue_mode_select(sdev, fn, data);
if (err == SCSI_DH_OK)
return 0;
@@ -836,8 +873,9 @@ static int rdac_bus_attach(struct scsi_device *sdev)
spin_unlock_irqrestore(sdev->request_queue->queue_lock, flags);
sdev_printk(KERN_NOTICE, sdev,
- "%s: LUN %d (%s)\n",
- RDAC_NAME, h->lun, lun_state[(int)h->lun_state]);
+ "%s: LUN %d (%s) (%s)\n",
+ RDAC_NAME, h->lun, mode[(int)h->mode],
+ lun_state[(int)h->lun_state]);
return 0;