Add a dedicated ALUA driver which can be used for native SCSI multipath
and also DH-based ALUA support.

Only core functions to submit a RTPG, STPG, tur, and also helper functions
are added.

The code from scsi_dh_alua.c to maintain the port groups is not added,
because it is quite intertwined with the DH code. However the port group
management code would be quite useful.

Hannes Reinecke originally authored this code.

Signed-off-by: John Garry <[email protected]>
---
 drivers/scsi/Kconfig                       |   9 +
 drivers/scsi/Makefile                      |   1 +
 drivers/scsi/device_handler/Kconfig        |   1 +
 drivers/scsi/device_handler/scsi_dh_alua.c | 198 +-------------------
 drivers/scsi/scsi_alua.c                   | 204 +++++++++++++++++++++
 include/scsi/scsi_alua.h                   |  50 +++++
 6 files changed, 269 insertions(+), 194 deletions(-)
 create mode 100644 drivers/scsi/scsi_alua.c
 create mode 100644 include/scsi/scsi_alua.h

diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
index cfab7ad1e3c2c..1a538c84ddf0a 100644
--- a/drivers/scsi/Kconfig
+++ b/drivers/scsi/Kconfig
@@ -86,6 +86,15 @@ config SCSI_MULTIPATH
 
          If unsure say N.
 
+config SCSI_ALUA
+       tristate "SPC-3 ALUA support"
+       depends on SCSI
+       help
+         SCSI support for generic SPC-3 Asymmetric Logical Unit
+         Access (ALUA).
+
+         If unsure, say Y.
+
 comment "SCSI support type (disk, tape, CD-ROM)"
        depends on SCSI
 
diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile
index 64b7a82828b81..053fb51d98092 100644
--- a/drivers/scsi/Makefile
+++ b/drivers/scsi/Makefile
@@ -153,6 +153,7 @@ obj-$(CONFIG_SCSI_ENCLOSURE)        += ses.o
 
 obj-$(CONFIG_SCSI_HISI_SAS) += hisi_sas/
 
+obj-$(CONFIG_SCSI_ALUA) += scsi_alua.o
 # This goes last, so that "real" scsi devices probe earlier
 obj-$(CONFIG_SCSI_DEBUG)       += scsi_debug.o
 scsi_mod-y                     += scsi.o hosts.o scsi_ioctl.o \
diff --git a/drivers/scsi/device_handler/Kconfig 
b/drivers/scsi/device_handler/Kconfig
index 368eb94c24562..ff06aea8c272c 100644
--- a/drivers/scsi/device_handler/Kconfig
+++ b/drivers/scsi/device_handler/Kconfig
@@ -35,6 +35,7 @@ config SCSI_DH_EMC
 config SCSI_DH_ALUA
        tristate "SPC-3 ALUA Device Handler"
        depends on SCSI_DH && SCSI
+       select SCSI_ALUA
        help
          SCSI Device handler for generic SPC-3 Asymmetric Logical Unit
          Access (ALUA).
diff --git a/drivers/scsi/device_handler/scsi_dh_alua.c 
b/drivers/scsi/device_handler/scsi_dh_alua.c
index e9edd45ae28a3..42fa6bf8bb480 100644
--- a/drivers/scsi/device_handler/scsi_dh_alua.c
+++ b/drivers/scsi/device_handler/scsi_dh_alua.c
@@ -14,31 +14,11 @@
 #include <scsi/scsi_dbg.h>
 #include <scsi/scsi_eh.h>
 #include <scsi/scsi_dh.h>
+#include <scsi/scsi_alua.h>
 
 #define ALUA_DH_NAME "alua"
 #define ALUA_DH_VER "2.0"
 
-#define TPGS_SUPPORT_NONE              0x00
-#define TPGS_SUPPORT_OPTIMIZED         0x01
-#define TPGS_SUPPORT_NONOPTIMIZED      0x02
-#define TPGS_SUPPORT_STANDBY           0x04
-#define TPGS_SUPPORT_UNAVAILABLE       0x08
-#define TPGS_SUPPORT_LBA_DEPENDENT     0x10
-#define TPGS_SUPPORT_OFFLINE           0x40
-#define TPGS_SUPPORT_TRANSITION                0x80
-#define TPGS_SUPPORT_ALL               0xdf
-
-#define RTPG_FMT_MASK                  0x70
-#define RTPG_FMT_EXT_HDR               0x10
-
-#define TPGS_MODE_UNINITIALIZED                 -1
-#define TPGS_MODE_NONE                 0x0
-#define TPGS_MODE_IMPLICIT             0x1
-#define TPGS_MODE_EXPLICIT             0x2
-
-#define ALUA_RTPG_SIZE                 128
-#define ALUA_FAILOVER_TIMEOUT          60
-#define ALUA_FAILOVER_RETRIES          5
 #define ALUA_RTPG_DELAY_MSECS          5
 #define ALUA_RTPG_RETRY_DELAY          2
 
