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