27  *    used to endorse or promote products derived from this software without
  28  *    specific prior written permission.
  29  *
  30  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  31  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  32  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  33  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  34  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  35  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  36  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
  37  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
  38  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  39  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  40  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
  41  * DAMAGE.
  42  */
  43 
  44 /*
  45  * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
  46  * Copyright (c) 2011 Bayard G. Bell. All rights reserved.
  47  * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
  48  * Copyright 2015, 2017 Citrus IT Limited. All rights reserved.
  49  * Copyright 2015 Garrett D'Amore <garrett@damore.org>
  50  */
  51 
  52 #include <sys/types.h>
  53 #include <sys/param.h>
  54 #include <sys/file.h>
  55 #include <sys/errno.h>
  56 #include <sys/open.h>
  57 #include <sys/cred.h>
  58 #include <sys/modctl.h>
  59 #include <sys/conf.h>
  60 #include <sys/devops.h>
  61 #include <sys/cmn_err.h>
  62 #include <sys/kmem.h>
  63 #include <sys/stat.h>
  64 #include <sys/mkdev.h>
  65 #include <sys/pci.h>
  66 #include <sys/scsi/scsi.h>
  67 #include <sys/ddi.h>
  68 #include <sys/sunddi.h>
  69 #include <sys/atomic.h>
  70 #include <sys/signal.h>
  71 #include <sys/byteorder.h>
  72 #include <sys/sdt.h>
  73 #include <sys/fs/dv_node.h>       /* devfs_clean */
  74 
  75 #include "mr_sas.h"
  76 
  77 /*
  78  * FMA header files
  79  */
  80 #include <sys/ddifm.h>
  81 #include <sys/fm/protocol.h>
  82 #include <sys/fm/util.h>
  83 #include <sys/fm/io/ddi.h>
  84 
  85 /* Macros to help Skinny and stock 2108/MFI live together. */
  86 #define WR_IB_PICK_QPORT(addr, instance) \
  87         if ((instance)->skinny) { \
  88                 WR_IB_LOW_QPORT((addr), (instance)); \
  89                 WR_IB_HIGH_QPORT(0, (instance)); \
  90         } else { \
  91                 WR_IB_QPORT((addr), (instance)); \
  92         }
  93 
 
