18fe96085Stim szeto /*
28fe96085Stim szeto  * CDDL HEADER START
38fe96085Stim szeto  *
48fe96085Stim szeto  * The contents of this file are subject to the terms of the
58fe96085Stim szeto  * Common Development and Distribution License (the "License").
68fe96085Stim szeto  * You may not use this file except in compliance with the License.
78fe96085Stim szeto  *
88fe96085Stim szeto  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
98fe96085Stim szeto  * or http://www.opensolaris.org/os/licensing.
108fe96085Stim szeto  * See the License for the specific language governing permissions
118fe96085Stim szeto  * and limitations under the License.
128fe96085Stim szeto  *
138fe96085Stim szeto  * When distributing Covered Code, include this CDDL HEADER in each
148fe96085Stim szeto  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
158fe96085Stim szeto  * If applicable, add the following below this CDDL HEADER, with the
168fe96085Stim szeto  * fields enclosed by brackets "[]" replaced with your own identifying
178fe96085Stim szeto  * information: Portions Copyright [yyyy] [name of copyright owner]
188fe96085Stim szeto  *
198fe96085Stim szeto  * CDDL HEADER END
208fe96085Stim szeto  */
218fe96085Stim szeto /*
22f4e76ddfSNattuvetty Bhavyan  * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
23*61dfa509SRick McNeal  * Copyright 2014 Nexenta Systems, Inc.  All rights reserved.
248fe96085Stim szeto  */
258fe96085Stim szeto 
268fe96085Stim szeto #include <sys/atomic.h>
278fe96085Stim szeto #include <sys/conf.h>
288fe96085Stim szeto #include <sys/byteorder.h>
298fe96085Stim szeto #include <sys/scsi/scsi_types.h>
308fe96085Stim szeto #include <sys/scsi/generic/persist.h>
318fe96085Stim szeto 
324558d122SViswanathan Kannappan #include <sys/lpif.h>
334558d122SViswanathan Kannappan #include <sys/stmf.h>
344558d122SViswanathan Kannappan #include <sys/stmf_ioctl.h>
354558d122SViswanathan Kannappan #include <sys/portif.h>
364558d122SViswanathan Kannappan #include <sys/stmf_sbd_ioctl.h>
374558d122SViswanathan Kannappan 
384558d122SViswanathan Kannappan #include "stmf_sbd.h"
394558d122SViswanathan Kannappan #include "sbd_impl.h"
408fe96085Stim szeto 
418fe96085Stim szeto #define	MAX_PGR_PARAM_LIST_LENGTH	(256 * 1024)
428fe96085Stim szeto 
43*61dfa509SRick McNeal int  sbd_pgr_reservation_conflict(scsi_task_t *, struct sbd_lu *sl);
4445039663SJohn Forte void sbd_pgr_reset(sbd_lu_t *);
45f4e76ddfSNattuvetty Bhavyan void sbd_pgr_initialize_it(scsi_task_t *, sbd_it_data_t *);
468fe96085Stim szeto void sbd_handle_pgr_in_cmd(scsi_task_t *, stmf_data_buf_t *);
478fe96085Stim szeto void sbd_handle_pgr_out_cmd(scsi_task_t *, stmf_data_buf_t *);
488fe96085Stim szeto void sbd_handle_pgr_out_data(scsi_task_t *, stmf_data_buf_t *);
498fe96085Stim szeto void sbd_pgr_keylist_dealloc(sbd_lu_t *);
508fe96085Stim szeto char *sbd_get_devid_string(sbd_lu_t *);
518fe96085Stim szeto 
527145ae3eSNattuvetty Bhavyan sbd_status_t sbd_pgr_meta_init(sbd_lu_t *);
538fe96085Stim szeto sbd_status_t sbd_pgr_meta_load(sbd_lu_t *);
548fe96085Stim szeto sbd_status_t sbd_pgr_meta_write(sbd_lu_t *);
558fe96085Stim szeto static void sbd_swap_pgr_info(sbd_pgr_info_t *);
568fe96085Stim szeto static void sbd_swap_pgrkey_info(sbd_pgr_key_info_t *);
578fe96085Stim szeto static void sbd_pgr_key_free(sbd_pgr_key_t *);
588fe96085Stim szeto static void sbd_pgr_remove_key(sbd_lu_t *, sbd_pgr_key_t *);
598fe96085Stim szeto static uint32_t sbd_pgr_remove_keys(sbd_lu_t *, sbd_it_data_t *,
608fe96085Stim szeto 	sbd_pgr_key_t *, uint64_t, boolean_t);
618fe96085Stim szeto static boolean_t sbd_pgr_key_compare(sbd_pgr_key_t *, scsi_devid_desc_t *,
62716c1805SNattuvetty Bhavyan 	stmf_remote_port_t *);
638fe96085Stim szeto static sbd_pgr_key_t *sbd_pgr_key_alloc(scsi_devid_desc_t *,
64716c1805SNattuvetty Bhavyan 	scsi_transport_id_t *, int16_t, int16_t);
658fe96085Stim szeto 
668fe96085Stim szeto static void sbd_pgr_set_pgr_check_flag(sbd_lu_t *, boolean_t);
678fe96085Stim szeto static void sbd_pgr_set_ua_conditions(sbd_lu_t *, sbd_it_data_t *, uint8_t);
688fe96085Stim szeto static void sbd_pgr_in_read_keys(scsi_task_t *, stmf_data_buf_t *);
698fe96085Stim szeto static void sbd_pgr_in_report_capabilities(scsi_task_t *, stmf_data_buf_t *);
708fe96085Stim szeto static void sbd_pgr_in_read_reservation(scsi_task_t *, stmf_data_buf_t *);
718fe96085Stim szeto static void sbd_pgr_in_read_full_status(scsi_task_t *, stmf_data_buf_t *);
728fe96085Stim szeto static void sbd_pgr_out_register(scsi_task_t *, stmf_data_buf_t *);
738fe96085Stim szeto static void sbd_pgr_out_reserve(scsi_task_t *);
748fe96085Stim szeto static void sbd_pgr_out_release(scsi_task_t *);
758fe96085Stim szeto static void sbd_pgr_out_clear(scsi_task_t *);
768fe96085Stim szeto static void sbd_pgr_out_preempt(scsi_task_t *, stmf_data_buf_t *);
778fe96085Stim szeto static void sbd_pgr_out_register_and_move(scsi_task_t *, stmf_data_buf_t *);
788fe96085Stim szeto 
798fe96085Stim szeto static sbd_pgr_key_t *sbd_pgr_do_register(sbd_lu_t *, sbd_it_data_t *,
80716c1805SNattuvetty Bhavyan 	scsi_devid_desc_t *, stmf_remote_port_t *, uint8_t, uint64_t);
818fe96085Stim szeto static void sbd_pgr_do_unregister(sbd_lu_t *, sbd_it_data_t *, sbd_pgr_key_t *);
828fe96085Stim szeto static void sbd_pgr_do_release(sbd_lu_t *, sbd_it_data_t *, uint8_t);
838fe96085Stim szeto static void sbd_pgr_do_reserve(sbd_pgr_t *, sbd_pgr_key_t *, sbd_it_data_t *it,
848fe96085Stim szeto 	stmf_scsi_session_t *, scsi_cdb_prout_t *);
858fe96085Stim szeto 
86*61dfa509SRick McNeal static boolean_t sbd_pgr_should_save(sbd_lu_t *);
878fe96085Stim szeto extern sbd_status_t sbd_write_meta_section(sbd_lu_t *, sm_section_hdr_t *);
888fe96085Stim szeto extern sbd_status_t sbd_read_meta_section(sbd_lu_t *, sm_section_hdr_t **,
898fe96085Stim szeto 	uint16_t);
908fe96085Stim szeto extern void sbd_swap_section_hdr(sm_section_hdr_t *);
918fe96085Stim szeto extern void sbd_handle_short_write_transfers(scsi_task_t *task,
928fe96085Stim szeto 	stmf_data_buf_t *dbuf, uint32_t cdb_xfer_size);
938fe96085Stim szeto extern void sbd_handle_short_read_transfers(scsi_task_t *task,
948fe96085Stim szeto 	stmf_data_buf_t *dbuf, uint8_t *p, uint32_t cdb_xfer_size,
958fe96085Stim szeto 	uint32_t cmd_xfer_size);
968fe96085Stim szeto extern uint16_t stmf_scsilib_get_lport_rtid(scsi_devid_desc_t *devid);
978fe96085Stim szeto extern scsi_devid_desc_t *stmf_scsilib_get_devid_desc(uint16_t rtpid);
9870c284caSPeter Cudhea - Sun Microsystems - Burlington, MA United States extern char sbd_ctoi(char c);
998fe96085Stim szeto 
1008fe96085Stim szeto /*
1018fe96085Stim szeto  *
1028fe96085Stim szeto  *
1038fe96085Stim szeto  *   +-----------+
1048fe96085Stim szeto  *   |           |sl_it_list
1058fe96085Stim szeto  *   |           |---------------------------------------+
1068fe96085Stim szeto  *   |           |                                       |
1078fe96085Stim szeto  *   |  sbd_lu_t |                                       |
1088fe96085Stim szeto  *   |           |                                       |
1098fe96085Stim szeto  *   |           |                                       |
1108fe96085Stim szeto  *   |           |                                       |
1118fe96085Stim szeto  *   +-----+-----+                                       V
1128fe96085Stim szeto  *         |                                          +-------+
1138fe96085Stim szeto  *         V                                          |       |
1148fe96085Stim szeto  *   +-----------+ pgr_key_list               +------>|       |
1158fe96085Stim szeto  *   |           |------------+  +-->(NULL)   | +- ---|sbd_it |
1168fe96085Stim szeto  *   |           |            |  |            | |     | _data |
1178fe96085Stim szeto  *   | sbd_pgr_t |            V  |            | |     |       |
1188fe96085Stim szeto  *   |           |          +-------+         | |     +-------+
1198fe96085Stim szeto  *   |           |---+      |       |         | |         |
1208fe96085Stim szeto  *   |           |   |      |sbd_pgr|---------+ |         v
1218fe96085Stim szeto  *   +-----------+   |      | _key_t|<----------+     +-------+
1228fe96085Stim szeto  *                   |      |       |                 |       |
1238fe96085Stim szeto  *                   |      |       |                 |       |
1248fe96085Stim szeto  *                   |      +-------+        +--------|       |
1258fe96085Stim szeto  *                   |         |^            |        |       |
1268fe96085Stim szeto  *                   |         ||            |        |       |
1278fe96085Stim szeto  *                   |         v|            |        +-------+
1288fe96085Stim szeto  *                   |      +-------+        |            |
1298fe96085Stim szeto  *                   |      |       |        |            v
1308fe96085Stim szeto  *                   |      |ALL_TG_|<-------+        +-------+
1318fe96085Stim szeto  *                   |      |PT = 1 |<---------+      |       |
1328fe96085Stim szeto  *                   |      |       |---+      |      |       |
1338fe96085Stim szeto  *                   |      |       |   |      +------|       |
1348fe96085Stim szeto  *          (pgr_rsvholder  +-------+   V             |       |
1358fe96085Stim szeto  *             pgr_flags&      |^     (NUll)          |       |
1368fe96085Stim szeto  *              RSVD_ONE)      ||                     +-------+
1378fe96085Stim szeto  *                   |         v|                         |
1388fe96085Stim szeto  *                   |      +-------+                     v
1398fe96085Stim szeto  *                   |      |       |                 +-------+
1408fe96085Stim szeto  *                   |      |  not  |                 |       |
1418fe96085Stim szeto  *                   |      |claimed|---+             |       |
1428fe96085Stim szeto  *                   |      |       |   |        +----| unreg |
1438fe96085Stim szeto  *                   |      |       |   V        |    |       |
1448fe96085Stim szeto  *                   |      +-------+ (NUll)     V    |       |
1458fe96085Stim szeto  *                   |         |^              (NUll) +-------+
1468fe96085Stim szeto  *                   |         ||                         |
1478fe96085Stim szeto  *                   |         v|                         v
1488fe96085Stim szeto  *                   |      +-------+                 +-------+
1498fe96085Stim szeto  *                   |      |       |                 |       |
1508fe96085Stim szeto  *                   |      |reserv-|<----------------|       |
1518fe96085Stim szeto  *                   +----->|  ation|---------------->|       |
1528fe96085Stim szeto  *                          |holder |                 |       |
1538fe96085Stim szeto  *                          |key    |                 |       |
1548fe96085Stim szeto  *                          +-------+                 +-------+
1558fe96085Stim szeto  *                              |^                        |
1568fe96085Stim szeto  *                              ||                        v
1578fe96085Stim szeto  *                              v|                    +-------+
1588fe96085Stim szeto  *                           +-------+                |       |
1598fe96085Stim szeto  *                           |       |                |       |
1608fe96085Stim szeto  *                           |  not  |---+       +----| unreg |
1618fe96085Stim szeto  *                           |claimed|   |       |    |       |
1628fe96085Stim szeto  *                           |       |   V       V    |       |
1638fe96085Stim szeto  *                           |       | (NUll)  (NUll) +-------+
1648fe96085Stim szeto  *                           +-------+                    |
1658fe96085Stim szeto  *                              |                         v
1668fe96085Stim szeto  *                              v                      (NULL)
1678fe96085Stim szeto  *                           (NULL)
1688fe96085Stim szeto  *
1698fe96085Stim szeto  *
1708fe96085Stim szeto  */
1718fe96085Stim szeto 
1728fe96085Stim szeto #define	PGR_CONFLICT_FREE_CMDS(cdb)	( \
1738fe96085Stim szeto 	/* ----------------------- */                                      \
1748fe96085Stim szeto 	/* SPC-3 (rev 23) Table 31 */                                      \
1758fe96085Stim szeto 	/* ----------------------- */                                      \
1768fe96085Stim szeto 	((cdb[0]) == SCMD_INQUIRY)					|| \
1778fe96085Stim szeto 	((cdb[0]) == SCMD_LOG_SENSE_G1)					|| \
1788fe96085Stim szeto 	((cdb[0]) == SCMD_PERSISTENT_RESERVE_IN)			|| \
1798fe96085Stim szeto 	((cdb[0]) == SCMD_REPORT_LUNS)					|| \
1808fe96085Stim szeto 	((cdb[0]) == SCMD_REQUEST_SENSE)				|| \
1818fe96085Stim szeto 	((cdb[0]) == SCMD_TEST_UNIT_READY)				|| \
1828fe96085Stim szeto 	/* PREVENT ALLOW MEDIUM REMOVAL with prevent == 0 */               \
1838fe96085Stim szeto 	((((cdb[0]) == SCMD_DOORLOCK) && (((cdb[4]) & 0x3) == 0)))	|| \
1848fe96085Stim szeto 	/* SERVICE ACTION IN with READ MEDIA SERIAL NUMBER (0x01) */       \
1858fe96085Stim szeto 	(((cdb[0]) == SCMD_SVC_ACTION_IN_G5) && (                          \
1868fe96085Stim szeto 	    ((cdb[1]) & 0x1F) == 0x01))					|| \
1878fe96085Stim szeto 	/* MAINTENANCE IN with service actions REPORT ALIASES (0x0Bh) */   \
1888fe96085Stim szeto 	/* REPORT DEVICE IDENTIFIER (0x05)  REPORT PRIORITY (0x0Eh) */     \
1898fe96085Stim szeto 	/* REPORT TARGET PORT GROUPS (0x0A) REPORT TIMESTAMP (0x0F) */     \
1908fe96085Stim szeto 	(((cdb[0]) == SCMD_MAINTENANCE_IN) && (                            \
1918fe96085Stim szeto 	    (((cdb[1]) & 0x1F) == 0x0B) ||                                 \
1928fe96085Stim szeto 	    (((cdb[1]) & 0x1F) == 0x05) ||                                 \
1938fe96085Stim szeto 	    (((cdb[1]) & 0x1F) == 0x0E) ||                                 \
1948fe96085Stim szeto 	    (((cdb[1]) & 0x1F) == 0x0A) ||                                 \
1958fe96085Stim szeto 	    (((cdb[1]) & 0x1F) == 0x0F)))				|| \
1968fe96085Stim szeto 	/* REGISTER and REGISTER_AND_IGNORE_EXISTING_KEY */                \
1978fe96085Stim szeto 	/* actions for PERSISTENT RESERVE OUT command */                   \
1988fe96085Stim szeto 	(((cdb[0]) == SCMD_PERSISTENT_RESERVE_OUT) && (                    \
1998fe96085Stim szeto 	    (((cdb[1]) & 0x1F) == PR_OUT_REGISTER_AND_IGNORE_EXISTING_KEY) || \
200*61dfa509SRick McNeal 	    (((cdb[1]) & 0x1F) == PR_OUT_REGISTER)))			|| \
2018fe96085Stim szeto 	/* ----------------------- */                                      \
2028fe96085Stim szeto 	/* SBC-3 (rev 17) Table 3  */                                      \
2038fe96085Stim szeto 	/* ----------------------- */                                      \
2048fe96085Stim szeto 	/* READ CAPACITY(10) */                                            \
2058fe96085Stim szeto 	((cdb[0]) == SCMD_READ_CAPACITY)				|| \
2068fe96085Stim szeto 	/* READ CAPACITY(16) */                                            \
2078fe96085Stim szeto 	(((cdb[0]) == SCMD_SVC_ACTION_IN_G4) && (                          \
2088fe96085Stim szeto 	    ((cdb[1]) & 0x1F) == 0x10))					|| \
2098fe96085Stim szeto 	/* START STOP UNIT with START bit 0 and POWER CONDITION 0  */      \
2108fe96085Stim szeto 	(((cdb[0]) == SCMD_START_STOP) && (                                \
2118fe96085Stim szeto 	    (((cdb[4]) & 0xF0) == 0) && (((cdb[4]) & 0x01) == 0))))
2128fe96085Stim szeto /* End of PGR_CONFLICT_FREE_CMDS */
2138fe96085Stim szeto 
2148fe96085Stim szeto /* Commands allowed for registered IT nexues but not reservation holder */
2158fe96085Stim szeto #define	PGR_REGISTERED_POSSIBLE_CMDS(cdb)	( \
2168fe96085Stim szeto 	(((cdb[0]) == SCMD_PERSISTENT_RESERVE_OUT) && (                \
2178fe96085Stim szeto 	    (((cdb[1]) & 0x1F) == PR_OUT_RELEASE)		||     \
2188fe96085Stim szeto 	    (((cdb[1]) & 0x1F) == PR_OUT_CLEAR)			||     \
2198fe96085Stim szeto 	    (((cdb[1]) & 0x1F) == PR_OUT_PREEMPT)		||     \
2208fe96085Stim szeto 	    (((cdb[1]) & 0x1F) == PR_OUT_PREEMPT_ABORT))))
2218fe96085Stim szeto 
2228fe96085Stim szeto /* List of commands allowed when WR_EX type reservation held */
2238fe96085Stim szeto #define	PGR_READ_POSSIBLE_CMDS(c)	(  \
2248fe96085Stim szeto 	((c) == SCMD_READ)		|| \
2258fe96085Stim szeto 	((c) == SCMD_READ_G1)		|| \
2268fe96085Stim szeto 	((c) == SCMD_READ_G4)		|| \
2278fe96085Stim szeto 	((c) == SCMD_READ_G5)		|| \
2288fe96085Stim szeto 	/* READ FETCH (10) (16) */         \
2298fe96085Stim szeto 	((c) == SCMD_READ_POSITION)	|| \
2308fe96085Stim szeto 	((c) == 0x90)			|| \
2318fe96085Stim szeto 	/* READ DEFECT DATA */             \
2328fe96085Stim szeto 	((c) == SCMD_READ_DEFECT_LIST)	|| \
2338fe96085Stim szeto 	((c) == 0xB7)			|| \
2348fe96085Stim szeto 	/* VERIFY (10) (16) (12) */        \
2358fe96085Stim szeto 	((c) == SCMD_VERIFY)		|| \
2368fe96085Stim szeto 	((c) == SCMD_VERIFY_G4)		|| \
2378fe96085Stim szeto 	((c) == SCMD_VERIFY_G5)		|| \
2388fe96085Stim szeto 	/* XDREAD (10) */                  \
2398fe96085Stim szeto 	((c) == 0x52))
2408fe96085Stim szeto 
2418fe96085Stim szeto #define	PGR_RESERVATION_HOLDER(pgr, key, it)	( \
2428fe96085Stim szeto 	((pgr)->pgr_flags & SBD_PGR_RSVD_ALL_REGISTRANTS) || ( \
2438fe96085Stim szeto 	    ((pgr)->pgr_rsvholder) && ((pgr)->pgr_rsvholder == (key)) && \
2448fe96085Stim szeto 	    ((key)->pgr_key_it) && ((key)->pgr_key_it == (it))))
2458fe96085Stim szeto 
2468fe96085Stim szeto #define	PGR_SET_FLAG(flg, val)		(atomic_or_8(&(flg), (val)))
2478fe96085Stim szeto #define	PGR_CLEAR_FLAG(flg, val)	(atomic_and_8(&(flg), ~(val)))
2488fe96085Stim szeto #define	PGR_CLEAR_RSV_FLAG(flg)		(atomic_and_8(&(flg), \
2498fe96085Stim szeto 	(~(SBD_PGR_RSVD_ALL_REGISTRANTS | SBD_PGR_RSVD_ONE))))
2508fe96085Stim szeto 
2518fe96085Stim szeto #define	PGR_VALID_SCOPE(scope)	((scope) == PR_LU_SCOPE)
2528fe96085Stim szeto #define	PGR_VALID_TYPE(type)	( \
2538fe96085Stim szeto 				((type) == PGR_TYPE_WR_EX)	|| \
2548fe96085Stim szeto 				((type) == PGR_TYPE_EX_AC)	|| \
2558fe96085Stim szeto 				((type) == PGR_TYPE_WR_EX_RO)	|| \
2568fe96085Stim szeto 				((type) == PGR_TYPE_EX_AC_RO)	|| \
2578fe96085Stim szeto 				((type) == PGR_TYPE_WR_EX_AR)	|| \
2588fe96085Stim szeto 				((type) == PGR_TYPE_EX_AC_AR))
2598fe96085Stim szeto 
260716c1805SNattuvetty Bhavyan #define	ALIGNED_TO_8BYTE_BOUNDARY(i)	(((i) + 7) & ~7)
2618fe96085Stim szeto 
2628fe96085Stim szeto static void
sbd_swap_pgr_info(sbd_pgr_info_t * spi)2638fe96085Stim szeto sbd_swap_pgr_info(sbd_pgr_info_t *spi)
2648fe96085Stim szeto {
2658fe96085Stim szeto 	sbd_swap_section_hdr(&spi->pgr_sms_header);
2668fe96085Stim szeto 	if (spi->pgr_data_order == SMS_DATA_ORDER)
2678fe96085Stim szeto 		return;
2688fe96085Stim szeto 	spi->pgr_sms_header.sms_chksum += SMS_DATA_ORDER - spi->pgr_data_order;
2698fe96085Stim szeto 	spi->pgr_rsvholder_indx		= BSWAP_32(spi->pgr_rsvholder_indx);
2708fe96085Stim szeto 	spi->pgr_numkeys		= BSWAP_32(spi->pgr_numkeys);
2718fe96085Stim szeto }
2728fe96085Stim szeto 
2738fe96085Stim szeto static void
sbd_swap_pgrkey_info(sbd_pgr_key_info_t * key)2748fe96085Stim szeto sbd_swap_pgrkey_info(sbd_pgr_key_info_t *key)
2758fe96085Stim szeto {
2768fe96085Stim szeto 	key->pgr_key			= BSWAP_64(key->pgr_key);
2778fe96085Stim szeto 	key->pgr_key_lpt_len		= BSWAP_16(key->pgr_key_lpt_len);
2788fe96085Stim szeto 	key->pgr_key_rpt_len		= BSWAP_16(key->pgr_key_rpt_len);
2798fe96085Stim szeto }
2808fe96085Stim szeto 
2817145ae3eSNattuvetty Bhavyan sbd_status_t
sbd_pgr_meta_init(sbd_lu_t * slu)2827145ae3eSNattuvetty Bhavyan sbd_pgr_meta_init(sbd_lu_t *slu)
2837145ae3eSNattuvetty Bhavyan {
2847145ae3eSNattuvetty Bhavyan 	sbd_pgr_info_t	*spi = NULL;
285*61dfa509SRick McNeal 	uint32_t	sz;
2867145ae3eSNattuvetty Bhavyan 	sbd_status_t	ret;
2877145ae3eSNattuvetty Bhavyan 
2887145ae3eSNattuvetty Bhavyan 	sz = sizeof (sbd_pgr_info_t);
2897145ae3eSNattuvetty Bhavyan 	spi = (sbd_pgr_info_t *)kmem_zalloc(sz, KM_SLEEP);
2907145ae3eSNattuvetty Bhavyan 	spi->pgr_data_order = SMS_DATA_ORDER;
2917145ae3eSNattuvetty Bhavyan 	spi->pgr_sms_header.sms_size = sz;
2927145ae3eSNattuvetty Bhavyan 	spi->pgr_sms_header.sms_id = SMS_ID_PGR_INFO;
2937145ae3eSNattuvetty Bhavyan 	spi->pgr_sms_header.sms_data_order = SMS_DATA_ORDER;
2947145ae3eSNattuvetty Bhavyan 
2957145ae3eSNattuvetty Bhavyan 	ret = sbd_write_meta_section(slu, (sm_section_hdr_t *)spi);
2967145ae3eSNattuvetty Bhavyan 	kmem_free(spi, sz);
2977145ae3eSNattuvetty Bhavyan 	return (ret);
2987145ae3eSNattuvetty Bhavyan }
2997145ae3eSNattuvetty Bhavyan 
300*61dfa509SRick McNeal /*
301*61dfa509SRick McNeal  * Evaluate common cases where a PERSISTENT RESERVE OUT CDB handler should call
302*61dfa509SRick McNeal  * sbd_pgr_meta_write().
303*61dfa509SRick McNeal  */
304*61dfa509SRick McNeal static boolean_t
sbd_pgr_should_save(sbd_lu_t * slu)305*61dfa509SRick McNeal sbd_pgr_should_save(sbd_lu_t *slu)
306*61dfa509SRick McNeal {
307*61dfa509SRick McNeal 	sbd_pgr_t		*pgr = slu->sl_pgr;
308*61dfa509SRick McNeal 
309*61dfa509SRick McNeal 	if (stmf_is_pgr_aptpl_always() == B_TRUE ||
310*61dfa509SRick McNeal 	    (pgr->pgr_flags & (SBD_PGR_APTPL)))
311*61dfa509SRick McNeal 		return (B_TRUE);
312*61dfa509SRick McNeal 	else
313*61dfa509SRick McNeal 		return (B_FALSE);
314*61dfa509SRick McNeal }
315*61dfa509SRick McNeal 
3168fe96085Stim szeto sbd_status_t
sbd_pgr_meta_load(sbd_lu_t * slu)3178fe96085Stim szeto sbd_pgr_meta_load(sbd_lu_t *slu)
3188fe96085Stim szeto {
3198fe96085Stim szeto 	sbd_pgr_t		*pgr = slu->sl_pgr;
3208fe96085Stim szeto 	sbd_pgr_info_t		*spi = NULL;
3218fe96085Stim szeto 	sbd_pgr_key_t		*key, *last_key = NULL;
3228fe96085Stim szeto 	sbd_pgr_key_info_t	*spi_key;
3238fe96085Stim szeto 	sbd_status_t		ret = SBD_SUCCESS;
324716c1805SNattuvetty Bhavyan 	scsi_devid_desc_t	*lpt;
3258fe96085Stim szeto 	uint8_t			*ptr, *keyoffset,  *endoffset;
3268fe96085Stim szeto 	uint32_t		i, sz;
3278fe96085Stim szeto 
3288fe96085Stim szeto 	ret = sbd_read_meta_section(slu, (sm_section_hdr_t **)&spi,
3298fe96085Stim szeto 	    SMS_ID_PGR_INFO);
3308fe96085Stim szeto 	if (ret != SBD_SUCCESS) {
3318fe96085Stim szeto 		/* No PGR section found, means volume made before PGR support */
3328fe96085Stim szeto 		if (ret == SBD_NOT_FOUND) {
3338fe96085Stim szeto 			/* So just create a default PGR section */
3347145ae3eSNattuvetty Bhavyan 			ret = sbd_pgr_meta_init(slu);
3358fe96085Stim szeto 		}
3368fe96085Stim szeto 		return (ret);
3378fe96085Stim szeto 	}
338716c1805SNattuvetty Bhavyan 
3398fe96085Stim szeto 	if (spi->pgr_data_order != SMS_DATA_ORDER) {
3408fe96085Stim szeto 		sbd_swap_pgr_info(spi);
3418fe96085Stim szeto 	}
3428fe96085Stim szeto 
3438fe96085Stim szeto 	pgr->pgr_flags = spi->pgr_flags;
344*61dfa509SRick McNeal 	/*
345*61dfa509SRick McNeal 	 * We reload APTPL reservations when:
346*61dfa509SRick McNeal 	 *  1. Global override is enabled
347*61dfa509SRick McNeal 	 *  2. APTPL was explicitly asserted in the PERSISTENT RESERVE OUT CDB
348*61dfa509SRick McNeal 	 */
349*61dfa509SRick McNeal 	if (stmf_is_pgr_aptpl_always() || (pgr->pgr_flags & SBD_PGR_APTPL)) {
3508fe96085Stim szeto 		pgr->pgr_rsv_type = spi->pgr_rsv_type;
3518fe96085Stim szeto 		pgr->pgr_rsv_scope = spi->pgr_rsv_scope;
3528fe96085Stim szeto 	} else {
3538fe96085Stim szeto 		PGR_CLEAR_RSV_FLAG(pgr->pgr_flags);
3548fe96085Stim szeto 	}
355716c1805SNattuvetty Bhavyan 
3568fe96085Stim szeto 	PGR_CLEAR_FLAG(slu->sl_pgr->pgr_flags, SBD_PGR_ALL_KEYS_HAS_IT);
3578fe96085Stim szeto 
3588fe96085Stim szeto 	endoffset	= (uint8_t *)spi;
3598fe96085Stim szeto 	endoffset	+= spi->pgr_sms_header.sms_size;
3608fe96085Stim szeto 	keyoffset	= (uint8_t *)(spi + 1);
3618fe96085Stim szeto 	for (i = 1; i <= spi->pgr_numkeys; i++) {
3628fe96085Stim szeto 
3638fe96085Stim szeto 		spi_key = (sbd_pgr_key_info_t *)keyoffset;
3648fe96085Stim szeto 		if (spi->pgr_data_order != SMS_DATA_ORDER) {
3658fe96085Stim szeto 			sbd_swap_pgrkey_info(spi_key);
3668fe96085Stim szeto 		}
3678fe96085Stim szeto 
3688fe96085Stim szeto 		/* Calculate the size and next offset */
369716c1805SNattuvetty Bhavyan 		sz = ALIGNED_TO_8BYTE_BOUNDARY(sizeof (sbd_pgr_key_info_t) - 1 +
3708fe96085Stim szeto 		    spi_key->pgr_key_lpt_len + spi_key->pgr_key_rpt_len);
3718fe96085Stim szeto 		keyoffset += sz;
3728fe96085Stim szeto 
3738fe96085Stim szeto 		/* Validate the key fields */
3748fe96085Stim szeto 		if (spi_key->pgr_key_rpt_len == 0 || endoffset < keyoffset ||
3758fe96085Stim szeto 		    (spi_key->pgr_key_lpt_len == 0 &&
3768fe96085Stim szeto 		    !(spi_key->pgr_key_flags & SBD_PGR_KEY_ALL_TG_PT))) {
377716c1805SNattuvetty Bhavyan 			ret = SBD_META_CORRUPTED;
378716c1805SNattuvetty Bhavyan 			goto sbd_pgr_meta_load_failed;
3798fe96085Stim szeto 		}
3808fe96085Stim szeto 
3818fe96085Stim szeto 		lpt = (scsi_devid_desc_t *)spi_key->pgr_key_it;
3828fe96085Stim szeto 		ptr = (uint8_t *)spi_key->pgr_key_it + spi_key->pgr_key_lpt_len;
383716c1805SNattuvetty Bhavyan 
384716c1805SNattuvetty Bhavyan 		if (spi_key->pgr_key_flags & SBD_PGR_KEY_TPT_ID_FLAG) {
385716c1805SNattuvetty Bhavyan 			uint16_t tpd_len = 0;
386716c1805SNattuvetty Bhavyan 
387716c1805SNattuvetty Bhavyan 			if (!stmf_scsilib_tptid_validate(
388716c1805SNattuvetty Bhavyan 			    (scsi_transport_id_t *)ptr,
389716c1805SNattuvetty Bhavyan 			    spi_key->pgr_key_rpt_len, &tpd_len)) {
390716c1805SNattuvetty Bhavyan 				ret = SBD_META_CORRUPTED;
391716c1805SNattuvetty Bhavyan 				goto sbd_pgr_meta_load_failed;
392716c1805SNattuvetty Bhavyan 			}
393716c1805SNattuvetty Bhavyan 			if (tpd_len != spi_key->pgr_key_rpt_len) {
394716c1805SNattuvetty Bhavyan 				ret = SBD_META_CORRUPTED;
395716c1805SNattuvetty Bhavyan 				goto sbd_pgr_meta_load_failed;
396716c1805SNattuvetty Bhavyan 			}
397716c1805SNattuvetty Bhavyan 			key = sbd_pgr_key_alloc(lpt, (scsi_transport_id_t *)ptr,
398716c1805SNattuvetty Bhavyan 			    spi_key->pgr_key_lpt_len, spi_key->pgr_key_rpt_len);
399716c1805SNattuvetty Bhavyan 		} else {
400716c1805SNattuvetty Bhavyan 			stmf_remote_port_t	*rpt = NULL;
401716c1805SNattuvetty Bhavyan 
402716c1805SNattuvetty Bhavyan 			/*
403716c1805SNattuvetty Bhavyan 			 * This block is executed only if the metadata was
404716c1805SNattuvetty Bhavyan 			 * stored before the implementation of Transport ID
405716c1805SNattuvetty Bhavyan 			 * support.
406716c1805SNattuvetty Bhavyan 			 */
407716c1805SNattuvetty Bhavyan 			rpt = stmf_scsilib_devid_to_remote_port(
408716c1805SNattuvetty Bhavyan 			    (scsi_devid_desc_t *)ptr);
409716c1805SNattuvetty Bhavyan 			if (rpt == NULL) {
410716c1805SNattuvetty Bhavyan 				ret = SBD_META_CORRUPTED;
411716c1805SNattuvetty Bhavyan 				goto sbd_pgr_meta_load_failed;
412716c1805SNattuvetty Bhavyan 			}
413716c1805SNattuvetty Bhavyan 			key = sbd_pgr_key_alloc(lpt, rpt->rport_tptid,
414716c1805SNattuvetty Bhavyan 			    spi_key->pgr_key_lpt_len, rpt->rport_tptid_sz);
415716c1805SNattuvetty Bhavyan 			stmf_remote_port_free(rpt);
416716c1805SNattuvetty Bhavyan 		}
4178fe96085Stim szeto 
4188fe96085Stim szeto 		key->pgr_key		= spi_key->pgr_key;
4198fe96085Stim szeto 		key->pgr_key_flags	= spi_key->pgr_key_flags;
4208fe96085Stim szeto 		key->pgr_key_prev	= last_key;
4218fe96085Stim szeto 
4228fe96085Stim szeto 		if (last_key) {
4238fe96085Stim szeto 			last_key->pgr_key_next = key;
4248fe96085Stim szeto 		} else {
4258fe96085Stim szeto 			pgr->pgr_keylist = key;
4268fe96085Stim szeto 		}
4278fe96085Stim szeto 		last_key = key;
4288fe96085Stim szeto 
4298fe96085Stim szeto 		if ((pgr->pgr_flags & SBD_PGR_RSVD_ONE) &&
4308fe96085Stim szeto 		    (i == spi->pgr_rsvholder_indx)) {
4318fe96085Stim szeto 			pgr->pgr_rsvholder = key;
4328fe96085Stim szeto 		}
4338fe96085Stim szeto 	}
4348fe96085Stim szeto 
4358fe96085Stim szeto 	kmem_free(spi, spi->pgr_sms_header.sms_size);
4368fe96085Stim szeto 	return (ret);
437716c1805SNattuvetty Bhavyan 
438716c1805SNattuvetty Bhavyan sbd_pgr_meta_load_failed:
439716c1805SNattuvetty Bhavyan 	{
440716c1805SNattuvetty Bhavyan 	char *lun_name = sbd_get_devid_string(slu);
441716c1805SNattuvetty Bhavyan 	sbd_pgr_keylist_dealloc(slu);
442716c1805SNattuvetty Bhavyan 	kmem_free(spi, spi->pgr_sms_header.sms_size);
443716c1805SNattuvetty Bhavyan 	cmn_err(CE_WARN, "sbd_pgr_meta_load: Failed to load PGR meta data "
444716c1805SNattuvetty Bhavyan 	    "for lun %s.", lun_name);
445716c1805SNattuvetty Bhavyan 	kmem_free(lun_name, strlen(lun_name) + 1);
446716c1805SNattuvetty Bhavyan 	return (ret);
447716c1805SNattuvetty Bhavyan 	}
4488fe96085Stim szeto }
4498fe96085Stim szeto 
4508fe96085Stim szeto sbd_status_t
sbd_pgr_meta_write(sbd_lu_t * slu)4518fe96085Stim szeto sbd_pgr_meta_write(sbd_lu_t *slu)
4528fe96085Stim szeto {
4538fe96085Stim szeto 	sbd_pgr_key_t		*key;
4548fe96085Stim szeto 	sbd_pgr_info_t		*spi;
4558fe96085Stim szeto 	sbd_pgr_key_info_t	*spi_key;
4568fe96085Stim szeto 	sbd_pgr_t		*pgr = slu->sl_pgr;
4578fe96085Stim szeto 	sbd_status_t		ret = SBD_SUCCESS;
4588fe96085Stim szeto 	uint32_t		sz, totalsz;
4598fe96085Stim szeto 
4608fe96085Stim szeto 	/* Calculate total pgr meta section size needed */
4618fe96085Stim szeto 	sz = sizeof (sbd_pgr_info_t);
462*61dfa509SRick McNeal 	if ((pgr->pgr_flags & SBD_PGR_APTPL) || stmf_is_pgr_aptpl_always()) {
4638fe96085Stim szeto 		key = pgr->pgr_keylist;
4648fe96085Stim szeto 		while (key != NULL) {
465716c1805SNattuvetty Bhavyan 			sz = ALIGNED_TO_8BYTE_BOUNDARY(sz +
4668fe96085Stim szeto 			    sizeof (sbd_pgr_key_info_t) - 1 +
4678fe96085Stim szeto 			    key->pgr_key_lpt_len + key->pgr_key_rpt_len);
4688fe96085Stim szeto 			key = key->pgr_key_next;
4698fe96085Stim szeto 		}
4708fe96085Stim szeto 	}
4718fe96085Stim szeto 	totalsz = sz;
4728fe96085Stim szeto 
4738fe96085Stim szeto 	spi = (sbd_pgr_info_t *)kmem_zalloc(totalsz, KM_SLEEP);
4748fe96085Stim szeto 	spi->pgr_flags		= pgr->pgr_flags;
4758fe96085Stim szeto 	spi->pgr_rsv_type	= pgr->pgr_rsv_type;
4768fe96085Stim szeto 	spi->pgr_rsv_scope	= pgr->pgr_rsv_scope;
4778fe96085Stim szeto 	spi->pgr_data_order	= SMS_DATA_ORDER;
4788fe96085Stim szeto 	spi->pgr_numkeys	= 0;
4798fe96085Stim szeto 
4808fe96085Stim szeto 	spi->pgr_sms_header.sms_size = totalsz;
4818fe96085Stim szeto 	spi->pgr_sms_header.sms_id = SMS_ID_PGR_INFO;
4828fe96085Stim szeto 	spi->pgr_sms_header.sms_data_order = SMS_DATA_ORDER;
4838fe96085Stim szeto 
484*61dfa509SRick McNeal 	if ((pgr->pgr_flags & SBD_PGR_APTPL) || stmf_is_pgr_aptpl_always()) {
4858fe96085Stim szeto 		uint8_t *ptr;
4868fe96085Stim szeto 		key = pgr->pgr_keylist;
4878fe96085Stim szeto 		sz = sizeof (sbd_pgr_info_t);
4888fe96085Stim szeto 		while (key != NULL) {
4898fe96085Stim szeto 			spi_key = (sbd_pgr_key_info_t *)((uint8_t *)spi + sz);
4908fe96085Stim szeto 			spi_key->pgr_key = key->pgr_key;
491716c1805SNattuvetty Bhavyan 			spi_key->pgr_key_flags = key->pgr_key_flags;
4928fe96085Stim szeto 			spi_key->pgr_key_lpt_len = key->pgr_key_lpt_len;
4938fe96085Stim szeto 			spi_key->pgr_key_rpt_len = key->pgr_key_rpt_len;
4948fe96085Stim szeto 			ptr = spi_key->pgr_key_it;
4958fe96085Stim szeto 			bcopy(key->pgr_key_lpt_id, ptr, key->pgr_key_lpt_len);
4968fe96085Stim szeto 			ptr += key->pgr_key_lpt_len;
4978fe96085Stim szeto 			bcopy(key->pgr_key_rpt_id, ptr, key->pgr_key_rpt_len);
4988fe96085Stim szeto 
4998fe96085Stim szeto 			spi->pgr_numkeys++;
5008fe96085Stim szeto 			if (key == pgr->pgr_rsvholder) {
5018fe96085Stim szeto 				spi->pgr_rsvholder_indx = spi->pgr_numkeys;
5028fe96085Stim szeto 			}
5038fe96085Stim szeto 
504716c1805SNattuvetty Bhavyan 			sz = ALIGNED_TO_8BYTE_BOUNDARY(sz +
5058fe96085Stim szeto 			    sizeof (sbd_pgr_key_info_t) - 1 +
5068fe96085Stim szeto 			    key->pgr_key_lpt_len + key->pgr_key_rpt_len);
5078fe96085Stim szeto 			key = key->pgr_key_next;
5088fe96085Stim szeto 		}
5098fe96085Stim szeto 	}
510*61dfa509SRick McNeal 	rw_downgrade(&pgr->pgr_lock);
5118fe96085Stim szeto 	ret = sbd_write_meta_section(slu, (sm_section_hdr_t *)spi);
512*61dfa509SRick McNeal 	if (!rw_tryupgrade(&pgr->pgr_lock)) {
513*61dfa509SRick McNeal 		rw_exit(&pgr->pgr_lock);
514*61dfa509SRick McNeal 		rw_enter(&pgr->pgr_lock, RW_WRITER);
515*61dfa509SRick McNeal 	}
5168fe96085Stim szeto 	kmem_free(spi, totalsz);
5178fe96085Stim szeto 	if (ret != SBD_SUCCESS) {
5188fe96085Stim szeto 		sbd_pgr_key_t	*tmp_list;
5198fe96085Stim szeto 		tmp_list = pgr->pgr_keylist;
5208fe96085Stim szeto 		pgr->pgr_keylist = NULL;
5218fe96085Stim szeto 		if (sbd_pgr_meta_load(slu) != SBD_SUCCESS) {
5228fe96085Stim szeto 			char *lun_name = sbd_get_devid_string(slu);
5238fe96085Stim szeto 			cmn_err(CE_WARN, "sbd_pgr_meta_write: Failed to revert "
5248fe96085Stim szeto 			    "back to existing PGR state after meta write "
5258fe96085Stim szeto 			    "failure, may cause PGR inconsistancy for lun %s.",
5268fe96085Stim szeto 			    lun_name);
5278fe96085Stim szeto 			kmem_free(lun_name, strlen(lun_name) + 1);
5288fe96085Stim szeto 			pgr->pgr_keylist = tmp_list;
5298fe96085Stim szeto 		} else {
5308fe96085Stim szeto 			key = pgr->pgr_keylist;
5318fe96085Stim szeto 			pgr->pgr_keylist = tmp_list;
5328fe96085Stim szeto 			sbd_pgr_set_pgr_check_flag(slu, B_TRUE);
5338fe96085Stim szeto 			sbd_pgr_keylist_dealloc(slu);
5348fe96085Stim szeto 			pgr->pgr_keylist = key;
5358fe96085Stim szeto 		}
5368fe96085Stim szeto 
5378fe96085Stim szeto 	}
5388fe96085Stim szeto 	return (ret);
5398fe96085Stim szeto }
5408fe96085Stim szeto 
5418fe96085Stim szeto static sbd_pgr_key_t *
sbd_pgr_key_alloc(scsi_devid_desc_t * lptid,scsi_transport_id_t * rptid,int16_t lpt_len,int16_t rpt_len)542716c1805SNattuvetty Bhavyan sbd_pgr_key_alloc(scsi_devid_desc_t *lptid, scsi_transport_id_t *rptid,
543*61dfa509SRick McNeal     int16_t lpt_len, int16_t rpt_len)
5448fe96085Stim szeto {
5458fe96085Stim szeto 	sbd_pgr_key_t *key;
5468fe96085Stim szeto 
5478fe96085Stim szeto 	key = (sbd_pgr_key_t *)kmem_zalloc(sizeof (sbd_pgr_key_t), KM_SLEEP);
5488fe96085Stim szeto 
549716c1805SNattuvetty Bhavyan 	if (lptid && lpt_len >= sizeof (scsi_devid_desc_t)) {
5508fe96085Stim szeto 		key->pgr_key_lpt_len = lpt_len;
5518fe96085Stim szeto 		key->pgr_key_lpt_id  = (scsi_devid_desc_t *)kmem_zalloc(
5528fe96085Stim szeto 		    lpt_len, KM_SLEEP);
5538fe96085Stim szeto 		bcopy(lptid, key->pgr_key_lpt_id, lpt_len);
5548fe96085Stim szeto 	}
5558fe96085Stim szeto 
556716c1805SNattuvetty Bhavyan 	if (rptid && rpt_len >= sizeof (scsi_transport_id_t)) {
557716c1805SNattuvetty Bhavyan 		key->pgr_key_flags |= SBD_PGR_KEY_TPT_ID_FLAG;
5588fe96085Stim szeto 		key->pgr_key_rpt_len = rpt_len;
559716c1805SNattuvetty Bhavyan 		key->pgr_key_rpt_id  = (scsi_transport_id_t *)kmem_zalloc(
5608fe96085Stim szeto 		    rpt_len, KM_SLEEP);
5618fe96085Stim szeto 		bcopy(rptid, key->pgr_key_rpt_id, rpt_len);
5628fe96085Stim szeto 	}
5638fe96085Stim szeto 
5648fe96085Stim szeto 	return (key);
5658fe96085Stim szeto }
5668fe96085Stim szeto 
5678fe96085Stim szeto static void
sbd_pgr_key_free(sbd_pgr_key_t * key)5688fe96085Stim szeto sbd_pgr_key_free(sbd_pgr_key_t *key)
5698fe96085Stim szeto {
5708fe96085Stim szeto 	if (key->pgr_key_lpt_id) {
5718fe96085Stim szeto 		kmem_free(key->pgr_key_lpt_id, key->pgr_key_lpt_len);
5728fe96085Stim szeto 	}
5738fe96085Stim szeto 	if (key->pgr_key_rpt_id) {
5748fe96085Stim szeto 		kmem_free(key->pgr_key_rpt_id, key->pgr_key_rpt_len);
5758fe96085Stim szeto 	}
5768fe96085Stim szeto 	kmem_free(key, sizeof (sbd_pgr_key_t));
5778fe96085Stim szeto }
5788fe96085Stim szeto 
5798fe96085Stim szeto void
sbd_pgr_keylist_dealloc(sbd_lu_t * slu)5808fe96085Stim szeto sbd_pgr_keylist_dealloc(sbd_lu_t *slu)
5818fe96085Stim szeto {
5828fe96085Stim szeto 	sbd_pgr_t	*pgr  = slu->sl_pgr;
5838fe96085Stim szeto 	sbd_it_data_t	*it;
5848fe96085Stim szeto 	sbd_pgr_key_t	*key;
5858fe96085Stim szeto 
5868fe96085Stim szeto 	mutex_enter(&slu->sl_lock);
5878fe96085Stim szeto 	for (it = slu->sl_it_list; it != NULL; it = it->sbd_it_next) {
5888fe96085Stim szeto 		it->pgr_key_ptr = NULL;
5898fe96085Stim szeto 	}
5908fe96085Stim szeto 	mutex_exit(&slu->sl_lock);
5918fe96085Stim szeto 
5928fe96085Stim szeto 	while (pgr->pgr_keylist != NULL) {
5938fe96085Stim szeto 		key = pgr->pgr_keylist;
5948fe96085Stim szeto 		pgr->pgr_keylist = key->pgr_key_next;
5958fe96085Stim szeto 		sbd_pgr_key_free(key);
5968fe96085Stim szeto 	}
5978fe96085Stim szeto }
5988fe96085Stim szeto 
59945039663SJohn Forte /*
60045039663SJohn Forte  * Reset and clear the keys, Can be used in the case of Lun Reset
60145039663SJohn Forte  */
60245039663SJohn Forte void
sbd_pgr_reset(sbd_lu_t * slu)60345039663SJohn Forte sbd_pgr_reset(sbd_lu_t *slu)
60445039663SJohn Forte {
60545039663SJohn Forte 	sbd_pgr_t	*pgr  = slu->sl_pgr;
60645039663SJohn Forte 
60745039663SJohn Forte 	rw_enter(&pgr->pgr_lock, RW_WRITER);
608*61dfa509SRick McNeal 	if (!(pgr->pgr_flags & SBD_PGR_APTPL) &&
609*61dfa509SRick McNeal 	    stmf_is_pgr_aptpl_always() == B_FALSE) {
61045039663SJohn Forte 		sbd_pgr_keylist_dealloc(slu);
61145039663SJohn Forte 		pgr->pgr_PRgeneration	= 0;
61245039663SJohn Forte 		pgr->pgr_rsvholder	= NULL;
61345039663SJohn Forte 		pgr->pgr_rsv_type	= 0;
61445039663SJohn Forte 		pgr->pgr_flags		= 0;
61545039663SJohn Forte 	}
61645039663SJohn Forte 	rw_exit(&pgr->pgr_lock);
61745039663SJohn Forte }
61845039663SJohn Forte 
6198fe96085Stim szeto static void
sbd_pgr_remove_key(sbd_lu_t * slu,sbd_pgr_key_t * key)6208fe96085Stim szeto sbd_pgr_remove_key(sbd_lu_t *slu, sbd_pgr_key_t *key)
6218fe96085Stim szeto {
6228fe96085Stim szeto 	sbd_pgr_t *pgr  = slu->sl_pgr;
6238fe96085Stim szeto 	sbd_it_data_t *it;
6248fe96085Stim szeto 
6258fe96085Stim szeto 	ASSERT(key);
6268fe96085Stim szeto 
6278fe96085Stim szeto 	mutex_enter(&slu->sl_lock);
6288fe96085Stim szeto 	if (key->pgr_key_flags & SBD_PGR_KEY_ALL_TG_PT) {
6298fe96085Stim szeto 		for (it = slu->sl_it_list; it != NULL; it = it->sbd_it_next) {
6308fe96085Stim szeto 			if (it->pgr_key_ptr == key)
6318fe96085Stim szeto 				it->pgr_key_ptr = NULL;
6328fe96085Stim szeto 		}
6338fe96085Stim szeto 	} else {
6348fe96085Stim szeto 		if (key->pgr_key_it) {
6358fe96085Stim szeto 			key->pgr_key_it->pgr_key_ptr = NULL;
6368fe96085Stim szeto 		}
6378fe96085Stim szeto 	}
6388fe96085Stim szeto 	mutex_exit(&slu->sl_lock);
6398fe96085Stim szeto 
6408fe96085Stim szeto 	if (key->pgr_key_next) {
6418fe96085Stim szeto 		key->pgr_key_next->pgr_key_prev = key->pgr_key_prev;
6428fe96085Stim szeto 	}
6438fe96085Stim szeto 	if (key->pgr_key_prev) {
6448fe96085Stim szeto 		key->pgr_key_prev->pgr_key_next = key->pgr_key_next;
6458fe96085Stim szeto 	} else {
6468fe96085Stim szeto 		pgr->pgr_keylist =  key->pgr_key_next;
6478fe96085Stim szeto 	}
6488fe96085Stim szeto 
6498fe96085Stim szeto 	sbd_pgr_key_free(key);
6508fe96085Stim szeto }
6518fe96085Stim szeto 
6528fe96085Stim szeto /*
6538fe96085Stim szeto  * Remove keys depends on boolean variable "match"
6548fe96085Stim szeto  * match = B_TRUE  ==>	Remove all keys which matches the given svc_key,
6558fe96085Stim szeto  *			except for IT equal to given "my_it".
6568fe96085Stim szeto  * match = B_FALSE ==>	Remove all keys which does not matches the svc_key,
6578fe96085Stim szeto  *			except for IT equal to given "my_it"
6588fe96085Stim szeto  */
6598fe96085Stim szeto static uint32_t
sbd_pgr_remove_keys(sbd_lu_t * slu,sbd_it_data_t * my_it,sbd_pgr_key_t * my_key,uint64_t svc_key,boolean_t match)6608fe96085Stim szeto sbd_pgr_remove_keys(sbd_lu_t *slu, sbd_it_data_t *my_it, sbd_pgr_key_t *my_key,
661*61dfa509SRick McNeal     uint64_t svc_key, boolean_t match)
6628fe96085Stim szeto {
6638fe96085Stim szeto 	sbd_pgr_t	*pgr  = slu->sl_pgr;
6648fe96085Stim szeto 	sbd_it_data_t	*it;
6658fe96085Stim szeto 	sbd_pgr_key_t	*nextkey, *key = pgr->pgr_keylist;
6668fe96085Stim szeto 	uint32_t	count = 0;
6678fe96085Stim szeto 
6688fe96085Stim szeto 	while (key) {
6698fe96085Stim szeto 
6708fe96085Stim szeto 		nextkey = key->pgr_key_next;
6718fe96085Stim szeto 		if (match == B_TRUE && key->pgr_key == svc_key ||
6728fe96085Stim szeto 		    match == B_FALSE && key->pgr_key != svc_key) {
6738fe96085Stim szeto 			/*
6748fe96085Stim szeto 			 * If the key is registered by current IT keep it,
6758fe96085Stim szeto 			 * but just remove pgr pointers from other ITs
6768fe96085Stim szeto 			 */
6778fe96085Stim szeto 			if (key == my_key) {
6788fe96085Stim szeto 				mutex_enter(&slu->sl_lock);
6798fe96085Stim szeto 				for (it = slu->sl_it_list; it != NULL;
6808fe96085Stim szeto 				    it = it->sbd_it_next) {
6818fe96085Stim szeto 					if (it->pgr_key_ptr == key &&
6828fe96085Stim szeto 					    it != my_it)
6838fe96085Stim szeto 						it->pgr_key_ptr = NULL;
6848fe96085Stim szeto 				}
6858fe96085Stim szeto 				mutex_exit(&slu->sl_lock);
6868fe96085Stim szeto 			} else {
6878fe96085Stim szeto 				sbd_pgr_remove_key(slu, key);
6888fe96085Stim szeto 			}
6898fe96085Stim szeto 			count++;
6908fe96085Stim szeto 		}
6918fe96085Stim szeto 		key = nextkey;
6928fe96085Stim szeto 	}
6938fe96085Stim szeto 	return (count);
6948fe96085Stim szeto }
6958fe96085Stim szeto 
6968fe96085Stim szeto static void
sbd_pgr_set_ua_conditions(sbd_lu_t * slu,sbd_it_data_t * my_it,uint8_t ua)6978fe96085Stim szeto sbd_pgr_set_ua_conditions(sbd_lu_t *slu, sbd_it_data_t *my_it, uint8_t ua)
6988fe96085Stim szeto {
6998fe96085Stim szeto 	sbd_it_data_t *it;
7008fe96085Stim szeto 
7018fe96085Stim szeto 	mutex_enter(&slu->sl_lock);
7028fe96085Stim szeto 	for (it = slu->sl_it_list; it != NULL; it = it->sbd_it_next) {
7038fe96085Stim szeto 		if (it == my_it)
7048fe96085Stim szeto 			continue;
7058fe96085Stim szeto 		it->sbd_it_ua_conditions |= ua;
7068fe96085Stim szeto 	}
7078fe96085Stim szeto 	mutex_exit(&slu->sl_lock);
7088fe96085Stim szeto }
7098fe96085Stim szeto 
7108fe96085Stim szeto /*
7118fe96085Stim szeto  * Set the SBD_IT_PGR_CHECK_FLAG  depends on variable "registered". See Below.
7128fe96085Stim szeto  *
7138fe96085Stim szeto  *   If
7148fe96085Stim szeto  *     registered is B_TRUE  => Set PGR_CHECK_FLAG on all registered IT nexus
7158fe96085Stim szeto  *     registered is B_FALSE => Set PGR_CHECK_FLAG on all unregistered IT nexus
7168fe96085Stim szeto  */
7178fe96085Stim szeto static void
sbd_pgr_set_pgr_check_flag(sbd_lu_t * slu,boolean_t registered)7188fe96085Stim szeto sbd_pgr_set_pgr_check_flag(sbd_lu_t *slu, boolean_t registered)
7198fe96085Stim szeto {
7208fe96085Stim szeto 	sbd_it_data_t *it;
7218fe96085Stim szeto 
7228fe96085Stim szeto 	PGR_CLEAR_FLAG(slu->sl_pgr->pgr_flags, SBD_PGR_ALL_KEYS_HAS_IT);
7238fe96085Stim szeto 	mutex_enter(&slu->sl_lock);
7248fe96085Stim szeto 	for (it = slu->sl_it_list; it != NULL; it = it->sbd_it_next) {
7258fe96085Stim szeto 		if (it->pgr_key_ptr) {
7268fe96085Stim szeto 			if (registered == B_TRUE)  {
7278fe96085Stim szeto 				it->sbd_it_flags |=  SBD_IT_PGR_CHECK_FLAG;
7288fe96085Stim szeto 			}
7298fe96085Stim szeto 		} else {
7308fe96085Stim szeto 			if (registered == B_FALSE)
7318fe96085Stim szeto 				it->sbd_it_flags |=  SBD_IT_PGR_CHECK_FLAG;
7328fe96085Stim szeto 		}
7338fe96085Stim szeto 	}
7348fe96085Stim szeto 	mutex_exit(&slu->sl_lock);
7358fe96085Stim szeto }
7368fe96085Stim szeto 
7378fe96085Stim szeto static boolean_t
sbd_pgr_key_compare(sbd_pgr_key_t * key,scsi_devid_desc_t * lpt,stmf_remote_port_t * rpt)7388fe96085Stim szeto sbd_pgr_key_compare(sbd_pgr_key_t *key, scsi_devid_desc_t *lpt,
739*61dfa509SRick McNeal     stmf_remote_port_t *rpt)
7408fe96085Stim szeto {
7418fe96085Stim szeto 	scsi_devid_desc_t *id;
7428fe96085Stim szeto 
743716c1805SNattuvetty Bhavyan 	if (!stmf_scsilib_tptid_compare(rpt->rport_tptid, key->pgr_key_rpt_id))
7448fe96085Stim szeto 			return (B_FALSE);
7458fe96085Stim szeto 
7468fe96085Stim szeto 	/*
7478fe96085Stim szeto 	 * You can skip target port name comparison if ALL_TG_PT flag
7488fe96085Stim szeto 	 * is set for this key;
7498fe96085Stim szeto 	 */
7508fe96085Stim szeto 	if (!(key->pgr_key_flags & SBD_PGR_KEY_ALL_TG_PT) && lpt) {
7518fe96085Stim szeto 		id = key->pgr_key_lpt_id;
7528fe96085Stim szeto 		if ((lpt->ident_length != id->ident_length) ||
7538fe96085Stim szeto 		    (memcmp(id->ident, lpt->ident, id->ident_length) != 0)) {
754716c1805SNattuvetty Bhavyan 			return (B_FALSE);
7558fe96085Stim szeto 		}
7568fe96085Stim szeto 	}
7578fe96085Stim szeto 	return (B_TRUE);
7588fe96085Stim szeto }
7598fe96085Stim szeto 
7608fe96085Stim szeto 
7618fe96085Stim szeto sbd_pgr_key_t *
sbd_pgr_key_registered(sbd_pgr_t * pgr,scsi_devid_desc_t * lpt,stmf_remote_port_t * rpt)7628fe96085Stim szeto sbd_pgr_key_registered(sbd_pgr_t *pgr, scsi_devid_desc_t *lpt,
763*61dfa509SRick McNeal     stmf_remote_port_t *rpt)
7648fe96085Stim szeto {
7658fe96085Stim szeto 	sbd_pgr_key_t *key;
7668fe96085Stim szeto 
7678fe96085Stim szeto 	for (key = pgr->pgr_keylist; key != NULL; key = key->pgr_key_next) {
7688fe96085Stim szeto 		if (sbd_pgr_key_compare(key, lpt, rpt) == B_TRUE) {
7698fe96085Stim szeto 			return (key);
7708fe96085Stim szeto 		}
7718fe96085Stim szeto 	}
7728fe96085Stim szeto 	return (NULL);
7738fe96085Stim szeto }
7748fe96085Stim szeto 
7758fe96085Stim szeto void
sbd_pgr_initialize_it(scsi_task_t * task,sbd_it_data_t * it)776f4e76ddfSNattuvetty Bhavyan sbd_pgr_initialize_it(scsi_task_t *task, sbd_it_data_t *it)
7778fe96085Stim szeto {
7788fe96085Stim szeto 	sbd_lu_t *slu = (sbd_lu_t *)task->task_lu->lu_provider_private;
779f4e76ddfSNattuvetty Bhavyan 	stmf_scsi_session_t	*ses = task->task_session;
7808fe96085Stim szeto 	sbd_pgr_t		*pgr = slu->sl_pgr;
7818fe96085Stim szeto 	sbd_pgr_key_t		*key;
782716c1805SNattuvetty Bhavyan 	scsi_devid_desc_t	*lpt, *id;
783716c1805SNattuvetty Bhavyan 	stmf_remote_port_t	*rpt;
7848fe96085Stim szeto 
7858fe96085Stim szeto 	if (pgr->pgr_flags & SBD_PGR_ALL_KEYS_HAS_IT)
7868fe96085Stim szeto 		return;
787716c1805SNattuvetty Bhavyan 
788716c1805SNattuvetty Bhavyan 	rpt = ses->ss_rport;
7898fe96085Stim szeto 	lpt = ses->ss_lport->lport_id;
7908fe96085Stim szeto 
7918fe96085Stim szeto 	rw_enter(&pgr->pgr_lock, RW_WRITER);
7928fe96085Stim szeto 	PGR_SET_FLAG(pgr->pgr_flags,  SBD_PGR_ALL_KEYS_HAS_IT);
7938fe96085Stim szeto 	for (key = pgr->pgr_keylist; key != NULL; key = key->pgr_key_next) {
7948fe96085Stim szeto 
7958fe96085Stim szeto 		if ((!(key->pgr_key_flags & SBD_PGR_KEY_ALL_TG_PT)) &&
7968fe96085Stim szeto 		    key->pgr_key_it != NULL)
7978fe96085Stim szeto 			continue;
7988fe96085Stim szeto 		/*
7998fe96085Stim szeto 		 * SBD_PGR_ALL_KEYS_HAS_IT is set only if no single key
8008fe96085Stim szeto 		 * in the list has SBD_PGR_KEY_ALL_TG_PT flag set and
8018fe96085Stim szeto 		 * pgr_key_it all keys points to some IT
8028fe96085Stim szeto 		 */
8038fe96085Stim szeto 		PGR_CLEAR_FLAG(pgr->pgr_flags, SBD_PGR_ALL_KEYS_HAS_IT);
8048fe96085Stim szeto 
8058fe96085Stim szeto 		/* Check if key matches with given lpt rpt combination */
8068fe96085Stim szeto 		if (sbd_pgr_key_compare(key, lpt, rpt) == B_FALSE)
8078fe96085Stim szeto 			continue;
8088fe96085Stim szeto 
8098fe96085Stim szeto 		/* IT nexus devid information matches with this key */
8108fe96085Stim szeto 		if (key->pgr_key_flags & SBD_PGR_KEY_ALL_TG_PT) {
8118fe96085Stim szeto 			/*
8128fe96085Stim szeto 			 * If ALL_TG_PT is set, pgr_key_it will point to NULL,
8138fe96085Stim szeto 			 * unless pgr->pgr_rsvholder pointing to this key.
8148fe96085Stim szeto 			 * In that case, pgr_key_it should point to the IT
8158fe96085Stim szeto 			 * which initiated that reservation.
8168fe96085Stim szeto 			 */
8178fe96085Stim szeto 			if (pgr->pgr_rsvholder == key) {
8188fe96085Stim szeto 				id = key->pgr_key_lpt_id;
8198fe96085Stim szeto 				if (lpt->ident_length == id->ident_length) {
8208fe96085Stim szeto 					if (memcmp(id->ident, lpt->ident,
8218fe96085Stim szeto 					    id->ident_length) == 0)
8228fe96085Stim szeto 						key->pgr_key_it = it;
8238fe96085Stim szeto 				}
8248fe96085Stim szeto 			}
8258fe96085Stim szeto 
8268fe96085Stim szeto 		} else {
8278fe96085Stim szeto 			key->pgr_key_it = it;
8288fe96085Stim szeto 		}
8298fe96085Stim szeto 
8308fe96085Stim szeto 		mutex_enter(&slu->sl_lock);
8318fe96085Stim szeto 		it->pgr_key_ptr = key;
8328fe96085Stim szeto 		mutex_exit(&slu->sl_lock);
8338fe96085Stim szeto 		rw_exit(&pgr->pgr_lock);
8348fe96085Stim szeto 		return;
8358fe96085Stim szeto 	}
8368fe96085Stim szeto 	rw_exit(&pgr->pgr_lock);
8378fe96085Stim szeto }
8388fe96085Stim szeto 
8398fe96085Stim szeto /*
8408fe96085Stim szeto  * Check for any PGR Reservation conflict. return 0 if access allowed
8418fe96085Stim szeto  */
8428fe96085Stim szeto int
sbd_pgr_reservation_conflict(scsi_task_t * task,sbd_lu_t * slu)843*61dfa509SRick McNeal sbd_pgr_reservation_conflict(scsi_task_t *task, sbd_lu_t *slu)
8448fe96085Stim szeto {
8458fe96085Stim szeto 	sbd_pgr_t	*pgr = slu->sl_pgr;
8468fe96085Stim szeto 	sbd_it_data_t	*it  = (sbd_it_data_t *)task->task_lu_itl_handle;
8478fe96085Stim szeto 
8488fe96085Stim szeto 	/* If Registered */
8498fe96085Stim szeto 	if (pgr->pgr_flags & SBD_PGR_RSVD_ALL_REGISTRANTS && it->pgr_key_ptr)
8508fe96085Stim szeto 			return (0);
8518fe96085Stim szeto 
8528fe96085Stim szeto 	/* If you are registered */
8538fe96085Stim szeto 	if (pgr->pgr_flags & SBD_PGR_RSVD_ONE) {
8548fe96085Stim szeto 		rw_enter(&pgr->pgr_lock, RW_READER);
8558fe96085Stim szeto 
8568fe96085Stim szeto 		/*
8578fe96085Stim szeto 		 * Note: it->pgr_key_ptr is protected by sl_lock. Also,
8588fe96085Stim szeto 		 *    it is expected to change its value only with pgr_lock
8598fe96085Stim szeto 		 *    held. Hence we are safe to read its value without
8608fe96085Stim szeto 		 *    grabbing sl_lock. But make sure that the value used is
8618fe96085Stim szeto 		 *    not from registers by using "volatile" keyword.
8628fe96085Stim szeto 		 *    Since this funtion is in performance path, we may want
8638fe96085Stim szeto 		 *    to avoid grabbing sl_lock.
8648fe96085Stim szeto 		 */
8658fe96085Stim szeto 		if ((volatile sbd_pgr_key_t *)it->pgr_key_ptr) {
8668fe96085Stim szeto 			/* If you are the reservation holder */
8678fe96085Stim szeto 			if (pgr->pgr_rsvholder == it->pgr_key_ptr &&
8688fe96085Stim szeto 			    it->pgr_key_ptr->pgr_key_it == it) {
8698fe96085Stim szeto 				rw_exit(&pgr->pgr_lock);
8708fe96085Stim szeto 				return (0);
8718fe96085Stim szeto 			}
8728fe96085Stim szeto 
8738fe96085Stim szeto 			/* If reserve type is not EX_AC */
8748fe96085Stim szeto 			if (pgr->pgr_rsv_type != PGR_TYPE_EX_AC) {
8758fe96085Stim szeto 				/* If reserve type is WR_EX allow read */
8768fe96085Stim szeto 				if (pgr->pgr_rsv_type == PGR_TYPE_WR_EX) {
8778fe96085Stim szeto 					if (PGR_READ_POSSIBLE_CMDS(
8788fe96085Stim szeto 					    task->task_cdb[0])) {
8798fe96085Stim szeto 						rw_exit(&pgr->pgr_lock);
8808fe96085Stim szeto 						return (0);
8818fe96085Stim szeto 					}
8828fe96085Stim szeto 				/* For all other reserve types allow access */
8838fe96085Stim szeto 				} else {
8848fe96085Stim szeto 					rw_exit(&pgr->pgr_lock);
8858fe96085Stim szeto 					return (0);
8868fe96085Stim szeto 				}
8878fe96085Stim szeto 			}
8888fe96085Stim szeto 
8898fe96085Stim szeto 			/* If registered, allow these commands */
8908fe96085Stim szeto 			if (PGR_REGISTERED_POSSIBLE_CMDS(task->task_cdb)) {
8918fe96085Stim szeto 				rw_exit(&pgr->pgr_lock);
8928fe96085Stim szeto 				return (0);
8938fe96085Stim szeto 			}
8948fe96085Stim szeto 		}
8958fe96085Stim szeto 		rw_exit(&pgr->pgr_lock);
8968fe96085Stim szeto 	}
8978fe96085Stim szeto 
8988fe96085Stim szeto 	/* For any case, allow these commands */
8998fe96085Stim szeto 	if (PGR_CONFLICT_FREE_CMDS(task->task_cdb)) {
9008fe96085Stim szeto 		return (0);
9018fe96085Stim szeto 	}
9028fe96085Stim szeto 
9038fe96085Stim szeto 	/* Give read access if reservation type WR_EX for registrants */
9048fe96085Stim szeto 	if (pgr->pgr_rsv_type == PGR_TYPE_WR_EX_RO ||
9058fe96085Stim szeto 	    pgr->pgr_rsv_type == PGR_TYPE_WR_EX_AR) {
9068fe96085Stim szeto 		if (PGR_READ_POSSIBLE_CMDS(task->task_cdb[0]))
9078fe96085Stim szeto 			return (0);
9088fe96085Stim szeto 	}
9098fe96085Stim szeto 
9108fe96085Stim szeto 	/* If  you reached here, No access for you */
9118fe96085Stim szeto 	return (1);
9128fe96085Stim szeto }
9138fe96085Stim szeto 
9148fe96085Stim szeto void
sbd_handle_pgr_in_cmd(scsi_task_t * task,stmf_data_buf_t * initial_dbuf)9158fe96085Stim szeto sbd_handle_pgr_in_cmd(scsi_task_t *task, stmf_data_buf_t *initial_dbuf)
9168fe96085Stim szeto {
9178fe96085Stim szeto 
9188fe96085Stim szeto 	sbd_lu_t	*slu = (sbd_lu_t *)task->task_lu->lu_provider_private;
9198fe96085Stim szeto 	sbd_pgr_t	*pgr = slu->sl_pgr;
9208fe96085Stim szeto 	scsi_cdb_prin_t *pr_in;
9218fe96085Stim szeto 
9228fe96085Stim szeto 	ASSERT(task->task_cdb[0] == SCMD_PERSISTENT_RESERVE_IN);
9238fe96085Stim szeto 
9248fe96085Stim szeto 	pr_in = (scsi_cdb_prin_t *)task->task_cdb;
9258fe96085Stim szeto 
9268fe96085Stim szeto 	rw_enter(&pgr->pgr_lock, RW_READER);
9278fe96085Stim szeto 	switch (pr_in->action) {
9288fe96085Stim szeto 	case PR_IN_READ_KEYS:
9298fe96085Stim szeto 		sbd_pgr_in_read_keys(task, initial_dbuf);
9308fe96085Stim szeto 		break;
9318fe96085Stim szeto 	case PR_IN_READ_RESERVATION:
9328fe96085Stim szeto 		sbd_pgr_in_read_reservation(task, initial_dbuf);
9338fe96085Stim szeto 		break;
9348fe96085Stim szeto 	case PR_IN_REPORT_CAPABILITIES:
9358fe96085Stim szeto 		sbd_pgr_in_report_capabilities(task, initial_dbuf);
9368fe96085Stim szeto 		break;
9378fe96085Stim szeto 	case PR_IN_READ_FULL_STATUS:
9388fe96085Stim szeto 		sbd_pgr_in_read_full_status(task, initial_dbuf);
9398fe96085Stim szeto 		break;
9408fe96085Stim szeto 	default :
9418fe96085Stim szeto 		stmf_scsilib_send_status(task, STATUS_CHECK,
9428fe96085Stim szeto 		    STMF_SAA_INVALID_FIELD_IN_CDB);
9438fe96085Stim szeto 		break;
9448fe96085Stim szeto 	}
9458fe96085Stim szeto 	rw_exit(&pgr->pgr_lock);
9468fe96085Stim szeto }
9478fe96085Stim szeto 
9488fe96085Stim szeto void
sbd_handle_pgr_out_cmd(scsi_task_t * task,stmf_data_buf_t * initial_dbuf)9498fe96085Stim szeto sbd_handle_pgr_out_cmd(scsi_task_t *task, stmf_data_buf_t *initial_dbuf)
9508fe96085Stim szeto {
9518fe96085Stim szeto 
9528fe96085Stim szeto 	scsi_cdb_prout_t *pr_out = (scsi_cdb_prout_t *)task->task_cdb;
9538fe96085Stim szeto 	uint32_t param_len;
9548fe96085Stim szeto 
9558fe96085Stim szeto 	ASSERT(task->task_cdb[0] == SCMD_PERSISTENT_RESERVE_OUT);
9568fe96085Stim szeto 
9578fe96085Stim szeto 	switch (pr_out->action) {
9588fe96085Stim szeto 		case PR_OUT_REGISTER:
9598fe96085Stim szeto 		case PR_OUT_RESERVE:
9608fe96085Stim szeto 		case PR_OUT_RELEASE:
9618fe96085Stim szeto 		case PR_OUT_CLEAR:
9628fe96085Stim szeto 		case PR_OUT_PREEMPT:
9638fe96085Stim szeto 		case PR_OUT_PREEMPT_ABORT:
9648fe96085Stim szeto 		case PR_OUT_REGISTER_AND_IGNORE_EXISTING_KEY:
9658fe96085Stim szeto 		case PR_OUT_REGISTER_MOVE:
9668fe96085Stim szeto 			param_len = READ_SCSI32(pr_out->param_len, uint32_t);
9678fe96085Stim szeto 			if (param_len < MAX_PGR_PARAM_LIST_LENGTH &&
9688fe96085Stim szeto 			    param_len > 0) {
9698fe96085Stim szeto 				sbd_handle_short_write_transfers(task,
9708fe96085Stim szeto 				    initial_dbuf, param_len);
9718fe96085Stim szeto 			} else {
9728fe96085Stim szeto 				stmf_scsilib_send_status(task, STATUS_CHECK,
9738fe96085Stim szeto 				    STMF_SAA_PARAM_LIST_LENGTH_ERROR);
9748fe96085Stim szeto 			}
9758fe96085Stim szeto 			break;
9768fe96085Stim szeto 		default :
9778fe96085Stim szeto 			stmf_scsilib_send_status(task, STATUS_CHECK,
9788fe96085Stim szeto 			    STMF_SAA_INVALID_FIELD_IN_CDB);
9798fe96085Stim szeto 			break;
9808fe96085Stim szeto 	}
9818fe96085Stim szeto }
9828fe96085Stim szeto 
9838fe96085Stim szeto void
sbd_handle_pgr_out_data(scsi_task_t * task,stmf_data_buf_t * dbuf)9848fe96085Stim szeto sbd_handle_pgr_out_data(scsi_task_t *task, stmf_data_buf_t *dbuf)
9858fe96085Stim szeto {
9868fe96085Stim szeto 	sbd_lu_t	*slu = (sbd_lu_t *)task->task_lu->lu_provider_private;
9878fe96085Stim szeto 	scsi_cdb_prout_t	*pr_out	= (scsi_cdb_prout_t *)task->task_cdb;
9888fe96085Stim szeto 	sbd_it_data_t		*it	= task->task_lu_itl_handle;
9898fe96085Stim szeto 	sbd_pgr_t		*pgr	= slu->sl_pgr;
9908fe96085Stim szeto 	sbd_pgr_key_t		*key;
9918fe96085Stim szeto 	scsi_prout_plist_t	*plist;
9928fe96085Stim szeto 	uint64_t		rsv_key;
993716c1805SNattuvetty Bhavyan 	uint32_t		buflen;
994716c1805SNattuvetty Bhavyan 	uint8_t			*buf;
9958fe96085Stim szeto 
9968fe96085Stim szeto 	ASSERT(task->task_cdb[0] == SCMD_PERSISTENT_RESERVE_OUT);
9978fe96085Stim szeto 
9988fe96085Stim szeto 	if (dbuf == NULL || dbuf->db_data_size < 24) {
9998fe96085Stim szeto 		stmf_scsilib_send_status(task, STATUS_CHECK,
10008fe96085Stim szeto 		    STMF_SAA_PARAM_LIST_LENGTH_ERROR);
10018fe96085Stim szeto 		return;
10028fe96085Stim szeto 	}
10038fe96085Stim szeto 
10048fe96085Stim szeto 	buf = dbuf->db_sglist[0].seg_addr;
10058fe96085Stim szeto 	buflen = dbuf->db_data_size;
10068fe96085Stim szeto 	plist = (scsi_prout_plist_t *)buf;
10078fe96085Stim szeto 
10088fe96085Stim szeto 	/* SPC3 - 6.12.1 */
10098fe96085Stim szeto 	if (pr_out->action != PR_OUT_REGISTER_MOVE && buflen != 24) {
10108fe96085Stim szeto 		if ((pr_out->action !=
10118fe96085Stim szeto 		    PR_OUT_REGISTER_AND_IGNORE_EXISTING_KEY &&
10128fe96085Stim szeto 		    pr_out->action != PR_OUT_REGISTER) ||
10138fe96085Stim szeto 		    plist->spec_i_pt == 0) {
10148fe96085Stim szeto 			stmf_scsilib_send_status(task, STATUS_CHECK,
10158fe96085Stim szeto 			    STMF_SAA_PARAM_LIST_LENGTH_ERROR);
10168fe96085Stim szeto 			return;
10178fe96085Stim szeto 		}
10188fe96085Stim szeto 	}
10198fe96085Stim szeto 
10208fe96085Stim szeto 	/*
10218fe96085Stim szeto 	 * Common Reservation Conflict Checks
10228fe96085Stim szeto 	 *
10238fe96085Stim szeto 	 * It is okey to handle REGISTER_MOVE with same plist here,
10248fe96085Stim szeto 	 * because we are only accessing reservation key feild.
10258fe96085Stim szeto 	 */
10268fe96085Stim szeto 	rw_enter(&pgr->pgr_lock, RW_WRITER);
10278fe96085Stim szeto 
10288fe96085Stim szeto 	/*
10298fe96085Stim szeto 	 * Currently it is not mandatory to have volatile keyword here,
10308fe96085Stim szeto 	 * because, it->pgr_key_ptr is not accessed yet. But still
10318fe96085Stim szeto 	 * keeping it to safe gaurd against any possible future changes.
10328fe96085Stim szeto 	 */
10338fe96085Stim szeto 	key = (sbd_pgr_key_t *)((volatile sbd_pgr_key_t *)it->pgr_key_ptr);
10348fe96085Stim szeto 	if (pr_out->action != PR_OUT_REGISTER &&
10358fe96085Stim szeto 	    pr_out->action != PR_OUT_REGISTER_AND_IGNORE_EXISTING_KEY) {
10368fe96085Stim szeto 		/* if IT is not yet registered send conflict status */
10378fe96085Stim szeto 		if (key == NULL) {
10388fe96085Stim szeto 			if (pr_out->action == PR_OUT_REGISTER_MOVE &&
10398fe96085Stim szeto 			    SBD_PGR_RSVD_NONE(pgr)) {
10408fe96085Stim szeto 				stmf_scsilib_send_status(task, STATUS_CHECK,
10418fe96085Stim szeto 				    STMF_SAA_INVALID_FIELD_IN_CDB);
10428fe96085Stim szeto 
10438fe96085Stim szeto 			} else {
10448fe96085Stim szeto 				stmf_scsilib_send_status(task,
10458fe96085Stim szeto 				    STATUS_RESERVATION_CONFLICT, 0);
10468fe96085Stim szeto 			}
10478fe96085Stim szeto 			rw_exit(&pgr->pgr_lock);
10488fe96085Stim szeto 			return;
10498fe96085Stim szeto 		}
10508fe96085Stim szeto 
10518fe96085Stim szeto 		/* Given reservation key should matches with registered key */
10528fe96085Stim szeto 		rsv_key = READ_SCSI64(plist->reservation_key, uint64_t);
10538fe96085Stim szeto 		if (key->pgr_key != rsv_key) {
10548fe96085Stim szeto 			stmf_scsilib_send_status(task,
10558fe96085Stim szeto 			    STATUS_RESERVATION_CONFLICT, 0);
10568fe96085Stim szeto 			rw_exit(&pgr->pgr_lock);
10578fe96085Stim szeto 			return;
10588fe96085Stim szeto 		}
10598fe96085Stim szeto 	}
10608fe96085Stim szeto 
10618fe96085Stim szeto 	switch (pr_out->action) {
10628fe96085Stim szeto 	case PR_OUT_REGISTER:
10638fe96085Stim szeto 	case PR_OUT_REGISTER_AND_IGNORE_EXISTING_KEY:
10648fe96085Stim szeto 		sbd_pgr_out_register(task, dbuf);
10658fe96085Stim szeto 		break;
10668fe96085Stim szeto 	case PR_OUT_REGISTER_MOVE:
10678fe96085Stim szeto 		sbd_pgr_out_register_and_move(task, dbuf);
10688fe96085Stim szeto 		break;
10698fe96085Stim szeto 	case PR_OUT_RESERVE:
10708fe96085Stim szeto 		sbd_pgr_out_reserve(task);
10718fe96085Stim szeto 		break;
10728fe96085Stim szeto 	case PR_OUT_RELEASE:
10738fe96085Stim szeto 		sbd_pgr_out_release(task);
10748fe96085Stim szeto 		break;
10758fe96085Stim szeto 	case PR_OUT_CLEAR:
10768fe96085Stim szeto 		sbd_pgr_out_clear(task);
10778fe96085Stim szeto 		break;
10788fe96085Stim szeto 	case PR_OUT_PREEMPT:
10798fe96085Stim szeto 	case PR_OUT_PREEMPT_ABORT:
10808fe96085Stim szeto 		sbd_pgr_out_preempt(task, dbuf);
10818fe96085Stim szeto 		break;
10828fe96085Stim szeto 	default :
10838fe96085Stim szeto 		stmf_scsilib_send_status(task, STATUS_CHECK,
10848fe96085Stim szeto 		    STMF_SAA_INVALID_FIELD_IN_CDB);
10858fe96085Stim szeto 		break;
10868fe96085Stim szeto 	}
10878fe96085Stim szeto 	rw_exit(&pgr->pgr_lock);
10888fe96085Stim szeto }
10898fe96085Stim szeto 
10908fe96085Stim szeto static void
sbd_pgr_in_read_keys(scsi_task_t * task,stmf_data_buf_t * initial_dbuf)10918fe96085Stim szeto sbd_pgr_in_read_keys(scsi_task_t *task, stmf_data_buf_t *initial_dbuf)
10928fe96085Stim szeto {
10938fe96085Stim szeto 	sbd_lu_t	*slu   = (sbd_lu_t *)task->task_lu->lu_provider_private;
10948fe96085Stim szeto 	sbd_pgr_t	*pgr   =  slu->sl_pgr;
10958fe96085Stim szeto 	sbd_pgr_key_t	*key;
10968fe96085Stim szeto 	scsi_prin_readrsrv_t *buf;
10978fe96085Stim szeto 	uint32_t buf_size, cdb_len, numkeys = 0;
10988fe96085Stim szeto 	uint64_t *reg_key;
10998fe96085Stim szeto 
11008fe96085Stim szeto 	ASSERT(task->task_cdb[0] == SCMD_PERSISTENT_RESERVE_IN);
11018fe96085Stim szeto 
11028fe96085Stim szeto 	cdb_len = READ_SCSI16(&task->task_cdb[7], uint16_t);
11038fe96085Stim szeto 	for (key = pgr->pgr_keylist; key != NULL; key = key->pgr_key_next)
11048fe96085Stim szeto 		++numkeys;
11058fe96085Stim szeto 	buf_size = 8 + numkeys * 8; /* minimum 8 bytes */
11068fe96085Stim szeto 	buf = kmem_zalloc(buf_size, KM_SLEEP);
11078fe96085Stim szeto 	SCSI_WRITE32(buf->PRgeneration, pgr->pgr_PRgeneration);
11088fe96085Stim szeto 	SCSI_WRITE32(buf->add_len, numkeys * 8);
11098fe96085Stim szeto 
11108fe96085Stim szeto 	reg_key = (uint64_t *)&buf->key_list;
11118fe96085Stim szeto 	for (key = pgr->pgr_keylist; key != NULL; key = key->pgr_key_next) {
11128fe96085Stim szeto 		SCSI_WRITE64(reg_key, key->pgr_key);
11138fe96085Stim szeto 		reg_key++;
11148fe96085Stim szeto 	}
11158fe96085Stim szeto 	sbd_handle_short_read_transfers(task, initial_dbuf, (uint8_t *)buf,
11168fe96085Stim szeto 	    cdb_len, buf_size);
11178fe96085Stim szeto 	kmem_free(buf, buf_size);
11188fe96085Stim szeto }
11198fe96085Stim szeto 
11208fe96085Stim szeto static void
sbd_pgr_in_read_reservation(scsi_task_t * task,stmf_data_buf_t * initial_dbuf)11218fe96085Stim szeto sbd_pgr_in_read_reservation(scsi_task_t *task, stmf_data_buf_t *initial_dbuf)
11228fe96085Stim szeto {
11238fe96085Stim szeto 	sbd_lu_t	*slu   = (sbd_lu_t *)task->task_lu->lu_provider_private;
11248fe96085Stim szeto 	sbd_pgr_t	*pgr   =  slu->sl_pgr;
11258fe96085Stim szeto 	scsi_prin_readrsrv_t *buf;
11268fe96085Stim szeto 	uint32_t cdb_len, buf_len, buf_size = 24;
11278fe96085Stim szeto 
11288fe96085Stim szeto 	ASSERT(task->task_cdb[0] == SCMD_PERSISTENT_RESERVE_IN);
11298fe96085Stim szeto 
11308fe96085Stim szeto 	cdb_len = READ_SCSI16(&task->task_cdb[7], uint16_t);
11318fe96085Stim szeto 	buf = kmem_zalloc(buf_size, KM_SLEEP); /* fixed size cdb, 24 bytes */
11328fe96085Stim szeto 	SCSI_WRITE32(buf->PRgeneration, pgr->pgr_PRgeneration);
11338fe96085Stim szeto 
11348fe96085Stim szeto 	if (SBD_PGR_RSVD_NONE(pgr)) {
11358fe96085Stim szeto 		SCSI_WRITE32(buf->add_len, 0);
11368fe96085Stim szeto 		buf_len = 8;
11378fe96085Stim szeto 	} else {
11388fe96085Stim szeto 		if (pgr->pgr_flags & SBD_PGR_RSVD_ALL_REGISTRANTS) {
11398fe96085Stim szeto 			SCSI_WRITE64(
11408fe96085Stim szeto 			    buf->key_list.res_key_list[0].reservation_key, 0);
11418fe96085Stim szeto 		} else {
11428fe96085Stim szeto 			SCSI_WRITE64(
11438fe96085Stim szeto 			    buf->key_list.res_key_list[0].reservation_key,
11448fe96085Stim szeto 			    pgr->pgr_rsvholder->pgr_key);
11458fe96085Stim szeto 		}
11468fe96085Stim szeto 		buf->key_list.res_key_list[0].type = pgr->pgr_rsv_type;
11478fe96085Stim szeto 		buf->key_list.res_key_list[0].scope = pgr->pgr_rsv_scope;
11488fe96085Stim szeto 		SCSI_WRITE32(buf->add_len, 16);
11498fe96085Stim szeto 		buf_len = 24;
11508fe96085Stim szeto 	}
11518fe96085Stim szeto 
11528fe96085Stim szeto 	sbd_handle_short_read_transfers(task, initial_dbuf, (uint8_t *)buf,
11538fe96085Stim szeto 	    cdb_len, buf_len);
11548fe96085Stim szeto 	kmem_free(buf, buf_size);
11558fe96085Stim szeto }
11568fe96085Stim szeto 
11578fe96085Stim szeto static void
sbd_pgr_in_report_capabilities(scsi_task_t * task,stmf_data_buf_t * initial_dbuf)11588fe96085Stim szeto sbd_pgr_in_report_capabilities(scsi_task_t *task,
1159*61dfa509SRick McNeal     stmf_data_buf_t *initial_dbuf)
11608fe96085Stim szeto {
11618fe96085Stim szeto 	sbd_lu_t	*slu   = (sbd_lu_t *)task->task_lu->lu_provider_private;
11628fe96085Stim szeto 	sbd_pgr_t	*pgr   =  slu->sl_pgr;
11638fe96085Stim szeto 	scsi_prin_rpt_cap_t buf;
11648fe96085Stim szeto 	uint32_t cdb_len;
11658fe96085Stim szeto 
11668fe96085Stim szeto 	ASSERT(task->task_cdb[0] == SCMD_PERSISTENT_RESERVE_IN);
11678fe96085Stim szeto 	ASSERT(pgr != NULL);
11688fe96085Stim szeto 
116970c284caSPeter Cudhea - Sun Microsystems - Burlington, MA United States 	bzero(&buf, sizeof (buf));
11708fe96085Stim szeto 	buf.ptpl_c		= 1;   /* Persist Through Power Loss C */
11718fe96085Stim szeto 	buf.atp_c		= 1;   /* All Target Ports Capable */
11728fe96085Stim szeto 	buf.sip_c		= 1;   /* Specify Initiator Ports Capable */
11738fe96085Stim szeto 	buf.crh			= 0;   /* Supports Reserve/Release exception */
11748fe96085Stim szeto 	buf.tmv			= 1;   /* Type Mask Valid */
11758fe96085Stim szeto 	buf.pr_type.wr_ex	= 1;   /* Write Exclusve */
11768fe96085Stim szeto 	buf.pr_type.ex_ac	= 1;   /* Exclusive Access */
11778fe96085Stim szeto 	buf.pr_type.wr_ex_ro	= 1;   /* Write Exclusive Registrants Only */
11788fe96085Stim szeto 	buf.pr_type.ex_ac_ro	= 1;   /* Exclusive Access Registrants Only */
11798fe96085Stim szeto 	buf.pr_type.wr_ex_ar	= 1;   /* Write Exclusive All Registrants */
11808fe96085Stim szeto 	buf.pr_type.ex_ac_ar	= 1;   /* Exclusive Access All Registrants */
11818fe96085Stim szeto 
11828fe96085Stim szeto 	/* Persist Though Power Loss Active */
11838fe96085Stim szeto 	buf.ptpl_a = pgr->pgr_flags & SBD_PGR_APTPL;
11848fe96085Stim szeto 	SCSI_WRITE16(&buf.length, 8);
11858fe96085Stim szeto 	cdb_len = READ_SCSI16(&task->task_cdb[7], uint16_t);
11868fe96085Stim szeto 	sbd_handle_short_read_transfers(task, initial_dbuf, (uint8_t *)&buf,
11878fe96085Stim szeto 	    cdb_len, 8);
11888fe96085Stim szeto }
11898fe96085Stim szeto 
1190716c1805SNattuvetty Bhavyan /* Minimum required size, SPC3 rev23 Table 110 */
1191716c1805SNattuvetty Bhavyan #define	PGR_IN_READ_FULL_STATUS_MINBUFSZ	8
1192716c1805SNattuvetty Bhavyan /* Full Satus Descriptor Fromat size, SPC3 rev23 Table 111 */
1193716c1805SNattuvetty Bhavyan #define	PGR_IN_READ_FULL_STATUS_DESCFMTSZ	24
1194716c1805SNattuvetty Bhavyan 
11958fe96085Stim szeto static void
sbd_pgr_in_read_full_status(scsi_task_t * task,stmf_data_buf_t * initial_dbuf)11968fe96085Stim szeto sbd_pgr_in_read_full_status(scsi_task_t *task,
1197*61dfa509SRick McNeal     stmf_data_buf_t *initial_dbuf)
11988fe96085Stim szeto {
11998fe96085Stim szeto 	sbd_lu_t	*slu   = (sbd_lu_t *)task->task_lu->lu_provider_private;
12008fe96085Stim szeto 	sbd_pgr_t	*pgr   = slu->sl_pgr;
12018fe96085Stim szeto 	sbd_pgr_key_t	*key;
1202*61dfa509SRick McNeal 	scsi_prin_status_t	*sts;
12038fe96085Stim szeto 	scsi_prin_full_status_t	*buf;
1204*61dfa509SRick McNeal 	uint32_t		i, buf_size, cdb_len;
12058fe96085Stim szeto 	uint8_t			*offset;
12068fe96085Stim szeto 
12078fe96085Stim szeto 	ASSERT(task->task_cdb[0] == SCMD_PERSISTENT_RESERVE_IN);
12088fe96085Stim szeto 	ASSERT(pgr != NULL);
12098fe96085Stim szeto 
1210716c1805SNattuvetty Bhavyan 	/* 4 byte allocation length for CDB, SPC3 rev23, Table 101 */
12118fe96085Stim szeto 	cdb_len = READ_SCSI16(&task->task_cdb[7], uint16_t);
12128fe96085Stim szeto 
1213716c1805SNattuvetty Bhavyan 	/* PRgeneration and additional length fields */
1214716c1805SNattuvetty Bhavyan 	buf_size = PGR_IN_READ_FULL_STATUS_MINBUFSZ;
12158fe96085Stim szeto 	for (key = pgr->pgr_keylist; key != NULL; key = key->pgr_key_next) {
1216716c1805SNattuvetty Bhavyan 		buf_size  = buf_size + PGR_IN_READ_FULL_STATUS_DESCFMTSZ +
1217716c1805SNattuvetty Bhavyan 		    key->pgr_key_rpt_len;
12188fe96085Stim szeto 	}
12198fe96085Stim szeto 
12208fe96085Stim szeto 	buf = kmem_zalloc(buf_size, KM_SLEEP);
12218fe96085Stim szeto 	SCSI_WRITE32(buf->PRgeneration, pgr->pgr_PRgeneration);
1222716c1805SNattuvetty Bhavyan 	SCSI_WRITE32(buf->add_len, buf_size - PGR_IN_READ_FULL_STATUS_MINBUFSZ);
12238fe96085Stim szeto 
12248fe96085Stim szeto 	offset	= (uint8_t *)&buf->full_desc[0];
12258fe96085Stim szeto 	key	= pgr->pgr_keylist;
12268fe96085Stim szeto 	i	= 0;
12278fe96085Stim szeto 	while (key) {
12288fe96085Stim szeto 		sts = (scsi_prin_status_t *)offset;
12298fe96085Stim szeto 		SCSI_WRITE64(sts->reservation_key, key->pgr_key);
12308fe96085Stim szeto 		if ((pgr->pgr_flags & SBD_PGR_RSVD_ALL_REGISTRANTS) ||
12318fe96085Stim szeto 		    (pgr->pgr_rsvholder && pgr->pgr_rsvholder == key)) {
12328fe96085Stim szeto 				sts->r_holder	= 1;
1233*61dfa509SRick McNeal 				sts->type	= pgr->pgr_rsv_type;
12348fe96085Stim szeto 				sts->scope	= pgr->pgr_rsv_scope;
12358fe96085Stim szeto 		}
12368fe96085Stim szeto 
12378fe96085Stim szeto 		if (key->pgr_key_flags & SBD_PGR_KEY_ALL_TG_PT) {
12388fe96085Stim szeto 			sts->all_tg_pt = 1;
12398fe96085Stim szeto 		} else {
12408fe96085Stim szeto 			SCSI_WRITE16(sts->rel_tgt_port_id,
12418fe96085Stim szeto 			    stmf_scsilib_get_lport_rtid(key->pgr_key_lpt_id));
12428fe96085Stim szeto 		}
1243716c1805SNattuvetty Bhavyan 		SCSI_WRITE32(sts->add_len, key->pgr_key_rpt_len);
1244716c1805SNattuvetty Bhavyan 		offset += PGR_IN_READ_FULL_STATUS_DESCFMTSZ;
1245716c1805SNattuvetty Bhavyan 		(void) memcpy(offset, key->pgr_key_rpt_id,
1246716c1805SNattuvetty Bhavyan 		    key->pgr_key_rpt_len);
1247716c1805SNattuvetty Bhavyan 		offset += key->pgr_key_rpt_len;
12488fe96085Stim szeto 		key = key->pgr_key_next;
12498fe96085Stim szeto 		++i;
12508fe96085Stim szeto 	}
125170c284caSPeter Cudhea - Sun Microsystems - Burlington, MA United States 	ASSERT(offset <= (uint8_t *)buf + buf_size);
12528fe96085Stim szeto 
12538fe96085Stim szeto 	sbd_handle_short_read_transfers(task, initial_dbuf, (uint8_t *)buf,
12548fe96085Stim szeto 	    cdb_len, buf_size);
12558fe96085Stim szeto 	kmem_free(buf, buf_size);
12568fe96085Stim szeto }
12578fe96085Stim szeto 
12588fe96085Stim szeto static void
sbd_pgr_out_register(scsi_task_t * task,stmf_data_buf_t * dbuf)12598fe96085Stim szeto sbd_pgr_out_register(scsi_task_t *task, stmf_data_buf_t *dbuf)
12608fe96085Stim szeto {
12618fe96085Stim szeto 	sbd_lu_t	*slu = (sbd_lu_t *)task->task_lu->lu_provider_private;
12628fe96085Stim szeto 	sbd_pgr_t		*pgr	= slu->sl_pgr;
12638fe96085Stim szeto 	stmf_scsi_session_t	*ses	= task->task_session;
12648fe96085Stim szeto 	sbd_it_data_t		*it	= task->task_lu_itl_handle;
12658fe96085Stim szeto 	sbd_pgr_key_t		*key	= it->pgr_key_ptr;
12668fe96085Stim szeto 	scsi_cdb_prout_t	*pr_out	= (scsi_cdb_prout_t *)task->task_cdb;
1267716c1805SNattuvetty Bhavyan 	scsi_devid_desc_t	*lpt	= ses->ss_lport->lport_id;
12688fe96085Stim szeto 	scsi_prout_plist_t	*plist;
1269716c1805SNattuvetty Bhavyan 	stmf_remote_port_t	rport;
1270716c1805SNattuvetty Bhavyan 	uint8_t			*buf, keyflag;
1271716c1805SNattuvetty Bhavyan 	uint32_t		buflen;
12728fe96085Stim szeto 	uint64_t		rsv_key, svc_key;
12738fe96085Stim szeto 
12748fe96085Stim szeto 	buf = dbuf->db_sglist[0].seg_addr;
12758fe96085Stim szeto 	plist = (scsi_prout_plist_t *)buf;
12768fe96085Stim szeto 	buflen = dbuf->db_data_size;
12778fe96085Stim szeto 	rsv_key = READ_SCSI64(plist->reservation_key, uint64_t);
12788fe96085Stim szeto 	svc_key = READ_SCSI64(plist->service_key, uint64_t);
12798fe96085Stim szeto 
12808fe96085Stim szeto 	/* Handling already registered IT session */
12818fe96085Stim szeto 	if (key) {
12828fe96085Stim szeto 
12838fe96085Stim szeto 		if (pr_out->action == PR_OUT_REGISTER &&
12848fe96085Stim szeto 		    key->pgr_key != rsv_key) {
12858fe96085Stim szeto 			stmf_scsilib_send_status(task,
12868fe96085Stim szeto 			    STATUS_RESERVATION_CONFLICT, 0);
12878fe96085Stim szeto 			return;
12888fe96085Stim szeto 		}
12898fe96085Stim szeto 		if (plist->spec_i_pt) {
12908fe96085Stim szeto 			stmf_scsilib_send_status(task, STATUS_CHECK,
12918fe96085Stim szeto 			    STMF_SAA_INVALID_FIELD_IN_CDB);
12928fe96085Stim szeto 			return;
12938fe96085Stim szeto 		}
12948fe96085Stim szeto 
12958fe96085Stim szeto 		if (plist->all_tg_pt !=
12968fe96085Stim szeto 		    (key->pgr_key_flags & SBD_PGR_KEY_ALL_TG_PT)) {
12978fe96085Stim szeto 			stmf_scsilib_send_status(task, STATUS_CHECK,
12988fe96085Stim szeto 			    STMF_SAA_INVALID_FIELD_IN_CDB);
12998fe96085Stim szeto 			return;
13008fe96085Stim szeto 		}
13018fe96085Stim szeto 
13028fe96085Stim szeto 		if (svc_key == 0) {
13038fe96085Stim szeto 			sbd_pgr_do_unregister(slu, it, key);
13048fe96085Stim szeto 		} else {
13058fe96085Stim szeto 			key->pgr_key = svc_key;
13068fe96085Stim szeto 		}
13078fe96085Stim szeto 
13088fe96085Stim szeto 		goto sbd_pgr_reg_done;
13098fe96085Stim szeto 	}
13108fe96085Stim szeto 
13118fe96085Stim szeto 	/* Handling unregistered IT session */
13128fe96085Stim szeto 	if (pr_out->action == PR_OUT_REGISTER && rsv_key != 0) {
13138fe96085Stim szeto 		stmf_scsilib_send_status(task, STATUS_RESERVATION_CONFLICT, 0);
13148fe96085Stim szeto 		return;
13158fe96085Stim szeto 	}
13168fe96085Stim szeto 
13178fe96085Stim szeto 	if (svc_key == 0) {
13188fe96085Stim szeto 		/* Do we need to consider aptpl here? I don't think so */
13198fe96085Stim szeto 		pgr->pgr_PRgeneration++;
13208fe96085Stim szeto 		stmf_scsilib_send_status(task, STATUS_GOOD, 0);
13218fe96085Stim szeto 		return;
13228fe96085Stim szeto 	}
13238fe96085Stim szeto 
1324716c1805SNattuvetty Bhavyan 	keyflag = SBD_PGR_KEY_TPT_ID_FLAG;
1325716c1805SNattuvetty Bhavyan 	if (plist->all_tg_pt) {
1326716c1805SNattuvetty Bhavyan 		keyflag |= SBD_PGR_KEY_ALL_TG_PT;
1327716c1805SNattuvetty Bhavyan 		lpt = NULL;
1328716c1805SNattuvetty Bhavyan 	}
1329716c1805SNattuvetty Bhavyan 
13308fe96085Stim szeto 	if (plist->spec_i_pt) {
1331716c1805SNattuvetty Bhavyan 		uint32_t max_tpdnum, tpdnum, i, adn_len = 0;
1332716c1805SNattuvetty Bhavyan 		uint16_t tpd_sz = 0;
1333716c1805SNattuvetty Bhavyan 		uint8_t *adn_dat;
1334716c1805SNattuvetty Bhavyan 		scsi_transport_id_t *tpd;
1335716c1805SNattuvetty Bhavyan 		stmf_remote_port_t *rpt_ary;
13368fe96085Stim szeto 
13378fe96085Stim szeto 		if (pr_out->action == PR_OUT_REGISTER_AND_IGNORE_EXISTING_KEY) {
13388fe96085Stim szeto 			stmf_scsilib_send_status(task, STATUS_CHECK,
13398fe96085Stim szeto 			    STMF_SAA_INVALID_FIELD_IN_CDB);
13408fe96085Stim szeto 			return;
13418fe96085Stim szeto 		}
13428fe96085Stim szeto 
1343716c1805SNattuvetty Bhavyan 		/* Length validation SPC3 rev23 Section 6.12.3 and Table 115 */
1344716c1805SNattuvetty Bhavyan 		if (buflen >= sizeof (scsi_prout_plist_t) - 1 +
1345716c1805SNattuvetty Bhavyan 		    sizeof (uint32_t))
1346716c1805SNattuvetty Bhavyan 			adn_len = READ_SCSI32(plist->apd, uint32_t);
1347716c1805SNattuvetty Bhavyan 		/* SPC3 rev23, adn_len should be multiple of 4 */
1348716c1805SNattuvetty Bhavyan 		if (adn_len % 4 != 0 ||
1349716c1805SNattuvetty Bhavyan 		    adn_len < sizeof (scsi_transport_id_t) +
1350716c1805SNattuvetty Bhavyan 		    sizeof (uint32_t) ||
1351716c1805SNattuvetty Bhavyan 		    buflen < sizeof (scsi_prout_plist_t) - 1 + adn_len) {
13528fe96085Stim szeto 			stmf_scsilib_send_status(task, STATUS_CHECK,
13538fe96085Stim szeto 			    STMF_SAA_PARAM_LIST_LENGTH_ERROR);
13548fe96085Stim szeto 			return;
13558fe96085Stim szeto 		}
1356716c1805SNattuvetty Bhavyan 
13578fe96085Stim szeto 		tpdnum = 0;
1358716c1805SNattuvetty Bhavyan 		adn_dat = plist->apd + sizeof (uint32_t);
1359716c1805SNattuvetty Bhavyan 		max_tpdnum = adn_len / sizeof (scsi_transport_id_t);
1360716c1805SNattuvetty Bhavyan 		rpt_ary = (stmf_remote_port_t *)kmem_zalloc(
1361716c1805SNattuvetty Bhavyan 		    sizeof (stmf_remote_port_t) * max_tpdnum, KM_SLEEP);
1362716c1805SNattuvetty Bhavyan 
13638fe96085Stim szeto 		/* Check the validity of given TransportIDs */
1364716c1805SNattuvetty Bhavyan 		while (adn_len != 0) {
1365716c1805SNattuvetty Bhavyan 			if (!stmf_scsilib_tptid_validate(
1366716c1805SNattuvetty Bhavyan 			    (scsi_transport_id_t *)adn_dat, adn_len, &tpd_sz))
13678fe96085Stim szeto 				break;
1368716c1805SNattuvetty Bhavyan 			/* SPC3 rev23, tpd_sz should be multiple of 4 */
1369716c1805SNattuvetty Bhavyan 			if (tpd_sz == 0 || tpd_sz % 4 != 0)
1370716c1805SNattuvetty Bhavyan 				break;
1371716c1805SNattuvetty Bhavyan 			tpd = (scsi_transport_id_t *)adn_dat;
1372716c1805SNattuvetty Bhavyan 
13738fe96085Stim szeto 			/* make sure that there is no duplicates */
13748fe96085Stim szeto 			for (i = 0; i < tpdnum; i++) {
1375716c1805SNattuvetty Bhavyan 				if (stmf_scsilib_tptid_compare(
1376716c1805SNattuvetty Bhavyan 				    rpt_ary[i].rport_tptid, tpd))
13778fe96085Stim szeto 					break;
13788fe96085Stim szeto 			}
1379716c1805SNattuvetty Bhavyan 			if (i < tpdnum)
13808fe96085Stim szeto 				break;
1381716c1805SNattuvetty Bhavyan 
1382716c1805SNattuvetty Bhavyan 			rpt_ary[tpdnum].rport_tptid = tpd;
1383716c1805SNattuvetty Bhavyan 			rpt_ary[tpdnum].rport_tptid_sz = tpd_sz;
1384716c1805SNattuvetty Bhavyan 
13858fe96085Stim szeto 			/* Check if the given IT nexus is already registered */
1386716c1805SNattuvetty Bhavyan 			if (sbd_pgr_key_registered(pgr, lpt, &rpt_ary[tpdnum]))
13878fe96085Stim szeto 				break;
13888fe96085Stim szeto 
1389716c1805SNattuvetty Bhavyan 			adn_len -= tpd_sz;
1390716c1805SNattuvetty Bhavyan 			adn_dat += tpd_sz;
1391716c1805SNattuvetty Bhavyan 			tpdnum++;
13928fe96085Stim szeto 		}
1393716c1805SNattuvetty Bhavyan 
1394716c1805SNattuvetty Bhavyan 		if (adn_len != 0) {
1395716c1805SNattuvetty Bhavyan 			kmem_free(rpt_ary,
1396716c1805SNattuvetty Bhavyan 			    sizeof (stmf_remote_port_t) * max_tpdnum);
13978fe96085Stim szeto 			stmf_scsilib_send_status(task, STATUS_CHECK,
13988fe96085Stim szeto 			    STMF_SAA_INVALID_FIELD_IN_CDB);
13998fe96085Stim szeto 			return;
14008fe96085Stim szeto 		}
1401716c1805SNattuvetty Bhavyan 
1402716c1805SNattuvetty Bhavyan 		for (i = 0; i < tpdnum; i++) {
1403716c1805SNattuvetty Bhavyan 			(void) sbd_pgr_do_register(slu, NULL, lpt, &rpt_ary[i],
1404716c1805SNattuvetty Bhavyan 			    keyflag, svc_key);
1405716c1805SNattuvetty Bhavyan 		}
1406716c1805SNattuvetty Bhavyan 		kmem_free(rpt_ary, sizeof (stmf_remote_port_t) * max_tpdnum);
14078fe96085Stim szeto 	}
14088fe96085Stim szeto 
1409716c1805SNattuvetty Bhavyan 	rport.rport_tptid = ses->ss_rport->rport_tptid;
1410716c1805SNattuvetty Bhavyan 	rport.rport_tptid_sz = ses->ss_rport->rport_tptid_sz;
1411716c1805SNattuvetty Bhavyan 
1412716c1805SNattuvetty Bhavyan 	(void) sbd_pgr_do_register(slu, it, lpt, &rport, keyflag, svc_key);
14138fe96085Stim szeto 
14148fe96085Stim szeto sbd_pgr_reg_done:
14158fe96085Stim szeto 
1416*61dfa509SRick McNeal 	if (plist->aptpl || (sbd_pgr_should_save(slu) == B_TRUE)) {
14178fe96085Stim szeto 		if (plist->aptpl)
14188fe96085Stim szeto 			PGR_SET_FLAG(pgr->pgr_flags, SBD_PGR_APTPL);
14198fe96085Stim szeto 		else
14208fe96085Stim szeto 			PGR_CLEAR_FLAG(pgr->pgr_flags, SBD_PGR_APTPL);
14218fe96085Stim szeto 
14228fe96085Stim szeto 		if (sbd_pgr_meta_write(slu) != SBD_SUCCESS) {
14238fe96085Stim szeto 			stmf_scsilib_send_status(task, STATUS_CHECK,
1424*61dfa509SRick McNeal 			    STMF_SAA_INSUFFICIENT_REG_RESRCS);
14258fe96085Stim szeto 			return;
14268fe96085Stim szeto 		}
14278fe96085Stim szeto 	}
14288fe96085Stim szeto 
14298fe96085Stim szeto 	pgr->pgr_PRgeneration++;
14308fe96085Stim szeto 	stmf_scsilib_send_status(task, STATUS_GOOD, 0);
14318fe96085Stim szeto }
14328fe96085Stim szeto 
14338fe96085Stim szeto static sbd_pgr_key_t *
sbd_pgr_do_register(sbd_lu_t * slu,sbd_it_data_t * it,scsi_devid_desc_t * lpt,stmf_remote_port_t * rpt,uint8_t keyflag,uint64_t svc_key)14348fe96085Stim szeto sbd_pgr_do_register(sbd_lu_t *slu, sbd_it_data_t *it, scsi_devid_desc_t *lpt,
1435*61dfa509SRick McNeal     stmf_remote_port_t *rpt, uint8_t keyflag, uint64_t svc_key)
14368fe96085Stim szeto {
14378fe96085Stim szeto 	sbd_pgr_t		*pgr = slu->sl_pgr;
14388fe96085Stim szeto 	sbd_pgr_key_t		*key;
1439716c1805SNattuvetty Bhavyan 	uint16_t		lpt_len = 0;
14408fe96085Stim szeto 
1441716c1805SNattuvetty Bhavyan 	if (lpt)
1442716c1805SNattuvetty Bhavyan 		lpt_len	= sizeof (scsi_devid_desc_t) + lpt->ident_length;
14438fe96085Stim szeto 
1444716c1805SNattuvetty Bhavyan 	key = sbd_pgr_key_alloc(lpt, rpt->rport_tptid,
1445716c1805SNattuvetty Bhavyan 	    lpt_len, rpt->rport_tptid_sz);
14468fe96085Stim szeto 	key->pgr_key = svc_key;
1447716c1805SNattuvetty Bhavyan 	key->pgr_key_flags |= keyflag;
14488fe96085Stim szeto 
1449716c1805SNattuvetty Bhavyan 	if (key->pgr_key_flags & SBD_PGR_KEY_ALL_TG_PT) {
14508fe96085Stim szeto 		/* set PGR_CHECK flag for all unregistered IT nexus */
14518fe96085Stim szeto 		sbd_pgr_set_pgr_check_flag(slu, B_FALSE);
14528fe96085Stim szeto 	} else {
14538fe96085Stim szeto 		key->pgr_key_it = it;
14548fe96085Stim szeto 	}
14558fe96085Stim szeto 
14568fe96085Stim szeto 	if (it) {
14578fe96085Stim szeto 		mutex_enter(&slu->sl_lock);
14588fe96085Stim szeto 		it->pgr_key_ptr = key;
14598fe96085Stim szeto 		mutex_exit(&slu->sl_lock);
1460716c1805SNattuvetty Bhavyan 	} else {
1461716c1805SNattuvetty Bhavyan 		sbd_pgr_set_pgr_check_flag(slu, B_FALSE);
14628fe96085Stim szeto 	}
14638fe96085Stim szeto 
14648fe96085Stim szeto 	key->pgr_key_next = pgr->pgr_keylist;
14658fe96085Stim szeto 	if (pgr->pgr_keylist) {
14668fe96085Stim szeto 		pgr->pgr_keylist->pgr_key_prev = key;
14678fe96085Stim szeto 	}
14688fe96085Stim szeto 	pgr->pgr_keylist = key;
14698fe96085Stim szeto 
14708fe96085Stim szeto 	return (key);
14718fe96085Stim szeto }
14728fe96085Stim szeto 
14738fe96085Stim szeto static void
sbd_pgr_do_unregister(sbd_lu_t * slu,sbd_it_data_t * it,sbd_pgr_key_t * key)14748fe96085Stim szeto sbd_pgr_do_unregister(sbd_lu_t *slu, sbd_it_data_t *it, sbd_pgr_key_t *key)
14758fe96085Stim szeto {
14768fe96085Stim szeto 	if (slu->sl_pgr->pgr_rsvholder == key) {
14778fe96085Stim szeto 		sbd_pgr_do_release(slu, it, SBD_UA_RESERVATIONS_RELEASED);
14788fe96085Stim szeto 	}
14798fe96085Stim szeto 
14808fe96085Stim szeto 	sbd_pgr_remove_key(slu, key);
14818fe96085Stim szeto 	if (slu->sl_pgr->pgr_keylist == NULL) {
14828fe96085Stim szeto 		PGR_CLEAR_RSV_FLAG(slu->sl_pgr->pgr_flags);
14838fe96085Stim szeto 	}
14848fe96085Stim szeto }
14858fe96085Stim szeto 
14868fe96085Stim szeto static void
sbd_pgr_out_reserve(scsi_task_t * task)14878fe96085Stim szeto sbd_pgr_out_reserve(scsi_task_t *task)
14888fe96085Stim szeto {
14898fe96085Stim szeto 	sbd_lu_t	*slu   = (sbd_lu_t *)task->task_lu->lu_provider_private;
14908fe96085Stim szeto 	stmf_scsi_session_t	*ses	= task->task_session;
14918fe96085Stim szeto 	scsi_cdb_prout_t	*pr_out	= (scsi_cdb_prout_t *)task->task_cdb;
14928fe96085Stim szeto 	sbd_it_data_t		*it	= task->task_lu_itl_handle;
14938fe96085Stim szeto 	sbd_pgr_t		*pgr	= slu->sl_pgr;
14948fe96085Stim szeto 	sbd_pgr_key_t		*key	= it->pgr_key_ptr;
14958fe96085Stim szeto 
14968fe96085Stim szeto 	ASSERT(key);
14978fe96085Stim szeto 
14988fe96085Stim szeto 	if (!(PGR_VALID_SCOPE(pr_out->scope) && PGR_VALID_TYPE(pr_out->type))) {
14998fe96085Stim szeto 		stmf_scsilib_send_status(task, STATUS_CHECK,
15008fe96085Stim szeto 		    STMF_SAA_INVALID_FIELD_IN_CDB);
15018fe96085Stim szeto 		return;
15028fe96085Stim szeto 	}
15038fe96085Stim szeto 
15048fe96085Stim szeto 	if (SBD_PGR_RSVD(pgr)) {
15058fe96085Stim szeto 		if (PGR_RESERVATION_HOLDER(pgr, key, it)) {
15068fe96085Stim szeto 			if (pgr->pgr_rsv_type != pr_out->type ||
15078fe96085Stim szeto 			    pgr->pgr_rsv_scope != pr_out->scope) {
15088fe96085Stim szeto 				stmf_scsilib_send_status(task,
15098fe96085Stim szeto 				    STATUS_RESERVATION_CONFLICT, 0);
15108fe96085Stim szeto 				return;
15118fe96085Stim szeto 			}
15128fe96085Stim szeto 		} else {
15138fe96085Stim szeto 			stmf_scsilib_send_status(task,
15148fe96085Stim szeto 			    STATUS_RESERVATION_CONFLICT, 0);
15158fe96085Stim szeto 			return;
15168fe96085Stim szeto 
15178fe96085Stim szeto 		}
15188fe96085Stim szeto 	/* In case there is no reservation exist */
15198fe96085Stim szeto 	} else {
15208fe96085Stim szeto 		sbd_pgr_do_reserve(pgr, key, it, ses, pr_out);
1521*61dfa509SRick McNeal 		if (sbd_pgr_should_save(slu) == B_TRUE) {
15228fe96085Stim szeto 			if (sbd_pgr_meta_write(slu) != SBD_SUCCESS) {
15238fe96085Stim szeto 				stmf_scsilib_send_status(task, STATUS_CHECK,
1524*61dfa509SRick McNeal 				    STMF_SAA_INSUFFICIENT_REG_RESRCS);
15258fe96085Stim szeto 				return;
15268fe96085Stim szeto 			}
15278fe96085Stim szeto 		}
15288fe96085Stim szeto 	}
15298fe96085Stim szeto 
15308fe96085Stim szeto 	stmf_scsilib_send_status(task, STATUS_GOOD, 0);
15318fe96085Stim szeto }
15328fe96085Stim szeto 
15338fe96085Stim szeto static void
sbd_pgr_do_reserve(sbd_pgr_t * pgr,sbd_pgr_key_t * key,sbd_it_data_t * it,stmf_scsi_session_t * ses,scsi_cdb_prout_t * pr_out)15348fe96085Stim szeto sbd_pgr_do_reserve(sbd_pgr_t *pgr, sbd_pgr_key_t *key, sbd_it_data_t *it,
1535*61dfa509SRick McNeal     stmf_scsi_session_t *ses, scsi_cdb_prout_t *pr_out)
15368fe96085Stim szeto {
15378fe96085Stim szeto 	scsi_devid_desc_t	*lpt;
15388fe96085Stim szeto 	uint16_t		lpt_len;
15398fe96085Stim szeto 
15408fe96085Stim szeto 	pgr->pgr_rsv_type = pr_out->type;
15418fe96085Stim szeto 	pgr->pgr_rsv_scope = pr_out->scope;
15428fe96085Stim szeto 	if (pr_out->type == PGR_TYPE_WR_EX_AR ||
15438fe96085Stim szeto 	    pr_out->type == PGR_TYPE_EX_AC_AR) {
15448fe96085Stim szeto 		PGR_SET_FLAG(pgr->pgr_flags, SBD_PGR_RSVD_ALL_REGISTRANTS);
15458fe96085Stim szeto 	} else {
15468fe96085Stim szeto 		if (key->pgr_key_flags & SBD_PGR_KEY_ALL_TG_PT) {
15478fe96085Stim szeto 			lpt = key->pgr_key_lpt_id;
15488fe96085Stim szeto 			lpt_len = key->pgr_key_lpt_len;
15498fe96085Stim szeto 			if (lpt_len > 0 && lpt != NULL) {
15508fe96085Stim szeto 				kmem_free(lpt, lpt_len);
15518fe96085Stim szeto 			}
15528fe96085Stim szeto 			lpt = ses->ss_lport->lport_id;
1553716c1805SNattuvetty Bhavyan 			lpt_len = sizeof (scsi_devid_desc_t) +
15548fe96085Stim szeto 			    lpt->ident_length;
15558fe96085Stim szeto 			key->pgr_key_lpt_len = lpt_len;
15568fe96085Stim szeto 			key->pgr_key_lpt_id = (scsi_devid_desc_t *)
15578fe96085Stim szeto 			    kmem_zalloc(lpt_len, KM_SLEEP);
15588fe96085Stim szeto 			bcopy(lpt, key->pgr_key_lpt_id, lpt_len);
15598fe96085Stim szeto 			key->pgr_key_it = it;
15608fe96085Stim szeto 		}
15618fe96085Stim szeto 
15628fe96085Stim szeto 		PGR_SET_FLAG(pgr->pgr_flags, SBD_PGR_RSVD_ONE);
15638fe96085Stim szeto 		pgr->pgr_rsvholder = key;
15648fe96085Stim szeto 	}
15658fe96085Stim szeto }
15668fe96085Stim szeto 
15678fe96085Stim szeto static void
sbd_pgr_out_release(scsi_task_t * task)15688fe96085Stim szeto sbd_pgr_out_release(scsi_task_t *task)
15698fe96085Stim szeto {
15708fe96085Stim szeto 	sbd_lu_t	*slu   = (sbd_lu_t *)task->task_lu->lu_provider_private;
15718fe96085Stim szeto 	scsi_cdb_prout_t	*pr_out	= (scsi_cdb_prout_t *)task->task_cdb;
15728fe96085Stim szeto 	sbd_it_data_t		*it	= task->task_lu_itl_handle;
15738fe96085Stim szeto 	sbd_pgr_t		*pgr	= slu->sl_pgr;
15748fe96085Stim szeto 	sbd_pgr_key_t		*key	= it->pgr_key_ptr;
15758fe96085Stim szeto 
15768fe96085Stim szeto 	ASSERT(key);
15778fe96085Stim szeto 
1578*61dfa509SRick McNeal 	/*
1579*61dfa509SRick McNeal 	 * XXX this does not honor APTPL
1580*61dfa509SRick McNeal 	 * (i.e., changes made to a formerly-persistent reservation are not
1581*61dfa509SRick McNeal 	 *  updated here!!!)
1582*61dfa509SRick McNeal 	 */
15838fe96085Stim szeto 	if (SBD_PGR_RSVD(pgr)) {
15848fe96085Stim szeto 		if (pgr->pgr_flags & SBD_PGR_RSVD_ALL_REGISTRANTS ||
15858fe96085Stim szeto 		    pgr->pgr_rsvholder == key) {
15868fe96085Stim szeto 			if (pgr->pgr_rsv_type != pr_out->type ||
15878fe96085Stim szeto 			    pgr->pgr_rsv_scope != pr_out->scope) {
15888fe96085Stim szeto 				stmf_scsilib_send_status(task, STATUS_CHECK,
15898fe96085Stim szeto 				    STMF_SAA_INVALID_RELEASE_OF_PR);
15908fe96085Stim szeto 				return;
15918fe96085Stim szeto 			}
15928fe96085Stim szeto 			sbd_pgr_do_release(slu, it,
15938fe96085Stim szeto 			    SBD_UA_RESERVATIONS_RELEASED);
1594*61dfa509SRick McNeal 
1595*61dfa509SRick McNeal 			/*
1596*61dfa509SRick McNeal 			 * XXX T10 SPC-3 5.6.10.2 says nothing about what to
1597*61dfa509SRick McNeal 			 * do in the event of a failure updating the
1598*61dfa509SRick McNeal 			 * PGR nvram store for a reservation associated with
1599*61dfa509SRick McNeal 			 * an APTPL-enabled (see SPC-3 5.6.4.1) I_T
1600*61dfa509SRick McNeal 			 * registration during a RELEASE service action.
1601*61dfa509SRick McNeal 			 *
1602*61dfa509SRick McNeal 			 * Technically, the CDB completed successfully, as per
1603*61dfa509SRick McNeal 			 * the spec, but at some point we may need to enter
1604*61dfa509SRick McNeal 			 * a recovery mode on the initiator(s) if we power cycle
1605*61dfa509SRick McNeal 			 * the target at the wrong instant...
1606*61dfa509SRick McNeal 			 */
1607*61dfa509SRick McNeal 			if (sbd_pgr_should_save(slu) == B_TRUE) {
1608*61dfa509SRick McNeal 				if (sbd_pgr_meta_write(slu) != SBD_SUCCESS) {
1609*61dfa509SRick McNeal 					stmf_scsilib_send_status(task,
1610*61dfa509SRick McNeal 					    STATUS_CHECK,
1611*61dfa509SRick McNeal 					    STMF_SAA_INSUFFICIENT_REG_RESRCS);
1612*61dfa509SRick McNeal 					return;
1613*61dfa509SRick McNeal 				}
1614*61dfa509SRick McNeal 			}
16158fe96085Stim szeto 		}
16168fe96085Stim szeto 	}
16178fe96085Stim szeto 	stmf_scsilib_send_status(task, STATUS_GOOD, 0);
16188fe96085Stim szeto }
16198fe96085Stim szeto 
16208fe96085Stim szeto static void
sbd_pgr_do_release(sbd_lu_t * slu,sbd_it_data_t * it,uint8_t ua_condition)16218fe96085Stim szeto sbd_pgr_do_release(sbd_lu_t *slu, sbd_it_data_t *it, uint8_t ua_condition)
16228fe96085Stim szeto {
16238fe96085Stim szeto 
16248fe96085Stim szeto 	sbd_pgr_t *pgr    =  slu->sl_pgr;
16258fe96085Stim szeto 
16268fe96085Stim szeto 	/* Reset pgr_flags */
16278fe96085Stim szeto 	PGR_CLEAR_RSV_FLAG(pgr->pgr_flags);
16288fe96085Stim szeto 	pgr->pgr_rsvholder = NULL;
16298fe96085Stim szeto 
16308fe96085Stim szeto 	/* set unit attention condition if necessary */
16318fe96085Stim szeto 	if (pgr->pgr_rsv_type != PGR_TYPE_WR_EX &&
16328fe96085Stim szeto 	    pgr->pgr_rsv_type != PGR_TYPE_EX_AC) {
16338fe96085Stim szeto 		sbd_pgr_set_ua_conditions(slu, it, ua_condition);
16348fe96085Stim szeto 	}
16358fe96085Stim szeto 	pgr->pgr_rsv_type = 0;
16368fe96085Stim szeto }
16378fe96085Stim szeto 
16388fe96085Stim szeto static void
sbd_pgr_out_clear(scsi_task_t * task)16398fe96085Stim szeto sbd_pgr_out_clear(scsi_task_t *task)
16408fe96085Stim szeto {
16418fe96085Stim szeto 	sbd_lu_t	*slu   = (sbd_lu_t *)task->task_lu->lu_provider_private;
16428fe96085Stim szeto 	sbd_it_data_t		*it	= task->task_lu_itl_handle;
16438fe96085Stim szeto 	sbd_pgr_t		*pgr	= slu->sl_pgr;
16448fe96085Stim szeto 
16458fe96085Stim szeto 	ASSERT(it->pgr_key_ptr);
16468fe96085Stim szeto 
16478fe96085Stim szeto 	PGR_CLEAR_RSV_FLAG(pgr->pgr_flags);
16488fe96085Stim szeto 	pgr->pgr_rsvholder = NULL;
16498fe96085Stim szeto 	pgr->pgr_rsv_type = 0;
16508fe96085Stim szeto 	mutex_enter(&slu->sl_lock);
16518fe96085Stim szeto 	/* Remove all pointers from IT to pgr keys */
16528fe96085Stim szeto 	for (it = slu->sl_it_list; it != NULL; it = it->sbd_it_next) {
16538fe96085Stim szeto 		it->pgr_key_ptr = NULL;
16548fe96085Stim szeto 	}
16558fe96085Stim szeto 	mutex_exit(&slu->sl_lock);
16568fe96085Stim szeto 	sbd_pgr_keylist_dealloc(slu);
16578fe96085Stim szeto 	sbd_pgr_set_ua_conditions(slu, it, SBD_UA_RESERVATIONS_PREEMPTED);
1658*61dfa509SRick McNeal 	if (sbd_pgr_should_save(slu) == B_TRUE) {
16598fe96085Stim szeto 		if (sbd_pgr_meta_write(slu) != SBD_SUCCESS) {
16608fe96085Stim szeto 			stmf_scsilib_send_status(task, STATUS_CHECK,
1661*61dfa509SRick McNeal 			    STMF_SAA_INSUFFICIENT_REG_RESRCS);
16628fe96085Stim szeto 			return;
16638fe96085Stim szeto 		}
16648fe96085Stim szeto 	}
16658fe96085Stim szeto 	pgr->pgr_PRgeneration++;
16668fe96085Stim szeto 	stmf_scsilib_send_status(task, STATUS_GOOD, 0);
16678fe96085Stim szeto }
16688fe96085Stim szeto 
16698fe96085Stim szeto static void
sbd_pgr_out_preempt(scsi_task_t * task,stmf_data_buf_t * dbuf)16708fe96085Stim szeto sbd_pgr_out_preempt(scsi_task_t *task, stmf_data_buf_t *dbuf)
16718fe96085Stim szeto {
16728fe96085Stim szeto 	sbd_lu_t	*slu   = (sbd_lu_t *)task->task_lu->lu_provider_private;
16738fe96085Stim szeto 	stmf_scsi_session_t	*ses	= task->task_session;
16748fe96085Stim szeto 	scsi_cdb_prout_t	*pr_out	= (scsi_cdb_prout_t *)task->task_cdb;
16758fe96085Stim szeto 	sbd_it_data_t		*it	= task->task_lu_itl_handle;
16768fe96085Stim szeto 	sbd_pgr_t		*pgr	= slu->sl_pgr;
16778fe96085Stim szeto 	sbd_pgr_key_t		*key	= it->pgr_key_ptr;
16788fe96085Stim szeto 	scsi_prout_plist_t	*plist;
16798fe96085Stim szeto 	uint8_t			*buf, change_rsv = 0;
16808fe96085Stim szeto 	uint64_t		svc_key;
16818fe96085Stim szeto 
16828fe96085Stim szeto 	ASSERT(key);
16838fe96085Stim szeto 
16848fe96085Stim szeto 	buf = dbuf->db_sglist[0].seg_addr;
16858fe96085Stim szeto 	plist = (scsi_prout_plist_t *)buf;
16868fe96085Stim szeto 	svc_key = READ_SCSI64(plist->service_key, uint64_t);
16878fe96085Stim szeto 
16888fe96085Stim szeto 	if (SBD_PGR_RSVD_NONE(pgr)) {
16898fe96085Stim szeto 		if (svc_key == 0 ||
16908fe96085Stim szeto 		    sbd_pgr_remove_keys(slu, it, key, svc_key, B_TRUE) == 0) {
16918fe96085Stim szeto 			stmf_scsilib_send_status(task,
16928fe96085Stim szeto 			    STATUS_RESERVATION_CONFLICT, 0);
16938fe96085Stim szeto 			return;
16948fe96085Stim szeto 		}
16958fe96085Stim szeto 
16968fe96085Stim szeto 	} else if (pgr->pgr_flags & SBD_PGR_RSVD_ONE) {
16978fe96085Stim szeto 		if (svc_key == 0) {
16988fe96085Stim szeto 			stmf_scsilib_send_status(task, STATUS_CHECK,
16998fe96085Stim szeto 			    STMF_SAA_INVALID_FIELD_IN_CDB);
17008fe96085Stim szeto 			return;
17018fe96085Stim szeto 		}
17028fe96085Stim szeto 
17038fe96085Stim szeto 		/* Validity check of scope and type */
17048fe96085Stim szeto 		if (pgr->pgr_rsvholder->pgr_key == svc_key) {
17058fe96085Stim szeto 			if (!(PGR_VALID_SCOPE(pr_out->scope) &&
17068fe96085Stim szeto 			    PGR_VALID_TYPE(pr_out->type))) {
17078fe96085Stim szeto 				stmf_scsilib_send_status(task, STATUS_CHECK,
17088fe96085Stim szeto 				    STMF_SAA_INVALID_FIELD_IN_CDB);
17098fe96085Stim szeto 				return;
17108fe96085Stim szeto 			}
17118fe96085Stim szeto 		}
17128fe96085Stim szeto 
17138fe96085Stim szeto 		if (pgr->pgr_rsvholder != key &&
17148fe96085Stim szeto 		    pgr->pgr_rsvholder->pgr_key == svc_key) {
17158fe96085Stim szeto 			sbd_pgr_do_release(slu, it,
17168fe96085Stim szeto 			    SBD_UA_REGISTRATIONS_PREEMPTED);
17178fe96085Stim szeto 			change_rsv = 1;
17188fe96085Stim szeto 		}
17198fe96085Stim szeto 
17208fe96085Stim szeto 		if (pgr->pgr_rsvholder == key &&
17218fe96085Stim szeto 		    pgr->pgr_rsvholder->pgr_key == svc_key) {
17228fe96085Stim szeto 			if (pr_out->scope != pgr->pgr_rsv_scope ||
17238fe96085Stim szeto 			    pr_out->type != pgr->pgr_rsv_type) {
17248fe96085Stim szeto 				sbd_pgr_do_release(slu, it,
17258fe96085Stim szeto 				    SBD_UA_REGISTRATIONS_PREEMPTED);
17268fe96085Stim szeto 				change_rsv = 1;
17278fe96085Stim szeto 			}
17288fe96085Stim szeto 		} else {
17298fe96085Stim szeto 			/*
17308fe96085Stim szeto 			 * Remove matched keys in all cases, except when the
17318fe96085Stim szeto 			 * current IT nexus holds the reservation and the given
17328fe96085Stim szeto 			 * svc_key matches with registered key.
17338fe96085Stim szeto 			 * Note that, if the reservation is held by another
17348fe96085Stim szeto 			 * IT nexus, and svc_key matches registered key for
17358fe96085Stim szeto 			 * that IT nexus, sbd_pgr_remove_key() is not expected
17368fe96085Stim szeto 			 * return 0. Hence, returning check condition after
17378fe96085Stim szeto 			 * releasing the reservation does not arise.
17388fe96085Stim szeto 			 */
17398fe96085Stim szeto 			if (sbd_pgr_remove_keys(slu, it, key, svc_key, B_TRUE)
17408fe96085Stim szeto 			    == 0) {
17418fe96085Stim szeto 				stmf_scsilib_send_status(task,
17428fe96085Stim szeto 				    STATUS_RESERVATION_CONFLICT, 0);
17438fe96085Stim szeto 				return;
17448fe96085Stim szeto 			}
17458fe96085Stim szeto 		}
17468fe96085Stim szeto 
17478fe96085Stim szeto 		if (change_rsv) {
17488fe96085Stim szeto 			sbd_pgr_do_reserve(pgr, key, it, ses, pr_out);
17498fe96085Stim szeto 		}
17508fe96085Stim szeto 
17518fe96085Stim szeto 	} else if (pgr->pgr_flags & SBD_PGR_RSVD_ALL_REGISTRANTS) {
17528fe96085Stim szeto 		if (svc_key == 0) {
17538fe96085Stim szeto 			if (!(PGR_VALID_SCOPE(pr_out->scope) &&
17548fe96085Stim szeto 			    PGR_VALID_TYPE(pr_out->type))) {
17558fe96085Stim szeto 				stmf_scsilib_send_status(task, STATUS_CHECK,
17568fe96085Stim szeto 				    STMF_SAA_INVALID_FIELD_IN_CDB);
17578fe96085Stim szeto 				return;
17588fe96085Stim szeto 			}
17598fe96085Stim szeto 			sbd_pgr_do_release(slu, it,
17608fe96085Stim szeto 			    SBD_UA_REGISTRATIONS_PREEMPTED);
17618fe96085Stim szeto 			(void) sbd_pgr_remove_keys(slu, it, key, 0, B_FALSE);
17628fe96085Stim szeto 			sbd_pgr_do_reserve(pgr, key, it, ses, pr_out);
17638fe96085Stim szeto 		} else {
17648fe96085Stim szeto 			if (sbd_pgr_remove_keys(slu, it, key, svc_key, B_TRUE)
17658fe96085Stim szeto 			    == 0) {
17668fe96085Stim szeto 				stmf_scsilib_send_status(task,
17678fe96085Stim szeto 				    STATUS_RESERVATION_CONFLICT, 0);
17688fe96085Stim szeto 				return;
17698fe96085Stim szeto 			}
17708fe96085Stim szeto 		}
17718fe96085Stim szeto 	}
17728fe96085Stim szeto 
1773*61dfa509SRick McNeal 	if (sbd_pgr_should_save(slu) == B_TRUE) {
17748fe96085Stim szeto 		if (sbd_pgr_meta_write(slu) != SBD_SUCCESS) {
17758fe96085Stim szeto 			stmf_scsilib_send_status(task, STATUS_CHECK,
1776*61dfa509SRick McNeal 			    STMF_SAA_INSUFFICIENT_REG_RESRCS);
17778fe96085Stim szeto 			return;
17788fe96085Stim szeto 		}
17798fe96085Stim szeto 	}
17808fe96085Stim szeto 
17818fe96085Stim szeto 	pgr->pgr_PRgeneration++;
17828fe96085Stim szeto 
17838fe96085Stim szeto 	if (pr_out->action == PR_OUT_PREEMPT_ABORT) {
178444b678cfSNattuvetty Bhavyan 		stmf_abort(STMF_QUEUE_ABORT_LU, task, STMF_ABORTED,
178544b678cfSNattuvetty Bhavyan 		    (void *)slu->sl_lu);
17868fe96085Stim szeto 	}
178744b678cfSNattuvetty Bhavyan 	stmf_scsilib_send_status(task, STATUS_GOOD, 0);
17888fe96085Stim szeto }
17898fe96085Stim szeto 
17908fe96085Stim szeto static void
sbd_pgr_out_register_and_move(scsi_task_t * task,stmf_data_buf_t * dbuf)17918fe96085Stim szeto sbd_pgr_out_register_and_move(scsi_task_t *task, stmf_data_buf_t *dbuf)
17928fe96085Stim szeto {
17938fe96085Stim szeto 	sbd_lu_t	*slu   = (sbd_lu_t *)task->task_lu->lu_provider_private;
17948fe96085Stim szeto 	sbd_it_data_t		*it	= task->task_lu_itl_handle;
17958fe96085Stim szeto 	sbd_pgr_t		*pgr	= slu->sl_pgr;
17968fe96085Stim szeto 	sbd_pgr_key_t		*key	= it->pgr_key_ptr;
1797716c1805SNattuvetty Bhavyan 	scsi_devid_desc_t	*lpt;
1798716c1805SNattuvetty Bhavyan 	stmf_remote_port_t	rport;
17998fe96085Stim szeto 	sbd_pgr_key_t		*newkey;
18008fe96085Stim szeto 	scsi_prout_reg_move_plist_t *plist;
18018fe96085Stim szeto 	uint8_t			*buf, lpt_len;
1802716c1805SNattuvetty Bhavyan 	uint16_t		tpd_len;
1803716c1805SNattuvetty Bhavyan 	uint32_t		adn_len;
18048fe96085Stim szeto 	uint64_t		svc_key;
18058fe96085Stim szeto 
18068fe96085Stim szeto 	/*
18078fe96085Stim szeto 	 * Check whether the key holds the reservation or current reservation
18088fe96085Stim szeto 	 * is of type all registrants.
18098fe96085Stim szeto 	 */
18108fe96085Stim szeto 	if (pgr->pgr_rsvholder != key) {
18118fe96085Stim szeto 		stmf_scsilib_send_status(task, STATUS_RESERVATION_CONFLICT, 0);
18128fe96085Stim szeto 		return;
18138fe96085Stim szeto 	}
18148fe96085Stim szeto 
18158fe96085Stim szeto 	buf = dbuf->db_sglist[0].seg_addr;
18168fe96085Stim szeto 	plist = (scsi_prout_reg_move_plist_t *)buf;
18178fe96085Stim szeto 	svc_key = READ_SCSI64(plist->service_key, uint64_t);
18188fe96085Stim szeto 	if (svc_key == 0) {
18198fe96085Stim szeto 		stmf_scsilib_send_status(task, STATUS_CHECK,
18208fe96085Stim szeto 		    STMF_SAA_INVALID_FIELD_IN_CDB);
18218fe96085Stim szeto 		return;
18228fe96085Stim szeto 	}
18238fe96085Stim szeto 
18248fe96085Stim szeto 	lpt = stmf_scsilib_get_devid_desc(READ_SCSI16(plist->rel_tgt_port_id,
18258fe96085Stim szeto 	    uint16_t));
18268fe96085Stim szeto 	if (lpt == NULL) {
18278fe96085Stim szeto 		stmf_scsilib_send_status(task, STATUS_CHECK,
18288fe96085Stim szeto 		    STMF_SAA_INVALID_FIELD_IN_CDB);
18298fe96085Stim szeto 		return;
18308fe96085Stim szeto 	}
18318fe96085Stim szeto 
1832716c1805SNattuvetty Bhavyan 	adn_len = READ_SCSI32(plist->tptid_len, uint32_t);
1833716c1805SNattuvetty Bhavyan 	if (!stmf_scsilib_tptid_validate(
1834716c1805SNattuvetty Bhavyan 	    (scsi_transport_id_t *)plist->tptid, adn_len, &tpd_len)) {
1835716c1805SNattuvetty Bhavyan 		kmem_free(lpt, sizeof (scsi_devid_desc_t) + lpt->ident_length);
18368fe96085Stim szeto 		stmf_scsilib_send_status(task, STATUS_CHECK,
18378fe96085Stim szeto 		    STMF_SAA_INVALID_FIELD_IN_PARAM_LIST);
18388fe96085Stim szeto 		return;
1839716c1805SNattuvetty Bhavyan 	}
1840716c1805SNattuvetty Bhavyan 
1841716c1805SNattuvetty Bhavyan 	rport.rport_tptid = (scsi_transport_id_t *)plist->tptid;
1842716c1805SNattuvetty Bhavyan 	rport.rport_tptid_sz = tpd_len;
1843716c1805SNattuvetty Bhavyan 
1844716c1805SNattuvetty Bhavyan 	if (sbd_pgr_key_compare(key, lpt, &rport)) {
1845716c1805SNattuvetty Bhavyan 		kmem_free(lpt, sizeof (scsi_devid_desc_t) + lpt->ident_length);
18468fe96085Stim szeto 		stmf_scsilib_send_status(task, STATUS_CHECK,
18478fe96085Stim szeto 		    STMF_SAA_INVALID_FIELD_IN_PARAM_LIST);
18488fe96085Stim szeto 		return;
18498fe96085Stim szeto 	}
18508fe96085Stim szeto 
1851716c1805SNattuvetty Bhavyan 	newkey = sbd_pgr_key_registered(pgr, lpt, &rport);
18528fe96085Stim szeto 	if (newkey) {
18538fe96085Stim szeto 		/* Set the pgr_key, irrespective of what it currently holds */
18548fe96085Stim szeto 		newkey->pgr_key = svc_key;
18558fe96085Stim szeto 
18568fe96085Stim szeto 		/* all_tg_pt is set for found key, copy lpt info to the key */
18578fe96085Stim szeto 		if (newkey->pgr_key_flags & SBD_PGR_KEY_ALL_TG_PT) {
18588fe96085Stim szeto 			if (newkey->pgr_key_lpt_id &&
18598fe96085Stim szeto 			    newkey->pgr_key_lpt_len > 0) {
18608fe96085Stim szeto 				kmem_free(newkey->pgr_key_lpt_id,
18618fe96085Stim szeto 				    newkey->pgr_key_lpt_len);
18628fe96085Stim szeto 			}
1863716c1805SNattuvetty Bhavyan 			lpt_len = sizeof (scsi_devid_desc_t) +
18648fe96085Stim szeto 			    lpt->ident_length;
18658fe96085Stim szeto 			newkey->pgr_key_lpt_len = lpt_len;
18668fe96085Stim szeto 			newkey->pgr_key_lpt_id = (scsi_devid_desc_t *)
18678fe96085Stim szeto 			    kmem_zalloc(lpt_len, KM_SLEEP);
18688fe96085Stim szeto 			bcopy(lpt, newkey->pgr_key_lpt_id, lpt_len);
18698fe96085Stim szeto 		}
1870716c1805SNattuvetty Bhavyan 		/* No IT nexus information, hence set PGR_CHEK flag */
1871716c1805SNattuvetty Bhavyan 		sbd_pgr_set_pgr_check_flag(slu, B_TRUE);
18728fe96085Stim szeto 	} else  {
1873716c1805SNattuvetty Bhavyan 		newkey = sbd_pgr_do_register(slu, NULL, lpt, &rport,
1874716c1805SNattuvetty Bhavyan 		    SBD_PGR_KEY_TPT_ID_FLAG, svc_key);
18758fe96085Stim szeto 	}
18768fe96085Stim szeto 
1877716c1805SNattuvetty Bhavyan 	kmem_free(lpt, sizeof (scsi_devid_desc_t) + lpt->ident_length);
18788fe96085Stim szeto 
18798fe96085Stim szeto 	/* Now reserve the key corresponding to the specified IT nexus */
18808fe96085Stim szeto 	pgr->pgr_rsvholder = newkey;
18818fe96085Stim szeto 
18828fe96085Stim szeto 	if (plist->unreg) {
18838fe96085Stim szeto 		sbd_pgr_do_unregister(slu, it, key);
18848fe96085Stim szeto 	}
18858fe96085Stim szeto 
18868fe96085Stim szeto 
1887*61dfa509SRick McNeal 	/* Write to disk if aptpl is currently set or this task is setting it */
1888*61dfa509SRick McNeal 	if (plist->aptpl || (sbd_pgr_should_save(slu) == B_TRUE)) {
18898fe96085Stim szeto 		if (plist->aptpl)
18908fe96085Stim szeto 			PGR_SET_FLAG(pgr->pgr_flags, SBD_PGR_APTPL);
18918fe96085Stim szeto 		else
18928fe96085Stim szeto 			PGR_CLEAR_FLAG(pgr->pgr_flags, SBD_PGR_APTPL);
18938fe96085Stim szeto 
18948fe96085Stim szeto 		if (sbd_pgr_meta_write(slu) != SBD_SUCCESS) {
18958fe96085Stim szeto 			stmf_scsilib_send_status(task, STATUS_CHECK,
1896*61dfa509SRick McNeal 			    STMF_SAA_INSUFFICIENT_REG_RESRCS);
18978fe96085Stim szeto 			return;
18988fe96085Stim szeto 		}
18998fe96085Stim szeto 	}
19008fe96085Stim szeto 
19018fe96085Stim szeto 	pgr->pgr_PRgeneration++;
19028fe96085Stim szeto 	stmf_scsilib_send_status(task, STATUS_GOOD, 0);
19038fe96085Stim szeto }
19048fe96085Stim szeto 
19058fe96085Stim szeto void
sbd_pgr_remove_it_handle(sbd_lu_t * sl,sbd_it_data_t * my_it)1906*61dfa509SRick McNeal sbd_pgr_remove_it_handle(sbd_lu_t *sl, sbd_it_data_t *my_it)
1907*61dfa509SRick McNeal {
19088fe96085Stim szeto 	sbd_it_data_t *it;
19098fe96085Stim szeto 
19108fe96085Stim szeto 	rw_enter(&sl->sl_pgr->pgr_lock, RW_WRITER);
19118fe96085Stim szeto 	mutex_enter(&sl->sl_lock);
19128fe96085Stim szeto 	for (it = sl->sl_it_list; it != NULL; it = it->sbd_it_next) {
19138fe96085Stim szeto 		if (it == my_it) {
19148fe96085Stim szeto 			if (it->pgr_key_ptr) {
19158fe96085Stim szeto 				sbd_pgr_key_t *key = it->pgr_key_ptr;
19168fe96085Stim szeto 				if (key->pgr_key_it == it) {
19178fe96085Stim szeto 					key->pgr_key_it = NULL;
19188fe96085Stim szeto 					sl->sl_pgr->pgr_flags &=
19198fe96085Stim szeto 					    ~SBD_PGR_ALL_KEYS_HAS_IT;
19208fe96085Stim szeto 				}
19218fe96085Stim szeto 			}
19228fe96085Stim szeto 			break;
19238fe96085Stim szeto 		}
19248fe96085Stim szeto 	}
19258fe96085Stim szeto 	mutex_exit(&sl->sl_lock);
19268fe96085Stim szeto 	rw_exit(&sl->sl_pgr->pgr_lock);
19278fe96085Stim szeto 
19288fe96085Stim szeto }
19298fe96085Stim szeto 
19308fe96085Stim szeto char *
sbd_get_devid_string(sbd_lu_t * sl)19318fe96085Stim szeto sbd_get_devid_string(sbd_lu_t *sl)
19328fe96085Stim szeto {
19338fe96085Stim szeto 	char *str = (char *)kmem_zalloc(33, KM_SLEEP);
19348fe96085Stim szeto 	(void) snprintf(str, 33,
19358fe96085Stim szeto 	    "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
19368fe96085Stim szeto 	    sl->sl_device_id[4], sl->sl_device_id[5], sl->sl_device_id[6],
19378fe96085Stim szeto 	    sl->sl_device_id[7], sl->sl_device_id[8], sl->sl_device_id[9],
19388fe96085Stim szeto 	    sl->sl_device_id[10], sl->sl_device_id[11], sl->sl_device_id[12],
19398fe96085Stim szeto 	    sl->sl_device_id[13], sl->sl_device_id[14], sl->sl_device_id[15],
19408fe96085Stim szeto 	    sl->sl_device_id[16], sl->sl_device_id[17], sl->sl_device_id[18],
19418fe96085Stim szeto 	    sl->sl_device_id[19]);
19428fe96085Stim szeto 	return (str);
19438fe96085Stim szeto }
1944