Print this page
7127 remove -Wno-missing-braces from Makefile.uts
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/uts/common/io/scsi/adapters/scsi_vhci/fops/sym_hds.c
+++ new/usr/src/uts/common/io/scsi/adapters/scsi_vhci/fops/sym_hds.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21
22 22 /* Portions Copyright 2008 Hitachi Ltd. */
23 23
24 24 /*
25 25 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
26 26 * Use is subject to license terms.
27 27 */
28 28
29 29 /*
30 30 * Implementation of "scsi_vhci_f_sym_hds" asymmetric-active-active
31 31 * failover_ops. The device has a preferred(owner)/non-preferred
32 32 * with no action needed to use the non-preferred path. This is really
33 33 * more inline with symmetric device so am using that prefix.
34 34 *
35 35 * This file imports the standard "scsi_vhci_f_sym", but with HDS specific
36 36 * knowledge related to preferred/non-preferred path.
37 37 */
38 38
39 39 #include <sys/conf.h>
40 40 #include <sys/file.h>
41 41 #include <sys/ddi.h>
42 42 #include <sys/sunddi.h>
43 43 #include <sys/scsi/scsi.h>
44 44 #include <sys/scsi/adapters/scsi_vhci.h>
45 45
46 46 /* Supported device table entries. */
47 47 char *hds_sym_dev_table[] = {
48 48 /* " 111111" */
49 49 /* "012345670123456789012345" */
50 50 /* "|-VID--||-----PID------|" */
51 51
52 52 "HITACHI DF",
53 53 NULL
54 54 };
55 55
56 56 static int hds_sym_device_probe(struct scsi_device *,
57 57 struct scsi_inquiry *, void **);
58 58 static void hds_sym_device_unprobe(struct scsi_device *, void *);
59 59 static void hds_sym_init();
60 60 static int hds_sym_get_opinfo(struct scsi_device *sd,
61 61 struct scsi_path_opinfo *opinfo, void *ctpriv);
62 62
63 63 #ifdef lint
64 64 #define scsi_vhci_failover_ops scsi_vhci_failover_ops_f_sym_hds
65 65 #endif /* lint */
66 66 /*
67 67 * Use the following for the Asymmetric-Active-Active fops.
68 68 * A different fops may get used for the Symmetric-Active-Active.
69 69 */
70 70 struct scsi_failover_ops scsi_vhci_failover_ops = {
71 71 SFO_REV,
72 72 SFO_NAME_SYM "_hds",
73 73 hds_sym_dev_table,
74 74 hds_sym_init,
75 75 hds_sym_device_probe,
76 76 hds_sym_device_unprobe,
77 77 NULL,
↓ open down ↓ |
77 lines elided |
↑ open up ↑ |
78 78 NULL,
79 79 hds_sym_get_opinfo,
80 80 /* The rest of the implementation comes from SFO_NAME_SYM import */
81 81 };
82 82
83 83 static struct modlmisc modlmisc = {
84 84 &mod_miscops, "f_sym_hds"
85 85 };
86 86
87 87 static struct modlinkage modlinkage = {
88 - MODREV_1, (void *)&modlmisc, NULL
88 + MODREV_1, { (void *)&modlmisc, NULL }
89 89 };
90 90
91 91 #define HDS_MAX_INQ_BUF_SIZE 0xff
92 92 #define HDS_INQ_PAGE_E0 0xe0
93 93 #define HDS_SAA_TYPE "DF00"
94 94 #define ASYM_ACTIVE_ACTIVE 0
95 95 #define SYM_ACTIVE_ACTIVE 1
96 96
97 97 extern struct scsi_failover_ops *vhci_failover_ops_by_name(char *);
98 98
99 99 int
100 100 _init()
101 101 {
102 102 return (mod_install(&modlinkage));
103 103 }
104 104
105 105 int
106 106 _fini()
107 107 {
108 108 return (mod_remove(&modlinkage));
109 109 }
110 110
111 111 int
112 112 _info(struct modinfo *modinfop)
113 113 {
114 114 return (mod_info(&modlinkage, modinfop));
115 115 }
116 116
117 117 static void
118 118 hds_sym_init()
119 119 {
120 120 struct scsi_failover_ops *sfo, *ssfo, clone;
121 121
122 122 /* clone SFO_NAME_SYM implementation for most things */
123 123 ssfo = vhci_failover_ops_by_name(SFO_NAME_SYM);
124 124 if (ssfo == NULL) {
125 125 VHCI_DEBUG(4, (CE_NOTE, NULL, "!hds_sym_init: "
126 126 "can't import " SFO_NAME_SYM "\n"));
127 127 return;
128 128 }
129 129 sfo = &scsi_vhci_failover_ops;
130 130 clone = *ssfo;
131 131 clone.sfo_rev = sfo->sfo_rev;
132 132 clone.sfo_name = sfo->sfo_name;
133 133 clone.sfo_devices = sfo->sfo_devices;
134 134 clone.sfo_init = sfo->sfo_init;
135 135 clone.sfo_device_probe = sfo->sfo_device_probe;
136 136 clone.sfo_device_unprobe = sfo->sfo_device_unprobe;
137 137 clone.sfo_path_get_opinfo = sfo->sfo_path_get_opinfo;
138 138 *sfo = clone;
139 139 }
140 140
141 141 /* ARGSUSED */
142 142 static int
143 143 hds_sym_device_probe(struct scsi_device *sd, struct scsi_inquiry *stdinq,
144 144 void **ctprivp)
145 145 {
146 146 char **dt;
147 147 char *dftype;
148 148 unsigned char len;
149 149 unsigned char *inq_data = (unsigned char *)stdinq;
150 150 unsigned char pv;
151 151 int ret;
152 152
153 153 VHCI_DEBUG(6, (CE_NOTE, NULL, "hds_sym_device_probe: vidpid %s\n",
154 154 stdinq->inq_vid));
155 155 for (dt = hds_sym_dev_table; *dt; dt++) {
156 156 if (strncmp(stdinq->inq_vid, *dt, strlen(*dt)))
157 157 continue;
158 158 len = inq_data[4];
159 159 if (len < 128) {
160 160 vhci_log(CE_NOTE, NULL,
161 161 "hds_sym_device_probe: vidpid %s len error: %d\n",
162 162 stdinq->inq_vid, len);
163 163 return (SFO_DEVICE_PROBE_PHCI);
164 164 }
165 165
166 166 dftype = (char *)&inq_data[128];
167 167 if (*dftype == 0) {
168 168 VHCI_DEBUG(4, (CE_NOTE, NULL,
169 169 "hds_sym_device_probe: vidpid %s"
170 170 " ASYM_ACTIVE_ACTIVE\n", stdinq->inq_vid));
171 171 pv = ASYM_ACTIVE_ACTIVE;
172 172 ret = SFO_DEVICE_PROBE_VHCI;
173 173 } else if (strncmp(dftype, HDS_SAA_TYPE,
174 174 strlen(HDS_SAA_TYPE)) == 0) {
175 175 VHCI_DEBUG(4, (CE_NOTE, NULL,
176 176 "hds_sym_device_probe: vidpid %s"
177 177 " SYM_ACTIVE_ACTIVE\n", stdinq->inq_vid));
178 178 pv = SYM_ACTIVE_ACTIVE;
179 179 ret = SFO_DEVICE_PROBE_VHCI;
180 180 } else
181 181 ret = SFO_DEVICE_PROBE_PHCI;
182 182
183 183 if (ret == SFO_DEVICE_PROBE_VHCI) {
184 184 /* ctprivp is NULL for vhci_is_dev_supported() probe */
185 185 if (ctprivp) {
186 186 /*
187 187 * Allocate failover module's 'client' private
188 188 * data on the first successfull path probe.
189 189 * NOTE: 'client' private means per lun guid,
190 190 * not per-path.
191 191 */
192 192 if (*ctprivp == NULL)
193 193 *ctprivp = kmem_alloc(sizeof (pv),
194 194 KM_SLEEP);
195 195
196 196 /* update private data */
197 197 *((unsigned char *)*ctprivp) = pv;
198 198 }
199 199 } else {
200 200 VHCI_DEBUG(4, (CE_NOTE, NULL,
201 201 "hds_sym_device_probe: vidpid %s"
202 202 " - unknown dftype: %d\n",
203 203 stdinq->inq_vid, *dftype));
204 204 }
205 205 return (SFO_DEVICE_PROBE_PHCI);
206 206
207 207 }
208 208 return (SFO_DEVICE_PROBE_PHCI);
209 209 }
210 210
211 211 /* ARGSUSED */
212 212 static void
213 213 hds_sym_device_unprobe(struct scsi_device *sd, void *ctpriv)
214 214 {
215 215 if (ctpriv != NULL) {
216 216 kmem_free(ctpriv, sizeof (unsigned char));
217 217 }
218 218 }
219 219
220 220
221 221 /*
222 222 * Local routine to get inquiry VPD page from the device.
223 223 *
224 224 * return 1 for failure
225 225 * return 0 for success
226 226 */
227 227 static int
228 228 hds_get_inquiry_vpd_page(struct scsi_device *sd, unsigned char page,
229 229 unsigned char *buf, int size)
230 230 {
231 231 int retval = 0;
232 232 struct buf *bp;
233 233 struct scsi_pkt *pkt;
234 234 struct scsi_address *ap;
235 235
236 236 if ((buf == NULL) || (size == 0)) {
237 237 return (1);
238 238 }
239 239 bp = getrbuf(KM_NOSLEEP);
240 240 if (bp == NULL) {
241 241 return (1);
242 242 }
243 243 bp->b_un.b_addr = (char *)buf;
244 244 bp->b_flags = B_READ;
245 245 bp->b_bcount = size;
246 246 bp->b_resid = 0;
247 247
248 248 ap = &sd->sd_address;
249 249 pkt = scsi_init_pkt(ap, NULL, bp, CDB_GROUP0,
250 250 sizeof (struct scsi_arq_status), 0, 0, NULL, NULL);
251 251 if (pkt == NULL) {
252 252 VHCI_DEBUG(4, (CE_WARN, NULL,
253 253 "hds_get_inquiry_vpd_page:"
254 254 "Failed to initialize packet"));
255 255 freerbuf(bp);
256 256 return (1);
257 257 }
258 258
259 259 /*
260 260 * Send the inquiry command for page xx to the target.
261 261 * Data is returned in the buf pointed to by buf.
262 262 */
263 263
264 264 pkt->pkt_cdbp[0] = SCMD_INQUIRY;
265 265 pkt->pkt_cdbp[1] = 0x1;
266 266 pkt->pkt_cdbp[2] = page;
267 267 pkt->pkt_cdbp[4] = (unsigned char)size;
268 268 pkt->pkt_time = 90;
269 269 retval = vhci_do_scsi_cmd(pkt);
270 270 scsi_destroy_pkt(pkt);
271 271 freerbuf(bp);
272 272 return (!retval);
273 273
274 274 }
275 275
276 276 /* ARGSUSED */
277 277 static int
278 278 hds_sym_get_opinfo(struct scsi_device *sd, struct scsi_path_opinfo *opinfo,
279 279 void *ctpriv)
280 280 {
281 281 unsigned char inq_vpd_buf[HDS_MAX_INQ_BUF_SIZE];
282 282
283 283 opinfo->opinfo_rev = OPINFO_REV;
284 284 (void) strcpy(opinfo->opinfo_path_attr, "primary");
285 285 opinfo->opinfo_path_state = SCSI_PATH_ACTIVE;
286 286 opinfo->opinfo_pswtch_best = 0; /* N/A */
287 287 opinfo->opinfo_pswtch_worst = 0; /* N/A */
288 288 opinfo->opinfo_xlf_capable = 0;
289 289 opinfo->opinfo_mode = SCSI_NO_FAILOVER;
290 290 ASSERT(ctpriv != NULL);
291 291 if (*((unsigned char *)ctpriv) == SYM_ACTIVE_ACTIVE) {
292 292 VHCI_DEBUG(4, (CE_NOTE, NULL,
293 293 "hds_get_opinfo: sd(%p): sym_active_active "
294 294 "preferred bit set ", (void*)sd));
295 295 opinfo->opinfo_preferred = PCLASS_PREFERRED;
296 296 return (0);
297 297 }
298 298 /* check if this is the preferred path */
299 299 if (hds_get_inquiry_vpd_page(sd, HDS_INQ_PAGE_E0, inq_vpd_buf,
300 300 sizeof (inq_vpd_buf)) != 0) {
301 301 VHCI_DEBUG(4, (CE_WARN, NULL,
302 302 "hds_get_opinfo: sd(%p):Unable to "
303 303 "get inquiry Page %x", (void*)sd, HDS_INQ_PAGE_E0));
304 304 return (1);
305 305 }
306 306 if (inq_vpd_buf[4] & 0x80) {
307 307 if (inq_vpd_buf[4] & 0x40) {
308 308 VHCI_DEBUG(4, (CE_NOTE, NULL,
309 309 "hds_get_opinfo: sd(%p): preferred bit set ",
310 310 (void*)sd));
311 311 opinfo->opinfo_preferred = PCLASS_PREFERRED;
312 312 } else {
313 313 VHCI_DEBUG(4, (CE_NOTE, NULL,
314 314 "hds_get_opinfo: sd(%p): non-preferred bit set ",
315 315 (void*)sd));
316 316 opinfo->opinfo_preferred = PCLASS_NONPREFERRED;
317 317 }
318 318 } else {
319 319 vhci_log(CE_NOTE, NULL,
320 320 "hds_get_opinfo: sd(%p): "
321 321 "get inquiry Page %x has invalid P/SVid bit set",
322 322 (void*)sd, HDS_INQ_PAGE_E0);
323 323 return (1);
324 324 }
325 325
326 326 return (0);
327 327 }
↓ open down ↓ |
229 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX