5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 /*
28 * Copyright (c) 2000 to 2010, LSI Corporation.
29 * All rights reserved.
30 *
31 * Redistribution and use in source and binary forms of all code within
32 * this file that is exclusively owned by LSI, with or without
33 * modification, is permitted provided that, in addition to the CDDL 1.0
34 * License requirements, the following conditions are met:
35 *
36 * Neither the name of the author nor the names of its contributors may be
37 * used to endorse or promote products derived from this software without
38 * specific prior written permission.
39 *
40 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
41 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
42 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
43 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
44 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
55 * mptsas_raid - This file contains all the RAID related functions for the
56 * MPT interface.
57 */
58
59 #if defined(lint) || defined(DEBUG)
60 #define MPTSAS_DEBUG
61 #endif
62
63 #define MPI_RAID_VOL_PAGE_0_PHYSDISK_MAX 2
64
65 /*
66 * standard header files
67 */
68 #include <sys/note.h>
69 #include <sys/scsi/scsi.h>
70 #include <sys/byteorder.h>
71 #include <sys/raidioctl.h>
72
73 #pragma pack(1)
74
75 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_type.h>
76 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2.h>
77 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_cnfg.h>
78 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_init.h>
79 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_ioc.h>
80 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_raid.h>
81 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_tool.h>
82
83 #pragma pack()
84
85 /*
86 * private header files.
87 */
88 #include <sys/scsi/adapters/mpt_sas/mptsas_var.h>
89
90 static int mptsas_get_raid_wwid(mptsas_t *mpt, mptsas_raidvol_t *raidvol);
91
92 extern int mptsas_check_dma_handle(ddi_dma_handle_t handle);
93 extern int mptsas_check_acc_handle(ddi_acc_handle_t handle);
94 extern mptsas_target_t *mptsas_tgt_alloc(mptsas_t *, uint16_t,
95 uint64_t, uint32_t, mptsas_phymask_t, uint8_t);
96
97 static int
98 mptsas_raidconf_page_0_cb(mptsas_t *mpt, caddr_t page_memp,
99 ddi_acc_handle_t accessp, uint16_t iocstatus, uint32_t iocloginfo,
100 va_list ap)
101 {
102 #ifndef __lock_lint
103 _NOTE(ARGUNUSED(ap))
104 #endif
105 pMpi2RaidConfigurationPage0_t raidconfig_page0;
106 pMpi2RaidConfig0ConfigElement_t element;
107 uint32_t *confignum;
108 int rval = DDI_SUCCESS, i;
549 case MPI2_RAID_PD_STATE_ONLINE:
550 default:
551 raidvol->m_diskstatus[i] =
552 RAID_DISKSTATUS_GOOD;
553 break;
554 }
555 }
556
557 return (rval);
558 }
559
560 /*
561 * RAID Action for System Shutdown. This request uses the dedicated TM slot to
562 * avoid a call to mptsas_save_cmd. Since Solaris requires that the mutex is
563 * not held during the mptsas_quiesce function, this RAID action must not use
564 * the normal code path of requests and replies.
565 */
566 void
567 mptsas_raid_action_system_shutdown(mptsas_t *mpt)
568 {
569 pMpi2RaidActionRequest_t action;
570 uint8_t ir_active = FALSE, reply_type;
571 uint8_t function, found_reply = FALSE;
572 uint16_t SMID, action_type;
573 mptsas_slots_t *slots = mpt->m_active;
574 int config, vol;
575 mptsas_cmd_t *cmd;
576 uint32_t request_desc_low, reply_addr;
577 int cnt;
578 pMpi2ReplyDescriptorsUnion_t reply_desc_union;
579 pMPI2DefaultReply_t reply;
580 pMpi2AddressReplyDescriptor_t address_reply;
581
582 /*
583 * Before doing the system shutdown RAID Action, make sure that the IOC
584 * supports IR and make sure there is a valid volume for the request.
585 */
586 if (mpt->m_ir_capable) {
587 for (config = 0; (config < mpt->m_num_raid_configs) &&
588 (!ir_active); config++) {
589 for (vol = 0; vol < MPTSAS_MAX_RAIDVOLS; vol++) {
590 if (mpt->m_raidconfig[config].m_raidvol[vol].
591 m_israid) {
592 ir_active = TRUE;
593 break;
594 }
595 }
596 }
612 /*
613 * Create the cmd and put it in the dedicated TM slot.
614 */
615 cmd = &(mpt->m_event_task_mgmt.m_event_cmd);
616 bzero((caddr_t)cmd, sizeof (*cmd));
617 cmd->cmd_pkt = NULL;
618 cmd->cmd_slot = MPTSAS_TM_SLOT(mpt);
619 slots->m_slot[MPTSAS_TM_SLOT(mpt)] = cmd;
620
621 /*
622 * Form message for raid action.
623 */
624 action = (pMpi2RaidActionRequest_t)(mpt->m_req_frame +
625 (mpt->m_req_frame_size * cmd->cmd_slot));
626 bzero(action, mpt->m_req_frame_size);
627 action->Function = MPI2_FUNCTION_RAID_ACTION;
628 action->Action = MPI2_RAID_ACTION_SYSTEM_SHUTDOWN_INITIATED;
629
630 /*
631 * Send RAID Action.
632 */
633 (void) ddi_dma_sync(mpt->m_dma_req_frame_hdl, 0, 0,
634 DDI_DMA_SYNC_FORDEV);
635 request_desc_low = (cmd->cmd_slot << 16) +
636 MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
637 MPTSAS_START_CMD(mpt, request_desc_low, 0);
638
639 /*
640 * Even though reply does not matter because the system is shutting
641 * down, wait no more than 5 seconds here to get the reply just because
642 * we don't want to leave it hanging if it's coming. Poll because
643 * interrupts are disabled when this function is called.
644 */
645 for (cnt = 0; cnt < 5000; cnt++) {
646 /*
647 * Check for a reply.
648 */
649 (void) ddi_dma_sync(mpt->m_dma_post_queue_hdl, 0, 0,
650 DDI_DMA_SYNC_FORCPU);
651
652 reply_desc_union = (pMpi2ReplyDescriptorsUnion_t)
653 MPTSAS_GET_NEXT_REPLY(mpt, mpt->m_post_index);
654
655 if (ddi_get32(mpt->m_acc_post_queue_hdl,
656 &reply_desc_union->Words.Low) == 0xFFFFFFFF ||
657 ddi_get32(mpt->m_acc_post_queue_hdl,
658 &reply_desc_union->Words.High) == 0xFFFFFFFF) {
659 drv_usecwait(1000);
660 continue;
661 }
662
663 /*
664 * There is a reply. If it's not an address reply, ignore it.
665 */
666 reply_type = ddi_get8(mpt->m_acc_post_queue_hdl,
667 &reply_desc_union->Default.ReplyFlags);
668 reply_type &= MPI2_RPY_DESCRIPT_FLAGS_TYPE_MASK;
669 if (reply_type != MPI2_RPY_DESCRIPT_FLAGS_ADDRESS_REPLY) {
670 goto clear_and_continue;
671 }
672
673 /*
708 goto clear_and_continue;
709 }
710
711 /*
712 * Finally, make sure this is the System Shutdown RAID action.
713 * If not, ignore reply.
714 */
715 action_type = ddi_get16(mpt->m_acc_reply_frame_hdl,
716 &reply->FunctionDependent1);
717 if (action_type !=
718 MPI2_RAID_ACTION_SYSTEM_SHUTDOWN_INITIATED) {
719 goto clear_and_continue;
720 }
721 found_reply = TRUE;
722
723 clear_and_continue:
724 /*
725 * Clear the reply descriptor for re-use and increment index.
726 */
727 ddi_put64(mpt->m_acc_post_queue_hdl,
728 &((uint64_t *)(void *)mpt->m_post_queue)[mpt->m_post_index],
729 0xFFFFFFFFFFFFFFFF);
730 (void) ddi_dma_sync(mpt->m_dma_post_queue_hdl, 0, 0,
731 DDI_DMA_SYNC_FORDEV);
732
733 /*
734 * Update the global reply index and keep looking for the
735 * reply if not found yet.
736 */
737 if (++mpt->m_post_index == mpt->m_post_queue_depth) {
738 mpt->m_post_index = 0;
739 }
740 ddi_put32(mpt->m_datap, &mpt->m_reg->ReplyPostHostIndex,
741 mpt->m_post_index);
742 if (!found_reply) {
743 continue;
744 }
745
746 break;
747 }
748
749 /*
750 * clear the used slot as the last step.
751 */
752 slots->m_slot[MPTSAS_TM_SLOT(mpt)] = NULL;
753 }
754
755 int
756 mptsas_delete_volume(mptsas_t *mpt, uint16_t volid)
757 {
758 int config, i = 0, vol = (-1);
759
760 for (config = 0; (config < mpt->m_num_raid_configs) && (vol != i);
761 config++) {
|
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 * Copyright (c) 2014, Tegile Systems Inc. All rights reserved.
26 */
27
28 /*
29 * Copyright (c) 2000 to 2010, LSI Corporation.
30 * All rights reserved.
31 *
32 * Redistribution and use in source and binary forms of all code within
33 * this file that is exclusively owned by LSI, with or without
34 * modification, is permitted provided that, in addition to the CDDL 1.0
35 * License requirements, the following conditions are met:
36 *
37 * Neither the name of the author nor the names of its contributors may be
38 * used to endorse or promote products derived from this software without
39 * specific prior written permission.
40 *
41 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
42 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
43 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
44 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
45 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
56 * mptsas_raid - This file contains all the RAID related functions for the
57 * MPT interface.
58 */
59
60 #if defined(lint) || defined(DEBUG)
61 #define MPTSAS_DEBUG
62 #endif
63
64 #define MPI_RAID_VOL_PAGE_0_PHYSDISK_MAX 2
65
66 /*
67 * standard header files
68 */
69 #include <sys/note.h>
70 #include <sys/scsi/scsi.h>
71 #include <sys/byteorder.h>
72 #include <sys/raidioctl.h>
73
74 #pragma pack(1)
75
76 #include <sys/scsi/adapters/mpt_sas3/mpi/mpi2_type.h>
77 #include <sys/scsi/adapters/mpt_sas3/mpi/mpi2.h>
78 #include <sys/scsi/adapters/mpt_sas3/mpi/mpi2_cnfg.h>
79 #include <sys/scsi/adapters/mpt_sas3/mpi/mpi2_init.h>
80 #include <sys/scsi/adapters/mpt_sas3/mpi/mpi2_ioc.h>
81 #include <sys/scsi/adapters/mpt_sas3/mpi/mpi2_raid.h>
82 #include <sys/scsi/adapters/mpt_sas3/mpi/mpi2_tool.h>
83
84 #pragma pack()
85
86 /*
87 * private header files.
88 */
89 #include <sys/scsi/adapters/mpt_sas3/mptsas3_var.h>
90
91 static int mptsas_get_raid_wwid(mptsas_t *mpt, mptsas_raidvol_t *raidvol);
92
93 extern int mptsas_check_dma_handle(ddi_dma_handle_t handle);
94 extern int mptsas_check_acc_handle(ddi_acc_handle_t handle);
95 extern mptsas_target_t *mptsas_tgt_alloc(mptsas_t *, uint16_t,
96 uint64_t, uint32_t, mptsas_phymask_t, uint8_t);
97
98 static int
99 mptsas_raidconf_page_0_cb(mptsas_t *mpt, caddr_t page_memp,
100 ddi_acc_handle_t accessp, uint16_t iocstatus, uint32_t iocloginfo,
101 va_list ap)
102 {
103 #ifndef __lock_lint
104 _NOTE(ARGUNUSED(ap))
105 #endif
106 pMpi2RaidConfigurationPage0_t raidconfig_page0;
107 pMpi2RaidConfig0ConfigElement_t element;
108 uint32_t *confignum;
109 int rval = DDI_SUCCESS, i;
550 case MPI2_RAID_PD_STATE_ONLINE:
551 default:
552 raidvol->m_diskstatus[i] =
553 RAID_DISKSTATUS_GOOD;
554 break;
555 }
556 }
557
558 return (rval);
559 }
560
561 /*
562 * RAID Action for System Shutdown. This request uses the dedicated TM slot to
563 * avoid a call to mptsas_save_cmd. Since Solaris requires that the mutex is
564 * not held during the mptsas_quiesce function, this RAID action must not use
565 * the normal code path of requests and replies.
566 */
567 void
568 mptsas_raid_action_system_shutdown(mptsas_t *mpt)
569 {
570 mptsas_reply_pqueue_t *rpqp;
571 pMpi2RaidActionRequest_t action;
572 uint8_t ir_active = FALSE, reply_type;
573 uint8_t function, found_reply = FALSE;
574 uint16_t SMID, action_type;
575 mptsas_slots_t *slots = mpt->m_active;
576 int config, vol;
577 mptsas_cmd_t *cmd;
578 uint32_t reply_addr;
579 uint64_t request_desc;
580 int cnt;
581 pMpi2ReplyDescriptorsUnion_t reply_desc_union;
582 pMPI2DefaultReply_t reply;
583 pMpi2AddressReplyDescriptor_t address_reply;
584
585 /*
586 * Before doing the system shutdown RAID Action, make sure that the IOC
587 * supports IR and make sure there is a valid volume for the request.
588 */
589 if (mpt->m_ir_capable) {
590 for (config = 0; (config < mpt->m_num_raid_configs) &&
591 (!ir_active); config++) {
592 for (vol = 0; vol < MPTSAS_MAX_RAIDVOLS; vol++) {
593 if (mpt->m_raidconfig[config].m_raidvol[vol].
594 m_israid) {
595 ir_active = TRUE;
596 break;
597 }
598 }
599 }
615 /*
616 * Create the cmd and put it in the dedicated TM slot.
617 */
618 cmd = &(mpt->m_event_task_mgmt.m_event_cmd);
619 bzero((caddr_t)cmd, sizeof (*cmd));
620 cmd->cmd_pkt = NULL;
621 cmd->cmd_slot = MPTSAS_TM_SLOT(mpt);
622 slots->m_slot[MPTSAS_TM_SLOT(mpt)] = cmd;
623
624 /*
625 * Form message for raid action.
626 */
627 action = (pMpi2RaidActionRequest_t)(mpt->m_req_frame +
628 (mpt->m_req_frame_size * cmd->cmd_slot));
629 bzero(action, mpt->m_req_frame_size);
630 action->Function = MPI2_FUNCTION_RAID_ACTION;
631 action->Action = MPI2_RAID_ACTION_SYSTEM_SHUTDOWN_INITIATED;
632
633 /*
634 * Send RAID Action.
635 * Defaults to MSIxIndex of 0, so check reply q 0 below.
636 */
637 (void) ddi_dma_sync(mpt->m_dma_req_frame_hdl, 0, 0,
638 DDI_DMA_SYNC_FORDEV);
639 request_desc = (cmd->cmd_slot << 16) +
640 MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
641 MPTSAS_START_CMD(mpt, request_desc);
642
643 /*
644 * Even though reply does not matter because the system is shutting
645 * down, wait no more than 5 seconds here to get the reply just because
646 * we don't want to leave it hanging if it's coming. Poll because
647 * interrupts are disabled when this function is called.
648 */
649 rpqp = mpt->m_rep_post_queues;
650 for (cnt = 0; cnt < 5000; cnt++) {
651 /*
652 * Check for a reply.
653 */
654 (void) ddi_dma_sync(mpt->m_dma_post_queue_hdl, 0, 0,
655 DDI_DMA_SYNC_FORCPU);
656
657 reply_desc_union = (pMpi2ReplyDescriptorsUnion_t)
658 MPTSAS_GET_NEXT_REPLY(rpqp, rpqp->rpq_index);
659
660 if (ddi_get32(mpt->m_acc_post_queue_hdl,
661 &reply_desc_union->Words.Low) == 0xFFFFFFFF ||
662 ddi_get32(mpt->m_acc_post_queue_hdl,
663 &reply_desc_union->Words.High) == 0xFFFFFFFF) {
664 drv_usecwait(1000);
665 continue;
666 }
667
668 /*
669 * There is a reply. If it's not an address reply, ignore it.
670 */
671 reply_type = ddi_get8(mpt->m_acc_post_queue_hdl,
672 &reply_desc_union->Default.ReplyFlags);
673 reply_type &= MPI2_RPY_DESCRIPT_FLAGS_TYPE_MASK;
674 if (reply_type != MPI2_RPY_DESCRIPT_FLAGS_ADDRESS_REPLY) {
675 goto clear_and_continue;
676 }
677
678 /*
713 goto clear_and_continue;
714 }
715
716 /*
717 * Finally, make sure this is the System Shutdown RAID action.
718 * If not, ignore reply.
719 */
720 action_type = ddi_get16(mpt->m_acc_reply_frame_hdl,
721 &reply->FunctionDependent1);
722 if (action_type !=
723 MPI2_RAID_ACTION_SYSTEM_SHUTDOWN_INITIATED) {
724 goto clear_and_continue;
725 }
726 found_reply = TRUE;
727
728 clear_and_continue:
729 /*
730 * Clear the reply descriptor for re-use and increment index.
731 */
732 ddi_put64(mpt->m_acc_post_queue_hdl,
733 &((uint64_t *)(void *)rpqp->rpq_queue)[rpqp->rpq_index],
734 0xFFFFFFFFFFFFFFFF);
735 (void) ddi_dma_sync(mpt->m_dma_post_queue_hdl, 0, 0,
736 DDI_DMA_SYNC_FORDEV);
737
738 /*
739 * Update the reply index and keep looking for the
740 * reply if not found yet.
741 */
742 if (++rpqp->rpq_index == mpt->m_post_queue_depth) {
743 rpqp->rpq_index = 0;
744 }
745
746 ddi_put32(mpt->m_datap, &mpt->m_reg->ReplyPostHostIndex,
747 rpqp->rpq_index);
748 if (!found_reply) {
749 continue;
750 }
751
752 break;
753 }
754
755 /*
756 * clear the used slot as the last step.
757 */
758 slots->m_slot[MPTSAS_TM_SLOT(mpt)] = NULL;
759 }
760
761 int
762 mptsas_delete_volume(mptsas_t *mpt, uint16_t volid)
763 {
764 int config, i = 0, vol = (-1);
765
766 for (config = 0; (config < mpt->m_num_raid_configs) && (vol != i);
767 config++) {
|