]> CyberLeo.Net >> Repos - FreeBSD/stable/10.git/blob - sys/dev/mps/mps_sas_lsi.c
MFC r269314 and r269316
[FreeBSD/stable/10.git] / sys / dev / mps / mps_sas_lsi.c
1 /*-
2  * Copyright (c) 2011, 2012 LSI Corp.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  *
26  * LSI MPT-Fusion Host Adapter FreeBSD
27  */
28
29 #include <sys/cdefs.h>
30 __FBSDID("$FreeBSD$");
31
32 /* Communications core for LSI MPT2 */
33
34 /* TODO Move headers to mpsvar */
35 #include <sys/types.h>
36 #include <sys/param.h>
37 #include <sys/systm.h>
38 #include <sys/kernel.h>
39 #include <sys/selinfo.h>
40 #include <sys/module.h>
41 #include <sys/bus.h>
42 #include <sys/conf.h>
43 #include <sys/bio.h>
44 #include <sys/malloc.h>
45 #include <sys/uio.h>
46 #include <sys/sysctl.h>
47 #include <sys/endian.h>
48 #include <sys/queue.h>
49 #include <sys/kthread.h>
50 #include <sys/taskqueue.h>
51 #include <sys/sbuf.h>
52
53 #include <machine/bus.h>
54 #include <machine/resource.h>
55 #include <sys/rman.h>
56
57 #include <machine/stdarg.h>
58
59 #include <cam/cam.h>
60 #include <cam/cam_ccb.h>
61 #include <cam/cam_debug.h>
62 #include <cam/cam_sim.h>
63 #include <cam/cam_xpt_sim.h>
64 #include <cam/cam_xpt_periph.h>
65 #include <cam/cam_periph.h>
66 #include <cam/scsi/scsi_all.h>
67 #include <cam/scsi/scsi_message.h>
68
69 #include <dev/mps/mpi/mpi2_type.h>
70 #include <dev/mps/mpi/mpi2.h>
71 #include <dev/mps/mpi/mpi2_ioc.h>
72 #include <dev/mps/mpi/mpi2_sas.h>
73 #include <dev/mps/mpi/mpi2_cnfg.h>
74 #include <dev/mps/mpi/mpi2_init.h>
75 #include <dev/mps/mpi/mpi2_raid.h>
76 #include <dev/mps/mpi/mpi2_tool.h>
77 #include <dev/mps/mps_ioctl.h>
78 #include <dev/mps/mpsvar.h>
79 #include <dev/mps/mps_table.h>
80 #include <dev/mps/mps_sas.h>
81
82 /* For Hashed SAS Address creation for SATA Drives */
83 #define MPT2SAS_SN_LEN 20
84 #define MPT2SAS_MN_LEN 40
85
86 struct mps_fw_event_work {
87         u16                     event;
88         void                    *event_data;
89         TAILQ_ENTRY(mps_fw_event_work)  ev_link;
90 };
91
92 union _sata_sas_address {
93         u8 wwid[8];
94         struct {
95                 u32 high;
96                 u32 low;
97         } word;
98 };
99
100 /*
101  * define the IDENTIFY DEVICE structure
102  */
103 struct _ata_identify_device_data {
104         u16 reserved1[10];      /* 0-9 */
105         u16 serial_number[10];  /* 10-19 */
106         u16 reserved2[7];       /* 20-26 */
107         u16 model_number[20];   /* 27-46*/
108         u16 reserved3[209];     /* 47-255*/
109 };
110 static u32 event_count;
111 static void mpssas_fw_work(struct mps_softc *sc,
112     struct mps_fw_event_work *fw_event);
113 static void mpssas_fw_event_free(struct mps_softc *,
114     struct mps_fw_event_work *);
115 static int mpssas_add_device(struct mps_softc *sc, u16 handle, u8 linkrate);
116 static int mpssas_get_sata_identify(struct mps_softc *sc, u16 handle,
117     Mpi2SataPassthroughReply_t *mpi_reply, char *id_buffer, int sz,
118     u32 devinfo);
119 int mpssas_get_sas_address_for_sata_disk(struct mps_softc *sc,
120     u64 *sas_address, u16 handle, u32 device_info);
121 static int mpssas_volume_add(struct mps_softc *sc,
122     u16 handle);
123 static void mpssas_SSU_to_SATA_devices(struct mps_softc *sc);
124 static void mpssas_stop_unit_done(struct cam_periph *periph,
125     union ccb *done_ccb);
126
127 void
128 mpssas_evt_handler(struct mps_softc *sc, uintptr_t data,
129     MPI2_EVENT_NOTIFICATION_REPLY *event)
130 {
131         struct mps_fw_event_work *fw_event;
132         u16 sz;
133
134         mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
135         mps_print_evt_sas(sc, event);
136         mpssas_record_event(sc, event);
137
138         fw_event = malloc(sizeof(struct mps_fw_event_work), M_MPT2,
139              M_ZERO|M_NOWAIT);
140         if (!fw_event) {
141                 printf("%s: allocate failed for fw_event\n", __func__);
142                 return;
143         }
144         sz = le16toh(event->EventDataLength) * 4;
145         fw_event->event_data = malloc(sz, M_MPT2, M_ZERO|M_NOWAIT);
146         if (!fw_event->event_data) {
147                 printf("%s: allocate failed for event_data\n", __func__);
148                 free(fw_event, M_MPT2);
149                 return;
150         }
151
152         bcopy(event->EventData, fw_event->event_data, sz);
153         fw_event->event = event->Event;
154         if ((event->Event == MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST ||
155             event->Event == MPI2_EVENT_SAS_ENCL_DEVICE_STATUS_CHANGE ||
156             event->Event == MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST) &&
157             sc->track_mapping_events)
158                 sc->pending_map_events++;
159
160         /*
161          * When wait_for_port_enable flag is set, make sure that all the events
162          * are processed. Increment the startup_refcount and decrement it after
163          * events are processed.
164          */
165         if ((event->Event == MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST ||
166             event->Event == MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST) &&
167             sc->wait_for_port_enable)
168                 mpssas_startup_increment(sc->sassc);
169
170         TAILQ_INSERT_TAIL(&sc->sassc->ev_queue, fw_event, ev_link);
171         taskqueue_enqueue(sc->sassc->ev_tq, &sc->sassc->ev_task);
172
173 }
174
175 static void
176 mpssas_fw_event_free(struct mps_softc *sc, struct mps_fw_event_work *fw_event)
177 {
178
179         free(fw_event->event_data, M_MPT2);
180         free(fw_event, M_MPT2);
181 }
182
183 /**
184  * _mps_fw_work - delayed task for processing firmware events
185  * @sc: per adapter object
186  * @fw_event: The fw_event_work object
187  * Context: user.
188  *
189  * Return nothing.
190  */
191 static void
192 mpssas_fw_work(struct mps_softc *sc, struct mps_fw_event_work *fw_event)
193 {
194         struct mpssas_softc *sassc;
195         sassc = sc->sassc;
196
197         mps_dprint(sc, MPS_EVENT, "(%d)->(%s) Working on  Event: [%x]\n",
198                         event_count++,__func__,fw_event->event);
199         switch (fw_event->event) {
200         case MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST: 
201         {
202                 MPI2_EVENT_DATA_SAS_TOPOLOGY_CHANGE_LIST *data;
203                 MPI2_EVENT_SAS_TOPO_PHY_ENTRY *phy;
204                 int i;
205
206                 data = (MPI2_EVENT_DATA_SAS_TOPOLOGY_CHANGE_LIST *)
207                     fw_event->event_data;
208
209                 mps_mapping_topology_change_event(sc, fw_event->event_data);
210
211                 for (i = 0; i < data->NumEntries; i++) {
212                         phy = &data->PHY[i];
213                         switch (phy->PhyStatus & MPI2_EVENT_SAS_TOPO_RC_MASK) {
214                         case MPI2_EVENT_SAS_TOPO_RC_TARG_ADDED:
215                                 if (mpssas_add_device(sc,
216                                     le16toh(phy->AttachedDevHandle), phy->LinkRate)){
217                                         printf("%s: failed to add device with "
218                                             "handle 0x%x\n", __func__,
219                                             le16toh(phy->AttachedDevHandle));
220                                         mpssas_prepare_remove(sassc, le16toh(
221                                                 phy->AttachedDevHandle));
222                                 }
223                                 break;
224                         case MPI2_EVENT_SAS_TOPO_RC_TARG_NOT_RESPONDING:
225                                 mpssas_prepare_remove(sassc,le16toh( 
226                                         phy->AttachedDevHandle));
227                                 break;
228                         case MPI2_EVENT_SAS_TOPO_RC_PHY_CHANGED:
229                         case MPI2_EVENT_SAS_TOPO_RC_NO_CHANGE:
230                         case MPI2_EVENT_SAS_TOPO_RC_DELAY_NOT_RESPONDING:
231                         default:
232                                 break;
233                         }
234                 }
235                 /*
236                  * refcount was incremented for this event in
237                  * mpssas_evt_handler.  Decrement it here because the event has
238                  * been processed.
239                  */
240                 mpssas_startup_decrement(sassc);
241                 break;
242         }
243         case MPI2_EVENT_SAS_DISCOVERY:
244         {
245                 MPI2_EVENT_DATA_SAS_DISCOVERY *data;
246
247                 data = (MPI2_EVENT_DATA_SAS_DISCOVERY *)fw_event->event_data;
248
249                 if (data->ReasonCode & MPI2_EVENT_SAS_DISC_RC_STARTED)
250                         mps_dprint(sc, MPS_TRACE,"SAS discovery start event\n");
251                 if (data->ReasonCode & MPI2_EVENT_SAS_DISC_RC_COMPLETED) {
252                         mps_dprint(sc, MPS_TRACE,"SAS discovery stop event\n");
253                         sassc->flags &= ~MPSSAS_IN_DISCOVERY;
254                         mpssas_discovery_end(sassc);
255                 }
256                 break;
257         }
258         case MPI2_EVENT_SAS_ENCL_DEVICE_STATUS_CHANGE:
259         {
260                 Mpi2EventDataSasEnclDevStatusChange_t *data;
261                 data = (Mpi2EventDataSasEnclDevStatusChange_t *)
262                     fw_event->event_data;
263                 mps_mapping_enclosure_dev_status_change_event(sc,
264                     fw_event->event_data);
265                 break;
266         }
267         case MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST:
268         {
269                 Mpi2EventIrConfigElement_t *element;
270                 int i;
271                 u8 foreign_config;
272                 Mpi2EventDataIrConfigChangeList_t *event_data;
273                 struct mpssas_target *targ;
274                 unsigned int id;
275
276                 event_data = fw_event->event_data;
277                 foreign_config = (le32toh(event_data->Flags) &
278                     MPI2_EVENT_IR_CHANGE_FLAGS_FOREIGN_CONFIG) ? 1 : 0;
279
280                 element =
281                     (Mpi2EventIrConfigElement_t *)&event_data->ConfigElement[0];
282                 id = mps_mapping_get_raid_id_from_handle
283                     (sc, element->VolDevHandle);
284
285                 mps_mapping_ir_config_change_event(sc, event_data);
286
287                 for (i = 0; i < event_data->NumElements; i++, element++) {
288                         switch (element->ReasonCode) {
289                         case MPI2_EVENT_IR_CHANGE_RC_VOLUME_CREATED:
290                         case MPI2_EVENT_IR_CHANGE_RC_ADDED:
291                                 if (!foreign_config) {
292                                         if (mpssas_volume_add(sc, le16toh(element->VolDevHandle))){
293                                                 printf("%s: failed to add RAID "
294                                                     "volume with handle 0x%x\n",
295                                                     __func__, le16toh(element->
296                                                     VolDevHandle));
297                                         }
298                                 }
299                                 break;
300                         case MPI2_EVENT_IR_CHANGE_RC_VOLUME_DELETED:
301                         case MPI2_EVENT_IR_CHANGE_RC_REMOVED:
302                                 /*
303                                  * Rescan after volume is deleted or removed.
304                                  */
305                                 if (!foreign_config) {
306                                         if (id == MPS_MAP_BAD_ID) {
307                                                 printf("%s: could not get ID "
308                                                     "for volume with handle "
309                                                     "0x%04x\n", __func__,
310                                                     le16toh(element->VolDevHandle));
311                                                 break;
312                                         }
313                                         
314                                         targ = &sassc->targets[id];
315                                         targ->handle = 0x0;
316                                         targ->encl_slot = 0x0;
317                                         targ->encl_handle = 0x0;
318                                         targ->exp_dev_handle = 0x0;
319                                         targ->phy_num = 0x0;
320                                         targ->linkrate = 0x0;
321                                         mpssas_rescan_target(sc, targ);
322                                         printf("RAID target id 0x%x removed\n",
323                                             targ->tid);
324                                 }
325                                 break;
326                         case MPI2_EVENT_IR_CHANGE_RC_PD_CREATED:
327                         case MPI2_EVENT_IR_CHANGE_RC_HIDE:
328                                 /*
329                                  * Phys Disk of a volume has been created.  Hide
330                                  * it from the OS.
331                                  */
332                                 targ = mpssas_find_target_by_handle(sassc, 0, element->PhysDiskDevHandle);
333                                 if (targ == NULL) 
334                                         break;
335                                 
336                                 /* Set raid component flags only if it is not WD.
337                                  * OR WrapDrive with WD_HIDE_ALWAYS/WD_HIDE_IF_VOLUME is set in NVRAM
338                                  */
339                                 if((!sc->WD_available) ||
340                                 ((sc->WD_available && 
341                                 (sc->WD_hide_expose == MPS_WD_HIDE_ALWAYS)) ||
342                                 (sc->WD_valid_config && (sc->WD_hide_expose ==
343                                 MPS_WD_HIDE_IF_VOLUME)))) {
344                                         targ->flags |= MPS_TARGET_FLAGS_RAID_COMPONENT;
345                                 }
346                                 mpssas_rescan_target(sc, targ);
347                                 
348                                 break;
349                         case MPI2_EVENT_IR_CHANGE_RC_PD_DELETED:
350                                 /*
351                                  * Phys Disk of a volume has been deleted.
352                                  * Expose it to the OS.
353                                  */
354                                 if (mpssas_add_device(sc,
355                                     le16toh(element->PhysDiskDevHandle), 0)){
356                                         printf("%s: failed to add device with "
357                                             "handle 0x%x\n", __func__,
358                                             le16toh(element->PhysDiskDevHandle));
359                                         mpssas_prepare_remove(sassc, le16toh(element->
360                                             PhysDiskDevHandle));
361                                 }
362                                 break;
363                         }
364                 }
365                 /*
366                  * refcount was incremented for this event in
367                  * mpssas_evt_handler.  Decrement it here because the event has
368                  * been processed.
369                  */
370                 mpssas_startup_decrement(sassc);
371                 break;
372         }
373         case MPI2_EVENT_IR_VOLUME:
374         {
375                 Mpi2EventDataIrVolume_t *event_data = fw_event->event_data;
376
377                 /*
378                  * Informational only.
379                  */
380                 mps_dprint(sc, MPS_EVENT, "Received IR Volume event:\n");
381                 switch (event_data->ReasonCode) {
382                 case MPI2_EVENT_IR_VOLUME_RC_SETTINGS_CHANGED:
383                         mps_dprint(sc, MPS_EVENT, "   Volume Settings "
384                             "changed from 0x%x to 0x%x for Volome with "
385                             "handle 0x%x", le32toh(event_data->PreviousValue),
386                             le32toh(event_data->NewValue),
387                             le16toh(event_data->VolDevHandle));
388                         break;
389                 case MPI2_EVENT_IR_VOLUME_RC_STATUS_FLAGS_CHANGED:
390                         mps_dprint(sc, MPS_EVENT, "   Volume Status "
391                             "changed from 0x%x to 0x%x for Volome with "
392                             "handle 0x%x", le32toh(event_data->PreviousValue),
393                             le32toh(event_data->NewValue),
394                             le16toh(event_data->VolDevHandle));
395                         break;
396                 case MPI2_EVENT_IR_VOLUME_RC_STATE_CHANGED:
397                         mps_dprint(sc, MPS_EVENT, "   Volume State "
398                             "changed from 0x%x to 0x%x for Volome with "
399                             "handle 0x%x", le32toh(event_data->PreviousValue),
400                             le32toh(event_data->NewValue),
401                             le16toh(event_data->VolDevHandle));
402                                 u32 state;
403                                 struct mpssas_target *targ;
404                                 state = le32toh(event_data->NewValue);
405                                 switch (state) {
406                                 case MPI2_RAID_VOL_STATE_MISSING:
407                                 case MPI2_RAID_VOL_STATE_FAILED:
408                                         mpssas_prepare_volume_remove(sassc, event_data->
409                                                         VolDevHandle);
410                                         break;
411                  
412                                 case MPI2_RAID_VOL_STATE_ONLINE:
413                                 case MPI2_RAID_VOL_STATE_DEGRADED:
414                                 case MPI2_RAID_VOL_STATE_OPTIMAL:
415                                         targ = mpssas_find_target_by_handle(sassc, 0, event_data->VolDevHandle);
416                                         if (targ) {
417                                                 printf("%s %d: Volume handle 0x%x is already added \n",
418                                                                 __func__, __LINE__ , event_data->VolDevHandle);
419                                                 break;
420                                         }
421                                         if (mpssas_volume_add(sc, le16toh(event_data->VolDevHandle))) {
422                                                 printf("%s: failed to add RAID "
423                                                         "volume with handle 0x%x\n",
424                                                         __func__, le16toh(event_data->
425                                                         VolDevHandle));
426                                         }
427                                         break;
428                                 default:
429                                         break;
430                                 }
431                         break;
432                 default:
433                         break;
434                 }
435                 break;
436         }
437         case MPI2_EVENT_IR_PHYSICAL_DISK:
438         {
439                 Mpi2EventDataIrPhysicalDisk_t *event_data =
440                     fw_event->event_data;
441                 struct mpssas_target *targ;
442
443                 /*
444                  * Informational only.
445                  */
446                 mps_dprint(sc, MPS_EVENT, "Received IR Phys Disk event:\n");
447                 switch (event_data->ReasonCode) {
448                 case MPI2_EVENT_IR_PHYSDISK_RC_SETTINGS_CHANGED:
449                         mps_dprint(sc, MPS_EVENT, "   Phys Disk Settings "
450                             "changed from 0x%x to 0x%x for Phys Disk Number "
451                             "%d and handle 0x%x at Enclosure handle 0x%x, Slot "
452                             "%d", le32toh(event_data->PreviousValue),
453                             le32toh(event_data->NewValue),
454                                 event_data->PhysDiskNum,
455                             le16toh(event_data->PhysDiskDevHandle),
456                             le16toh(event_data->EnclosureHandle), le16toh(event_data->Slot));
457                         break;
458                 case MPI2_EVENT_IR_PHYSDISK_RC_STATUS_FLAGS_CHANGED:
459                         mps_dprint(sc, MPS_EVENT, "   Phys Disk Status changed "
460                             "from 0x%x to 0x%x for Phys Disk Number %d and "
461                             "handle 0x%x at Enclosure handle 0x%x, Slot %d",
462                                 le32toh(event_data->PreviousValue),
463                             le32toh(event_data->NewValue), event_data->PhysDiskNum,
464                             le16toh(event_data->PhysDiskDevHandle),
465                             le16toh(event_data->EnclosureHandle), le16toh(event_data->Slot));
466                         break;
467                 case MPI2_EVENT_IR_PHYSDISK_RC_STATE_CHANGED:
468                         mps_dprint(sc, MPS_EVENT, "   Phys Disk State changed "
469                             "from 0x%x to 0x%x for Phys Disk Number %d and "
470                             "handle 0x%x at Enclosure handle 0x%x, Slot %d",
471                                 le32toh(event_data->PreviousValue),
472                             le32toh(event_data->NewValue), event_data->PhysDiskNum,
473                             le16toh(event_data->PhysDiskDevHandle),
474                             le16toh(event_data->EnclosureHandle), le16toh(event_data->Slot));
475                         switch (event_data->NewValue) {
476                                 case MPI2_RAID_PD_STATE_ONLINE:
477                                 case MPI2_RAID_PD_STATE_DEGRADED:
478                                 case MPI2_RAID_PD_STATE_REBUILDING:
479                                 case MPI2_RAID_PD_STATE_OPTIMAL:
480                                 case MPI2_RAID_PD_STATE_HOT_SPARE:
481                                         targ = mpssas_find_target_by_handle(sassc, 0, 
482                                                         event_data->PhysDiskDevHandle);
483                                         if (targ) {
484                                                 if(!sc->WD_available) {
485                                                         targ->flags |= MPS_TARGET_FLAGS_RAID_COMPONENT;
486                                                         printf("%s %d: Found Target for handle 0x%x.  \n",
487                                                         __func__, __LINE__ , event_data->PhysDiskDevHandle);
488                                                 } else if ((sc->WD_available && 
489                                                         (sc->WD_hide_expose == MPS_WD_HIDE_ALWAYS)) ||
490                                                         (sc->WD_valid_config && (sc->WD_hide_expose ==
491                                                         MPS_WD_HIDE_IF_VOLUME))) {
492                                                         targ->flags |= MPS_TARGET_FLAGS_RAID_COMPONENT;
493                                                         printf("%s %d: WD: Found Target for handle 0x%x.  \n",
494                                                         __func__, __LINE__ , event_data->PhysDiskDevHandle);
495                                                 }
496                                         }               
497                                 break;
498                                 case MPI2_RAID_PD_STATE_OFFLINE:
499                                 case MPI2_RAID_PD_STATE_NOT_CONFIGURED:
500                                 case MPI2_RAID_PD_STATE_NOT_COMPATIBLE:
501                                 default:
502                                         targ = mpssas_find_target_by_handle(sassc, 0, 
503                                                         event_data->PhysDiskDevHandle);
504                                         if (targ) {
505                                                 targ->flags |= ~MPS_TARGET_FLAGS_RAID_COMPONENT;
506                                                 printf("%s %d: Found Target for handle 0x%x.  \n",
507                                                 __func__, __LINE__ , event_data->PhysDiskDevHandle);
508                                         }
509                                 break;
510                         }
511                 default:
512                         break;
513                 }
514                 break;
515         }
516         case MPI2_EVENT_IR_OPERATION_STATUS:
517         {
518                 Mpi2EventDataIrOperationStatus_t *event_data =
519                     fw_event->event_data;
520
521                 /*
522                  * Informational only.
523                  */
524                 mps_dprint(sc, MPS_EVENT, "Received IR Op Status event:\n");
525                 mps_dprint(sc, MPS_EVENT, "   RAID Operation of %d is %d "
526                     "percent complete for Volume with handle 0x%x",
527                     event_data->RAIDOperation, event_data->PercentComplete,
528                     le16toh(event_data->VolDevHandle));
529                 break;
530         }
531         case MPI2_EVENT_LOG_ENTRY_ADDED:
532         {
533                 pMpi2EventDataLogEntryAdded_t   logEntry;
534                 uint16_t                        logQualifier;
535                 uint8_t                         logCode;
536
537                 logEntry = (pMpi2EventDataLogEntryAdded_t)fw_event->event_data;
538                 logQualifier = logEntry->LogEntryQualifier;
539
540                 if (logQualifier == MPI2_WD_LOG_ENTRY) {
541                         logCode = logEntry->LogData[0];
542
543                         switch (logCode) {
544                         case MPI2_WD_SSD_THROTTLING:
545                                 printf("WarpDrive Warning: IO Throttling has "
546                                     "occurred in the WarpDrive subsystem. "
547                                     "Check WarpDrive documentation for "
548                                     "additional details\n");
549                                 break;
550                         case MPI2_WD_DRIVE_LIFE_WARN:
551                                 printf("WarpDrive Warning: Program/Erase "
552                                     "Cycles for the WarpDrive subsystem in "
553                                     "degraded range. Check WarpDrive "
554                                     "documentation for additional details\n");
555                                 break;
556                         case MPI2_WD_DRIVE_LIFE_DEAD:
557                                 printf("WarpDrive Fatal Error: There are no "
558                                     "Program/Erase Cycles for the WarpDrive "
559                                     "subsystem. The storage device will be in "
560                                     "read-only mode. Check WarpDrive "
561                                     "documentation for additional details\n");
562                                 break;
563                         case MPI2_WD_RAIL_MON_FAIL:
564                                 printf("WarpDrive Fatal Error: The Backup Rail "
565                                     "Monitor has failed on the WarpDrive "
566                                     "subsystem. Check WarpDrive documentation "
567                                     "for additional details\n");
568                                 break;
569                         default:
570                                 break;
571                         }
572                 }
573                 break;
574         }
575         case MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE:
576         case MPI2_EVENT_SAS_BROADCAST_PRIMITIVE:
577         default:
578                 mps_dprint(sc, MPS_TRACE,"Unhandled event 0x%0X\n",
579                     fw_event->event);
580                 break;
581
582         }
583         mps_dprint(sc, MPS_EVENT, "(%d)->(%s) Event Free: [%x]\n",event_count,__func__, fw_event->event);
584         mpssas_fw_event_free(sc, fw_event);
585 }
586
587 void
588 mpssas_firmware_event_work(void *arg, int pending)
589 {
590         struct mps_fw_event_work *fw_event;
591         struct mps_softc *sc;
592
593         sc = (struct mps_softc *)arg;
594         mps_lock(sc);
595         while ((fw_event = TAILQ_FIRST(&sc->sassc->ev_queue)) != NULL) {
596                 TAILQ_REMOVE(&sc->sassc->ev_queue, fw_event, ev_link);
597                 mpssas_fw_work(sc, fw_event);
598         }
599         mps_unlock(sc);
600 }
601
602 static int
603 mpssas_add_device(struct mps_softc *sc, u16 handle, u8 linkrate){
604         char devstring[80];
605         struct mpssas_softc *sassc;
606         struct mpssas_target *targ;
607         Mpi2ConfigReply_t mpi_reply;
608         Mpi2SasDevicePage0_t config_page;
609         uint64_t sas_address, sata_sas_address;
610         uint64_t parent_sas_address = 0;
611         u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags);
612         u32 device_info, parent_devinfo = 0;
613         unsigned int id;
614         int ret;
615         int error = 0;
616         struct mpssas_lun *lun;
617
618         sassc = sc->sassc;
619         mpssas_startup_increment(sassc);
620         if ((mps_config_get_sas_device_pg0(sc, &mpi_reply, &config_page,
621              MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, handle))) {
622                 printf("%s: error reading SAS device page0\n", __func__);
623                 error = ENXIO;
624                 goto out;
625         }
626
627         device_info = le32toh(config_page.DeviceInfo);
628
629         if (((device_info & MPI2_SAS_DEVICE_INFO_SMP_TARGET) == 0)
630          && (le16toh(config_page.ParentDevHandle) != 0)) {
631                 Mpi2ConfigReply_t tmp_mpi_reply;
632                 Mpi2SasDevicePage0_t parent_config_page;
633
634                 if ((mps_config_get_sas_device_pg0(sc, &tmp_mpi_reply,
635                      &parent_config_page, MPI2_SAS_DEVICE_PGAD_FORM_HANDLE,
636                      le16toh(config_page.ParentDevHandle)))) {
637                         printf("%s: error reading SAS device %#x page0\n",
638                                __func__, le16toh(config_page.ParentDevHandle));
639                 } else {
640                         parent_sas_address = parent_config_page.SASAddress.High;
641                         parent_sas_address = (parent_sas_address << 32) |
642                                 parent_config_page.SASAddress.Low;
643                         parent_devinfo = le32toh(parent_config_page.DeviceInfo);
644                 }
645         }
646         /* TODO Check proper endianess */
647         sas_address = config_page.SASAddress.High;
648         sas_address = (sas_address << 32) | 
649             config_page.SASAddress.Low;
650
651         if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE)
652                     == MPI2_IOCPAGE8_FLAGS_DEVICE_PERSISTENCE_MAPPING) {
653                 if (device_info & MPI2_SAS_DEVICE_INFO_SATA_DEVICE) {
654                         ret = mpssas_get_sas_address_for_sata_disk(sc,
655                             &sata_sas_address, handle, device_info);
656                         if (!ret)
657                                 id = mps_mapping_get_sas_id(sc,
658                                     sata_sas_address, handle);
659                         else
660                                 id = mps_mapping_get_sas_id(sc,
661                                     sas_address, handle);
662                 } else
663                         id = mps_mapping_get_sas_id(sc, sas_address,
664                             handle);
665         } else
666                 id = mps_mapping_get_sas_id(sc, sas_address, handle);
667
668         if (id == MPS_MAP_BAD_ID) {
669                 printf("failure at %s:%d/%s()! Could not get ID for device "
670                     "with handle 0x%04x\n", __FILE__, __LINE__, __func__,
671                     handle);
672                 error = ENXIO;
673                 goto out;
674         }
675
676         if (mpssas_check_id(sassc, id) != 0) {
677                 device_printf(sc->mps_dev, "Excluding target id %d\n", id);
678                 error = ENXIO;
679                 goto out;
680         }
681
682         mps_dprint(sc, MPS_MAPPING, "SAS Address from SAS device page0 = %jx\n",
683             sas_address);
684         targ = &sassc->targets[id];
685         targ->devinfo = device_info;
686         targ->devname = le32toh(config_page.DeviceName.High);
687         targ->devname = (targ->devname << 32) | 
688             le32toh(config_page.DeviceName.Low);
689         targ->encl_handle = le16toh(config_page.EnclosureHandle);
690         targ->encl_slot = le16toh(config_page.Slot);
691         targ->handle = handle;
692         targ->parent_handle = le16toh(config_page.ParentDevHandle);
693         targ->sasaddr = mps_to_u64(&config_page.SASAddress);
694         targ->parent_sasaddr = le64toh(parent_sas_address);
695         targ->parent_devinfo = parent_devinfo;
696         targ->tid = id;
697         targ->linkrate = (linkrate>>4);
698         targ->flags = 0;
699         TAILQ_INIT(&targ->commands);
700         TAILQ_INIT(&targ->timedout_commands);
701         while(!SLIST_EMPTY(&targ->luns)) {
702                 lun = SLIST_FIRST(&targ->luns);
703                 SLIST_REMOVE_HEAD(&targ->luns, lun_link);
704                 free(lun, M_MPT2);
705         }
706         SLIST_INIT(&targ->luns);
707
708         mps_describe_devinfo(targ->devinfo, devstring, 80);
709         mps_dprint(sc, MPS_MAPPING, "Found device <%s> <%s> <0x%04x> <%d/%d>\n", devstring,
710             mps_describe_table(mps_linkrate_names, targ->linkrate),
711             targ->handle, targ->encl_handle, targ->encl_slot);
712
713 #if __FreeBSD_version < 1000039
714         if ((sassc->flags & MPSSAS_IN_STARTUP) == 0)
715 #endif
716                 mpssas_rescan_target(sc, targ);
717         mps_dprint(sc, MPS_MAPPING, "Target id 0x%x added\n", targ->tid);
718 out:
719         mpssas_startup_decrement(sassc);
720         return (error);
721         
722 }
723         
724 int
725 mpssas_get_sas_address_for_sata_disk(struct mps_softc *sc,
726     u64 *sas_address, u16 handle, u32 device_info)
727 {
728         Mpi2SataPassthroughReply_t mpi_reply;
729         int i, rc, try_count;
730         u32 *bufferptr;
731         union _sata_sas_address hash_address;
732         struct _ata_identify_device_data ata_identify;
733         u8 buffer[MPT2SAS_MN_LEN + MPT2SAS_SN_LEN];
734         u32 ioc_status;
735         u8 sas_status;
736
737         memset(&ata_identify, 0, sizeof(ata_identify));
738         try_count = 0;
739         do {
740                 rc = mpssas_get_sata_identify(sc, handle, &mpi_reply,
741                     (char *)&ata_identify, sizeof(ata_identify), device_info);
742                 try_count++;
743                 ioc_status = le16toh(mpi_reply.IOCStatus)
744                     & MPI2_IOCSTATUS_MASK;
745                 sas_status = mpi_reply.SASStatus;
746         } while ((rc == -EAGAIN || ioc_status || sas_status) &&
747             (try_count < 5));
748
749         if (rc == 0 && !ioc_status && !sas_status) {
750                 mps_dprint(sc, MPS_MAPPING, "%s: got SATA identify successfully "
751                            "for handle = 0x%x with try_count = %d\n",
752                            __func__, handle, try_count);
753         } else {
754                 mps_dprint(sc, MPS_MAPPING, "%s: handle = 0x%x failed\n",
755                            __func__, handle);
756                 return -1;
757         }
758         /* Copy & byteswap the 40 byte model number to a buffer */
759         for (i = 0; i < MPT2SAS_MN_LEN; i += 2) {
760                 buffer[i] = ((u8 *)ata_identify.model_number)[i + 1];
761                 buffer[i + 1] = ((u8 *)ata_identify.model_number)[i];
762         }
763         /* Copy & byteswap the 20 byte serial number to a buffer */
764         for (i = 0; i < MPT2SAS_SN_LEN; i += 2) {
765                 buffer[MPT2SAS_MN_LEN + i] =
766                         ((u8 *)ata_identify.serial_number)[i + 1];
767                 buffer[MPT2SAS_MN_LEN + i + 1] =
768                         ((u8 *)ata_identify.serial_number)[i];
769         }
770         bufferptr = (u32 *)buffer;
771         /* There are 60 bytes to hash down to 8. 60 isn't divisible by 8,
772          * so loop through the first 56 bytes (7*8),
773          * and then add in the last dword.
774          */
775         hash_address.word.low  = 0;
776         hash_address.word.high = 0;
777         for (i = 0; (i < ((MPT2SAS_MN_LEN+MPT2SAS_SN_LEN)/8)); i++) {
778                 hash_address.word.low += *bufferptr;
779                 bufferptr++;
780                 hash_address.word.high += *bufferptr;
781                 bufferptr++;
782         }
783         /* Add the last dword */
784         hash_address.word.low += *bufferptr;
785         /* Make sure the hash doesn't start with 5, because it could clash
786          * with a SAS address. Change 5 to a D.
787          */
788         if ((hash_address.word.high & 0x000000F0) == (0x00000050))
789                 hash_address.word.high |= 0x00000080;
790         *sas_address = (u64)hash_address.wwid[0] << 56 |
791             (u64)hash_address.wwid[1] << 48 | (u64)hash_address.wwid[2] << 40 |
792             (u64)hash_address.wwid[3] << 32 | (u64)hash_address.wwid[4] << 24 |
793             (u64)hash_address.wwid[5] << 16 | (u64)hash_address.wwid[6] <<  8 |
794             (u64)hash_address.wwid[7];
795         return 0;
796 }
797
798 static int
799 mpssas_get_sata_identify(struct mps_softc *sc, u16 handle,
800     Mpi2SataPassthroughReply_t *mpi_reply, char *id_buffer, int sz, u32 devinfo)
801 {
802         Mpi2SataPassthroughRequest_t *mpi_request;
803         Mpi2SataPassthroughReply_t *reply;
804         struct mps_command *cm;
805         char *buffer;
806         int error = 0;
807
808         buffer = malloc( sz, M_MPT2, M_NOWAIT | M_ZERO);
809         if (!buffer)
810                 return ENOMEM;
811
812         if ((cm = mps_alloc_command(sc)) == NULL) {
813                 free(buffer, M_MPT2);
814                 return (EBUSY);
815         }
816         mpi_request = (MPI2_SATA_PASSTHROUGH_REQUEST *)cm->cm_req;
817         bzero(mpi_request,sizeof(MPI2_SATA_PASSTHROUGH_REQUEST));
818         mpi_request->Function = MPI2_FUNCTION_SATA_PASSTHROUGH;
819         mpi_request->VF_ID = 0;
820         mpi_request->DevHandle = htole16(handle);
821         mpi_request->PassthroughFlags = (MPI2_SATA_PT_REQ_PT_FLAGS_PIO |
822             MPI2_SATA_PT_REQ_PT_FLAGS_READ);
823         mpi_request->DataLength = htole32(sz);
824         mpi_request->CommandFIS[0] = 0x27;
825         mpi_request->CommandFIS[1] = 0x80;
826         mpi_request->CommandFIS[2] =  (devinfo &
827             MPI2_SAS_DEVICE_INFO_ATAPI_DEVICE) ? 0xA1 : 0xEC;
828         cm->cm_sge = &mpi_request->SGL;
829         cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
830         cm->cm_flags = MPS_CM_FLAGS_SGE_SIMPLE | MPS_CM_FLAGS_DATAIN;
831         cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
832         cm->cm_data = buffer;
833         cm->cm_length = htole32(sz);
834         error = mps_wait_command(sc, cm, 60, CAN_SLEEP);
835         reply = (Mpi2SataPassthroughReply_t *)cm->cm_reply;
836         if (error || (reply == NULL)) {
837                 /* FIXME */
838                 /*
839                  * If the request returns an error then we need to do a diag
840                  * reset
841                  */ 
842                 printf("%s: request for page completed with error %d",
843                     __func__, error);
844                 error = ENXIO;
845                 goto out;
846         }
847         bcopy(buffer, id_buffer, sz);
848         bcopy(reply, mpi_reply, sizeof(Mpi2SataPassthroughReply_t));
849         if ((le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK) !=
850             MPI2_IOCSTATUS_SUCCESS) {
851                 printf("%s: error reading SATA PASSTHRU; iocstatus = 0x%x\n",
852                     __func__, reply->IOCStatus);
853                 error = ENXIO;
854                 goto out;
855         }
856 out:
857         mps_free_command(sc, cm);
858         free(buffer, M_MPT2);   
859         return (error);
860 }
861
862 static int
863 mpssas_volume_add(struct mps_softc *sc, u16 handle)
864 {
865         struct mpssas_softc *sassc;
866         struct mpssas_target *targ;
867         u64 wwid;
868         unsigned int id;
869         int error = 0;
870         struct mpssas_lun *lun;
871
872         sassc = sc->sassc;
873         mpssas_startup_increment(sassc);
874         /* wwid is endian safe */
875         mps_config_get_volume_wwid(sc, handle, &wwid);
876         if (!wwid) {
877                 printf("%s: invalid WWID; cannot add volume to mapping table\n",
878                     __func__);
879                 error = ENXIO;
880                 goto out;
881         }
882
883         id = mps_mapping_get_raid_id(sc, wwid, handle);
884         if (id == MPS_MAP_BAD_ID) {
885                 printf("%s: could not get ID for volume with handle 0x%04x and "
886                     "WWID 0x%016llx\n", __func__, handle,
887                     (unsigned long long)wwid);
888                 error = ENXIO;
889                 goto out;
890         }
891
892         targ = &sassc->targets[id];
893         targ->tid = id;
894         targ->handle = handle;
895         targ->devname = wwid;
896         TAILQ_INIT(&targ->commands);
897         TAILQ_INIT(&targ->timedout_commands);
898         while(!SLIST_EMPTY(&targ->luns)) {
899                 lun = SLIST_FIRST(&targ->luns);
900                 SLIST_REMOVE_HEAD(&targ->luns, lun_link);
901                 free(lun, M_MPT2);
902         }
903         SLIST_INIT(&targ->luns);
904 #if __FreeBSD_version < 1000039
905         if ((sassc->flags & MPSSAS_IN_STARTUP) == 0)
906 #endif
907                 mpssas_rescan_target(sc, targ);
908         mps_dprint(sc, MPS_MAPPING, "RAID target id %d added (WWID = 0x%jx)\n",
909             targ->tid, wwid);
910 out:
911         mpssas_startup_decrement(sassc);
912         return (error);
913 }
914
915 /**
916  * mpssas_SSU_to_SATA_devices 
917  * @sc: per adapter object
918  *
919  * Looks through the target list and issues a StartStopUnit SCSI command to each
920  * SATA direct-access device.  This helps to ensure that data corruption is
921  * avoided when the system is being shut down.  This must be called after the IR
922  * System Shutdown RAID Action is sent if in IR mode.
923  *
924  * Return nothing.
925  */
926 static void
927 mpssas_SSU_to_SATA_devices(struct mps_softc *sc)
928 {
929         struct mpssas_softc *sassc = sc->sassc;
930         union ccb *ccb;
931         path_id_t pathid = cam_sim_path(sassc->sim);
932         target_id_t targetid;
933         struct mpssas_target *target;
934         struct mpssas_lun *lun;
935         char path_str[64];
936         struct timeval cur_time, start_time;
937
938         /*
939          * For each LUN of each target, issue a StartStopUnit command to stop
940          * the device.
941          */
942         sc->SSU_started = TRUE;
943         sc->SSU_refcount = 0;
944         for (targetid = 0; targetid < sc->facts->MaxTargets; targetid++) {
945                 target = &sassc->targets[targetid];
946                 if (target->handle == 0x0) {
947                         continue;
948                 }
949
950                 SLIST_FOREACH(lun, &target->luns, lun_link) {
951                         ccb = xpt_alloc_ccb_nowait();
952                         if (ccb == NULL) {
953                                 mps_dprint(sc, MPS_FAULT, "Unable to alloc CCB "
954                                     "to stop unit.\n");
955                                 return;
956                         }
957
958                         /*
959                          * The stop_at_shutdown flag will be set if this LUN is
960                          * a SATA direct-access end device.
961                          */
962                         if (lun->stop_at_shutdown) {
963                                 if (xpt_create_path(&ccb->ccb_h.path,
964                                     xpt_periph, pathid, targetid,
965                                     lun->lun_id) != CAM_REQ_CMP) {
966                                         mps_dprint(sc, MPS_FAULT, "Unable to "
967                                             "create LUN path to stop unit.\n");
968                                         xpt_free_ccb(ccb);
969                                         return;
970                                 }
971                                 xpt_path_string(ccb->ccb_h.path, path_str,
972                                     sizeof(path_str));
973
974                                 mps_dprint(sc, MPS_INFO, "Sending StopUnit: "
975                                     "path %s handle %d\n", path_str,
976                                     target->handle);
977                         
978                                 /*
979                                  * Issue a START STOP UNIT command for the LUN.
980                                  * Increment the SSU counter to be used to
981                                  * count the number of required replies.
982                                  */
983                                 mps_dprint(sc, MPS_INFO, "Incrementing SSU "
984                                     "count\n");
985                                 sc->SSU_refcount++;
986                                 ccb->ccb_h.target_id =
987                                     xpt_path_target_id(ccb->ccb_h.path);
988                                 ccb->ccb_h.target_lun = lun->lun_id;
989                                 ccb->ccb_h.ppriv_ptr1 = sassc;
990                                 scsi_start_stop(&ccb->csio,
991                                     /*retries*/0,
992                                     mpssas_stop_unit_done,
993                                     MSG_SIMPLE_Q_TAG,
994                                     /*start*/FALSE,
995                                     /*load/eject*/0,
996                                     /*immediate*/FALSE,
997                                     MPS_SENSE_LEN,
998                                     /*timeout*/10000);
999                                 xpt_action(ccb);
1000                         }
1001                 }
1002         }
1003
1004         /*
1005          * Wait until all of the SSU commands have completed or time has
1006          * expired (60 seconds).  pause for 100ms each time through.  If any
1007          * command times out, the target will be reset in the SCSI command
1008          * timeout routine.
1009          */
1010         getmicrotime(&start_time);
1011         while (sc->SSU_refcount) {
1012                 pause("mpswait", hz/10);
1013                 
1014                 getmicrotime(&cur_time);
1015                 if ((cur_time.tv_sec - start_time.tv_sec) > 60) {
1016                         mps_dprint(sc, MPS_FAULT, "Time has expired waiting "
1017                             "for SSU commands to complete.\n");
1018                         break;
1019                 }
1020         }
1021 }
1022
1023 static void
1024 mpssas_stop_unit_done(struct cam_periph *periph, union ccb *done_ccb)
1025 {
1026         struct mpssas_softc *sassc;
1027         char path_str[64];
1028
1029         sassc = (struct mpssas_softc *)done_ccb->ccb_h.ppriv_ptr1;
1030
1031         xpt_path_string(done_ccb->ccb_h.path, path_str, sizeof(path_str));
1032         mps_dprint(sassc->sc, MPS_INFO, "Completing stop unit for %s\n",
1033             path_str);
1034
1035         if (done_ccb == NULL)
1036                 return;
1037
1038         /*
1039          * Nothing more to do except free the CCB and path.  If the command
1040          * timed out, an abort reset, then target reset will be issued during
1041          * the SCSI Command process.
1042          */
1043         xpt_free_path(done_ccb->ccb_h.path);
1044         xpt_free_ccb(done_ccb);
1045 }
1046
1047 /**
1048  * mpssas_ir_shutdown - IR shutdown notification
1049  * @sc: per adapter object
1050  *
1051  * Sending RAID Action to alert the Integrated RAID subsystem of the IOC that
1052  * the host system is shutting down.
1053  *
1054  * Return nothing.
1055  */
1056 void
1057 mpssas_ir_shutdown(struct mps_softc *sc)
1058 {
1059         u16 volume_mapping_flags;
1060         u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags);
1061         struct dev_mapping_table *mt_entry;
1062         u32 start_idx, end_idx;
1063         unsigned int id, found_volume = 0;
1064         struct mps_command *cm;
1065         Mpi2RaidActionRequest_t *action;
1066
1067         mps_dprint(sc, MPS_TRACE, "%s\n", __func__);
1068
1069         /* is IR firmware build loaded? */
1070         if (!sc->ir_firmware)
1071                 goto out;
1072
1073         /* are there any volumes?  Look at IR target IDs. */
1074         // TODO-later, this should be looked up in the RAID config structure
1075         // when it is implemented.
1076         volume_mapping_flags = le16toh(sc->ioc_pg8.IRVolumeMappingFlags) &
1077             MPI2_IOCPAGE8_IRFLAGS_MASK_VOLUME_MAPPING_MODE;
1078         if (volume_mapping_flags == MPI2_IOCPAGE8_IRFLAGS_LOW_VOLUME_MAPPING) {
1079                 start_idx = 0;
1080                 if (ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_RESERVED_TARGETID_0)
1081                         start_idx = 1;
1082         } else
1083                 start_idx = sc->max_devices - sc->max_volumes;
1084         end_idx = start_idx + sc->max_volumes - 1;
1085
1086         for (id = start_idx; id < end_idx; id++) {
1087                 mt_entry = &sc->mapping_table[id];
1088                 if ((mt_entry->physical_id != 0) &&
1089                     (mt_entry->missing_count == 0)) {
1090                         found_volume = 1;
1091                         break;
1092                 }
1093         }
1094
1095         if (!found_volume)
1096                 goto out;
1097
1098         if ((cm = mps_alloc_command(sc)) == NULL) {
1099                 printf("%s: command alloc failed\n", __func__);
1100                 goto out;
1101         }
1102
1103         action = (MPI2_RAID_ACTION_REQUEST *)cm->cm_req;
1104         action->Function = MPI2_FUNCTION_RAID_ACTION;
1105         action->Action = MPI2_RAID_ACTION_SYSTEM_SHUTDOWN_INITIATED;
1106         cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
1107         mps_lock(sc);
1108         mps_wait_command(sc, cm, 5, CAN_SLEEP);
1109         mps_unlock(sc);
1110
1111         /*
1112          * Don't check for reply, just leave.
1113          */
1114         if (cm)
1115                 mps_free_command(sc, cm);
1116
1117 out:
1118         mpssas_SSU_to_SATA_devices(sc);
1119 }