Print this page
hg changesets 607a5b46a793..b706c96317c3
Fix ncpus for early boot config
Purge the ack to the interrupt before exiting mptsas_intr()
Changes from code review
Update tx waitq's code.
Create 2 threads, divide the workflow and deliver
to the hardware from the threads.
Added code to support using MSI-X interrupts across multiple
reply queues. Not tested with anything other than 3008 yet.
Changes to enable driver to compile.
Header paths, object lists, etc.


   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++) {