7724         mrevt->event = event;
7725         mrevt->wwn = wwn;
7726 
7727         if ((ddi_taskq_dispatch(instance->taskq,
7728             (void (*)(void *))mrsas_issue_evt_taskq, mrevt, DDI_NOSLEEP)) !=
7729             DDI_SUCCESS) {
7730                 con_log(CL_ANN1, (CE_NOTE,
7731                     "mr_sas: Event task failed for t%dl%d event = %d",
7732                     tgt, lun, event));
7733                 kmem_free(mrevt, sizeof (struct mrsas_eventinfo));
7734                 return (DDI_FAILURE);
7735         }
7736         DTRACE_PROBE3(service_evt, int, tgt, int, lun, int, event);
7737         return (DDI_SUCCESS);
7738 }
7739 
7740 static void
7741 mrsas_issue_evt_taskq(struct mrsas_eventinfo *mrevt)
7742 {
7743         struct mrsas_instance *instance = mrevt->instance;
7744         dev_info_t *dip, *pdip;
7745         int circ1 = 0;
7746         char *devname;
7747 
7748         con_log(CL_ANN1, (CE_NOTE, "mrsas_issue_evt_taskq: called for"
7749             " tgt %d lun %d event %d",
7750             mrevt->tgt, mrevt->lun, mrevt->event));
7751 
7752         if (mrevt->tgt < MRDRV_MAX_LD && mrevt->lun == 0) {
7753                 mutex_enter(&instance->config_dev_mtx);
7754                 dip = instance->mr_ld_list[mrevt->tgt].dip;
7755                 mutex_exit(&instance->config_dev_mtx);
7756         } else {
7757                 mutex_enter(&instance->config_dev_mtx);
7758                 dip = instance->mr_tbolt_pd_list[mrevt->tgt].dip;
7759                 mutex_exit(&instance->config_dev_mtx);
7760         }
7761 
7762 
7763         ndi_devi_enter(instance->dip, &circ1);
7764         switch (mrevt->event) {
7765         case MRSAS_EVT_CONFIG_TGT:
7766                 if (dip == NULL) {
7767 
7768                         if (mrevt->lun == 0) {
7769                                 (void) mrsas_config_ld(instance, mrevt->tgt,
7770                                     0, NULL);
7771                         } else if (instance->tbolt || instance->skinny) {
7772                                 (void) mrsas_tbolt_config_pd(instance,
7773                                     mrevt->tgt,
7774                                     1, NULL);
7775                         }
7776                         con_log(CL_ANN1, (CE_NOTE,
7777                             "mr_sas: EVT_CONFIG_TGT called:"
7778                             " for tgt %d lun %d event %d",
7779                             mrevt->tgt, mrevt->lun, mrevt->event));
7780 
7781                 } else {
7782                         con_log(CL_ANN1, (CE_NOTE,
7783                             "mr_sas: EVT_CONFIG_TGT dip != NULL:"
7784                             " for tgt %d lun %d event %d",
7785                             mrevt->tgt, mrevt->lun, mrevt->event));
7786                 }
7787                 break;
7788         case MRSAS_EVT_UNCONFIG_TGT:
7789                 if (dip) {
7790                         if (i_ddi_devi_attached(dip)) {
7791 
7792                                 pdip = ddi_get_parent(dip);
7793 
7794                                 devname = kmem_zalloc(MAXNAMELEN + 1, KM_SLEEP);
7795                                 (void) ddi_deviname(dip, devname);
7796 
7797                                 (void) devfs_clean(pdip, devname + 1,
7798                                     DV_CLEAN_FORCE);
7799                                 kmem_free(devname, MAXNAMELEN + 1);
7800                         }
7801                         (void) ndi_devi_offline(dip, NDI_DEVI_REMOVE);
7802                         con_log(CL_ANN1, (CE_NOTE,
7803                             "mr_sas: EVT_UNCONFIG_TGT called:"
7804                             " for tgt %d lun %d event %d",
7805                             mrevt->tgt, mrevt->lun, mrevt->event));
7806                 } else {
7807                         con_log(CL_ANN1, (CE_NOTE,
7808                             "mr_sas: EVT_UNCONFIG_TGT dip == NULL:"
7809                             " for tgt %d lun %d event %d",
7810                             mrevt->tgt, mrevt->lun, mrevt->event));
7811                 }
7812                 break;
7813         }
7814         kmem_free(mrevt, sizeof (struct mrsas_eventinfo));
7815         ndi_devi_exit(instance->dip, circ1);
7816 }
7817 
7818 
7819 int
7820 mrsas_mode_sense_build(struct scsi_pkt *pkt)
7821 {
 
 | 
 
 
  27  *    used to endorse or promote products derived from this software without
  28  *    specific prior written permission.
  29  *
  30  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  31  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  32  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  33  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  34  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  35  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  36  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
  37  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
  38  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  39  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  40  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
  41  * DAMAGE.
  42  */
  43 
  44 /*
  45  * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
  46  * Copyright (c) 2011 Bayard G. Bell. All rights reserved.
  47  * Copyright 2018 Nexenta Systems, Inc.
  48  * Copyright 2015, 2017 Citrus IT Limited. All rights reserved.
  49  * Copyright 2015 Garrett D'Amore <garrett@damore.org>
  50  */
  51 
  52 #include <sys/types.h>
  53 #include <sys/param.h>
  54 #include <sys/file.h>
  55 #include <sys/errno.h>
  56 #include <sys/open.h>
  57 #include <sys/cred.h>
  58 #include <sys/modctl.h>
  59 #include <sys/conf.h>
  60 #include <sys/devops.h>
  61 #include <sys/cmn_err.h>
  62 #include <sys/kmem.h>
  63 #include <sys/stat.h>
  64 #include <sys/mkdev.h>
  65 #include <sys/pci.h>
  66 #include <sys/scsi/scsi.h>
  67 #include <sys/ddi.h>
  68 #include <sys/sunddi.h>
  69 #include <sys/atomic.h>
  70 #include <sys/signal.h>
  71 #include <sys/byteorder.h>
  72 #include <sys/sdt.h>
  73 
  74 #include "mr_sas.h"
  75 
  76 /*
  77  * FMA header files
  78  */
  79 #include <sys/ddifm.h>
  80 #include <sys/fm/protocol.h>
  81 #include <sys/fm/util.h>
  82 #include <sys/fm/io/ddi.h>
  83 
  84 /* Macros to help Skinny and stock 2108/MFI live together. */
  85 #define WR_IB_PICK_QPORT(addr, instance) \
  86         if ((instance)->skinny) { \
  87                 WR_IB_LOW_QPORT((addr), (instance)); \
  88                 WR_IB_HIGH_QPORT(0, (instance)); \
  89         } else { \
  90                 WR_IB_QPORT((addr), (instance)); \
  91         }
  92 
 
7723         mrevt->event = event;
7724         mrevt->wwn = wwn;
7725 
7726         if ((ddi_taskq_dispatch(instance->taskq,
7727             (void (*)(void *))mrsas_issue_evt_taskq, mrevt, DDI_NOSLEEP)) !=
7728             DDI_SUCCESS) {
7729                 con_log(CL_ANN1, (CE_NOTE,
7730                     "mr_sas: Event task failed for t%dl%d event = %d",
7731                     tgt, lun, event));
7732                 kmem_free(mrevt, sizeof (struct mrsas_eventinfo));
7733                 return (DDI_FAILURE);
7734         }
7735         DTRACE_PROBE3(service_evt, int, tgt, int, lun, int, event);
7736         return (DDI_SUCCESS);
7737 }
7738 
7739 static void
7740 mrsas_issue_evt_taskq(struct mrsas_eventinfo *mrevt)
7741 {
7742         struct mrsas_instance *instance = mrevt->instance;
7743         dev_info_t *dip;
7744         int circ1 = 0;
7745 
7746         con_log(CL_ANN1, (CE_NOTE, "mrsas_issue_evt_taskq: called for"
7747             " tgt %d lun %d event %d",
7748             mrevt->tgt, mrevt->lun, mrevt->event));
7749 
7750         if (mrevt->tgt < MRDRV_MAX_LD && mrevt->lun == 0) {
7751                 mutex_enter(&instance->config_dev_mtx);
7752                 dip = instance->mr_ld_list[mrevt->tgt].dip;
7753                 mutex_exit(&instance->config_dev_mtx);
7754         } else {
7755                 mutex_enter(&instance->config_dev_mtx);
7756                 dip = instance->mr_tbolt_pd_list[mrevt->tgt].dip;
7757                 mutex_exit(&instance->config_dev_mtx);
7758         }
7759 
7760 
7761         ndi_devi_enter(instance->dip, &circ1);
7762         switch (mrevt->event) {
7763         case MRSAS_EVT_CONFIG_TGT:
7764                 if (dip == NULL) {
7765                         if (mrevt->lun == 0) {
7766                                 (void) mrsas_config_ld(instance, mrevt->tgt,
7767                                     0, NULL);
7768                         } else if (instance->tbolt || instance->skinny) {
7769                                 (void) mrsas_tbolt_config_pd(instance,
7770                                     mrevt->tgt,
7771                                     1, NULL);
7772                         }
7773                         con_log(CL_ANN1, (CE_NOTE,
7774                             "mr_sas: EVT_CONFIG_TGT called:"
7775                             " for tgt %d lun %d event %d",
7776                             mrevt->tgt, mrevt->lun, mrevt->event));
7777                 } else {
7778                         con_log(CL_ANN1, (CE_NOTE,
7779                             "mr_sas: EVT_CONFIG_TGT dip != NULL:"
7780                             " for tgt %d lun %d event %d",
7781                             mrevt->tgt, mrevt->lun, mrevt->event));
7782                 }
7783                 break;
7784         case MRSAS_EVT_UNCONFIG_TGT:
7785                 if (dip) {
7786                         (void) ndi_devi_offline(dip,
7787                             NDI_DEVFS_CLEAN | NDI_DEVI_REMOVE);
7788                         con_log(CL_ANN1, (CE_NOTE,
7789                             "mr_sas: EVT_UNCONFIG_TGT called:"
7790                             " for tgt %d lun %d event %d",
7791                             mrevt->tgt, mrevt->lun, mrevt->event));
7792                 } else {
7793                         con_log(CL_ANN1, (CE_NOTE,
7794                             "mr_sas: EVT_UNCONFIG_TGT dip == NULL:"
7795                             " for tgt %d lun %d event %d",
7796                             mrevt->tgt, mrevt->lun, mrevt->event));
7797                 }
7798                 break;
7799         }
7800         kmem_free(mrevt, sizeof (struct mrsas_eventinfo));
7801         ndi_devi_exit(instance->dip, circ1);
7802 }
7803 
7804 
7805 int
7806 mrsas_mode_sense_build(struct scsi_pkt *pkt)
7807 {
 
 |