xref: /illumos-gate/usr/src/uts/common/io/scsi/adapters/mpt_sas/mptsas_raid.c (revision 24fe0b3bf671e123467ce1df0b67cadd3614c8e4)
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 2009 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 /*
28  * Copyright (c) 2000 to 2009, LSI Corporation.
29  * All rights reserved.
30  *
31  * Redistribution and use in source and binary forms of all code within
32  * this file that is exclusively owned by LSI, with or without
33  * modification, is permitted provided that, in addition to the CDDL 1.0
34  * License requirements, the following conditions are met:
35  *
36  *    Neither the name of the author nor the names of its contributors may be
37  *    used to endorse or promote products derived from this software without
38  *    specific prior written permission.
39  *
40  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
41  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
42  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
43  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
44  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
45  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
46  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
47  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
48  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
49  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
50  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
51  * DAMAGE.
52  */
53 
54 /*
55  * mptsas_raid - This file contains all the RAID related functions for the
56  * MPT interface.
57  */
58 
59 #if defined(lint) || defined(DEBUG)
60 #define	MPTSAS_DEBUG
61 #endif
62 
63 #define	MPI_RAID_VOL_PAGE_0_PHYSDISK_MAX	2
64 
65 /*
66  * standard header files
67  */
68 #include <sys/note.h>
69 #include <sys/scsi/scsi.h>
70 #include <sys/byteorder.h>
71 #include <sys/raidioctl.h>
72 
73 #pragma pack(1)
74 
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 
81 #pragma pack()
82 
83 /*
84  * private header files.
85  */
86 #include <sys/scsi/adapters/mpt_sas/mptsas_var.h>
87 
88 static int mptsas_get_raid_wwid(mptsas_t *mpt, mptsas_raidvol_t *raidvol);
89 
90 extern int mptsas_check_dma_handle(ddi_dma_handle_t handle);
91 extern int mptsas_check_acc_handle(ddi_acc_handle_t handle);
92 extern mptsas_target_t *mptsas_tgt_alloc(mptsas_hash_table_t *, uint16_t,
93     uint64_t, uint32_t, uint8_t, uint8_t);
94 
95 static int
96 mptsas_raidconf_page_0_cb(mptsas_t *mpt, caddr_t page_memp,
97     ddi_acc_handle_t accessp, uint16_t iocstatus, uint32_t iocloginfo,
98     va_list ap)
99 {
100 #ifndef __lock_lint
101 	_NOTE(ARGUNUSED(ap))
102 #endif
103 	pMpi2RaidConfigurationPage0_t	raidconfig_page0;
104 	pMpi2RaidConfig0ConfigElement_t	element;
105 	uint32_t *confignum;
106 	int rval = DDI_SUCCESS, i;
107 	uint8_t numelements, vol, disk;
108 	uint16_t elementtype, voldevhandle;
109 	uint16_t etype_vol, etype_pd, etype_hs;
110 	uint16_t etype_oce;
111 	mptsas_slots_t *slots = mpt->m_active;
112 	m_raidconfig_t *raidconfig;
113 	uint64_t raidwwn;
114 	uint32_t native;
115 	mptsas_target_t	*ptgt;
116 	uint32_t configindex;
117 
118 	if (iocstatus == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE) {
119 		return (DDI_FAILURE);
120 	}
121 
122 	if (iocstatus != MPI2_IOCSTATUS_SUCCESS) {
123 		mptsas_log(mpt, CE_WARN, "mptsas_get_raid_conf_page0 "
124 		    "config: IOCStatus=0x%x, IOCLogInfo=0x%x",
125 		    iocstatus, iocloginfo);
126 		rval = DDI_FAILURE;
127 		return (rval);
128 	}
129 	confignum = va_arg(ap,  uint32_t *);
130 	configindex = va_arg(ap, uint32_t);
131 	raidconfig_page0 = (pMpi2RaidConfigurationPage0_t)page_memp;
132 	/*
133 	 * Get all RAID configurations.
134 	 */
135 	etype_vol = MPI2_RAIDCONFIG0_EFLAGS_VOLUME_ELEMENT;
136 	etype_pd = MPI2_RAIDCONFIG0_EFLAGS_VOL_PHYS_DISK_ELEMENT;
137 	etype_hs = MPI2_RAIDCONFIG0_EFLAGS_HOT_SPARE_ELEMENT;
138 	etype_oce = MPI2_RAIDCONFIG0_EFLAGS_OCE_ELEMENT;
139 	/*
140 	 * Set up page address for next time through.
141 	 */
142 	*confignum =  ddi_get8(accessp,
143 	    &raidconfig_page0->ConfigNum);
144 
145 	/*
146 	 * Point to the right config in the structure.
147 	 * Increment the number of valid RAID configs.
148 	 */
149 	raidconfig = &slots->m_raidconfig[configindex];
150 	slots->m_num_raid_configs++;
151 
152 	/*
153 	 * Set the native flag if this is not a foreign
154 	 * configuration.
155 	 */
156 	native = ddi_get32(accessp, &raidconfig_page0->Flags);
157 	if (native & MPI2_RAIDCONFIG0_FLAG_FOREIGN_CONFIG) {
158 		native = FALSE;
159 	} else {
160 		native = TRUE;
161 	}
162 	raidconfig->m_native = (uint8_t)native;
163 
164 	/*
165 	 * Get volume information for the volumes in the
166 	 * config.
167 	 */
168 	numelements = ddi_get8(accessp, &raidconfig_page0->NumElements);
169 	vol = 0;
170 	disk = 0;
171 	element = (pMpi2RaidConfig0ConfigElement_t)
172 	    &raidconfig_page0->ConfigElement;
173 
174 	for (i = 0; i < numelements; i++, element++) {
175 		/*
176 		 * Get the element type.  Could be Volume,
177 		 * PhysDisk, Hot Spare, or Online Capacity
178 		 * Expansion PhysDisk.
179 		 */
180 		elementtype = ddi_get16(accessp, &element->ElementFlags);
181 		elementtype &= MPI2_RAIDCONFIG0_EFLAGS_MASK_ELEMENT_TYPE;
182 
183 		/*
184 		 * For volumes, get the RAID settings and the
185 		 * WWID.
186 		 */
187 		if (elementtype == etype_vol) {
188 			voldevhandle = ddi_get16(accessp,
189 			    &element->VolDevHandle);
190 			raidconfig->m_raidvol[vol].m_israid = 1;
191 			raidconfig->m_raidvol[vol].
192 			    m_raidhandle = voldevhandle;
193 			/*
194 			 * Get the settings for the raid
195 			 * volume.  This includes the
196 			 * DevHandles for the disks making up
197 			 * the raid volume.
198 			 */
199 			if (mptsas_get_raid_settings(mpt,
200 			    &raidconfig->m_raidvol[vol]))
201 				continue;
202 
203 			/*
204 			 * Get the WWID of the RAID volume for
205 			 * SAS HBA
206 			 */
207 			if (mptsas_get_raid_wwid(mpt,
208 			    &raidconfig->m_raidvol[vol]))
209 				continue;
210 
211 			raidwwn = raidconfig->m_raidvol[vol].
212 			    m_raidwwid;
213 
214 			/*
215 			 * RAID uses phymask of 0.
216 			 */
217 			ptgt = mptsas_tgt_alloc(&slots->m_tgttbl,
218 			    voldevhandle, raidwwn, 0, 0, 0);
219 
220 			raidconfig->m_raidvol[vol].m_raidtgt =
221 			    ptgt;
222 
223 			/*
224 			 * Increment volume index within this
225 			 * raid config.
226 			 */
227 			vol++;
228 		} else if ((elementtype == etype_pd) ||
229 		    (elementtype == etype_hs) ||
230 		    (elementtype == etype_oce)) {
231 			/*
232 			 * For all other element types, put
233 			 * their DevHandles in the phys disk
234 			 * list of the config.  These are all
235 			 * some variation of a Phys Disk and
236 			 * this list is used to keep these
237 			 * disks from going online.
238 			 */
239 			raidconfig->m_physdisk_devhdl[disk] = ddi_get16(accessp,
240 			    &element->PhysDiskDevHandle);
241 
242 			/*
243 			 * Increment disk index within this
244 			 * raid config.
245 			 */
246 			disk++;
247 		}
248 	}
249 
250 	return (rval);
251 }
252 
253 int
254 mptsas_get_raid_info(mptsas_t *mpt)
255 {
256 	int rval = DDI_SUCCESS;
257 	uint32_t confignum, pageaddress;
258 	uint8_t configindex;
259 	mptsas_slots_t *slots = mpt->m_active;
260 
261 	ASSERT(mutex_owned(&mpt->m_mutex));
262 
263 	/*
264 	 * Clear all RAID info before starting.
265 	 */
266 	bzero(slots->m_raidconfig, sizeof (slots->m_raidconfig));
267 	slots->m_num_raid_configs = 0;
268 
269 	configindex = 0;
270 	confignum = 0xff;
271 	pageaddress = MPI2_RAID_PGAD_FORM_GET_NEXT_CONFIGNUM | confignum;
272 	while (rval == DDI_SUCCESS) {
273 		/*
274 		 * Get the header and config page.  reply contains the reply
275 		 * frame, which holds status info for the request.
276 		 */
277 		rval = mptsas_access_config_page(mpt,
278 		    MPI2_CONFIG_ACTION_PAGE_READ_CURRENT,
279 		    MPI2_CONFIG_EXTPAGETYPE_RAID_CONFIG, 0, pageaddress,
280 		    mptsas_raidconf_page_0_cb, &confignum, configindex);
281 		configindex++;
282 		pageaddress = MPI2_RAID_PGAD_FORM_GET_NEXT_CONFIGNUM |
283 		    confignum;
284 	}
285 
286 	return (rval);
287 }
288 
289 static int
290 mptsas_raidvol_page_0_cb(mptsas_t *mpt, caddr_t page_memp,
291     ddi_acc_handle_t accessp, uint16_t iocstatus, uint32_t iocloginfo,
292     va_list ap)
293 {
294 #ifndef __lock_lint
295 	_NOTE(ARGUNUSED(ap))
296 #endif
297 	pMpi2RaidVolPage0_t raidpage;
298 	int rval = DDI_SUCCESS, i;
299 	mptsas_raidvol_t *raidvol;
300 	uint8_t	numdisks, volstate, voltype, physdisknum;
301 	uint32_t volsetting;
302 	uint32_t statusflags, resync_flag;
303 
304 	if (iocstatus == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE)
305 		return (DDI_FAILURE);
306 
307 	if (iocstatus != MPI2_IOCSTATUS_SUCCESS) {
308 		mptsas_log(mpt, CE_WARN, "mptsas_raidvol_page0_cb "
309 		    "config: IOCStatus=0x%x, IOCLogInfo=0x%x",
310 		    iocstatus, iocloginfo);
311 		rval = DDI_FAILURE;
312 		return (rval);
313 	}
314 
315 	raidvol = va_arg(ap,  mptsas_raidvol_t *);
316 
317 	raidpage = (pMpi2RaidVolPage0_t)page_memp;
318 	volstate = ddi_get8(accessp, &raidpage->VolumeState);
319 	volsetting = ddi_get32(accessp,
320 	    (uint32_t *)(void *)&raidpage->VolumeSettings);
321 	statusflags = ddi_get32(accessp, &raidpage->VolumeStatusFlags);
322 	voltype = ddi_get8(accessp, &raidpage->VolumeType);
323 
324 	raidvol->m_state = volstate;
325 	raidvol->m_statusflags = statusflags;
326 	/*
327 	 * Volume size is not used right now. Set to 0.
328 	 */
329 	raidvol->m_raidsize = 0;
330 	raidvol->m_settings = volsetting;
331 	raidvol->m_raidlevel = voltype;
332 
333 	if (statusflags & MPI2_RAIDVOL0_STATUS_FLAG_QUIESCED) {
334 		mptsas_log(mpt, CE_NOTE, "?Volume %d is quiesced\n",
335 		    raidvol->m_raidhandle);
336 	}
337 
338 	if (statusflags &
339 	    MPI2_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS) {
340 		mptsas_log(mpt, CE_NOTE, "?Volume %d is resyncing\n",
341 		    raidvol->m_raidhandle);
342 	}
343 
344 	resync_flag = MPI2_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS;
345 	switch (volstate) {
346 	case MPI2_RAID_VOL_STATE_OPTIMAL:
347 		mptsas_log(mpt, CE_NOTE, "?Volume %d is "
348 		    "optimal\n", raidvol->m_raidhandle);
349 		break;
350 	case MPI2_RAID_VOL_STATE_DEGRADED:
351 		if ((statusflags & resync_flag) == 0) {
352 			mptsas_log(mpt, CE_WARN, "Volume %d "
353 			    "is degraded\n",
354 			    raidvol->m_raidhandle);
355 		}
356 		break;
357 	case MPI2_RAID_VOL_STATE_FAILED:
358 		mptsas_log(mpt, CE_WARN, "Volume %d is "
359 		    "failed\n", raidvol->m_raidhandle);
360 		break;
361 	case MPI2_RAID_VOL_STATE_MISSING:
362 		mptsas_log(mpt, CE_WARN, "Volume %d is "
363 		    "missing\n", raidvol->m_raidhandle);
364 		break;
365 	default:
366 		break;
367 	}
368 	numdisks = raidpage->NumPhysDisks;
369 	raidvol->m_ndisks = numdisks;
370 	for (i = 0; i < numdisks; i++) {
371 		physdisknum = raidpage->PhysDisk[i].PhysDiskNum;
372 		raidvol->m_disknum[i] = physdisknum;
373 		if (mptsas_get_physdisk_settings(mpt, raidvol,
374 		    physdisknum))
375 			break;
376 	}
377 	return (rval);
378 }
379 
380 int
381 mptsas_get_raid_settings(mptsas_t *mpt, mptsas_raidvol_t *raidvol)
382 {
383 	int rval = DDI_SUCCESS;
384 	uint32_t page_address;
385 
386 	ASSERT(mutex_owned(&mpt->m_mutex));
387 
388 	/*
389 	 * Get the header and config page.  reply contains the reply frame,
390 	 * which holds status info for the request.
391 	 */
392 	page_address = (MPI2_RAID_VOLUME_PGAD_FORM_MASK &
393 	    MPI2_RAID_VOLUME_PGAD_FORM_HANDLE) | raidvol->m_raidhandle;
394 	rval = mptsas_access_config_page(mpt,
395 	    MPI2_CONFIG_ACTION_PAGE_READ_CURRENT,
396 	    MPI2_CONFIG_PAGETYPE_RAID_VOLUME, 0, page_address,
397 	    mptsas_raidvol_page_0_cb, raidvol);
398 
399 	return (rval);
400 }
401 
402 static int
403 mptsas_raidvol_page_1_cb(mptsas_t *mpt, caddr_t page_memp,
404     ddi_acc_handle_t accessp, uint16_t iocstatus, uint32_t iocloginfo,
405     va_list ap)
406 {
407 #ifndef __lock_lint
408 	_NOTE(ARGUNUSED(ap))
409 #endif
410 	pMpi2RaidVolPage1_t	raidpage;
411 	int			rval = DDI_SUCCESS, i;
412 	uint8_t			*sas_addr = NULL;
413 	uint8_t			tmp_sas_wwn[SAS_WWN_BYTE_SIZE];
414 	uint64_t		*sas_wwn;
415 
416 	if (iocstatus != MPI2_IOCSTATUS_SUCCESS) {
417 		mptsas_log(mpt, CE_WARN, "mptsas_raidvol_page_1_cb "
418 		    "config: IOCStatus=0x%x, IOCLogInfo=0x%x",
419 		    iocstatus, iocloginfo);
420 		rval = DDI_FAILURE;
421 		return (rval);
422 	}
423 	sas_wwn = va_arg(ap, uint64_t *);
424 
425 	raidpage = (pMpi2RaidVolPage1_t)page_memp;
426 	sas_addr = (uint8_t *)(&raidpage->WWID);
427 	for (i = 0; i < SAS_WWN_BYTE_SIZE; i++) {
428 		tmp_sas_wwn[i] = ddi_get8(accessp, sas_addr + i);
429 	}
430 	bcopy(tmp_sas_wwn, sas_wwn, SAS_WWN_BYTE_SIZE);
431 	*sas_wwn = LE_64(*sas_wwn);
432 	return (rval);
433 }
434 
435 static int
436 mptsas_get_raid_wwid(mptsas_t *mpt, mptsas_raidvol_t *raidvol)
437 {
438 	int rval = DDI_SUCCESS;
439 	uint32_t page_address;
440 	uint64_t sas_wwn;
441 
442 	ASSERT(mutex_owned(&mpt->m_mutex));
443 
444 	/*
445 	 * Get the header and config page.  reply contains the reply frame,
446 	 * which holds status info for the request.
447 	 */
448 	page_address = (MPI2_RAID_VOLUME_PGAD_FORM_MASK &
449 	    MPI2_RAID_VOLUME_PGAD_FORM_HANDLE) | raidvol->m_raidhandle;
450 	rval = mptsas_access_config_page(mpt,
451 	    MPI2_CONFIG_ACTION_PAGE_READ_CURRENT,
452 	    MPI2_CONFIG_PAGETYPE_RAID_VOLUME, 1, page_address,
453 	    mptsas_raidvol_page_1_cb, &sas_wwn);
454 
455 	/*
456 	 * Get the required information from the page.
457 	 */
458 	if (rval == DDI_SUCCESS) {
459 
460 		/*
461 		 * replace top nibble of WWID of RAID to '3' for OBP
462 		 */
463 		sas_wwn = MPTSAS_RAID_WWID(sas_wwn);
464 		raidvol->m_raidwwid = sas_wwn;
465 	}
466 
467 done:
468 	return (rval);
469 }
470 
471 static int
472 mptsas_raidphydsk_page_0_cb(mptsas_t *mpt, caddr_t page_memp,
473     ddi_acc_handle_t accessp, uint16_t iocstatus, uint32_t iocloginfo,
474     va_list ap)
475 {
476 #ifndef __lock_lint
477 	_NOTE(ARGUNUSED(ap))
478 #endif
479 	pMpi2RaidPhysDiskPage0_t	diskpage;
480 	int			rval = DDI_SUCCESS;
481 	uint16_t		*devhdl;
482 	uint8_t			*state;
483 
484 	if (iocstatus == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE)
485 		return (DDI_FAILURE);
486 
487 	if (iocstatus != MPI2_IOCSTATUS_SUCCESS) {
488 		mptsas_log(mpt, CE_WARN, "mptsas_raidphydsk_page0_cb "
489 		    "config: IOCStatus=0x%x, IOCLogInfo=0x%x",
490 		    iocstatus, iocloginfo);
491 		rval = DDI_FAILURE;
492 		return (rval);
493 	}
494 	devhdl = va_arg(ap, uint16_t *);
495 	state = va_arg(ap, uint8_t *);
496 	diskpage = (pMpi2RaidPhysDiskPage0_t)page_memp;
497 	*devhdl = ddi_get16(accessp, &diskpage->DevHandle);
498 	*state = ddi_get8(accessp, &diskpage->PhysDiskState);
499 	return (rval);
500 }
501 
502 int
503 mptsas_get_physdisk_settings(mptsas_t *mpt, mptsas_raidvol_t *raidvol,
504     uint8_t physdisknum)
505 {
506 	int			rval = DDI_SUCCESS, i;
507 	uint8_t			state;
508 	uint16_t		devhdl;
509 	uint32_t		page_address;
510 
511 	ASSERT(mutex_owned(&mpt->m_mutex));
512 
513 	/*
514 	 * Get the header and config page.  reply contains the reply frame,
515 	 * which holds status info for the request.
516 	 */
517 	page_address = (MPI2_PHYSDISK_PGAD_FORM_MASK &
518 	    MPI2_PHYSDISK_PGAD_FORM_PHYSDISKNUM) | physdisknum;
519 	rval = mptsas_access_config_page(mpt,
520 	    MPI2_CONFIG_ACTION_PAGE_READ_CURRENT,
521 	    MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK, 0, page_address,
522 	    mptsas_raidphydsk_page_0_cb, &devhdl, &state);
523 
524 	/*
525 	 * Get the required information from the page.
526 	 */
527 	if (rval == DDI_SUCCESS) {
528 		for (i = 0; i < MPTSAS_MAX_DISKS_IN_VOL; i++) {
529 			/* find the correct position in the arrays */
530 			if (raidvol->m_disknum[i] == physdisknum)
531 				break;
532 		}
533 		raidvol->m_devhdl[i] = devhdl;
534 
535 		switch (state) {
536 			case MPI2_RAID_PD_STATE_OFFLINE:
537 				raidvol->m_diskstatus[i] =
538 				    RAID_DISKSTATUS_FAILED;
539 				break;
540 
541 			case MPI2_RAID_PD_STATE_HOT_SPARE:
542 			case MPI2_RAID_PD_STATE_NOT_CONFIGURED:
543 			case MPI2_RAID_PD_STATE_NOT_COMPATIBLE:
544 				break;
545 
546 			case MPI2_RAID_PD_STATE_DEGRADED:
547 			case MPI2_RAID_PD_STATE_OPTIMAL:
548 			case MPI2_RAID_PD_STATE_REBUILDING:
549 			case MPI2_RAID_PD_STATE_ONLINE:
550 			default:
551 				raidvol->m_diskstatus[i] =
552 				    RAID_DISKSTATUS_GOOD;
553 				break;
554 		}
555 	}
556 
557 	return (rval);
558 }
559 
560 int
561 mptsas_delete_volume(mptsas_t *mpt, uint16_t volid)
562 {
563 	int		config, i, vol = (-1);
564 	mptsas_slots_t	*slots = mpt->m_active;
565 
566 	for (config = 0; config < slots->m_num_raid_configs; config++) {
567 		for (i = 0; i < MPTSAS_MAX_RAIDVOLS; i++) {
568 			if (slots->m_raidconfig[config].m_raidvol[i].
569 			    m_raidhandle == volid) {
570 				vol = i;
571 				break;
572 			}
573 		}
574 	}
575 
576 	if (vol < 0) {
577 		mptsas_log(mpt, CE_WARN, "raid doesn't exist at specified "
578 		    "target.");
579 		return (-1);
580 	}
581 
582 	slots->m_raidconfig[config].m_raidvol[vol].m_israid = 0;
583 	slots->m_raidconfig[config].m_raidvol[vol].m_ndisks = 0;
584 	for (i = 0; i < MPTSAS_MAX_DISKS_IN_VOL; i++) {
585 		slots->m_raidconfig[config].m_raidvol[vol].m_disknum[i] = 0;
586 		slots->m_raidconfig[config].m_raidvol[vol].m_devhdl[i] = 0;
587 	}
588 
589 	return (0);
590 }
591