@@ -119,70 +99,6 @@ static void release_port_group(struct kref *kref)
        kfree_rcu(pg, rcu);
 }
 
-/*
- * submit_rtpg - Issue a REPORT TARGET GROUP STATES command
- * @sdev: sdev the command should be sent to
- */
-static int submit_rtpg(struct scsi_device *sdev, unsigned char *buff,
-                      int bufflen, struct scsi_sense_hdr *sshdr,
-                      bool ext_hdr_unsupp)
-{
-       u8 cdb[MAX_COMMAND_SIZE];
-       blk_opf_t opf = REQ_OP_DRV_IN | REQ_FAILFAST_DEV |
-                               REQ_FAILFAST_TRANSPORT | REQ_FAILFAST_DRIVER;
-       const struct scsi_exec_args exec_args = {
-               .sshdr = sshdr,
-       };
-
-       /* Prepare the command. */
-       memset(cdb, 0x0, MAX_COMMAND_SIZE);
-       cdb[0] = MAINTENANCE_IN;
-       if (ext_hdr_unsupp)
-               cdb[1] = MI_REPORT_TARGET_PGS;
-       else
-               cdb[1] = MI_REPORT_TARGET_PGS | MI_EXT_HDR_PARAM_FMT;
-       put_unaligned_be32(bufflen, &cdb[6]);
-
-       return scsi_execute_cmd(sdev, cdb, opf, buff, bufflen,
-                               ALUA_FAILOVER_TIMEOUT * HZ,
-                               ALUA_FAILOVER_RETRIES, &exec_args);
-}
-
-/*
- * submit_stpg - Issue a SET TARGET PORT GROUP command
- *
- * Currently we're only setting the current target port group state
- * to 'active/optimized' and let the array firmware figure out
- * the states of the remaining groups.
- */
-static int submit_stpg(struct scsi_device *sdev, int group_id,
-                      struct scsi_sense_hdr *sshdr)
-{
-       u8 cdb[MAX_COMMAND_SIZE];
-       unsigned char stpg_data[8];
-       int stpg_len = 8;
-       blk_opf_t opf = REQ_OP_DRV_OUT | REQ_FAILFAST_DEV |
-                               REQ_FAILFAST_TRANSPORT | REQ_FAILFAST_DRIVER;
-       const struct scsi_exec_args exec_args = {
-               .sshdr = sshdr,
-       };
-
-       /* Prepare the data buffer */
-       memset(stpg_data, 0, stpg_len);
-       stpg_data[4] = SCSI_ACCESS_STATE_OPTIMAL;
-       put_unaligned_be16(group_id, &stpg_data[6]);
-
-       /* Prepare the command. */
-       memset(cdb, 0x0, MAX_COMMAND_SIZE);
-       cdb[0] = MAINTENANCE_OUT;
-       cdb[1] = MO_SET_TARGET_PGS;
-       put_unaligned_be32(stpg_len, &cdb[6]);
-
-       return scsi_execute_cmd(sdev, cdb, opf, stpg_data,
-                               stpg_len, ALUA_FAILOVER_TIMEOUT * HZ,
-                               ALUA_FAILOVER_RETRIES, &exec_args);
-}
-
 static struct alua_port_group *alua_find_get_pg(char *id_str, size_t id_size,
                                                int group_id)
 {
@@ -265,58 +181,6 @@ static struct alua_port_group *alua_alloc_pg(struct 
scsi_device *sdev,
        return pg;
 }
 
-/*
- * alua_check_tpgs - Evaluate TPGS setting
- * @sdev: device to be checked
- *
- * Examine the TPGS setting of the sdev to find out if ALUA
- * is supported.
- */
-static int alua_check_tpgs(struct scsi_device *sdev)
-{
-       int tpgs = TPGS_MODE_NONE;
-
-       /*
-        * ALUA support for non-disk devices is fraught with
-        * difficulties, so disable it for now.
-        */
-       if (sdev->type != TYPE_DISK) {
-               sdev_printk(KERN_INFO, sdev,
-                           "%s: disable for non-disk devices\n",
-                           ALUA_DH_NAME);
-               return tpgs;
-       }
-
-       tpgs = scsi_device_tpgs(sdev);
-       switch (tpgs) {
-       case TPGS_MODE_EXPLICIT|TPGS_MODE_IMPLICIT:
-               sdev_printk(KERN_INFO, sdev,
-                           "%s: supports implicit and explicit TPGS\n",
-                           ALUA_DH_NAME);
-               break;
-       case TPGS_MODE_EXPLICIT:
-               sdev_printk(KERN_INFO, sdev, "%s: supports explicit TPGS\n",
-                           ALUA_DH_NAME);
-               break;
-       case TPGS_MODE_IMPLICIT:
-               sdev_printk(KERN_INFO, sdev, "%s: supports implicit TPGS\n",
-                           ALUA_DH_NAME);
-               break;
-       case TPGS_MODE_NONE:
-               sdev_printk(KERN_INFO, sdev, "%s: not supported\n",
-                           ALUA_DH_NAME);
-               break;
-       default:
-               sdev_printk(KERN_INFO, sdev,
-                           "%s: unsupported TPGS setting %d\n",
-                           ALUA_DH_NAME, tpgs);
-               tpgs = TPGS_MODE_NONE;
-               break;
-       }
-
-       return tpgs;
-}
-
 /*
  * alua_check_vpd - Evaluate INQUIRY vpd page 0x83
  * @sdev: device to be checked
@@ -393,27 +257,6 @@ static int alua_check_vpd(struct scsi_device *sdev, struct 
alua_dh_data *h,
        return SCSI_DH_OK;
 }
 
-static char print_alua_state(unsigned char state)
-{
-       switch (state) {
-       case SCSI_ACCESS_STATE_OPTIMAL:
-               return 'A';
-       case SCSI_ACCESS_STATE_ACTIVE:
-               return 'N';
-       case SCSI_ACCESS_STATE_STANDBY:
-               return 'S';
-       case SCSI_ACCESS_STATE_UNAVAILABLE:
-               return 'U';
-       case SCSI_ACCESS_STATE_LBA:
-               return 'L';
-       case SCSI_ACCESS_STATE_OFFLINE:
-               return 'O';
-       case SCSI_ACCESS_STATE_TRANSITIONING:
-               return 'T';
-       default:
-               return 'X';
-       }
-}
 
 static void alua_handle_state_transition(struct scsi_device *sdev)
 {
@@ -500,30 +343,6 @@ static enum scsi_disposition alua_check_sense(struct 
scsi_device *sdev,
        return SCSI_RETURN_NOT_HANDLED;
 }
 
-/*
- * alua_tur - Send a TEST UNIT READY
- * @sdev: device to which the TEST UNIT READY command should be send
- *
- * Send a TEST UNIT READY to @sdev to figure out the device state
- * Returns SCSI_DH_RETRY if the sense code is NOT READY/ALUA TRANSITIONING,
- * SCSI_DH_OK if no error occurred, and SCSI_DH_IO otherwise.
- */
-static int alua_tur(struct scsi_device *sdev)
-{
-       struct scsi_sense_hdr sense_hdr;
-       int retval;
-
-       retval = scsi_test_unit_ready(sdev, ALUA_FAILOVER_TIMEOUT * HZ,
-                                     ALUA_FAILOVER_RETRIES, &sense_hdr);
-       if ((sense_hdr.sense_key == NOT_READY ||
-            sense_hdr.sense_key == UNIT_ATTENTION) &&
-           sense_hdr.asc == 0x04 && sense_hdr.ascq == 0x0a)
-               return SCSI_DH_RETRY;
-       else if (retval)
-               return SCSI_DH_IO;
-       else
-               return SCSI_DH_OK;
-}
 
 /*
  * alua_rtpg - Evaluate REPORT TARGET GROUP STATES
@@ -722,17 +541,8 @@ static int alua_rtpg(struct scsi_device *sdev, struct 
alua_port_group *pg)
 
        if (group_id_old != pg->group_id || state_old != pg->state ||
                pref_old != pg->pref || valid_states_old != pg->valid_states)
-               sdev_printk(KERN_INFO, sdev,
-                       "%s: port group %02x state %c %s supports 
%c%c%c%c%c%c%c\n",
-                       ALUA_DH_NAME, pg->group_id, print_alua_state(pg->state),
-                       pg->pref ? "preferred" : "non-preferred",
-                       pg->valid_states&TPGS_SUPPORT_TRANSITION?'T':'t',
-                       pg->valid_states&TPGS_SUPPORT_OFFLINE?'O':'o',
-                       pg->valid_states&TPGS_SUPPORT_LBA_DEPENDENT?'L':'l',
-                       pg->valid_states&TPGS_SUPPORT_UNAVAILABLE?'U':'u',
-                       pg->valid_states&TPGS_SUPPORT_STANDBY?'S':'s',
-                       pg->valid_states&TPGS_SUPPORT_NONOPTIMIZED?'N':'n',
-                       pg->valid_states&TPGS_SUPPORT_OPTIMIZED?'A':'a');
+               alua_print_info(sdev, pg->group_id, pg->state, pg->pref,
+                                               pg->valid_states);
 
        switch (pg->state) {
        case SCSI_ACCESS_STATE_TRANSITIONING:
@@ -911,7 +721,7 @@ static void alua_rtpg_work(struct work_struct *work)
                pg->flags &= ~ALUA_PG_RUN_RTPG;
                spin_unlock_irqrestore(&pg->lock, flags);
                if (state == SCSI_ACCESS_STATE_TRANSITIONING) {
-                       if (alua_tur(sdev) == SCSI_DH_RETRY) {
+                       if (alua_tur(sdev) == -EAGAIN) {
                                spin_lock_irqsave(&pg->lock, flags);
                                pg->flags &= ~ALUA_PG_RUNNING;
                                pg->flags |= ALUA_PG_RUN_RTPG;
diff --git a/drivers/scsi/scsi_alua.c b/drivers/scsi/scsi_alua.c
new file mode 100644
index 0000000000000..2e4102192dcb9
--- /dev/null
+++ b/drivers/scsi/scsi_alua.c
@@ -0,0 +1,204 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Generic SCSI-3 ALUA SCSI driver
+ *
+ * Copyright (C) 2007-2010 Hannes Reinecke, SUSE Linux Products GmbH.
+ * All rights reserved.
+ */
+
+#include <scsi/scsi.h>
+#include <scsi/scsi_proto.h>
+#include <scsi/scsi_dbg.h>
+#include <scsi/scsi_eh.h>
+#include <scsi/scsi_alua.h>
+
+#define DRV_NAME "alua"
+
+#define ALUA_FAILOVER_RETRIES          5
+
+/*
+ * alua_check_tpgs - Evaluate TPGS setting
+ * @sdev: device to be checked
+ *
+ * Examine the TPGS setting of the sdev to find out if ALUA
+ * is supported.
+ */
+int alua_check_tpgs(struct scsi_device *sdev)
+{
+       int tpgs = TPGS_MODE_NONE;
+
+       /*
+        * ALUA support for non-disk devices is fraught with
+        * difficulties, so disable it for now.
+        */
+       if (sdev->type != TYPE_DISK) {
+               sdev_printk(KERN_INFO, sdev,
+                           "%s: disable for non-disk devices\n",
+                           DRV_NAME);
+               return tpgs;
+       }
+
+       tpgs = scsi_device_tpgs(sdev);
+       switch (tpgs) {
+       case TPGS_MODE_EXPLICIT|TPGS_MODE_IMPLICIT:
+               sdev_printk(KERN_INFO, sdev,
+                           "%s: supports implicit and explicit TPGS\n",
+                           DRV_NAME);
+               break;
+       case TPGS_MODE_EXPLICIT:
+               sdev_printk(KERN_INFO, sdev, "%s: supports explicit TPGS\n",
+                           DRV_NAME);
+               break;
+       case TPGS_MODE_IMPLICIT:
+               sdev_printk(KERN_INFO, sdev, "%s: supports implicit TPGS\n",
+                           DRV_NAME);
+               break;
+       case TPGS_MODE_NONE:
+               sdev_printk(KERN_INFO, sdev, "%s: not supported\n",
+                           DRV_NAME);
+               break;
+       default:
+               sdev_printk(KERN_INFO, sdev,
+                           "%s: unsupported TPGS setting %d\n",
+                           DRV_NAME, tpgs);
+               tpgs = TPGS_MODE_NONE;
+               break;
+       }
+
+       return tpgs;
+}
+EXPORT_SYMBOL_GPL(alua_check_tpgs);
+
+/*
+ * alua_tur - Send a TEST UNIT READY
+ * @sdev: device to which the TEST UNIT READY command should be send
+ *
+ * Send a TEST UNIT READY to @sdev to figure out the device state
+ * Returns SCSI_DH_RETRY if the sense code is NOT READY/ALUA TRANSITIONING,
+ * 0 if no error occurred, and SCSI_DH_IO otherwise.
+ */
+int alua_tur(struct scsi_device *sdev)
+{
+       struct scsi_sense_hdr sense_hdr;
+       int retval;
+
+       retval = scsi_test_unit_ready(sdev, ALUA_FAILOVER_TIMEOUT * HZ,
+                                     ALUA_FAILOVER_RETRIES, &sense_hdr);
+       if ((sense_hdr.sense_key == NOT_READY ||
+            sense_hdr.sense_key == UNIT_ATTENTION) &&
+           sense_hdr.asc == 0x04 && sense_hdr.ascq == 0x0a)
+               return -EAGAIN;
+       else if (retval)
+               return -EIO;
+       else
+               return 0;
+}
+EXPORT_SYMBOL_GPL(alua_tur);
+
+/*
+ * submit_rtpg - Issue a REPORT TARGET GROUP STATES command
+ * @sdev: sdev the command should be sent to
+ */
+int submit_rtpg(struct scsi_device *sdev, unsigned char *buff,
+                      int bufflen, struct scsi_sense_hdr *sshdr,
+                      bool alua_rtpg_ext_hdr_unsupp)
+{
+       u8 cdb[MAX_COMMAND_SIZE];
+       blk_opf_t opf = REQ_OP_DRV_IN | REQ_FAILFAST_DEV |
+                               REQ_FAILFAST_TRANSPORT | REQ_FAILFAST_DRIVER;
+       const struct scsi_exec_args exec_args = {
+               .sshdr = sshdr,
+       };
+
+       /* Prepare the command. */
+       memset(cdb, 0x0, MAX_COMMAND_SIZE);
+       cdb[0] = MAINTENANCE_IN;
+       if (alua_rtpg_ext_hdr_unsupp)
+               cdb[1] = MI_REPORT_TARGET_PGS;
+       else
+               cdb[1] = MI_REPORT_TARGET_PGS | MI_EXT_HDR_PARAM_FMT;
+       put_unaligned_be32(bufflen, &cdb[6]);
+
+       return scsi_execute_cmd(sdev, cdb, opf, buff, bufflen,
+                               ALUA_FAILOVER_TIMEOUT * HZ,
+                               ALUA_FAILOVER_RETRIES, &exec_args);
+}
+EXPORT_SYMBOL_GPL(submit_rtpg);
+
+static char print_alua_state(unsigned char state)
+{
+       switch (state) {
+       case SCSI_ACCESS_STATE_OPTIMAL:
+               return 'A';
+       case SCSI_ACCESS_STATE_ACTIVE:
+               return 'N';
+       case SCSI_ACCESS_STATE_STANDBY:
+               return 'S';
+       case SCSI_ACCESS_STATE_UNAVAILABLE:
+               return 'U';
+       case SCSI_ACCESS_STATE_LBA:
+               return 'L';
+       case SCSI_ACCESS_STATE_OFFLINE:
+               return 'O';
+       case SCSI_ACCESS_STATE_TRANSITIONING:
+               return 'T';
+       default:
+               return 'X';
+       }
+}
+
+void alua_print_info(struct scsi_device *sdev, int group_id, int state,
+               int pref, int valid_states)
+{
+       sdev_printk(KERN_INFO, sdev,
+               "alua: port group %02x state %c %s supports %c%c%c%c%c%c%c\n",
+               group_id, print_alua_state(state),
+               pref ? "preferred" : "non-preferred",
+               valid_states&TPGS_SUPPORT_TRANSITION?'T':'t',
+               valid_states&TPGS_SUPPORT_OFFLINE?'O':'o',
+               valid_states&TPGS_SUPPORT_LBA_DEPENDENT?'L':'l',
+               valid_states&TPGS_SUPPORT_UNAVAILABLE?'U':'u',
+               valid_states&TPGS_SUPPORT_STANDBY?'S':'s',
+               valid_states&TPGS_SUPPORT_NONOPTIMIZED?'N':'n',
+               valid_states&TPGS_SUPPORT_OPTIMIZED?'A':'a');
+}
+EXPORT_SYMBOL_GPL(alua_print_info);
+
+/*
+ * submit_stpg - Issue a SET TARGET PORT GROUP command
+ *
+ * Currently we're only setting the current target port group state
+ * to 'active/optimized' and let the array firmware figure out
+ * the states of the remaining groups.
+ */
+int submit_stpg(struct scsi_device *sdev, int group_id,
+                      struct scsi_sense_hdr *sshdr)
+{
+       u8 cdb[MAX_COMMAND_SIZE];
+       unsigned char stpg_data[8];
+       int stpg_len = 8;
+       blk_opf_t opf = REQ_OP_DRV_OUT | REQ_FAILFAST_DEV |
+                               REQ_FAILFAST_TRANSPORT | REQ_FAILFAST_DRIVER;
+       const struct scsi_exec_args exec_args = {
+               .sshdr = sshdr,
+       };
+
+       /* Prepare the data buffer */
+       memset(stpg_data, 0, stpg_len);
+       stpg_data[4] = SCSI_ACCESS_STATE_OPTIMAL;
+       put_unaligned_be16(group_id, &stpg_data[6]);
+
+       /* Prepare the command. */
+       memset(cdb, 0x0, MAX_COMMAND_SIZE);
+       cdb[0] = MAINTENANCE_OUT;
+       cdb[1] = MO_SET_TARGET_PGS;
+       put_unaligned_be32(stpg_len, &cdb[6]);
+
+       return scsi_execute_cmd(sdev, cdb, opf, stpg_data,
+                               stpg_len, ALUA_FAILOVER_TIMEOUT * HZ,
+                               ALUA_FAILOVER_RETRIES, &exec_args);
+}
+EXPORT_SYMBOL_GPL(submit_stpg);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("scsi_alua");
diff --git a/include/scsi/scsi_alua.h b/include/scsi/scsi_alua.h
new file mode 100644
index 0000000000000..51b5ed1836c99
--- /dev/null
+++ b/include/scsi/scsi_alua.h
@@ -0,0 +1,50 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Generic SCSI-3 ALUA SCSI Device Handler
+ *
+ * Copyright (C) 2007-2010 Hannes Reinecke, SUSE Linux Products GmbH.
+ * All rights reserved.
+ */
+#ifndef _SCSI_ALUA_H
+#define _SCSI_ALUA_H
+
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/unaligned.h>
+#include <scsi/scsi.h>
+#include <scsi/scsi_proto.h>
+#include <scsi/scsi_dbg.h>
+#include <scsi/scsi_eh.h>
+
+#define TPGS_SUPPORT_NONE              0x00
+#define TPGS_SUPPORT_OPTIMIZED         0x01
+#define TPGS_SUPPORT_NONOPTIMIZED      0x02
+#define TPGS_SUPPORT_STANDBY           0x04
+#define TPGS_SUPPORT_UNAVAILABLE       0x08
+#define TPGS_SUPPORT_LBA_DEPENDENT     0x10
+#define TPGS_SUPPORT_OFFLINE           0x40
+#define TPGS_SUPPORT_TRANSITION                0x80
+#define TPGS_SUPPORT_ALL               0xdf
+
+#define RTPG_FMT_MASK                  0x70
+#define RTPG_FMT_EXT_HDR               0x10
+
+#define TPGS_MODE_UNINITIALIZED                 -1
+#define TPGS_MODE_NONE                 0x0
+#define TPGS_MODE_IMPLICIT             0x1
+#define TPGS_MODE_EXPLICIT             0x2
+
+#define ALUA_RTPG_SIZE                 128
+#define ALUA_FAILOVER_TIMEOUT          60
+
+int alua_check_tpgs(struct scsi_device *sdev);
+int submit_rtpg(struct scsi_device *sdev, unsigned char *buff,
+                      int bufflen, struct scsi_sense_hdr *sshdr,
+                      bool alua_rtpg_ext_hdr_unsupp);
+int alua_tur(struct scsi_device *sdev);
+void alua_print_info(struct scsi_device *sdev, int group_id, int state,
+               int pref, int valid_states);
+int submit_stpg(struct scsi_device *sdev, int group_id,
+                      struct scsi_sense_hdr *sshdr);
+#endif // _SCSI_ALUA_H
-- 
2.43.5


Reply via email to