Print this page
hg changesets 607a5b46a793..b706c96317c3
Fix ncpus for early boot config
Purge the ack to the interrupt before exiting mptsas_intr()
Changes from code review
Update tx waitq's code.
Create 2 threads, divide the workflow and deliver
to the hardware from the threads.
Added code to support using MSI-X interrupts across multiple
reply queues. Not tested with anything other than 3008 yet.
Changes to enable driver to compile.
Header paths, object lists, etc.
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/uts/common/io/scsi/adapters/mpt_sas3/mptsas3_raid.c
+++ new/usr/src/uts/common/io/scsi/adapters/mpt_sas3/mptsas3_raid.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.
↓ open down ↓ |
14 lines elided |
↑ open up ↑ |
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 /*
23 23 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
24 24 * Use is subject to license terms.
25 + * Copyright (c) 2014, Tegile Systems Inc. All rights reserved.
25 26 */
26 27
27 28 /*
28 29 * Copyright (c) 2000 to 2010, LSI Corporation.
29 30 * All rights reserved.
30 31 *
31 32 * Redistribution and use in source and binary forms of all code within
32 33 * this file that is exclusively owned by LSI, with or without
33 34 * modification, is permitted provided that, in addition to the CDDL 1.0
34 35 * License requirements, the following conditions are met:
35 36 *
36 37 * Neither the name of the author nor the names of its contributors may be
37 38 * used to endorse or promote products derived from this software without
38 39 * specific prior written permission.
39 40 *
40 41 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
41 42 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
42 43 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
43 44 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
44 45 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
45 46 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
46 47 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
47 48 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
48 49 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
49 50 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
50 51 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
51 52 * DAMAGE.
52 53 */
53 54
54 55 /*
55 56 * mptsas_raid - This file contains all the RAID related functions for the
56 57 * MPT interface.
57 58 */
58 59
59 60 #if defined(lint) || defined(DEBUG)
60 61 #define MPTSAS_DEBUG
61 62 #endif
62 63
63 64 #define MPI_RAID_VOL_PAGE_0_PHYSDISK_MAX 2
64 65
↓ open down ↓ |
30 lines elided |
↑ open up ↑ |
65 66 /*
66 67 * standard header files
67 68 */
68 69 #include <sys/note.h>
69 70 #include <sys/scsi/scsi.h>
70 71 #include <sys/byteorder.h>
71 72 #include <sys/raidioctl.h>
72 73
73 74 #pragma pack(1)
74 75
75 -#include <sys/scsi/adapters/mpt_sas/mpi/mpi2_type.h>
76 -#include <sys/scsi/adapters/mpt_sas/mpi/mpi2.h>
77 -#include <sys/scsi/adapters/mpt_sas/mpi/mpi2_cnfg.h>
78 -#include <sys/scsi/adapters/mpt_sas/mpi/mpi2_init.h>
79 -#include <sys/scsi/adapters/mpt_sas/mpi/mpi2_ioc.h>
80 -#include <sys/scsi/adapters/mpt_sas/mpi/mpi2_raid.h>
81 -#include <sys/scsi/adapters/mpt_sas/mpi/mpi2_tool.h>
76 +#include <sys/scsi/adapters/mpt_sas3/mpi/mpi2_type.h>
77 +#include <sys/scsi/adapters/mpt_sas3/mpi/mpi2.h>
78 +#include <sys/scsi/adapters/mpt_sas3/mpi/mpi2_cnfg.h>
79 +#include <sys/scsi/adapters/mpt_sas3/mpi/mpi2_init.h>
80 +#include <sys/scsi/adapters/mpt_sas3/mpi/mpi2_ioc.h>
81 +#include <sys/scsi/adapters/mpt_sas3/mpi/mpi2_raid.h>
82 +#include <sys/scsi/adapters/mpt_sas3/mpi/mpi2_tool.h>
82 83
83 84 #pragma pack()
84 85
85 86 /*
86 87 * private header files.
87 88 */
88 -#include <sys/scsi/adapters/mpt_sas/mptsas_var.h>
89 +#include <sys/scsi/adapters/mpt_sas3/mptsas3_var.h>
89 90
90 91 static int mptsas_get_raid_wwid(mptsas_t *mpt, mptsas_raidvol_t *raidvol);
91 92
92 93 extern int mptsas_check_dma_handle(ddi_dma_handle_t handle);
93 94 extern int mptsas_check_acc_handle(ddi_acc_handle_t handle);
94 95 extern mptsas_target_t *mptsas_tgt_alloc(mptsas_t *, uint16_t,
95 96 uint64_t, uint32_t, mptsas_phymask_t, uint8_t);
96 97
97 98 static int
98 99 mptsas_raidconf_page_0_cb(mptsas_t *mpt, caddr_t page_memp,
99 100 ddi_acc_handle_t accessp, uint16_t iocstatus, uint32_t iocloginfo,
100 101 va_list ap)
101 102 {
102 103 #ifndef __lock_lint
103 104 _NOTE(ARGUNUSED(ap))
104 105 #endif
105 106 pMpi2RaidConfigurationPage0_t raidconfig_page0;
106 107 pMpi2RaidConfig0ConfigElement_t element;
107 108 uint32_t *confignum;
108 109 int rval = DDI_SUCCESS, i;
109 110 uint8_t numelements, vol, disk;
110 111 uint16_t elementtype, voldevhandle;
111 112 uint16_t etype_vol, etype_pd, etype_hs;
112 113 uint16_t etype_oce;
113 114 m_raidconfig_t *raidconfig;
114 115 uint64_t raidwwn;
115 116 uint32_t native;
116 117 mptsas_target_t *ptgt;
117 118 uint32_t configindex;
118 119
119 120 if (iocstatus == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE) {
120 121 return (DDI_FAILURE);
121 122 }
122 123
123 124 if (iocstatus != MPI2_IOCSTATUS_SUCCESS) {
124 125 mptsas_log(mpt, CE_WARN, "mptsas_get_raid_conf_page0 "
125 126 "config: IOCStatus=0x%x, IOCLogInfo=0x%x",
126 127 iocstatus, iocloginfo);
127 128 rval = DDI_FAILURE;
128 129 return (rval);
129 130 }
130 131 confignum = va_arg(ap, uint32_t *);
131 132 configindex = va_arg(ap, uint32_t);
132 133 raidconfig_page0 = (pMpi2RaidConfigurationPage0_t)page_memp;
133 134 /*
134 135 * Get all RAID configurations.
135 136 */
136 137 etype_vol = MPI2_RAIDCONFIG0_EFLAGS_VOLUME_ELEMENT;
137 138 etype_pd = MPI2_RAIDCONFIG0_EFLAGS_VOL_PHYS_DISK_ELEMENT;
138 139 etype_hs = MPI2_RAIDCONFIG0_EFLAGS_HOT_SPARE_ELEMENT;
139 140 etype_oce = MPI2_RAIDCONFIG0_EFLAGS_OCE_ELEMENT;
140 141 /*
141 142 * Set up page address for next time through.
142 143 */
143 144 *confignum = ddi_get8(accessp,
144 145 &raidconfig_page0->ConfigNum);
145 146
146 147 /*
147 148 * Point to the right config in the structure.
148 149 * Increment the number of valid RAID configs.
149 150 */
150 151 raidconfig = &mpt->m_raidconfig[configindex];
151 152 mpt->m_num_raid_configs++;
152 153
153 154 /*
154 155 * Set the native flag if this is not a foreign
155 156 * configuration.
156 157 */
157 158 native = ddi_get32(accessp, &raidconfig_page0->Flags);
158 159 if (native & MPI2_RAIDCONFIG0_FLAG_FOREIGN_CONFIG) {
159 160 native = FALSE;
160 161 } else {
161 162 native = TRUE;
162 163 }
163 164 raidconfig->m_native = (uint8_t)native;
164 165
165 166 /*
166 167 * Get volume information for the volumes in the
167 168 * config.
168 169 */
169 170 numelements = ddi_get8(accessp, &raidconfig_page0->NumElements);
170 171 vol = 0;
171 172 disk = 0;
172 173 element = (pMpi2RaidConfig0ConfigElement_t)
173 174 &raidconfig_page0->ConfigElement;
174 175
175 176 for (i = 0; ((i < numelements) && native); i++, element++) {
176 177 /*
177 178 * Get the element type. Could be Volume,
178 179 * PhysDisk, Hot Spare, or Online Capacity
179 180 * Expansion PhysDisk.
180 181 */
181 182 elementtype = ddi_get16(accessp, &element->ElementFlags);
182 183 elementtype &= MPI2_RAIDCONFIG0_EFLAGS_MASK_ELEMENT_TYPE;
183 184
184 185 /*
185 186 * For volumes, get the RAID settings and the
186 187 * WWID.
187 188 */
188 189 if (elementtype == etype_vol) {
189 190 voldevhandle = ddi_get16(accessp,
190 191 &element->VolDevHandle);
191 192 raidconfig->m_raidvol[vol].m_israid = 1;
192 193 raidconfig->m_raidvol[vol].
193 194 m_raidhandle = voldevhandle;
194 195 /*
195 196 * Get the settings for the raid
196 197 * volume. This includes the
197 198 * DevHandles for the disks making up
198 199 * the raid volume.
199 200 */
200 201 if (mptsas_get_raid_settings(mpt,
201 202 &raidconfig->m_raidvol[vol]))
202 203 continue;
203 204
204 205 /*
205 206 * Get the WWID of the RAID volume for
206 207 * SAS HBA
207 208 */
208 209 if (mptsas_get_raid_wwid(mpt,
209 210 &raidconfig->m_raidvol[vol]))
210 211 continue;
211 212
212 213 raidwwn = raidconfig->m_raidvol[vol].
213 214 m_raidwwid;
214 215
215 216 /*
216 217 * RAID uses phymask of 0.
217 218 */
218 219 ptgt = mptsas_tgt_alloc(mpt,
219 220 voldevhandle, raidwwn, 0, 0, 0);
220 221
221 222 raidconfig->m_raidvol[vol].m_raidtgt =
222 223 ptgt;
223 224
224 225 /*
225 226 * Increment volume index within this
226 227 * raid config.
227 228 */
228 229 vol++;
229 230 } else if ((elementtype == etype_pd) ||
230 231 (elementtype == etype_hs) ||
231 232 (elementtype == etype_oce)) {
232 233 /*
233 234 * For all other element types, put
234 235 * their DevHandles in the phys disk
235 236 * list of the config. These are all
236 237 * some variation of a Phys Disk and
237 238 * this list is used to keep these
238 239 * disks from going online.
239 240 */
240 241 raidconfig->m_physdisk_devhdl[disk] = ddi_get16(accessp,
241 242 &element->PhysDiskDevHandle);
242 243
243 244 /*
244 245 * Increment disk index within this
245 246 * raid config.
246 247 */
247 248 disk++;
248 249 }
249 250 }
250 251
251 252 return (rval);
252 253 }
253 254
254 255 int
255 256 mptsas_get_raid_info(mptsas_t *mpt)
256 257 {
257 258 int rval = DDI_SUCCESS;
258 259 uint32_t confignum, pageaddress;
259 260 uint8_t configindex;
260 261
261 262 ASSERT(mutex_owned(&mpt->m_mutex));
262 263
263 264 /*
264 265 * Clear all RAID info before starting.
265 266 */
266 267 bzero(mpt->m_raidconfig, sizeof (mpt->m_raidconfig));
267 268 mpt->m_num_raid_configs = 0;
268 269
269 270 configindex = 0;
270 271 confignum = 0xff;
271 272 pageaddress = MPI2_RAID_PGAD_FORM_GET_NEXT_CONFIGNUM | confignum;
272 273 while (rval == DDI_SUCCESS) {
273 274 /*
274 275 * Get the header and config page. reply contains the reply
275 276 * frame, which holds status info for the request.
276 277 */
277 278 rval = mptsas_access_config_page(mpt,
278 279 MPI2_CONFIG_ACTION_PAGE_READ_CURRENT,
279 280 MPI2_CONFIG_EXTPAGETYPE_RAID_CONFIG, 0, pageaddress,
280 281 mptsas_raidconf_page_0_cb, &confignum, configindex);
281 282 configindex++;
282 283 pageaddress = MPI2_RAID_PGAD_FORM_GET_NEXT_CONFIGNUM |
283 284 confignum;
284 285 }
285 286
286 287 return (rval);
287 288 }
288 289
289 290 static int
290 291 mptsas_raidvol_page_0_cb(mptsas_t *mpt, caddr_t page_memp,
291 292 ddi_acc_handle_t accessp, uint16_t iocstatus, uint32_t iocloginfo,
292 293 va_list ap)
293 294 {
294 295 #ifndef __lock_lint
295 296 _NOTE(ARGUNUSED(ap))
296 297 #endif
297 298 pMpi2RaidVolPage0_t raidpage;
298 299 int rval = DDI_SUCCESS, i;
299 300 mptsas_raidvol_t *raidvol;
300 301 uint8_t numdisks, volstate, voltype, physdisknum;
301 302 uint32_t volsetting;
302 303 uint32_t statusflags, resync_flag;
303 304
304 305 if (iocstatus == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE)
305 306 return (DDI_FAILURE);
306 307
307 308 if (iocstatus != MPI2_IOCSTATUS_SUCCESS) {
308 309 mptsas_log(mpt, CE_WARN, "mptsas_raidvol_page0_cb "
309 310 "config: IOCStatus=0x%x, IOCLogInfo=0x%x",
310 311 iocstatus, iocloginfo);
311 312 rval = DDI_FAILURE;
312 313 return (rval);
313 314 }
314 315
315 316 raidvol = va_arg(ap, mptsas_raidvol_t *);
316 317
317 318 raidpage = (pMpi2RaidVolPage0_t)page_memp;
318 319 volstate = ddi_get8(accessp, &raidpage->VolumeState);
319 320 volsetting = ddi_get32(accessp,
320 321 (uint32_t *)(void *)&raidpage->VolumeSettings);
321 322 statusflags = ddi_get32(accessp, &raidpage->VolumeStatusFlags);
322 323 voltype = ddi_get8(accessp, &raidpage->VolumeType);
323 324
324 325 raidvol->m_state = volstate;
325 326 raidvol->m_statusflags = statusflags;
326 327 /*
327 328 * Volume size is not used right now. Set to 0.
328 329 */
329 330 raidvol->m_raidsize = 0;
330 331 raidvol->m_settings = volsetting;
331 332 raidvol->m_raidlevel = voltype;
332 333
333 334 if (statusflags & MPI2_RAIDVOL0_STATUS_FLAG_QUIESCED) {
334 335 mptsas_log(mpt, CE_NOTE, "?Volume %d is quiesced\n",
335 336 raidvol->m_raidhandle);
336 337 }
337 338
338 339 if (statusflags &
339 340 MPI2_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS) {
340 341 mptsas_log(mpt, CE_NOTE, "?Volume %d is resyncing\n",
341 342 raidvol->m_raidhandle);
342 343 }
343 344
344 345 resync_flag = MPI2_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS;
345 346 switch (volstate) {
346 347 case MPI2_RAID_VOL_STATE_OPTIMAL:
347 348 mptsas_log(mpt, CE_NOTE, "?Volume %d is "
348 349 "optimal\n", raidvol->m_raidhandle);
349 350 break;
350 351 case MPI2_RAID_VOL_STATE_DEGRADED:
351 352 if ((statusflags & resync_flag) == 0) {
352 353 mptsas_log(mpt, CE_WARN, "Volume %d "
353 354 "is degraded\n",
354 355 raidvol->m_raidhandle);
355 356 }
356 357 break;
357 358 case MPI2_RAID_VOL_STATE_FAILED:
358 359 mptsas_log(mpt, CE_WARN, "Volume %d is "
359 360 "failed\n", raidvol->m_raidhandle);
360 361 break;
361 362 case MPI2_RAID_VOL_STATE_MISSING:
362 363 mptsas_log(mpt, CE_WARN, "Volume %d is "
363 364 "missing\n", raidvol->m_raidhandle);
364 365 break;
365 366 default:
366 367 break;
367 368 }
368 369 numdisks = raidpage->NumPhysDisks;
369 370 raidvol->m_ndisks = numdisks;
370 371 for (i = 0; i < numdisks; i++) {
371 372 physdisknum = raidpage->PhysDisk[i].PhysDiskNum;
372 373 raidvol->m_disknum[i] = physdisknum;
373 374 if (mptsas_get_physdisk_settings(mpt, raidvol,
374 375 physdisknum))
375 376 break;
376 377 }
377 378 return (rval);
378 379 }
379 380
380 381 int
381 382 mptsas_get_raid_settings(mptsas_t *mpt, mptsas_raidvol_t *raidvol)
382 383 {
383 384 int rval = DDI_SUCCESS;
384 385 uint32_t page_address;
385 386
386 387 ASSERT(mutex_owned(&mpt->m_mutex));
387 388
388 389 /*
389 390 * Get the header and config page. reply contains the reply frame,
390 391 * which holds status info for the request.
391 392 */
392 393 page_address = (MPI2_RAID_VOLUME_PGAD_FORM_MASK &
393 394 MPI2_RAID_VOLUME_PGAD_FORM_HANDLE) | raidvol->m_raidhandle;
394 395 rval = mptsas_access_config_page(mpt,
395 396 MPI2_CONFIG_ACTION_PAGE_READ_CURRENT,
396 397 MPI2_CONFIG_PAGETYPE_RAID_VOLUME, 0, page_address,
397 398 mptsas_raidvol_page_0_cb, raidvol);
398 399
399 400 return (rval);
400 401 }
401 402
402 403 static int
403 404 mptsas_raidvol_page_1_cb(mptsas_t *mpt, caddr_t page_memp,
404 405 ddi_acc_handle_t accessp, uint16_t iocstatus, uint32_t iocloginfo,
405 406 va_list ap)
406 407 {
407 408 #ifndef __lock_lint
408 409 _NOTE(ARGUNUSED(ap))
409 410 #endif
410 411 pMpi2RaidVolPage1_t raidpage;
411 412 int rval = DDI_SUCCESS, i;
412 413 uint8_t *sas_addr = NULL;
413 414 uint8_t tmp_sas_wwn[SAS_WWN_BYTE_SIZE];
414 415 uint64_t *sas_wwn;
415 416
416 417 if (iocstatus != MPI2_IOCSTATUS_SUCCESS) {
417 418 mptsas_log(mpt, CE_WARN, "mptsas_raidvol_page_1_cb "
418 419 "config: IOCStatus=0x%x, IOCLogInfo=0x%x",
419 420 iocstatus, iocloginfo);
420 421 rval = DDI_FAILURE;
421 422 return (rval);
422 423 }
423 424 sas_wwn = va_arg(ap, uint64_t *);
424 425
425 426 raidpage = (pMpi2RaidVolPage1_t)page_memp;
426 427 sas_addr = (uint8_t *)(&raidpage->WWID);
427 428 for (i = 0; i < SAS_WWN_BYTE_SIZE; i++) {
428 429 tmp_sas_wwn[i] = ddi_get8(accessp, sas_addr + i);
429 430 }
430 431 bcopy(tmp_sas_wwn, sas_wwn, SAS_WWN_BYTE_SIZE);
431 432 *sas_wwn = LE_64(*sas_wwn);
432 433 return (rval);
433 434 }
434 435
435 436 static int
436 437 mptsas_get_raid_wwid(mptsas_t *mpt, mptsas_raidvol_t *raidvol)
437 438 {
438 439 int rval = DDI_SUCCESS;
439 440 uint32_t page_address;
440 441 uint64_t sas_wwn;
441 442
442 443 ASSERT(mutex_owned(&mpt->m_mutex));
443 444
444 445 /*
445 446 * Get the header and config page. reply contains the reply frame,
446 447 * which holds status info for the request.
447 448 */
448 449 page_address = (MPI2_RAID_VOLUME_PGAD_FORM_MASK &
449 450 MPI2_RAID_VOLUME_PGAD_FORM_HANDLE) | raidvol->m_raidhandle;
450 451 rval = mptsas_access_config_page(mpt,
451 452 MPI2_CONFIG_ACTION_PAGE_READ_CURRENT,
452 453 MPI2_CONFIG_PAGETYPE_RAID_VOLUME, 1, page_address,
453 454 mptsas_raidvol_page_1_cb, &sas_wwn);
454 455
455 456 /*
456 457 * Get the required information from the page.
457 458 */
458 459 if (rval == DDI_SUCCESS) {
459 460
460 461 /*
461 462 * replace top nibble of WWID of RAID to '3' for OBP
462 463 */
463 464 sas_wwn = MPTSAS_RAID_WWID(sas_wwn);
464 465 raidvol->m_raidwwid = sas_wwn;
465 466 }
466 467
467 468 done:
468 469 return (rval);
469 470 }
470 471
471 472 static int
472 473 mptsas_raidphydsk_page_0_cb(mptsas_t *mpt, caddr_t page_memp,
473 474 ddi_acc_handle_t accessp, uint16_t iocstatus, uint32_t iocloginfo,
474 475 va_list ap)
475 476 {
476 477 #ifndef __lock_lint
477 478 _NOTE(ARGUNUSED(ap))
478 479 #endif
479 480 pMpi2RaidPhysDiskPage0_t diskpage;
480 481 int rval = DDI_SUCCESS;
481 482 uint16_t *devhdl;
482 483 uint8_t *state;
483 484
484 485 if (iocstatus == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE)
485 486 return (DDI_FAILURE);
486 487
487 488 if (iocstatus != MPI2_IOCSTATUS_SUCCESS) {
488 489 mptsas_log(mpt, CE_WARN, "mptsas_raidphydsk_page0_cb "
489 490 "config: IOCStatus=0x%x, IOCLogInfo=0x%x",
490 491 iocstatus, iocloginfo);
491 492 rval = DDI_FAILURE;
492 493 return (rval);
493 494 }
494 495 devhdl = va_arg(ap, uint16_t *);
495 496 state = va_arg(ap, uint8_t *);
496 497 diskpage = (pMpi2RaidPhysDiskPage0_t)page_memp;
497 498 *devhdl = ddi_get16(accessp, &diskpage->DevHandle);
498 499 *state = ddi_get8(accessp, &diskpage->PhysDiskState);
499 500 return (rval);
500 501 }
501 502
502 503 int
503 504 mptsas_get_physdisk_settings(mptsas_t *mpt, mptsas_raidvol_t *raidvol,
504 505 uint8_t physdisknum)
505 506 {
506 507 int rval = DDI_SUCCESS, i;
507 508 uint8_t state;
508 509 uint16_t devhdl;
509 510 uint32_t page_address;
510 511
511 512 ASSERT(mutex_owned(&mpt->m_mutex));
512 513
513 514 /*
514 515 * Get the header and config page. reply contains the reply frame,
515 516 * which holds status info for the request.
516 517 */
517 518 page_address = (MPI2_PHYSDISK_PGAD_FORM_MASK &
518 519 MPI2_PHYSDISK_PGAD_FORM_PHYSDISKNUM) | physdisknum;
519 520 rval = mptsas_access_config_page(mpt,
520 521 MPI2_CONFIG_ACTION_PAGE_READ_CURRENT,
521 522 MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK, 0, page_address,
522 523 mptsas_raidphydsk_page_0_cb, &devhdl, &state);
523 524
524 525 /*
525 526 * Get the required information from the page.
526 527 */
527 528 if (rval == DDI_SUCCESS) {
528 529 for (i = 0; i < MPTSAS_MAX_DISKS_IN_VOL; i++) {
529 530 /* find the correct position in the arrays */
530 531 if (raidvol->m_disknum[i] == physdisknum)
531 532 break;
532 533 }
533 534 raidvol->m_devhdl[i] = devhdl;
534 535
535 536 switch (state) {
536 537 case MPI2_RAID_PD_STATE_OFFLINE:
537 538 raidvol->m_diskstatus[i] =
538 539 RAID_DISKSTATUS_FAILED;
539 540 break;
540 541
541 542 case MPI2_RAID_PD_STATE_HOT_SPARE:
542 543 case MPI2_RAID_PD_STATE_NOT_CONFIGURED:
543 544 case MPI2_RAID_PD_STATE_NOT_COMPATIBLE:
544 545 break;
545 546
546 547 case MPI2_RAID_PD_STATE_DEGRADED:
547 548 case MPI2_RAID_PD_STATE_OPTIMAL:
548 549 case MPI2_RAID_PD_STATE_REBUILDING:
549 550 case MPI2_RAID_PD_STATE_ONLINE:
550 551 default:
551 552 raidvol->m_diskstatus[i] =
552 553 RAID_DISKSTATUS_GOOD;
553 554 break;
554 555 }
555 556 }
556 557
557 558 return (rval);
558 559 }
↓ open down ↓ |
460 lines elided |
↑ open up ↑ |
559 560
560 561 /*
561 562 * RAID Action for System Shutdown. This request uses the dedicated TM slot to
562 563 * avoid a call to mptsas_save_cmd. Since Solaris requires that the mutex is
563 564 * not held during the mptsas_quiesce function, this RAID action must not use
564 565 * the normal code path of requests and replies.
565 566 */
566 567 void
567 568 mptsas_raid_action_system_shutdown(mptsas_t *mpt)
568 569 {
570 + mptsas_reply_pqueue_t *rpqp;
569 571 pMpi2RaidActionRequest_t action;
570 572 uint8_t ir_active = FALSE, reply_type;
571 573 uint8_t function, found_reply = FALSE;
572 574 uint16_t SMID, action_type;
573 575 mptsas_slots_t *slots = mpt->m_active;
574 576 int config, vol;
575 577 mptsas_cmd_t *cmd;
576 - uint32_t request_desc_low, reply_addr;
578 + uint32_t reply_addr;
579 + uint64_t request_desc;
577 580 int cnt;
578 581 pMpi2ReplyDescriptorsUnion_t reply_desc_union;
579 582 pMPI2DefaultReply_t reply;
580 583 pMpi2AddressReplyDescriptor_t address_reply;
581 584
582 585 /*
583 586 * Before doing the system shutdown RAID Action, make sure that the IOC
584 587 * supports IR and make sure there is a valid volume for the request.
585 588 */
586 589 if (mpt->m_ir_capable) {
587 590 for (config = 0; (config < mpt->m_num_raid_configs) &&
588 591 (!ir_active); config++) {
589 592 for (vol = 0; vol < MPTSAS_MAX_RAIDVOLS; vol++) {
590 593 if (mpt->m_raidconfig[config].m_raidvol[vol].
591 594 m_israid) {
592 595 ir_active = TRUE;
593 596 break;
594 597 }
595 598 }
596 599 }
597 600 }
598 601 if (!ir_active) {
599 602 return;
600 603 }
601 604
602 605 /*
603 606 * If TM slot is already being used (highly unlikely), show message and
604 607 * don't issue the RAID action.
605 608 */
606 609 if (slots->m_slot[MPTSAS_TM_SLOT(mpt)] != NULL) {
607 610 mptsas_log(mpt, CE_WARN, "RAID Action slot in use. Cancelling"
608 611 " System Shutdown RAID Action.\n");
609 612 return;
610 613 }
611 614
612 615 /*
613 616 * Create the cmd and put it in the dedicated TM slot.
614 617 */
615 618 cmd = &(mpt->m_event_task_mgmt.m_event_cmd);
616 619 bzero((caddr_t)cmd, sizeof (*cmd));
617 620 cmd->cmd_pkt = NULL;
618 621 cmd->cmd_slot = MPTSAS_TM_SLOT(mpt);
619 622 slots->m_slot[MPTSAS_TM_SLOT(mpt)] = cmd;
620 623
621 624 /*
↓ open down ↓ |
35 lines elided |
↑ open up ↑ |
622 625 * Form message for raid action.
623 626 */
624 627 action = (pMpi2RaidActionRequest_t)(mpt->m_req_frame +
625 628 (mpt->m_req_frame_size * cmd->cmd_slot));
626 629 bzero(action, mpt->m_req_frame_size);
627 630 action->Function = MPI2_FUNCTION_RAID_ACTION;
628 631 action->Action = MPI2_RAID_ACTION_SYSTEM_SHUTDOWN_INITIATED;
629 632
630 633 /*
631 634 * Send RAID Action.
635 + * Defaults to MSIxIndex of 0, so check reply q 0 below.
632 636 */
633 637 (void) ddi_dma_sync(mpt->m_dma_req_frame_hdl, 0, 0,
634 638 DDI_DMA_SYNC_FORDEV);
635 - request_desc_low = (cmd->cmd_slot << 16) +
639 + request_desc = (cmd->cmd_slot << 16) +
636 640 MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
637 - MPTSAS_START_CMD(mpt, request_desc_low, 0);
641 + MPTSAS_START_CMD(mpt, request_desc);
638 642
639 643 /*
640 644 * Even though reply does not matter because the system is shutting
641 645 * down, wait no more than 5 seconds here to get the reply just because
642 646 * we don't want to leave it hanging if it's coming. Poll because
643 647 * interrupts are disabled when this function is called.
644 648 */
649 + rpqp = mpt->m_rep_post_queues;
645 650 for (cnt = 0; cnt < 5000; cnt++) {
646 651 /*
647 652 * Check for a reply.
648 653 */
649 654 (void) ddi_dma_sync(mpt->m_dma_post_queue_hdl, 0, 0,
650 655 DDI_DMA_SYNC_FORCPU);
651 656
652 657 reply_desc_union = (pMpi2ReplyDescriptorsUnion_t)
653 - MPTSAS_GET_NEXT_REPLY(mpt, mpt->m_post_index);
658 + MPTSAS_GET_NEXT_REPLY(rpqp, rpqp->rpq_index);
654 659
655 660 if (ddi_get32(mpt->m_acc_post_queue_hdl,
656 661 &reply_desc_union->Words.Low) == 0xFFFFFFFF ||
657 662 ddi_get32(mpt->m_acc_post_queue_hdl,
658 663 &reply_desc_union->Words.High) == 0xFFFFFFFF) {
659 664 drv_usecwait(1000);
660 665 continue;
661 666 }
662 667
663 668 /*
664 669 * There is a reply. If it's not an address reply, ignore it.
665 670 */
666 671 reply_type = ddi_get8(mpt->m_acc_post_queue_hdl,
667 672 &reply_desc_union->Default.ReplyFlags);
668 673 reply_type &= MPI2_RPY_DESCRIPT_FLAGS_TYPE_MASK;
669 674 if (reply_type != MPI2_RPY_DESCRIPT_FLAGS_ADDRESS_REPLY) {
670 675 goto clear_and_continue;
671 676 }
672 677
673 678 /*
674 679 * SMID must be the TM slot since that's what we're using for
675 680 * this RAID action. If not, ignore this reply.
676 681 */
677 682 address_reply =
678 683 (pMpi2AddressReplyDescriptor_t)reply_desc_union;
679 684 SMID = ddi_get16(mpt->m_acc_post_queue_hdl,
680 685 &address_reply->SMID);
681 686 if (SMID != MPTSAS_TM_SLOT(mpt)) {
682 687 goto clear_and_continue;
683 688 }
684 689
685 690 /*
686 691 * If reply frame is not in the proper range ignore it.
687 692 */
688 693 reply_addr = ddi_get32(mpt->m_acc_post_queue_hdl,
689 694 &address_reply->ReplyFrameAddress);
690 695 if ((reply_addr < mpt->m_reply_frame_dma_addr) ||
691 696 (reply_addr >= (mpt->m_reply_frame_dma_addr +
692 697 (mpt->m_reply_frame_size * mpt->m_free_queue_depth))) ||
693 698 ((reply_addr - mpt->m_reply_frame_dma_addr) %
694 699 mpt->m_reply_frame_size != 0)) {
695 700 goto clear_and_continue;
696 701 }
697 702
698 703 /*
699 704 * If not a RAID action reply ignore it.
700 705 */
701 706 (void) ddi_dma_sync(mpt->m_dma_reply_frame_hdl, 0, 0,
702 707 DDI_DMA_SYNC_FORCPU);
703 708 reply = (pMPI2DefaultReply_t)(mpt->m_reply_frame +
704 709 (reply_addr - mpt->m_reply_frame_dma_addr));
705 710 function = ddi_get8(mpt->m_acc_reply_frame_hdl,
706 711 &reply->Function);
707 712 if (function != MPI2_FUNCTION_RAID_ACTION) {
708 713 goto clear_and_continue;
709 714 }
710 715
711 716 /*
712 717 * Finally, make sure this is the System Shutdown RAID action.
713 718 * If not, ignore reply.
714 719 */
715 720 action_type = ddi_get16(mpt->m_acc_reply_frame_hdl,
716 721 &reply->FunctionDependent1);
717 722 if (action_type !=
↓ open down ↓ |
54 lines elided |
↑ open up ↑ |
718 723 MPI2_RAID_ACTION_SYSTEM_SHUTDOWN_INITIATED) {
719 724 goto clear_and_continue;
720 725 }
721 726 found_reply = TRUE;
722 727
723 728 clear_and_continue:
724 729 /*
725 730 * Clear the reply descriptor for re-use and increment index.
726 731 */
727 732 ddi_put64(mpt->m_acc_post_queue_hdl,
728 - &((uint64_t *)(void *)mpt->m_post_queue)[mpt->m_post_index],
733 + &((uint64_t *)(void *)rpqp->rpq_queue)[rpqp->rpq_index],
729 734 0xFFFFFFFFFFFFFFFF);
730 735 (void) ddi_dma_sync(mpt->m_dma_post_queue_hdl, 0, 0,
731 736 DDI_DMA_SYNC_FORDEV);
732 737
733 738 /*
734 - * Update the global reply index and keep looking for the
739 + * Update the reply index and keep looking for the
735 740 * reply if not found yet.
736 741 */
737 - if (++mpt->m_post_index == mpt->m_post_queue_depth) {
738 - mpt->m_post_index = 0;
742 + if (++rpqp->rpq_index == mpt->m_post_queue_depth) {
743 + rpqp->rpq_index = 0;
739 744 }
745 +
740 746 ddi_put32(mpt->m_datap, &mpt->m_reg->ReplyPostHostIndex,
741 - mpt->m_post_index);
747 + rpqp->rpq_index);
742 748 if (!found_reply) {
743 749 continue;
744 750 }
745 751
746 752 break;
747 753 }
748 754
749 755 /*
750 756 * clear the used slot as the last step.
751 757 */
752 758 slots->m_slot[MPTSAS_TM_SLOT(mpt)] = NULL;
753 759 }
754 760
755 761 int
756 762 mptsas_delete_volume(mptsas_t *mpt, uint16_t volid)
757 763 {
758 764 int config, i = 0, vol = (-1);
759 765
760 766 for (config = 0; (config < mpt->m_num_raid_configs) && (vol != i);
761 767 config++) {
762 768 for (i = 0; i < MPTSAS_MAX_RAIDVOLS; i++) {
763 769 if (mpt->m_raidconfig[config].m_raidvol[i].
764 770 m_raidhandle == volid) {
765 771 vol = i;
766 772 break;
767 773 }
768 774 }
769 775 }
770 776
771 777 if (vol < 0) {
772 778 mptsas_log(mpt, CE_WARN, "raid doesn't exist at specified "
773 779 "target.");
774 780 return (-1);
775 781 }
776 782
777 783 mpt->m_raidconfig[config].m_raidvol[vol].m_israid = 0;
778 784 mpt->m_raidconfig[config].m_raidvol[vol].m_ndisks = 0;
779 785 for (i = 0; i < MPTSAS_MAX_DISKS_IN_VOL; i++) {
780 786 mpt->m_raidconfig[config].m_raidvol[vol].m_disknum[i] = 0;
781 787 mpt->m_raidconfig[config].m_raidvol[vol].m_devhdl[i] = 0;
782 788 }
783 789
784 790 return (0);
785 791 }
↓ open down ↓ |
34 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX