1 /*-
2 * Routines for handling the integrated RAID features LSI MPT Fusion adapters.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 *
6 * Copyright (c) 2005, WHEEL Sp. z o.o.
7 * Copyright (c) 2005 Justin T. Gibbs.
8 * All rights reserved.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions are
12 * met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
16 * substantially similar to the "NO WARRANTY" disclaimer below
17 * ("Disclaimer") and any redistribution must be conditioned upon including
18 * a substantially similar Disclaimer requirement for further binary
19 * redistribution.
20 * 3. Neither the names of the above listed copyright holders nor the names
21 * of any contributors may be used to endorse or promote products derived
22 * from this software without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
25 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
28 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
32 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF THE COPYRIGHT
34 * OWNER OR CONTRIBUTOR IS ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35 */
36 /*-
37 * Some Breakage and Bug Fixing added later.
38 * Copyright (c) 2006, by Matthew Jacob
39 * All Rights Reserved
40 *
41 * Support from LSI-Logic has also gone a great deal toward making this a
42 * workable subsystem and is gratefully acknowledged.
43 */
44
45 #include <sys/cdefs.h>
46 __FBSDID("$FreeBSD$");
47
48 #include <dev/mpt/mpt.h>
49 #include <dev/mpt/mpt_raid.h>
50
51 #include "dev/mpt/mpilib/mpi_ioc.h" /* XXX Fix Event Handling!!! */
52 #include "dev/mpt/mpilib/mpi_raid.h"
53
54 #include <cam/cam.h>
55 #include <cam/cam_ccb.h>
56 #include <cam/cam_periph.h>
57 #include <cam/cam_sim.h>
58 #include <cam/cam_xpt_sim.h>
59
60 #include <sys/callout.h>
61 #include <sys/kthread.h>
62 #include <sys/sysctl.h>
63
64 #include <machine/stdarg.h>
65
66 struct mpt_raid_action_result
67 {
68 union {
69 MPI_RAID_VOL_INDICATOR indicator_struct;
70 uint32_t new_settings;
71 uint8_t phys_disk_num;
72 } action_data;
73 uint16_t action_status;
74 };
75
76 #define REQ_TO_RAID_ACTION_RESULT(req) ((struct mpt_raid_action_result *) \
77 (((MSG_RAID_ACTION_REQUEST *)(req->req_vbuf)) + 1))
78
79 #define REQ_IOCSTATUS(req) ((req)->IOCStatus & MPI_IOCSTATUS_MASK)
80
81 static mpt_probe_handler_t mpt_raid_probe;
82 static mpt_attach_handler_t mpt_raid_attach;
83 static mpt_enable_handler_t mpt_raid_enable;
84 static mpt_event_handler_t mpt_raid_event;
85 static mpt_shutdown_handler_t mpt_raid_shutdown;
86 static mpt_reset_handler_t mpt_raid_ioc_reset;
87 static mpt_detach_handler_t mpt_raid_detach;
88
89 static struct mpt_personality mpt_raid_personality =
90 {
91 .name = "mpt_raid",
92 .probe = mpt_raid_probe,
93 .attach = mpt_raid_attach,
94 .enable = mpt_raid_enable,
95 .event = mpt_raid_event,
96 .reset = mpt_raid_ioc_reset,
97 .shutdown = mpt_raid_shutdown,
98 .detach = mpt_raid_detach,
99 };
100
101 DECLARE_MPT_PERSONALITY(mpt_raid, SI_ORDER_THIRD);
102 MPT_PERSONALITY_DEPEND(mpt_raid, mpt_cam, 1, 1, 1);
103
104 static mpt_reply_handler_t mpt_raid_reply_handler;
105 static int mpt_raid_reply_frame_handler(struct mpt_softc *mpt, request_t *req,
106 MSG_DEFAULT_REPLY *reply_frame);
107 static int mpt_spawn_raid_thread(struct mpt_softc *mpt);
108 static void mpt_terminate_raid_thread(struct mpt_softc *mpt);
109 static void mpt_raid_thread(void *arg);
110 static timeout_t mpt_raid_timer;
111 #if 0
112 static void mpt_enable_vol(struct mpt_softc *mpt,
113 struct mpt_raid_volume *mpt_vol, int enable);
114 #endif
115 static void mpt_verify_mwce(struct mpt_softc *, struct mpt_raid_volume *);
116 static void mpt_adjust_queue_depth(struct mpt_softc *, struct mpt_raid_volume *,
117 struct cam_path *);
118 static void mpt_raid_sysctl_attach(struct mpt_softc *);
119
120 static const char *mpt_vol_type(struct mpt_raid_volume *vol);
121 static const char *mpt_vol_state(struct mpt_raid_volume *vol);
122 static const char *mpt_disk_state(struct mpt_raid_disk *disk);
123 static void mpt_vol_prt(struct mpt_softc *mpt, struct mpt_raid_volume *vol,
124 const char *fmt, ...);
125 static void mpt_disk_prt(struct mpt_softc *mpt, struct mpt_raid_disk *disk,
126 const char *fmt, ...);
127
128 static int mpt_issue_raid_req(struct mpt_softc *mpt,
129 struct mpt_raid_volume *vol, struct mpt_raid_disk *disk, request_t *req,
130 u_int Action, uint32_t ActionDataWord, bus_addr_t addr, bus_size_t len,
131 int write, int wait);
132
133 static int mpt_refresh_raid_data(struct mpt_softc *mpt);
134 static void mpt_schedule_raid_refresh(struct mpt_softc *mpt);
135
136 static uint32_t raid_handler_id = MPT_HANDLER_ID_NONE;
137
138 static const char *
mpt_vol_type(struct mpt_raid_volume * vol)139 mpt_vol_type(struct mpt_raid_volume *vol)
140 {
141 switch (vol->config_page->VolumeType) {
142 case MPI_RAID_VOL_TYPE_IS:
143 return ("RAID-0");
144 case MPI_RAID_VOL_TYPE_IME:
145 return ("RAID-1E");
146 case MPI_RAID_VOL_TYPE_IM:
147 return ("RAID-1");
148 default:
149 return ("Unknown");
150 }
151 }
152
153 static const char *
mpt_vol_state(struct mpt_raid_volume * vol)154 mpt_vol_state(struct mpt_raid_volume *vol)
155 {
156 switch (vol->config_page->VolumeStatus.State) {
157 case MPI_RAIDVOL0_STATUS_STATE_OPTIMAL:
158 return ("Optimal");
159 case MPI_RAIDVOL0_STATUS_STATE_DEGRADED:
160 return ("Degraded");
161 case MPI_RAIDVOL0_STATUS_STATE_FAILED:
162 return ("Failed");
163 default:
164 return ("Unknown");
165 }
166 }
167
168 static const char *
mpt_disk_state(struct mpt_raid_disk * disk)169 mpt_disk_state(struct mpt_raid_disk *disk)
170 {
171 switch (disk->config_page.PhysDiskStatus.State) {
172 case MPI_PHYSDISK0_STATUS_ONLINE:
173 return ("Online");
174 case MPI_PHYSDISK0_STATUS_MISSING:
175 return ("Missing");
176 case MPI_PHYSDISK0_STATUS_NOT_COMPATIBLE:
177 return ("Incompatible");
178 case MPI_PHYSDISK0_STATUS_FAILED:
179 return ("Failed");
180 case MPI_PHYSDISK0_STATUS_INITIALIZING:
181 return ("Initializing");
182 case MPI_PHYSDISK0_STATUS_OFFLINE_REQUESTED:
183 return ("Offline Requested");
184 case MPI_PHYSDISK0_STATUS_FAILED_REQUESTED:
185 return ("Failed per Host Request");
186 case MPI_PHYSDISK0_STATUS_OTHER_OFFLINE:
187 return ("Offline");
188 default:
189 return ("Unknown");
190 }
191 }
192
193 static void
mpt_vol_prt(struct mpt_softc * mpt,struct mpt_raid_volume * vol,const char * fmt,...)194 mpt_vol_prt(struct mpt_softc *mpt, struct mpt_raid_volume *vol,
195 const char *fmt, ...)
196 {
197 va_list ap;
198
199 printf("%s:vol%d(%s:%d:%d): ", device_get_nameunit(mpt->dev),
200 (u_int)(vol - mpt->raid_volumes), device_get_nameunit(mpt->dev),
201 vol->config_page->VolumeBus, vol->config_page->VolumeID);
202 va_start(ap, fmt);
203 vprintf(fmt, ap);
204 va_end(ap);
205 }
206
207 static void
mpt_disk_prt(struct mpt_softc * mpt,struct mpt_raid_disk * disk,const char * fmt,...)208 mpt_disk_prt(struct mpt_softc *mpt, struct mpt_raid_disk *disk,
209 const char *fmt, ...)
210 {
211 va_list ap;
212
213 if (disk->volume != NULL) {
214 printf("(%s:vol%d:%d): ",
215 device_get_nameunit(mpt->dev),
216 disk->volume->config_page->VolumeID,
217 disk->member_number);
218 } else {
219 printf("(%s:%d:%d): ", device_get_nameunit(mpt->dev),
220 disk->config_page.PhysDiskBus,
221 disk->config_page.PhysDiskID);
222 }
223 va_start(ap, fmt);
224 vprintf(fmt, ap);
225 va_end(ap);
226 }
227
228 static void
mpt_raid_async(void * callback_arg,u_int32_t code,struct cam_path * path,void * arg)229 mpt_raid_async(void *callback_arg, u_int32_t code,
230 struct cam_path *path, void *arg)
231 {
232 struct mpt_softc *mpt;
233
234 mpt = (struct mpt_softc*)callback_arg;
235 switch (code) {
236 case AC_FOUND_DEVICE:
237 {
238 struct ccb_getdev *cgd;
239 struct mpt_raid_volume *mpt_vol;
240
241 cgd = (struct ccb_getdev *)arg;
242 if (cgd == NULL) {
243 break;
244 }
245
246 mpt_lprt(mpt, MPT_PRT_DEBUG, "Callback for %d\n",
247 cgd->ccb_h.target_id);
248
249 RAID_VOL_FOREACH(mpt, mpt_vol) {
250 if ((mpt_vol->flags & MPT_RVF_ACTIVE) == 0)
251 continue;
252
253 if (mpt_vol->config_page->VolumeID
254 == cgd->ccb_h.target_id) {
255 mpt_adjust_queue_depth(mpt, mpt_vol, path);
256 break;
257 }
258 }
259 }
260 default:
261 break;
262 }
263 }
264
265 static int
mpt_raid_probe(struct mpt_softc * mpt)266 mpt_raid_probe(struct mpt_softc *mpt)
267 {
268
269 if (mpt->ioc_page2 == NULL || mpt->ioc_page2->MaxPhysDisks == 0) {
270 return (ENODEV);
271 }
272 return (0);
273 }
274
275 static int
mpt_raid_attach(struct mpt_softc * mpt)276 mpt_raid_attach(struct mpt_softc *mpt)
277 {
278 struct ccb_setasync csa;
279 mpt_handler_t handler;
280 int error;
281
282 mpt_callout_init(mpt, &mpt->raid_timer);
283
284 error = mpt_spawn_raid_thread(mpt);
285 if (error != 0) {
286 mpt_prt(mpt, "Unable to spawn RAID thread!\n");
287 goto cleanup;
288 }
289
290 MPT_LOCK(mpt);
291 handler.reply_handler = mpt_raid_reply_handler;
292 error = mpt_register_handler(mpt, MPT_HANDLER_REPLY, handler,
293 &raid_handler_id);
294 if (error != 0) {
295 mpt_prt(mpt, "Unable to register RAID haandler!\n");
296 goto cleanup;
297 }
298
299 xpt_setup_ccb(&csa.ccb_h, mpt->path, 5);
300 csa.ccb_h.func_code = XPT_SASYNC_CB;
301 csa.event_enable = AC_FOUND_DEVICE;
302 csa.callback = mpt_raid_async;
303 csa.callback_arg = mpt;
304 xpt_action((union ccb *)&csa);
305 if (csa.ccb_h.status != CAM_REQ_CMP) {
306 mpt_prt(mpt, "mpt_raid_attach: Unable to register "
307 "CAM async handler.\n");
308 }
309 MPT_UNLOCK(mpt);
310
311 mpt_raid_sysctl_attach(mpt);
312 return (0);
313 cleanup:
314 MPT_UNLOCK(mpt);
315 mpt_raid_detach(mpt);
316 return (error);
317 }
318
319 static int
mpt_raid_enable(struct mpt_softc * mpt)320 mpt_raid_enable(struct mpt_softc *mpt)
321 {
322
323 return (0);
324 }
325
326 static void
mpt_raid_detach(struct mpt_softc * mpt)327 mpt_raid_detach(struct mpt_softc *mpt)
328 {
329 struct ccb_setasync csa;
330 mpt_handler_t handler;
331
332 mpt_callout_drain(mpt, &mpt->raid_timer);
333
334 MPT_LOCK(mpt);
335 mpt_terminate_raid_thread(mpt);
336 handler.reply_handler = mpt_raid_reply_handler;
337 mpt_deregister_handler(mpt, MPT_HANDLER_REPLY, handler,
338 raid_handler_id);
339 xpt_setup_ccb(&csa.ccb_h, mpt->path, /*priority*/5);
340 csa.ccb_h.func_code = XPT_SASYNC_CB;
341 csa.event_enable = 0;
342 csa.callback = mpt_raid_async;
343 csa.callback_arg = mpt;
344 xpt_action((union ccb *)&csa);
345 MPT_UNLOCK(mpt);
346 }
347
348 static void
mpt_raid_ioc_reset(struct mpt_softc * mpt,int type)349 mpt_raid_ioc_reset(struct mpt_softc *mpt, int type)
350 {
351
352 /* Nothing to do yet. */
353 }
354
355 static const char *raid_event_txt[] =
356 {
357 "Volume Created",
358 "Volume Deleted",
359 "Volume Settings Changed",
360 "Volume Status Changed",
361 "Volume Physical Disk Membership Changed",
362 "Physical Disk Created",
363 "Physical Disk Deleted",
364 "Physical Disk Settings Changed",
365 "Physical Disk Status Changed",
366 "Domain Validation Required",
367 "SMART Data Received",
368 "Replace Action Started",
369 };
370
371 static int
mpt_raid_event(struct mpt_softc * mpt,request_t * req,MSG_EVENT_NOTIFY_REPLY * msg)372 mpt_raid_event(struct mpt_softc *mpt, request_t *req,
373 MSG_EVENT_NOTIFY_REPLY *msg)
374 {
375 EVENT_DATA_RAID *raid_event;
376 struct mpt_raid_volume *mpt_vol;
377 struct mpt_raid_disk *mpt_disk;
378 CONFIG_PAGE_RAID_VOL_0 *vol_pg;
379 int i;
380 int print_event;
381
382 if (msg->Event != MPI_EVENT_INTEGRATED_RAID) {
383 return (0);
384 }
385
386 raid_event = (EVENT_DATA_RAID *)&msg->Data;
387
388 mpt_vol = NULL;
389 vol_pg = NULL;
390 if (mpt->raid_volumes != NULL && mpt->ioc_page2 != NULL) {
391 for (i = 0; i < mpt->ioc_page2->MaxVolumes; i++) {
392 mpt_vol = &mpt->raid_volumes[i];
393 vol_pg = mpt_vol->config_page;
394
395 if ((mpt_vol->flags & MPT_RVF_ACTIVE) == 0)
396 continue;
397
398 if (vol_pg->VolumeID == raid_event->VolumeID
399 && vol_pg->VolumeBus == raid_event->VolumeBus)
400 break;
401 }
402 if (i >= mpt->ioc_page2->MaxVolumes) {
403 mpt_vol = NULL;
404 vol_pg = NULL;
405 }
406 }
407
408 mpt_disk = NULL;
409 if (raid_event->PhysDiskNum != 0xFF && mpt->raid_disks != NULL) {
410 mpt_disk = mpt->raid_disks + raid_event->PhysDiskNum;
411 if ((mpt_disk->flags & MPT_RDF_ACTIVE) == 0) {
412 mpt_disk = NULL;
413 }
414 }
415
416 print_event = 1;
417 switch(raid_event->ReasonCode) {
418 case MPI_EVENT_RAID_RC_VOLUME_CREATED:
419 case MPI_EVENT_RAID_RC_VOLUME_DELETED:
420 break;
421 case MPI_EVENT_RAID_RC_VOLUME_STATUS_CHANGED:
422 if (mpt_vol != NULL) {
423 if ((mpt_vol->flags & MPT_RVF_UP2DATE) != 0) {
424 mpt_vol->flags &= ~MPT_RVF_UP2DATE;
425 } else {
426 /*
427 * Coalesce status messages into one
428 * per background run of our RAID thread.
429 * This removes "spurious" status messages
430 * from our output.
431 */
432 print_event = 0;
433 }
434 }
435 break;
436 case MPI_EVENT_RAID_RC_VOLUME_SETTINGS_CHANGED:
437 case MPI_EVENT_RAID_RC_VOLUME_PHYSDISK_CHANGED:
438 mpt->raid_rescan++;
439 if (mpt_vol != NULL) {
440 mpt_vol->flags &= ~(MPT_RVF_UP2DATE|MPT_RVF_ANNOUNCED);
441 }
442 break;
443 case MPI_EVENT_RAID_RC_PHYSDISK_CREATED:
444 case MPI_EVENT_RAID_RC_PHYSDISK_DELETED:
445 mpt->raid_rescan++;
446 break;
447 case MPI_EVENT_RAID_RC_PHYSDISK_SETTINGS_CHANGED:
448 case MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED:
449 mpt->raid_rescan++;
450 if (mpt_disk != NULL) {
451 mpt_disk->flags &= ~MPT_RDF_UP2DATE;
452 }
453 break;
454 case MPI_EVENT_RAID_RC_DOMAIN_VAL_NEEDED:
455 mpt->raid_rescan++;
456 break;
457 case MPI_EVENT_RAID_RC_SMART_DATA:
458 case MPI_EVENT_RAID_RC_REPLACE_ACTION_STARTED:
459 break;
460 }
461
462 if (print_event) {
463 if (mpt_disk != NULL) {
464 mpt_disk_prt(mpt, mpt_disk, "");
465 } else if (mpt_vol != NULL) {
466 mpt_vol_prt(mpt, mpt_vol, "");
467 } else {
468 mpt_prt(mpt, "Volume(%d:%d", raid_event->VolumeBus,
469 raid_event->VolumeID);
470
471 if (raid_event->PhysDiskNum != 0xFF)
472 mpt_prtc(mpt, ":%d): ",
473 raid_event->PhysDiskNum);
474 else
475 mpt_prtc(mpt, "): ");
476 }
477
478 if (raid_event->ReasonCode >= NUM_ELEMENTS(raid_event_txt))
479 mpt_prtc(mpt, "Unhandled RaidEvent %#x\n",
480 raid_event->ReasonCode);
481 else
482 mpt_prtc(mpt, "%s\n",
483 raid_event_txt[raid_event->ReasonCode]);
484 }
485
486 if (raid_event->ReasonCode == MPI_EVENT_RAID_RC_SMART_DATA) {
487 /* XXX Use CAM's print sense for this... */
488 if (mpt_disk != NULL)
489 mpt_disk_prt(mpt, mpt_disk, "");
490 else
491 mpt_prt(mpt, "Volume(%d:%d:%d: ",
492 raid_event->VolumeBus, raid_event->VolumeID,
493 raid_event->PhysDiskNum);
494 mpt_prtc(mpt, "ASC 0x%x, ASCQ 0x%x)\n",
495 raid_event->ASC, raid_event->ASCQ);
496 }
497
498 mpt_raid_wakeup(mpt);
499 return (1);
500 }
501
502 static void
mpt_raid_shutdown(struct mpt_softc * mpt)503 mpt_raid_shutdown(struct mpt_softc *mpt)
504 {
505 struct mpt_raid_volume *mpt_vol;
506
507 if (mpt->raid_mwce_setting != MPT_RAID_MWCE_REBUILD_ONLY) {
508 return;
509 }
510
511 mpt->raid_mwce_setting = MPT_RAID_MWCE_OFF;
512 RAID_VOL_FOREACH(mpt, mpt_vol) {
513 mpt_verify_mwce(mpt, mpt_vol);
514 }
515 }
516
517 static int
mpt_raid_reply_handler(struct mpt_softc * mpt,request_t * req,uint32_t reply_desc,MSG_DEFAULT_REPLY * reply_frame)518 mpt_raid_reply_handler(struct mpt_softc *mpt, request_t *req,
519 uint32_t reply_desc, MSG_DEFAULT_REPLY *reply_frame)
520 {
521 int free_req;
522
523 if (req == NULL)
524 return (TRUE);
525
526 free_req = TRUE;
527 if (reply_frame != NULL)
528 free_req = mpt_raid_reply_frame_handler(mpt, req, reply_frame);
529 #ifdef NOTYET
530 else if (req->ccb != NULL) {
531 /* Complete Quiesce CCB with error... */
532 }
533 #endif
534
535 req->state &= ~REQ_STATE_QUEUED;
536 req->state |= REQ_STATE_DONE;
537 TAILQ_REMOVE(&mpt->request_pending_list, req, links);
538
539 if ((req->state & REQ_STATE_NEED_WAKEUP) != 0) {
540 wakeup(req);
541 } else if (free_req) {
542 mpt_free_request(mpt, req);
543 }
544
545 return (TRUE);
546 }
547
548 /*
549 * Parse additional completion information in the reply
550 * frame for RAID I/O requests.
551 */
552 static int
mpt_raid_reply_frame_handler(struct mpt_softc * mpt,request_t * req,MSG_DEFAULT_REPLY * reply_frame)553 mpt_raid_reply_frame_handler(struct mpt_softc *mpt, request_t *req,
554 MSG_DEFAULT_REPLY *reply_frame)
555 {
556 MSG_RAID_ACTION_REPLY *reply;
557 struct mpt_raid_action_result *action_result;
558 MSG_RAID_ACTION_REQUEST *rap;
559
560 reply = (MSG_RAID_ACTION_REPLY *)reply_frame;
561 req->IOCStatus = le16toh(reply->IOCStatus);
562 rap = (MSG_RAID_ACTION_REQUEST *)req->req_vbuf;
563
564 switch (rap->Action) {
565 case MPI_RAID_ACTION_QUIESCE_PHYS_IO:
566 mpt_prt(mpt, "QUIESCE PHYSIO DONE\n");
567 break;
568 case MPI_RAID_ACTION_ENABLE_PHYS_IO:
569 mpt_prt(mpt, "ENABLY PHYSIO DONE\n");
570 break;
571 default:
572 break;
573 }
574 action_result = REQ_TO_RAID_ACTION_RESULT(req);
575 memcpy(&action_result->action_data, &reply->ActionData,
576 sizeof(action_result->action_data));
577 action_result->action_status = le16toh(reply->ActionStatus);
578 return (TRUE);
579 }
580
581 /*
582 * Utiltity routine to perform a RAID action command;
583 */
584 static int
mpt_issue_raid_req(struct mpt_softc * mpt,struct mpt_raid_volume * vol,struct mpt_raid_disk * disk,request_t * req,u_int Action,uint32_t ActionDataWord,bus_addr_t addr,bus_size_t len,int write,int wait)585 mpt_issue_raid_req(struct mpt_softc *mpt, struct mpt_raid_volume *vol,
586 struct mpt_raid_disk *disk, request_t *req, u_int Action,
587 uint32_t ActionDataWord, bus_addr_t addr, bus_size_t len,
588 int write, int wait)
589 {
590 MSG_RAID_ACTION_REQUEST *rap;
591 SGE_SIMPLE32 *se;
592
593 rap = req->req_vbuf;
594 memset(rap, 0, sizeof *rap);
595 rap->Action = Action;
596 rap->ActionDataWord = htole32(ActionDataWord);
597 rap->Function = MPI_FUNCTION_RAID_ACTION;
598 rap->VolumeID = vol->config_page->VolumeID;
599 rap->VolumeBus = vol->config_page->VolumeBus;
600 if (disk != NULL)
601 rap->PhysDiskNum = disk->config_page.PhysDiskNum;
602 else
603 rap->PhysDiskNum = 0xFF;
604 se = (SGE_SIMPLE32 *)&rap->ActionDataSGE;
605 se->Address = htole32(addr);
606 MPI_pSGE_SET_LENGTH(se, len);
607 MPI_pSGE_SET_FLAGS(se, (MPI_SGE_FLAGS_SIMPLE_ELEMENT |
608 MPI_SGE_FLAGS_LAST_ELEMENT | MPI_SGE_FLAGS_END_OF_BUFFER |
609 MPI_SGE_FLAGS_END_OF_LIST |
610 (write ? MPI_SGE_FLAGS_HOST_TO_IOC : MPI_SGE_FLAGS_IOC_TO_HOST)));
611 se->FlagsLength = htole32(se->FlagsLength);
612 rap->MsgContext = htole32(req->index | raid_handler_id);
613
614 mpt_check_doorbell(mpt);
615 mpt_send_cmd(mpt, req);
616
617 if (wait) {
618 return (mpt_wait_req(mpt, req, REQ_STATE_DONE, REQ_STATE_DONE,
619 /*sleep_ok*/FALSE, /*time_ms*/2000));
620 } else {
621 return (0);
622 }
623 }
624
625 /*************************** RAID Status Monitoring ***************************/
626 static int
mpt_spawn_raid_thread(struct mpt_softc * mpt)627 mpt_spawn_raid_thread(struct mpt_softc *mpt)
628 {
629 int error;
630
631 /*
632 * Freeze out any CAM transactions until our thread
633 * is able to run at least once. We need to update
634 * our RAID pages before acception I/O or we may
635 * reject I/O to an ID we later determine is for a
636 * hidden physdisk.
637 */
638 MPT_LOCK(mpt);
639 xpt_freeze_simq(mpt->phydisk_sim, 1);
640 MPT_UNLOCK(mpt);
641 error = kproc_create(mpt_raid_thread, mpt,
642 &mpt->raid_thread, /*flags*/0, /*altstack*/0,
643 "mpt_raid%d", mpt->unit);
644 if (error != 0) {
645 MPT_LOCK(mpt);
646 xpt_release_simq(mpt->phydisk_sim, /*run_queue*/FALSE);
647 MPT_UNLOCK(mpt);
648 }
649 return (error);
650 }
651
652 static void
mpt_terminate_raid_thread(struct mpt_softc * mpt)653 mpt_terminate_raid_thread(struct mpt_softc *mpt)
654 {
655
656 if (mpt->raid_thread == NULL) {
657 return;
658 }
659 mpt->shutdwn_raid = 1;
660 wakeup(&mpt->raid_volumes);
661 /*
662 * Sleep on a slightly different location
663 * for this interlock just for added safety.
664 */
665 mpt_sleep(mpt, &mpt->raid_thread, PUSER, "thtrm", 0);
666 }
667
668 static void
mpt_raid_thread(void * arg)669 mpt_raid_thread(void *arg)
670 {
671 struct mpt_softc *mpt;
672 int firstrun;
673
674 mpt = (struct mpt_softc *)arg;
675 firstrun = 1;
676 MPT_LOCK(mpt);
677 while (mpt->shutdwn_raid == 0) {
678
679 if (mpt->raid_wakeup == 0) {
680 mpt_sleep(mpt, &mpt->raid_volumes, PUSER, "idle", 0);
681 continue;
682 }
683
684 mpt->raid_wakeup = 0;
685
686 if (mpt_refresh_raid_data(mpt)) {
687 mpt_schedule_raid_refresh(mpt); /* XX NOT QUITE RIGHT */
688 continue;
689 }
690
691 /*
692 * Now that we have our first snapshot of RAID data,
693 * allow CAM to access our physical disk bus.
694 */
695 if (firstrun) {
696 firstrun = 0;
697 xpt_release_simq(mpt->phydisk_sim, TRUE);
698 }
699
700 if (mpt->raid_rescan != 0) {
701 union ccb *ccb;
702 int error;
703
704 mpt->raid_rescan = 0;
705 MPT_UNLOCK(mpt);
706
707 ccb = xpt_alloc_ccb();
708
709 MPT_LOCK(mpt);
710 error = xpt_create_path(&ccb->ccb_h.path, NULL,
711 cam_sim_path(mpt->phydisk_sim),
712 CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD);
713 if (error != CAM_REQ_CMP) {
714 xpt_free_ccb(ccb);
715 mpt_prt(mpt, "Unable to rescan RAID Bus!\n");
716 } else {
717 xpt_rescan(ccb);
718 }
719 }
720 }
721 mpt->raid_thread = NULL;
722 wakeup(&mpt->raid_thread);
723 MPT_UNLOCK(mpt);
724 kproc_exit(0);
725 }
726
727 #if 0
728 static void
729 mpt_raid_quiesce_timeout(void *arg)
730 {
731
732 /* Complete the CCB with error */
733 /* COWWWW */
734 }
735
736 static timeout_t mpt_raid_quiesce_timeout;
737 cam_status
738 mpt_raid_quiesce_disk(struct mpt_softc *mpt, struct mpt_raid_disk *mpt_disk,
739 request_t *req)
740 {
741 union ccb *ccb;
742
743 ccb = req->ccb;
744 if ((mpt_disk->flags & MPT_RDF_QUIESCED) != 0)
745 return (CAM_REQ_CMP);
746
747 if ((mpt_disk->flags & MPT_RDF_QUIESCING) == 0) {
748 int rv;
749
750 mpt_disk->flags |= MPT_RDF_QUIESCING;
751 xpt_freeze_devq(ccb->ccb_h.path, 1);
752
753 rv = mpt_issue_raid_req(mpt, mpt_disk->volume, mpt_disk, req,
754 MPI_RAID_ACTION_QUIESCE_PHYS_IO,
755 /*ActionData*/0, /*addr*/0,
756 /*len*/0, /*write*/FALSE,
757 /*wait*/FALSE);
758 if (rv != 0)
759 return (CAM_REQ_CMP_ERR);
760
761 mpt_req_timeout(req, mpt_raid_quiesce_timeout, ccb, 5 * hz);
762 #if 0
763 if (rv == ETIMEDOUT) {
764 mpt_disk_prt(mpt, mpt_disk, "mpt_raid_quiesce_disk: "
765 "Quiece Timed-out\n");
766 xpt_release_devq(ccb->ccb_h.path, 1, /*run*/0);
767 return (CAM_REQ_CMP_ERR);
768 }
769
770 ar = REQ_TO_RAID_ACTION_RESULT(req);
771 if (rv != 0
772 || REQ_IOCSTATUS(req) != MPI_IOCSTATUS_SUCCESS
773 || (ar->action_status != MPI_RAID_ACTION_ASTATUS_SUCCESS)) {
774 mpt_disk_prt(mpt, mpt_disk, "Quiece Failed"
775 "%d:%x:%x\n", rv, req->IOCStatus,
776 ar->action_status);
777 xpt_release_devq(ccb->ccb_h.path, 1, /*run*/0);
778 return (CAM_REQ_CMP_ERR);
779 }
780 #endif
781 return (CAM_REQ_INPROG);
782 }
783 return (CAM_REQUEUE_REQ);
784 }
785 #endif
786
787 /* XXX Ignores that there may be multiple buses/IOCs involved. */
788 cam_status
mpt_map_physdisk(struct mpt_softc * mpt,union ccb * ccb,target_id_t * tgt)789 mpt_map_physdisk(struct mpt_softc *mpt, union ccb *ccb, target_id_t *tgt)
790 {
791 struct mpt_raid_disk *mpt_disk;
792
793 mpt_disk = mpt->raid_disks + ccb->ccb_h.target_id;
794 if (ccb->ccb_h.target_id < mpt->raid_max_disks
795 && (mpt_disk->flags & MPT_RDF_ACTIVE) != 0) {
796 *tgt = mpt_disk->config_page.PhysDiskID;
797 return (0);
798 }
799 mpt_lprt(mpt, MPT_PRT_DEBUG1, "mpt_map_physdisk(%d) - Not Active\n",
800 ccb->ccb_h.target_id);
801 return (-1);
802 }
803
804 /* XXX Ignores that there may be multiple buses/IOCs involved. */
805 int
mpt_is_raid_member(struct mpt_softc * mpt,target_id_t tgt)806 mpt_is_raid_member(struct mpt_softc *mpt, target_id_t tgt)
807 {
808 struct mpt_raid_disk *mpt_disk;
809 int i;
810
811 if (mpt->ioc_page2 == NULL || mpt->ioc_page2->MaxPhysDisks == 0)
812 return (0);
813 for (i = 0; i < mpt->ioc_page2->MaxPhysDisks; i++) {
814 mpt_disk = &mpt->raid_disks[i];
815 if ((mpt_disk->flags & MPT_RDF_ACTIVE) != 0 &&
816 mpt_disk->config_page.PhysDiskID == tgt)
817 return (1);
818 }
819 return (0);
820
821 }
822
823 /* XXX Ignores that there may be multiple buses/IOCs involved. */
824 int
mpt_is_raid_volume(struct mpt_softc * mpt,target_id_t tgt)825 mpt_is_raid_volume(struct mpt_softc *mpt, target_id_t tgt)
826 {
827 CONFIG_PAGE_IOC_2_RAID_VOL *ioc_vol;
828 CONFIG_PAGE_IOC_2_RAID_VOL *ioc_last_vol;
829
830 if (mpt->ioc_page2 == NULL || mpt->ioc_page2->MaxPhysDisks == 0) {
831 return (0);
832 }
833 ioc_vol = mpt->ioc_page2->RaidVolume;
834 ioc_last_vol = ioc_vol + mpt->ioc_page2->NumActiveVolumes;
835 for (;ioc_vol != ioc_last_vol; ioc_vol++) {
836 if (ioc_vol->VolumeID == tgt) {
837 return (1);
838 }
839 }
840 return (0);
841 }
842
843 #if 0
844 static void
845 mpt_enable_vol(struct mpt_softc *mpt, struct mpt_raid_volume *mpt_vol,
846 int enable)
847 {
848 request_t *req;
849 struct mpt_raid_action_result *ar;
850 CONFIG_PAGE_RAID_VOL_0 *vol_pg;
851 int enabled;
852 int rv;
853
854 vol_pg = mpt_vol->config_page;
855 enabled = vol_pg->VolumeStatus.Flags & MPI_RAIDVOL0_STATUS_FLAG_ENABLED;
856
857 /*
858 * If the setting matches the configuration,
859 * there is nothing to do.
860 */
861 if ((enabled && enable)
862 || (!enabled && !enable))
863 return;
864
865 req = mpt_get_request(mpt, /*sleep_ok*/TRUE);
866 if (req == NULL) {
867 mpt_vol_prt(mpt, mpt_vol,
868 "mpt_enable_vol: Get request failed!\n");
869 return;
870 }
871
872 rv = mpt_issue_raid_req(mpt, mpt_vol, /*disk*/NULL, req,
873 enable ? MPI_RAID_ACTION_ENABLE_VOLUME
874 : MPI_RAID_ACTION_DISABLE_VOLUME,
875 /*data*/0, /*addr*/0, /*len*/0,
876 /*write*/FALSE, /*wait*/TRUE);
877 if (rv == ETIMEDOUT) {
878 mpt_vol_prt(mpt, mpt_vol, "mpt_enable_vol: "
879 "%s Volume Timed-out\n",
880 enable ? "Enable" : "Disable");
881 return;
882 }
883 ar = REQ_TO_RAID_ACTION_RESULT(req);
884 if (rv != 0
885 || REQ_IOCSTATUS(req) != MPI_IOCSTATUS_SUCCESS
886 || (ar->action_status != MPI_RAID_ACTION_ASTATUS_SUCCESS)) {
887 mpt_vol_prt(mpt, mpt_vol, "%s Volume Failed: %d:%x:%x\n",
888 enable ? "Enable" : "Disable",
889 rv, req->IOCStatus, ar->action_status);
890 }
891
892 mpt_free_request(mpt, req);
893 }
894 #endif
895
896 static void
mpt_verify_mwce(struct mpt_softc * mpt,struct mpt_raid_volume * mpt_vol)897 mpt_verify_mwce(struct mpt_softc *mpt, struct mpt_raid_volume *mpt_vol)
898 {
899 request_t *req;
900 struct mpt_raid_action_result *ar;
901 CONFIG_PAGE_RAID_VOL_0 *vol_pg;
902 uint32_t data;
903 int rv;
904 int resyncing;
905 int mwce;
906
907 vol_pg = mpt_vol->config_page;
908 resyncing = vol_pg->VolumeStatus.Flags
909 & MPI_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS;
910 mwce = vol_pg->VolumeSettings.Settings
911 & MPI_RAIDVOL0_SETTING_WRITE_CACHING_ENABLE;
912
913 /*
914 * If the setting matches the configuration,
915 * there is nothing to do.
916 */
917 switch (mpt->raid_mwce_setting) {
918 case MPT_RAID_MWCE_REBUILD_ONLY:
919 if ((resyncing && mwce) || (!resyncing && !mwce)) {
920 return;
921 }
922 mpt_vol->flags ^= MPT_RVF_WCE_CHANGED;
923 if ((mpt_vol->flags & MPT_RVF_WCE_CHANGED) == 0) {
924 /*
925 * Wait one more status update to see if
926 * resyncing gets enabled. It gets disabled
927 * temporarilly when WCE is changed.
928 */
929 return;
930 }
931 break;
932 case MPT_RAID_MWCE_ON:
933 if (mwce)
934 return;
935 break;
936 case MPT_RAID_MWCE_OFF:
937 if (!mwce)
938 return;
939 break;
940 case MPT_RAID_MWCE_NC:
941 return;
942 }
943
944 req = mpt_get_request(mpt, /*sleep_ok*/TRUE);
945 if (req == NULL) {
946 mpt_vol_prt(mpt, mpt_vol,
947 "mpt_verify_mwce: Get request failed!\n");
948 return;
949 }
950
951 vol_pg->VolumeSettings.Settings ^=
952 MPI_RAIDVOL0_SETTING_WRITE_CACHING_ENABLE;
953 memcpy(&data, &vol_pg->VolumeSettings, sizeof(data));
954 vol_pg->VolumeSettings.Settings ^=
955 MPI_RAIDVOL0_SETTING_WRITE_CACHING_ENABLE;
956 rv = mpt_issue_raid_req(mpt, mpt_vol, /*disk*/NULL, req,
957 MPI_RAID_ACTION_CHANGE_VOLUME_SETTINGS,
958 data, /*addr*/0, /*len*/0,
959 /*write*/FALSE, /*wait*/TRUE);
960 if (rv == ETIMEDOUT) {
961 mpt_vol_prt(mpt, mpt_vol, "mpt_verify_mwce: "
962 "Write Cache Enable Timed-out\n");
963 return;
964 }
965 ar = REQ_TO_RAID_ACTION_RESULT(req);
966 if (rv != 0
967 || REQ_IOCSTATUS(req) != MPI_IOCSTATUS_SUCCESS
968 || (ar->action_status != MPI_RAID_ACTION_ASTATUS_SUCCESS)) {
969 mpt_vol_prt(mpt, mpt_vol, "Write Cache Enable Failed: "
970 "%d:%x:%x\n", rv, req->IOCStatus,
971 ar->action_status);
972 } else {
973 vol_pg->VolumeSettings.Settings ^=
974 MPI_RAIDVOL0_SETTING_WRITE_CACHING_ENABLE;
975 }
976 mpt_free_request(mpt, req);
977 }
978
979 static void
mpt_verify_resync_rate(struct mpt_softc * mpt,struct mpt_raid_volume * mpt_vol)980 mpt_verify_resync_rate(struct mpt_softc *mpt, struct mpt_raid_volume *mpt_vol)
981 {
982 request_t *req;
983 struct mpt_raid_action_result *ar;
984 CONFIG_PAGE_RAID_VOL_0 *vol_pg;
985 u_int prio;
986 int rv;
987
988 vol_pg = mpt_vol->config_page;
989
990 if (mpt->raid_resync_rate == MPT_RAID_RESYNC_RATE_NC)
991 return;
992
993 /*
994 * If the current RAID resync rate does not
995 * match our configured rate, update it.
996 */
997 prio = vol_pg->VolumeSettings.Settings
998 & MPI_RAIDVOL0_SETTING_PRIORITY_RESYNC;
999 if (vol_pg->ResyncRate != 0
1000 && vol_pg->ResyncRate != mpt->raid_resync_rate) {
1001
1002 req = mpt_get_request(mpt, /*sleep_ok*/TRUE);
1003 if (req == NULL) {
1004 mpt_vol_prt(mpt, mpt_vol, "mpt_verify_resync_rate: "
1005 "Get request failed!\n");
1006 return;
1007 }
1008
1009 rv = mpt_issue_raid_req(mpt, mpt_vol, /*disk*/NULL, req,
1010 MPI_RAID_ACTION_SET_RESYNC_RATE,
1011 mpt->raid_resync_rate, /*addr*/0,
1012 /*len*/0, /*write*/FALSE, /*wait*/TRUE);
1013 if (rv == ETIMEDOUT) {
1014 mpt_vol_prt(mpt, mpt_vol, "mpt_refresh_raid_data: "
1015 "Resync Rate Setting Timed-out\n");
1016 return;
1017 }
1018
1019 ar = REQ_TO_RAID_ACTION_RESULT(req);
1020 if (rv != 0
1021 || REQ_IOCSTATUS(req) != MPI_IOCSTATUS_SUCCESS
1022 || (ar->action_status != MPI_RAID_ACTION_ASTATUS_SUCCESS)) {
1023 mpt_vol_prt(mpt, mpt_vol, "Resync Rate Setting Failed: "
1024 "%d:%x:%x\n", rv, req->IOCStatus,
1025 ar->action_status);
1026 } else
1027 vol_pg->ResyncRate = mpt->raid_resync_rate;
1028 mpt_free_request(mpt, req);
1029 } else if ((prio && mpt->raid_resync_rate < 128)
1030 || (!prio && mpt->raid_resync_rate >= 128)) {
1031 uint32_t data;
1032
1033 req = mpt_get_request(mpt, /*sleep_ok*/TRUE);
1034 if (req == NULL) {
1035 mpt_vol_prt(mpt, mpt_vol, "mpt_verify_resync_rate: "
1036 "Get request failed!\n");
1037 return;
1038 }
1039
1040 vol_pg->VolumeSettings.Settings ^=
1041 MPI_RAIDVOL0_SETTING_PRIORITY_RESYNC;
1042 memcpy(&data, &vol_pg->VolumeSettings, sizeof(data));
1043 vol_pg->VolumeSettings.Settings ^=
1044 MPI_RAIDVOL0_SETTING_PRIORITY_RESYNC;
1045 rv = mpt_issue_raid_req(mpt, mpt_vol, /*disk*/NULL, req,
1046 MPI_RAID_ACTION_CHANGE_VOLUME_SETTINGS,
1047 data, /*addr*/0, /*len*/0,
1048 /*write*/FALSE, /*wait*/TRUE);
1049 if (rv == ETIMEDOUT) {
1050 mpt_vol_prt(mpt, mpt_vol, "mpt_refresh_raid_data: "
1051 "Resync Rate Setting Timed-out\n");
1052 return;
1053 }
1054 ar = REQ_TO_RAID_ACTION_RESULT(req);
1055 if (rv != 0
1056 || REQ_IOCSTATUS(req) != MPI_IOCSTATUS_SUCCESS
1057 || (ar->action_status != MPI_RAID_ACTION_ASTATUS_SUCCESS)) {
1058 mpt_vol_prt(mpt, mpt_vol, "Resync Rate Setting Failed: "
1059 "%d:%x:%x\n", rv, req->IOCStatus,
1060 ar->action_status);
1061 } else {
1062 vol_pg->VolumeSettings.Settings ^=
1063 MPI_RAIDVOL0_SETTING_PRIORITY_RESYNC;
1064 }
1065
1066 mpt_free_request(mpt, req);
1067 }
1068 }
1069
1070 static void
mpt_adjust_queue_depth(struct mpt_softc * mpt,struct mpt_raid_volume * mpt_vol,struct cam_path * path)1071 mpt_adjust_queue_depth(struct mpt_softc *mpt, struct mpt_raid_volume *mpt_vol,
1072 struct cam_path *path)
1073 {
1074 struct ccb_relsim crs;
1075
1076 xpt_setup_ccb(&crs.ccb_h, path, /*priority*/5);
1077 crs.ccb_h.func_code = XPT_REL_SIMQ;
1078 crs.ccb_h.flags = CAM_DEV_QFREEZE;
1079 crs.release_flags = RELSIM_ADJUST_OPENINGS;
1080 crs.openings = mpt->raid_queue_depth;
1081 xpt_action((union ccb *)&crs);
1082 if (crs.ccb_h.status != CAM_REQ_CMP)
1083 mpt_vol_prt(mpt, mpt_vol, "mpt_adjust_queue_depth failed "
1084 "with CAM status %#x\n", crs.ccb_h.status);
1085 }
1086
1087 static void
mpt_announce_vol(struct mpt_softc * mpt,struct mpt_raid_volume * mpt_vol)1088 mpt_announce_vol(struct mpt_softc *mpt, struct mpt_raid_volume *mpt_vol)
1089 {
1090 CONFIG_PAGE_RAID_VOL_0 *vol_pg;
1091 u_int i;
1092
1093 vol_pg = mpt_vol->config_page;
1094 mpt_vol_prt(mpt, mpt_vol, "Settings (");
1095 for (i = 1; i <= 0x8000; i <<= 1) {
1096 switch (vol_pg->VolumeSettings.Settings & i) {
1097 case MPI_RAIDVOL0_SETTING_WRITE_CACHING_ENABLE:
1098 mpt_prtc(mpt, " Member-WCE");
1099 break;
1100 case MPI_RAIDVOL0_SETTING_OFFLINE_ON_SMART:
1101 mpt_prtc(mpt, " Offline-On-SMART-Err");
1102 break;
1103 case MPI_RAIDVOL0_SETTING_AUTO_CONFIGURE:
1104 mpt_prtc(mpt, " Hot-Plug-Spares");
1105 break;
1106 case MPI_RAIDVOL0_SETTING_PRIORITY_RESYNC:
1107 mpt_prtc(mpt, " High-Priority-ReSync");
1108 break;
1109 default:
1110 break;
1111 }
1112 }
1113 mpt_prtc(mpt, " )\n");
1114 if (vol_pg->VolumeSettings.HotSparePool != 0) {
1115 mpt_vol_prt(mpt, mpt_vol, "Using Spare Pool%s",
1116 powerof2(vol_pg->VolumeSettings.HotSparePool)
1117 ? ":" : "s:");
1118 for (i = 0; i < 8; i++) {
1119 u_int mask;
1120
1121 mask = 0x1 << i;
1122 if ((vol_pg->VolumeSettings.HotSparePool & mask) == 0)
1123 continue;
1124 mpt_prtc(mpt, " %d", i);
1125 }
1126 mpt_prtc(mpt, "\n");
1127 }
1128 mpt_vol_prt(mpt, mpt_vol, "%d Members:\n", vol_pg->NumPhysDisks);
1129 for (i = 0; i < vol_pg->NumPhysDisks; i++){
1130 struct mpt_raid_disk *mpt_disk;
1131 CONFIG_PAGE_RAID_PHYS_DISK_0 *disk_pg;
1132 int pt_bus = cam_sim_bus(mpt->phydisk_sim);
1133 U8 f, s;
1134
1135 mpt_disk = mpt->raid_disks + vol_pg->PhysDisk[i].PhysDiskNum;
1136 disk_pg = &mpt_disk->config_page;
1137 mpt_prtc(mpt, " ");
1138 mpt_prtc(mpt, "(%s:%d:%d:0): ", device_get_nameunit(mpt->dev),
1139 pt_bus, disk_pg->PhysDiskID);
1140 if (vol_pg->VolumeType == MPI_RAID_VOL_TYPE_IM) {
1141 mpt_prtc(mpt, "%s", mpt_disk->member_number == 0?
1142 "Primary" : "Secondary");
1143 } else {
1144 mpt_prtc(mpt, "Stripe Position %d",
1145 mpt_disk->member_number);
1146 }
1147 f = disk_pg->PhysDiskStatus.Flags;
1148 s = disk_pg->PhysDiskStatus.State;
1149 if (f & MPI_PHYSDISK0_STATUS_FLAG_OUT_OF_SYNC) {
1150 mpt_prtc(mpt, " Out of Sync");
1151 }
1152 if (f & MPI_PHYSDISK0_STATUS_FLAG_QUIESCED) {
1153 mpt_prtc(mpt, " Quiesced");
1154 }
1155 if (f & MPI_PHYSDISK0_STATUS_FLAG_INACTIVE_VOLUME) {
1156 mpt_prtc(mpt, " Inactive");
1157 }
1158 if (f & MPI_PHYSDISK0_STATUS_FLAG_OPTIMAL_PREVIOUS) {
1159 mpt_prtc(mpt, " Was Optimal");
1160 }
1161 if (f & MPI_PHYSDISK0_STATUS_FLAG_NOT_OPTIMAL_PREVIOUS) {
1162 mpt_prtc(mpt, " Was Non-Optimal");
1163 }
1164 switch (s) {
1165 case MPI_PHYSDISK0_STATUS_ONLINE:
1166 mpt_prtc(mpt, " Online");
1167 break;
1168 case MPI_PHYSDISK0_STATUS_MISSING:
1169 mpt_prtc(mpt, " Missing");
1170 break;
1171 case MPI_PHYSDISK0_STATUS_NOT_COMPATIBLE:
1172 mpt_prtc(mpt, " Incompatible");
1173 break;
1174 case MPI_PHYSDISK0_STATUS_FAILED:
1175 mpt_prtc(mpt, " Failed");
1176 break;
1177 case MPI_PHYSDISK0_STATUS_INITIALIZING:
1178 mpt_prtc(mpt, " Initializing");
1179 break;
1180 case MPI_PHYSDISK0_STATUS_OFFLINE_REQUESTED:
1181 mpt_prtc(mpt, " Requested Offline");
1182 break;
1183 case MPI_PHYSDISK0_STATUS_FAILED_REQUESTED:
1184 mpt_prtc(mpt, " Requested Failed");
1185 break;
1186 case MPI_PHYSDISK0_STATUS_OTHER_OFFLINE:
1187 default:
1188 mpt_prtc(mpt, " Offline Other (%x)", s);
1189 break;
1190 }
1191 mpt_prtc(mpt, "\n");
1192 }
1193 }
1194
1195 static void
mpt_announce_disk(struct mpt_softc * mpt,struct mpt_raid_disk * mpt_disk)1196 mpt_announce_disk(struct mpt_softc *mpt, struct mpt_raid_disk *mpt_disk)
1197 {
1198 CONFIG_PAGE_RAID_PHYS_DISK_0 *disk_pg;
1199 int rd_bus = cam_sim_bus(mpt->sim);
1200 int pt_bus = cam_sim_bus(mpt->phydisk_sim);
1201 u_int i;
1202
1203 disk_pg = &mpt_disk->config_page;
1204 mpt_disk_prt(mpt, mpt_disk,
1205 "Physical (%s:%d:%d:0), Pass-thru (%s:%d:%d:0)\n",
1206 device_get_nameunit(mpt->dev), rd_bus,
1207 disk_pg->PhysDiskID, device_get_nameunit(mpt->dev),
1208 pt_bus, mpt_disk - mpt->raid_disks);
1209 if (disk_pg->PhysDiskSettings.HotSparePool == 0)
1210 return;
1211 mpt_disk_prt(mpt, mpt_disk, "Member of Hot Spare Pool%s",
1212 powerof2(disk_pg->PhysDiskSettings.HotSparePool)
1213 ? ":" : "s:");
1214 for (i = 0; i < 8; i++) {
1215 u_int mask;
1216
1217 mask = 0x1 << i;
1218 if ((disk_pg->PhysDiskSettings.HotSparePool & mask) == 0)
1219 continue;
1220 mpt_prtc(mpt, " %d", i);
1221 }
1222 mpt_prtc(mpt, "\n");
1223 }
1224
1225 static void
mpt_refresh_raid_disk(struct mpt_softc * mpt,struct mpt_raid_disk * mpt_disk,IOC_3_PHYS_DISK * ioc_disk)1226 mpt_refresh_raid_disk(struct mpt_softc *mpt, struct mpt_raid_disk *mpt_disk,
1227 IOC_3_PHYS_DISK *ioc_disk)
1228 {
1229 int rv;
1230
1231 rv = mpt_read_cfg_header(mpt, MPI_CONFIG_PAGETYPE_RAID_PHYSDISK,
1232 /*PageNumber*/0, ioc_disk->PhysDiskNum,
1233 &mpt_disk->config_page.Header,
1234 /*sleep_ok*/TRUE, /*timeout_ms*/5000);
1235 if (rv != 0) {
1236 mpt_prt(mpt, "mpt_refresh_raid_disk: "
1237 "Failed to read RAID Disk Hdr(%d)\n",
1238 ioc_disk->PhysDiskNum);
1239 return;
1240 }
1241 rv = mpt_read_cur_cfg_page(mpt, ioc_disk->PhysDiskNum,
1242 &mpt_disk->config_page.Header,
1243 sizeof(mpt_disk->config_page),
1244 /*sleep_ok*/TRUE, /*timeout_ms*/5000);
1245 if (rv != 0)
1246 mpt_prt(mpt, "mpt_refresh_raid_disk: "
1247 "Failed to read RAID Disk Page(%d)\n",
1248 ioc_disk->PhysDiskNum);
1249 mpt2host_config_page_raid_phys_disk_0(&mpt_disk->config_page);
1250 }
1251
1252 static void
mpt_refresh_raid_vol(struct mpt_softc * mpt,struct mpt_raid_volume * mpt_vol,CONFIG_PAGE_IOC_2_RAID_VOL * ioc_vol)1253 mpt_refresh_raid_vol(struct mpt_softc *mpt, struct mpt_raid_volume *mpt_vol,
1254 CONFIG_PAGE_IOC_2_RAID_VOL *ioc_vol)
1255 {
1256 CONFIG_PAGE_RAID_VOL_0 *vol_pg;
1257 struct mpt_raid_action_result *ar;
1258 request_t *req;
1259 int rv;
1260 int i;
1261
1262 vol_pg = mpt_vol->config_page;
1263 mpt_vol->flags &= ~MPT_RVF_UP2DATE;
1264
1265 rv = mpt_read_cfg_header(mpt, MPI_CONFIG_PAGETYPE_RAID_VOLUME, 0,
1266 ioc_vol->VolumePageNumber, &vol_pg->Header, TRUE, 5000);
1267 if (rv != 0) {
1268 mpt_vol_prt(mpt, mpt_vol,
1269 "mpt_refresh_raid_vol: Failed to read RAID Vol Hdr(%d)\n",
1270 ioc_vol->VolumePageNumber);
1271 return;
1272 }
1273
1274 rv = mpt_read_cur_cfg_page(mpt, ioc_vol->VolumePageNumber,
1275 &vol_pg->Header, mpt->raid_page0_len, TRUE, 5000);
1276 if (rv != 0) {
1277 mpt_vol_prt(mpt, mpt_vol,
1278 "mpt_refresh_raid_vol: Failed to read RAID Vol Page(%d)\n",
1279 ioc_vol->VolumePageNumber);
1280 return;
1281 }
1282 mpt2host_config_page_raid_vol_0(vol_pg);
1283
1284 mpt_vol->flags |= MPT_RVF_ACTIVE;
1285
1286 /* Update disk entry array data. */
1287 for (i = 0; i < vol_pg->NumPhysDisks; i++) {
1288 struct mpt_raid_disk *mpt_disk;
1289 mpt_disk = mpt->raid_disks + vol_pg->PhysDisk[i].PhysDiskNum;
1290 mpt_disk->volume = mpt_vol;
1291 mpt_disk->member_number = vol_pg->PhysDisk[i].PhysDiskMap;
1292 if (vol_pg->VolumeType == MPI_RAID_VOL_TYPE_IM) {
1293 mpt_disk->member_number--;
1294 }
1295 }
1296
1297 if ((vol_pg->VolumeStatus.Flags
1298 & MPI_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS) == 0)
1299 return;
1300
1301 req = mpt_get_request(mpt, TRUE);
1302 if (req == NULL) {
1303 mpt_vol_prt(mpt, mpt_vol,
1304 "mpt_refresh_raid_vol: Get request failed!\n");
1305 return;
1306 }
1307 rv = mpt_issue_raid_req(mpt, mpt_vol, NULL, req,
1308 MPI_RAID_ACTION_INDICATOR_STRUCT, 0, 0, 0, FALSE, TRUE);
1309 if (rv == ETIMEDOUT) {
1310 mpt_vol_prt(mpt, mpt_vol,
1311 "mpt_refresh_raid_vol: Progress Indicator fetch timeout\n");
1312 mpt_free_request(mpt, req);
1313 return;
1314 }
1315
1316 ar = REQ_TO_RAID_ACTION_RESULT(req);
1317 if (rv == 0
1318 && ar->action_status == MPI_RAID_ACTION_ASTATUS_SUCCESS
1319 && REQ_IOCSTATUS(req) == MPI_IOCSTATUS_SUCCESS) {
1320 memcpy(&mpt_vol->sync_progress,
1321 &ar->action_data.indicator_struct,
1322 sizeof(mpt_vol->sync_progress));
1323 mpt2host_mpi_raid_vol_indicator(&mpt_vol->sync_progress);
1324 } else {
1325 mpt_vol_prt(mpt, mpt_vol,
1326 "mpt_refresh_raid_vol: Progress indicator fetch failed!\n");
1327 }
1328 mpt_free_request(mpt, req);
1329 }
1330
1331 /*
1332 * Update in-core information about RAID support. We update any entries
1333 * that didn't previously exists or have been marked as needing to
1334 * be updated by our event handler. Interesting changes are displayed
1335 * to the console.
1336 */
1337 static int
mpt_refresh_raid_data(struct mpt_softc * mpt)1338 mpt_refresh_raid_data(struct mpt_softc *mpt)
1339 {
1340 CONFIG_PAGE_IOC_2_RAID_VOL *ioc_vol;
1341 CONFIG_PAGE_IOC_2_RAID_VOL *ioc_last_vol;
1342 IOC_3_PHYS_DISK *ioc_disk;
1343 IOC_3_PHYS_DISK *ioc_last_disk;
1344 CONFIG_PAGE_RAID_VOL_0 *vol_pg;
1345 size_t len;
1346 int rv;
1347 int i;
1348 u_int nonopt_volumes;
1349
1350 if (mpt->ioc_page2 == NULL || mpt->ioc_page3 == NULL) {
1351 return (0);
1352 }
1353
1354 /*
1355 * Mark all items as unreferenced by the configuration.
1356 * This allows us to find, report, and discard stale
1357 * entries.
1358 */
1359 for (i = 0; i < mpt->ioc_page2->MaxPhysDisks; i++) {
1360 mpt->raid_disks[i].flags &= ~MPT_RDF_REFERENCED;
1361 }
1362 for (i = 0; i < mpt->ioc_page2->MaxVolumes; i++) {
1363 mpt->raid_volumes[i].flags &= ~MPT_RVF_REFERENCED;
1364 }
1365
1366 /*
1367 * Get Physical Disk information.
1368 */
1369 len = mpt->ioc_page3->Header.PageLength * sizeof(uint32_t);
1370 rv = mpt_read_cur_cfg_page(mpt, /*PageAddress*/0,
1371 &mpt->ioc_page3->Header, len,
1372 /*sleep_ok*/TRUE, /*timeout_ms*/5000);
1373 if (rv) {
1374 mpt_prt(mpt,
1375 "mpt_refresh_raid_data: Failed to read IOC Page 3\n");
1376 return (-1);
1377 }
1378 mpt2host_config_page_ioc3(mpt->ioc_page3);
1379
1380 ioc_disk = mpt->ioc_page3->PhysDisk;
1381 ioc_last_disk = ioc_disk + mpt->ioc_page3->NumPhysDisks;
1382 for (; ioc_disk != ioc_last_disk; ioc_disk++) {
1383 struct mpt_raid_disk *mpt_disk;
1384
1385 mpt_disk = mpt->raid_disks + ioc_disk->PhysDiskNum;
1386 mpt_disk->flags |= MPT_RDF_REFERENCED;
1387 if ((mpt_disk->flags & (MPT_RDF_ACTIVE|MPT_RDF_UP2DATE))
1388 != (MPT_RDF_ACTIVE|MPT_RDF_UP2DATE)) {
1389
1390 mpt_refresh_raid_disk(mpt, mpt_disk, ioc_disk);
1391
1392 }
1393 mpt_disk->flags |= MPT_RDF_ACTIVE;
1394 mpt->raid_rescan++;
1395 }
1396
1397 /*
1398 * Refresh volume data.
1399 */
1400 len = mpt->ioc_page2->Header.PageLength * sizeof(uint32_t);
1401 rv = mpt_read_cur_cfg_page(mpt, /*PageAddress*/0,
1402 &mpt->ioc_page2->Header, len,
1403 /*sleep_ok*/TRUE, /*timeout_ms*/5000);
1404 if (rv) {
1405 mpt_prt(mpt, "mpt_refresh_raid_data: "
1406 "Failed to read IOC Page 2\n");
1407 return (-1);
1408 }
1409 mpt2host_config_page_ioc2(mpt->ioc_page2);
1410
1411 ioc_vol = mpt->ioc_page2->RaidVolume;
1412 ioc_last_vol = ioc_vol + mpt->ioc_page2->NumActiveVolumes;
1413 for (;ioc_vol != ioc_last_vol; ioc_vol++) {
1414 struct mpt_raid_volume *mpt_vol;
1415
1416 mpt_vol = mpt->raid_volumes + ioc_vol->VolumePageNumber;
1417 mpt_vol->flags |= MPT_RVF_REFERENCED;
1418 vol_pg = mpt_vol->config_page;
1419 if (vol_pg == NULL)
1420 continue;
1421 if (((mpt_vol->flags & (MPT_RVF_ACTIVE|MPT_RVF_UP2DATE))
1422 != (MPT_RVF_ACTIVE|MPT_RVF_UP2DATE))
1423 || (vol_pg->VolumeStatus.Flags
1424 & MPI_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS) != 0) {
1425
1426 mpt_refresh_raid_vol(mpt, mpt_vol, ioc_vol);
1427 }
1428 mpt_vol->flags |= MPT_RVF_ACTIVE;
1429 }
1430
1431 nonopt_volumes = 0;
1432 for (i = 0; i < mpt->ioc_page2->MaxVolumes; i++) {
1433 struct mpt_raid_volume *mpt_vol;
1434 uint64_t total;
1435 uint64_t left;
1436 int m;
1437 u_int prio;
1438
1439 mpt_vol = &mpt->raid_volumes[i];
1440
1441 if ((mpt_vol->flags & MPT_RVF_ACTIVE) == 0) {
1442 continue;
1443 }
1444
1445 vol_pg = mpt_vol->config_page;
1446 if ((mpt_vol->flags & (MPT_RVF_REFERENCED|MPT_RVF_ANNOUNCED))
1447 == MPT_RVF_ANNOUNCED) {
1448 mpt_vol_prt(mpt, mpt_vol, "No longer configured\n");
1449 mpt_vol->flags = 0;
1450 continue;
1451 }
1452
1453 if ((mpt_vol->flags & MPT_RVF_ANNOUNCED) == 0) {
1454 mpt_announce_vol(mpt, mpt_vol);
1455 mpt_vol->flags |= MPT_RVF_ANNOUNCED;
1456 }
1457
1458 if (vol_pg->VolumeStatus.State !=
1459 MPI_RAIDVOL0_STATUS_STATE_OPTIMAL)
1460 nonopt_volumes++;
1461
1462 if ((mpt_vol->flags & MPT_RVF_UP2DATE) != 0)
1463 continue;
1464
1465 mpt_vol->flags |= MPT_RVF_UP2DATE;
1466 mpt_vol_prt(mpt, mpt_vol, "%s - %s\n",
1467 mpt_vol_type(mpt_vol), mpt_vol_state(mpt_vol));
1468 mpt_verify_mwce(mpt, mpt_vol);
1469
1470 if (vol_pg->VolumeStatus.Flags == 0) {
1471 continue;
1472 }
1473
1474 mpt_vol_prt(mpt, mpt_vol, "Status (");
1475 for (m = 1; m <= 0x80; m <<= 1) {
1476 switch (vol_pg->VolumeStatus.Flags & m) {
1477 case MPI_RAIDVOL0_STATUS_FLAG_ENABLED:
1478 mpt_prtc(mpt, " Enabled");
1479 break;
1480 case MPI_RAIDVOL0_STATUS_FLAG_QUIESCED:
1481 mpt_prtc(mpt, " Quiesced");
1482 break;
1483 case MPI_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS:
1484 mpt_prtc(mpt, " Re-Syncing");
1485 break;
1486 case MPI_RAIDVOL0_STATUS_FLAG_VOLUME_INACTIVE:
1487 mpt_prtc(mpt, " Inactive");
1488 break;
1489 default:
1490 break;
1491 }
1492 }
1493 mpt_prtc(mpt, " )\n");
1494
1495 if ((vol_pg->VolumeStatus.Flags
1496 & MPI_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS) == 0)
1497 continue;
1498
1499 mpt_verify_resync_rate(mpt, mpt_vol);
1500
1501 left = MPT_U64_2_SCALAR(mpt_vol->sync_progress.BlocksRemaining);
1502 total = MPT_U64_2_SCALAR(mpt_vol->sync_progress.TotalBlocks);
1503 if (vol_pg->ResyncRate != 0) {
1504
1505 prio = ((u_int)vol_pg->ResyncRate * 100000) / 0xFF;
1506 mpt_vol_prt(mpt, mpt_vol, "Rate %d.%d%%\n",
1507 prio / 1000, prio % 1000);
1508 } else {
1509 prio = vol_pg->VolumeSettings.Settings
1510 & MPI_RAIDVOL0_SETTING_PRIORITY_RESYNC;
1511 mpt_vol_prt(mpt, mpt_vol, "%s Priority Re-Sync\n",
1512 prio ? "High" : "Low");
1513 }
1514 mpt_vol_prt(mpt, mpt_vol, "%ju of %ju "
1515 "blocks remaining\n", (uintmax_t)left,
1516 (uintmax_t)total);
1517
1518 /* Periodically report on sync progress. */
1519 mpt_schedule_raid_refresh(mpt);
1520 }
1521
1522 for (i = 0; i < mpt->ioc_page2->MaxPhysDisks; i++) {
1523 struct mpt_raid_disk *mpt_disk;
1524 CONFIG_PAGE_RAID_PHYS_DISK_0 *disk_pg;
1525 int m;
1526
1527 mpt_disk = &mpt->raid_disks[i];
1528 disk_pg = &mpt_disk->config_page;
1529
1530 if ((mpt_disk->flags & MPT_RDF_ACTIVE) == 0)
1531 continue;
1532
1533 if ((mpt_disk->flags & (MPT_RDF_REFERENCED|MPT_RDF_ANNOUNCED))
1534 == MPT_RDF_ANNOUNCED) {
1535 mpt_disk_prt(mpt, mpt_disk, "No longer configured\n");
1536 mpt_disk->flags = 0;
1537 mpt->raid_rescan++;
1538 continue;
1539 }
1540
1541 if ((mpt_disk->flags & MPT_RDF_ANNOUNCED) == 0) {
1542
1543 mpt_announce_disk(mpt, mpt_disk);
1544 mpt_disk->flags |= MPT_RVF_ANNOUNCED;
1545 }
1546
1547 if ((mpt_disk->flags & MPT_RDF_UP2DATE) != 0)
1548 continue;
1549
1550 mpt_disk->flags |= MPT_RDF_UP2DATE;
1551 mpt_disk_prt(mpt, mpt_disk, "%s\n", mpt_disk_state(mpt_disk));
1552 if (disk_pg->PhysDiskStatus.Flags == 0)
1553 continue;
1554
1555 mpt_disk_prt(mpt, mpt_disk, "Status (");
1556 for (m = 1; m <= 0x80; m <<= 1) {
1557 switch (disk_pg->PhysDiskStatus.Flags & m) {
1558 case MPI_PHYSDISK0_STATUS_FLAG_OUT_OF_SYNC:
1559 mpt_prtc(mpt, " Out-Of-Sync");
1560 break;
1561 case MPI_PHYSDISK0_STATUS_FLAG_QUIESCED:
1562 mpt_prtc(mpt, " Quiesced");
1563 break;
1564 default:
1565 break;
1566 }
1567 }
1568 mpt_prtc(mpt, " )\n");
1569 }
1570
1571 mpt->raid_nonopt_volumes = nonopt_volumes;
1572 return (0);
1573 }
1574
1575 static void
mpt_raid_timer(void * arg)1576 mpt_raid_timer(void *arg)
1577 {
1578 struct mpt_softc *mpt;
1579
1580 mpt = (struct mpt_softc *)arg;
1581 MPT_LOCK_ASSERT(mpt);
1582 mpt_raid_wakeup(mpt);
1583 }
1584
1585 static void
mpt_schedule_raid_refresh(struct mpt_softc * mpt)1586 mpt_schedule_raid_refresh(struct mpt_softc *mpt)
1587 {
1588
1589 callout_reset(&mpt->raid_timer, MPT_RAID_SYNC_REPORT_INTERVAL,
1590 mpt_raid_timer, mpt);
1591 }
1592
1593 void
mpt_raid_free_mem(struct mpt_softc * mpt)1594 mpt_raid_free_mem(struct mpt_softc *mpt)
1595 {
1596
1597 if (mpt->raid_volumes) {
1598 struct mpt_raid_volume *mpt_raid;
1599 int i;
1600 for (i = 0; i < mpt->raid_max_volumes; i++) {
1601 mpt_raid = &mpt->raid_volumes[i];
1602 if (mpt_raid->config_page) {
1603 free(mpt_raid->config_page, M_DEVBUF);
1604 mpt_raid->config_page = NULL;
1605 }
1606 }
1607 free(mpt->raid_volumes, M_DEVBUF);
1608 mpt->raid_volumes = NULL;
1609 }
1610 if (mpt->raid_disks) {
1611 free(mpt->raid_disks, M_DEVBUF);
1612 mpt->raid_disks = NULL;
1613 }
1614 if (mpt->ioc_page2) {
1615 free(mpt->ioc_page2, M_DEVBUF);
1616 mpt->ioc_page2 = NULL;
1617 }
1618 if (mpt->ioc_page3) {
1619 free(mpt->ioc_page3, M_DEVBUF);
1620 mpt->ioc_page3 = NULL;
1621 }
1622 mpt->raid_max_volumes = 0;
1623 mpt->raid_max_disks = 0;
1624 }
1625
1626 static int
mpt_raid_set_vol_resync_rate(struct mpt_softc * mpt,u_int rate)1627 mpt_raid_set_vol_resync_rate(struct mpt_softc *mpt, u_int rate)
1628 {
1629 struct mpt_raid_volume *mpt_vol;
1630
1631 if ((rate > MPT_RAID_RESYNC_RATE_MAX
1632 || rate < MPT_RAID_RESYNC_RATE_MIN)
1633 && rate != MPT_RAID_RESYNC_RATE_NC)
1634 return (EINVAL);
1635
1636 MPT_LOCK(mpt);
1637 mpt->raid_resync_rate = rate;
1638 RAID_VOL_FOREACH(mpt, mpt_vol) {
1639 if ((mpt_vol->flags & MPT_RVF_ACTIVE) == 0) {
1640 continue;
1641 }
1642 mpt_verify_resync_rate(mpt, mpt_vol);
1643 }
1644 MPT_UNLOCK(mpt);
1645 return (0);
1646 }
1647
1648 static int
mpt_raid_set_vol_queue_depth(struct mpt_softc * mpt,u_int vol_queue_depth)1649 mpt_raid_set_vol_queue_depth(struct mpt_softc *mpt, u_int vol_queue_depth)
1650 {
1651 struct mpt_raid_volume *mpt_vol;
1652
1653 if (vol_queue_depth > 255 || vol_queue_depth < 1)
1654 return (EINVAL);
1655
1656 MPT_LOCK(mpt);
1657 mpt->raid_queue_depth = vol_queue_depth;
1658 RAID_VOL_FOREACH(mpt, mpt_vol) {
1659 struct cam_path *path;
1660 int error;
1661
1662 if ((mpt_vol->flags & MPT_RVF_ACTIVE) == 0)
1663 continue;
1664
1665 mpt->raid_rescan = 0;
1666
1667 error = xpt_create_path(&path, NULL,
1668 cam_sim_path(mpt->sim),
1669 mpt_vol->config_page->VolumeID,
1670 /*lun*/0);
1671 if (error != CAM_REQ_CMP) {
1672 mpt_vol_prt(mpt, mpt_vol, "Unable to allocate path!\n");
1673 continue;
1674 }
1675 mpt_adjust_queue_depth(mpt, mpt_vol, path);
1676 xpt_free_path(path);
1677 }
1678 MPT_UNLOCK(mpt);
1679 return (0);
1680 }
1681
1682 static int
mpt_raid_set_vol_mwce(struct mpt_softc * mpt,mpt_raid_mwce_t mwce)1683 mpt_raid_set_vol_mwce(struct mpt_softc *mpt, mpt_raid_mwce_t mwce)
1684 {
1685 struct mpt_raid_volume *mpt_vol;
1686 int force_full_resync;
1687
1688 MPT_LOCK(mpt);
1689 if (mwce == mpt->raid_mwce_setting) {
1690 MPT_UNLOCK(mpt);
1691 return (0);
1692 }
1693
1694 /*
1695 * Catch MWCE being left on due to a failed shutdown. Since
1696 * sysctls cannot be set by the loader, we treat the first
1697 * setting of this varible specially and force a full volume
1698 * resync if MWCE is enabled and a resync is in progress.
1699 */
1700 force_full_resync = 0;
1701 if (mpt->raid_mwce_set == 0
1702 && mpt->raid_mwce_setting == MPT_RAID_MWCE_NC
1703 && mwce == MPT_RAID_MWCE_REBUILD_ONLY)
1704 force_full_resync = 1;
1705
1706 mpt->raid_mwce_setting = mwce;
1707 RAID_VOL_FOREACH(mpt, mpt_vol) {
1708 CONFIG_PAGE_RAID_VOL_0 *vol_pg;
1709 int resyncing;
1710 int mwce;
1711
1712 if ((mpt_vol->flags & MPT_RVF_ACTIVE) == 0)
1713 continue;
1714
1715 vol_pg = mpt_vol->config_page;
1716 resyncing = vol_pg->VolumeStatus.Flags
1717 & MPI_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS;
1718 mwce = vol_pg->VolumeSettings.Settings
1719 & MPI_RAIDVOL0_SETTING_WRITE_CACHING_ENABLE;
1720 if (force_full_resync && resyncing && mwce) {
1721
1722 /*
1723 * XXX disable/enable volume should force a resync,
1724 * but we'll need to queice, drain, and restart
1725 * I/O to do that.
1726 */
1727 mpt_vol_prt(mpt, mpt_vol, "WARNING - Unsafe shutdown "
1728 "detected. Suggest full resync.\n");
1729 }
1730 mpt_verify_mwce(mpt, mpt_vol);
1731 }
1732 mpt->raid_mwce_set = 1;
1733 MPT_UNLOCK(mpt);
1734 return (0);
1735 }
1736
1737 static const char *mpt_vol_mwce_strs[] =
1738 {
1739 "On",
1740 "Off",
1741 "On-During-Rebuild",
1742 "NC"
1743 };
1744
1745 static int
mpt_raid_sysctl_vol_member_wce(SYSCTL_HANDLER_ARGS)1746 mpt_raid_sysctl_vol_member_wce(SYSCTL_HANDLER_ARGS)
1747 {
1748 char inbuf[20];
1749 struct mpt_softc *mpt;
1750 const char *str;
1751 int error;
1752 u_int size;
1753 u_int i;
1754
1755 GIANT_REQUIRED;
1756
1757 mpt = (struct mpt_softc *)arg1;
1758 str = mpt_vol_mwce_strs[mpt->raid_mwce_setting];
1759 error = SYSCTL_OUT(req, str, strlen(str) + 1);
1760 if (error || !req->newptr) {
1761 return (error);
1762 }
1763
1764 size = req->newlen - req->newidx;
1765 if (size >= sizeof(inbuf)) {
1766 return (EINVAL);
1767 }
1768
1769 error = SYSCTL_IN(req, inbuf, size);
1770 if (error) {
1771 return (error);
1772 }
1773 inbuf[size] = '\0';
1774 for (i = 0; i < NUM_ELEMENTS(mpt_vol_mwce_strs); i++) {
1775 if (strcmp(mpt_vol_mwce_strs[i], inbuf) == 0) {
1776 return (mpt_raid_set_vol_mwce(mpt, i));
1777 }
1778 }
1779 return (EINVAL);
1780 }
1781
1782 static int
mpt_raid_sysctl_vol_resync_rate(SYSCTL_HANDLER_ARGS)1783 mpt_raid_sysctl_vol_resync_rate(SYSCTL_HANDLER_ARGS)
1784 {
1785 struct mpt_softc *mpt;
1786 u_int raid_resync_rate;
1787 int error;
1788
1789 GIANT_REQUIRED;
1790
1791 mpt = (struct mpt_softc *)arg1;
1792 raid_resync_rate = mpt->raid_resync_rate;
1793
1794 error = sysctl_handle_int(oidp, &raid_resync_rate, 0, req);
1795 if (error || !req->newptr) {
1796 return error;
1797 }
1798
1799 return (mpt_raid_set_vol_resync_rate(mpt, raid_resync_rate));
1800 }
1801
1802 static int
mpt_raid_sysctl_vol_queue_depth(SYSCTL_HANDLER_ARGS)1803 mpt_raid_sysctl_vol_queue_depth(SYSCTL_HANDLER_ARGS)
1804 {
1805 struct mpt_softc *mpt;
1806 u_int raid_queue_depth;
1807 int error;
1808
1809 GIANT_REQUIRED;
1810
1811 mpt = (struct mpt_softc *)arg1;
1812 raid_queue_depth = mpt->raid_queue_depth;
1813
1814 error = sysctl_handle_int(oidp, &raid_queue_depth, 0, req);
1815 if (error || !req->newptr) {
1816 return error;
1817 }
1818
1819 return (mpt_raid_set_vol_queue_depth(mpt, raid_queue_depth));
1820 }
1821
1822 static void
mpt_raid_sysctl_attach(struct mpt_softc * mpt)1823 mpt_raid_sysctl_attach(struct mpt_softc *mpt)
1824 {
1825 struct sysctl_ctx_list *ctx = device_get_sysctl_ctx(mpt->dev);
1826 struct sysctl_oid *tree = device_get_sysctl_tree(mpt->dev);
1827
1828 SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
1829 "vol_member_wce", CTLTYPE_STRING | CTLFLAG_RW, mpt, 0,
1830 mpt_raid_sysctl_vol_member_wce, "A",
1831 "volume member WCE(On,Off,On-During-Rebuild,NC)");
1832
1833 SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
1834 "vol_queue_depth", CTLTYPE_INT | CTLFLAG_RW, mpt, 0,
1835 mpt_raid_sysctl_vol_queue_depth, "I",
1836 "default volume queue depth");
1837
1838 SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
1839 "vol_resync_rate", CTLTYPE_INT | CTLFLAG_RW, mpt, 0,
1840 mpt_raid_sysctl_vol_resync_rate, "I",
1841 "volume resync priority (0 == NC, 1 - 255)");
1842 SYSCTL_ADD_UINT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
1843 "nonoptimal_volumes", CTLFLAG_RD,
1844 &mpt->raid_nonopt_volumes, 0,
1845 "number of nonoptimal volumes");
1846 }
1847