Print this page
9702 HBA drivers don't need the redundant devfs_clean step
Reviewed by: Dan Fields <dan.fields@nexenta.com>
Reviewed by: Rick McNeal <rick.mcneal@nexenta.com>
   1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   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  * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
  23  *






  24  * Fibre Channel SCSI ULP Mapping driver
  25  */
  26 
  27 #include <sys/scsi/scsi.h>
  28 #include <sys/types.h>
  29 #include <sys/varargs.h>
  30 #include <sys/devctl.h>
  31 #include <sys/thread.h>
  32 #include <sys/thread.h>
  33 #include <sys/open.h>
  34 #include <sys/file.h>
  35 #include <sys/sunndi.h>
  36 #include <sys/console.h>
  37 #include <sys/proc.h>
  38 #include <sys/time.h>
  39 #include <sys/utsname.h>
  40 #include <sys/scsi/impl/scsi_reset_notify.h>
  41 #include <sys/ndi_impldefs.h>
  42 #include <sys/byteorder.h>
  43 #include <sys/fs/dv_node.h>
  44 #include <sys/ctype.h>
  45 #include <sys/sunmdi.h>
  46 
  47 #include <sys/fibre-channel/fc.h>
  48 #include <sys/fibre-channel/impl/fc_ulpif.h>
  49 #include <sys/fibre-channel/ulp/fcpvar.h>
  50 
  51 /*
  52  * Discovery Process
  53  * =================
  54  *
  55  *    The discovery process is a major function of FCP.  In order to help
  56  * understand that function a flow diagram is given here.  This diagram
  57  * doesn't claim to cover all the cases and the events that can occur during
  58  * the discovery process nor the subtleties of the code.  The code paths shown
  59  * are simplified.  Its purpose is to help the reader (and potentially bug
  60  * fixer) have an overall view of the logic of the code.  For that reason the
  61  * diagram covers the simple case of the line coming up cleanly or of a new
  62  * port attaching to FCP the link being up.  The reader must keep in mind
  63  * that:


8134                                     "Can not ONLINE LUN; D_ID=%x, LUN=%x\n",
8135                                     plun->lun_tgt->tgt_d_id, plun->lun_num);
8136                         }
8137                 }
8138         }
8139 }
8140 
8141 
8142 /*
8143  * function to online/offline devices
8144  */
8145 static int
8146 fcp_trigger_lun(struct fcp_lun *plun, child_info_t *cip, int old_mpxio,
8147     int online, int lcount, int tcount, int flags)
8148 {
8149         int                     rval = NDI_FAILURE;
8150         int                     circ;
8151         child_info_t            *ccip;
8152         struct fcp_port         *pptr = plun->lun_tgt->tgt_port;
8153         int                     is_mpxio = pptr->port_mpxio;
8154         dev_info_t              *cdip, *pdip;
8155         char                    *devname;
8156 
8157         if ((old_mpxio != 0) && (plun->lun_mpxio != old_mpxio)) {
8158                 /*
8159                  * When this event gets serviced, lun_cip and lun_mpxio
8160                  * has changed, so it should be invalidated now.
8161                  */
8162                 FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
8163                     FCP_BUF_LEVEL_2, 0, "fcp_trigger_lun: lun_mpxio changed: "
8164                     "plun: %p, cip: %p, what:%d", plun, cip, online);
8165                 return (rval);
8166         }
8167 
8168         FCP_TRACE(fcp_logq, pptr->port_instbuf,
8169             fcp_trace, FCP_BUF_LEVEL_2, 0,
8170             "fcp_trigger_lun: plun=%p target=%x lun=%d cip=%p what=%x "
8171             "flags=%x mpxio=%x\n",
8172             plun, LUN_TGT->tgt_d_id, plun->lun_num, cip, online, flags,
8173             plun->lun_mpxio);
8174 
8175         /*
8176          * lun_mpxio needs checking here because we can end up in a race
8177          * condition where this task has been dispatched while lun_mpxio is
8178          * set, but an earlier FCP_ONLINE task for the same LUN tried to
8179          * enable MPXIO for the LUN, but was unable to, and hence cleared
8180          * the flag. We rely on the serialization of the tasks here. We return
8181          * NDI_SUCCESS so any callers continue without reporting spurious
8182          * errors, and the still think we're an MPXIO LUN.
8183          */
8184 
8185         if (online == FCP_MPXIO_PATH_CLEAR_BUSY ||
8186             online == FCP_MPXIO_PATH_SET_BUSY) {
8187                 if (plun->lun_mpxio) {
8188                         rval = fcp_update_mpxio_path(plun, cip, online);
8189                 } else {
8190                         rval = NDI_SUCCESS;
8191                 }
8192                 return (rval);
8193         }
8194 
8195         /*
8196          * Explicit devfs_clean() due to ndi_devi_offline() not
8197          * executing devfs_clean() if parent lock is held.
8198          */
8199         ASSERT(!servicing_interrupt());
8200         if (online == FCP_OFFLINE) {
8201                 if (plun->lun_mpxio == 0) {
8202                         if (plun->lun_cip == cip) {
8203                                 cdip = DIP(plun->lun_cip);
8204                         } else {
8205                                 cdip = DIP(cip);
8206                         }
8207                 } else if ((plun->lun_cip == cip) && plun->lun_cip) {
8208                         cdip = mdi_pi_get_client(PIP(plun->lun_cip));
8209                 } else if ((plun->lun_cip != cip) && cip) {
8210                         /*
8211                          * This means a DTYPE/GUID change, we shall get the
8212                          * dip of the old cip instead of the current lun_cip.
8213                          */
8214                         cdip = mdi_pi_get_client(PIP(cip));
8215                 }
8216                 if (cdip) {
8217                         if (i_ddi_devi_attached(cdip)) {
8218                                 pdip = ddi_get_parent(cdip);
8219                                 devname = kmem_alloc(MAXNAMELEN + 1, KM_SLEEP);
8220                                 ndi_devi_enter(pdip, &circ);
8221                                 (void) ddi_deviname(cdip, devname);
8222                                 /*
8223                                  * Release parent lock before calling
8224                                  * devfs_clean().
8225                                  */
8226                                 ndi_devi_exit(pdip, circ);
8227                                 (void) devfs_clean(pdip, devname + 1,
8228                                     DV_CLEAN_FORCE);
8229                                 kmem_free(devname, MAXNAMELEN + 1);
8230                         }
8231                 }
8232         }
8233 
8234         if (fc_ulp_busy_port(pptr->port_fp_handle) != 0) {
8235                 return (NDI_FAILURE);
8236         }
8237 
8238         if (is_mpxio) {
8239                 mdi_devi_enter(pptr->port_dip, &circ);
8240         } else {
8241                 ndi_devi_enter(pptr->port_dip, &circ);
8242         }
8243 
8244         mutex_enter(&pptr->port_mutex);
8245         mutex_enter(&plun->lun_mutex);
8246 
8247         if (online == FCP_ONLINE) {
8248                 ccip = fcp_get_cip(plun, cip, lcount, tcount);
8249                 if (ccip == NULL) {
8250                         goto fail;
8251                 }
8252         } else {
8253                 if (fcp_is_child_present(plun, cip) != FC_SUCCESS) {


13295         if (plun->lun_cip == NULL) {
13296                 FCP_TRACE(fcp_logq, pptr->port_instbuf,
13297                     fcp_trace, FCP_BUF_LEVEL_3, 0,
13298                     "fcp_offline_child: plun->lun_cip is NULL: "
13299                     "plun: %p lun state: %x num: %d target state: %x",
13300                     plun, plun->lun_state, plun->lun_num,
13301                     plun->lun_tgt->tgt_port->port_state);
13302                 return (NDI_FAILURE);
13303         }
13304 
13305         /*
13306          * We will use this value twice. Make a copy to be sure we use
13307          * the same value in both places.
13308          */
13309         lun_mpxio = plun->lun_mpxio;
13310 
13311         if (lun_mpxio == 0) {
13312                 cdip = DIP(cip);
13313                 mutex_exit(&plun->lun_mutex);
13314                 mutex_exit(&pptr->port_mutex);
13315                 rval = ndi_devi_offline(DIP(cip), flags);
13316                 if (rval != NDI_SUCCESS) {
13317                         FCP_TRACE(fcp_logq, pptr->port_instbuf,
13318                             fcp_trace, FCP_BUF_LEVEL_3, 0,
13319                             "fcp_offline_child: ndi_devi_offline failed "
13320                             "rval=%x cip=%p", rval, cip);
13321                 }
13322         } else {
13323                 cdip = mdi_pi_get_client(PIP(cip));
13324                 mutex_exit(&plun->lun_mutex);
13325                 mutex_exit(&pptr->port_mutex);
13326 
13327                 /*
13328                  * Exit phci to avoid deadlock with power management code
13329                  * during mdi_pi_offline
13330                  */
13331                 mdi_hold_path(PIP(cip));
13332                 mdi_devi_exit_phci(pptr->port_dip, *circ);
13333 
13334                 rval = mdi_pi_offline(PIP(cip), flags);
13335 


   1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   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 (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
  24  */
  25 
  26 /*
  27  * Copyright 2018 Nexenta Systems, Inc.
  28  */
  29 
  30 /*
  31  * Fibre Channel SCSI ULP Mapping driver
  32  */
  33 
  34 #include <sys/scsi/scsi.h>
  35 #include <sys/types.h>
  36 #include <sys/varargs.h>
  37 #include <sys/devctl.h>
  38 #include <sys/thread.h>
  39 #include <sys/thread.h>
  40 #include <sys/open.h>
  41 #include <sys/file.h>
  42 #include <sys/sunndi.h>
  43 #include <sys/console.h>
  44 #include <sys/proc.h>
  45 #include <sys/time.h>
  46 #include <sys/utsname.h>
  47 #include <sys/scsi/impl/scsi_reset_notify.h>
  48 #include <sys/ndi_impldefs.h>
  49 #include <sys/byteorder.h>

  50 #include <sys/ctype.h>
  51 #include <sys/sunmdi.h>
  52 
  53 #include <sys/fibre-channel/fc.h>
  54 #include <sys/fibre-channel/impl/fc_ulpif.h>
  55 #include <sys/fibre-channel/ulp/fcpvar.h>
  56 
  57 /*
  58  * Discovery Process
  59  * =================
  60  *
  61  *    The discovery process is a major function of FCP.  In order to help
  62  * understand that function a flow diagram is given here.  This diagram
  63  * doesn't claim to cover all the cases and the events that can occur during
  64  * the discovery process nor the subtleties of the code.  The code paths shown
  65  * are simplified.  Its purpose is to help the reader (and potentially bug
  66  * fixer) have an overall view of the logic of the code.  For that reason the
  67  * diagram covers the simple case of the line coming up cleanly or of a new
  68  * port attaching to FCP the link being up.  The reader must keep in mind
  69  * that:


8140                                     "Can not ONLINE LUN; D_ID=%x, LUN=%x\n",
8141                                     plun->lun_tgt->tgt_d_id, plun->lun_num);
8142                         }
8143                 }
8144         }
8145 }
8146 
8147 
8148 /*
8149  * function to online/offline devices
8150  */
8151 static int
8152 fcp_trigger_lun(struct fcp_lun *plun, child_info_t *cip, int old_mpxio,
8153     int online, int lcount, int tcount, int flags)
8154 {
8155         int                     rval = NDI_FAILURE;
8156         int                     circ;
8157         child_info_t            *ccip;
8158         struct fcp_port         *pptr = plun->lun_tgt->tgt_port;
8159         int                     is_mpxio = pptr->port_mpxio;


8160 
8161         if ((old_mpxio != 0) && (plun->lun_mpxio != old_mpxio)) {
8162                 /*
8163                  * When this event gets serviced, lun_cip and lun_mpxio
8164                  * has changed, so it should be invalidated now.
8165                  */
8166                 FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
8167                     FCP_BUF_LEVEL_2, 0, "fcp_trigger_lun: lun_mpxio changed: "
8168                     "plun: %p, cip: %p, what:%d", plun, cip, online);
8169                 return (rval);
8170         }
8171 
8172         FCP_TRACE(fcp_logq, pptr->port_instbuf,
8173             fcp_trace, FCP_BUF_LEVEL_2, 0,
8174             "fcp_trigger_lun: plun=%p target=%x lun=%d cip=%p what=%x "
8175             "flags=%x mpxio=%x\n",
8176             plun, LUN_TGT->tgt_d_id, plun->lun_num, cip, online, flags,
8177             plun->lun_mpxio);
8178 
8179         /*
8180          * lun_mpxio needs checking here because we can end up in a race
8181          * condition where this task has been dispatched while lun_mpxio is
8182          * set, but an earlier FCP_ONLINE task for the same LUN tried to
8183          * enable MPXIO for the LUN, but was unable to, and hence cleared
8184          * the flag. We rely on the serialization of the tasks here. We return
8185          * NDI_SUCCESS so any callers continue without reporting spurious
8186          * errors, and the still think we're an MPXIO LUN.
8187          */
8188 
8189         if (online == FCP_MPXIO_PATH_CLEAR_BUSY ||
8190             online == FCP_MPXIO_PATH_SET_BUSY) {
8191                 if (plun->lun_mpxio) {
8192                         rval = fcp_update_mpxio_path(plun, cip, online);
8193                 } else {
8194                         rval = NDI_SUCCESS;
8195                 }
8196                 return (rval);
8197         }
8198 







































8199         if (fc_ulp_busy_port(pptr->port_fp_handle) != 0) {
8200                 return (NDI_FAILURE);
8201         }
8202 
8203         if (is_mpxio) {
8204                 mdi_devi_enter(pptr->port_dip, &circ);
8205         } else {
8206                 ndi_devi_enter(pptr->port_dip, &circ);
8207         }
8208 
8209         mutex_enter(&pptr->port_mutex);
8210         mutex_enter(&plun->lun_mutex);
8211 
8212         if (online == FCP_ONLINE) {
8213                 ccip = fcp_get_cip(plun, cip, lcount, tcount);
8214                 if (ccip == NULL) {
8215                         goto fail;
8216                 }
8217         } else {
8218                 if (fcp_is_child_present(plun, cip) != FC_SUCCESS) {


13260         if (plun->lun_cip == NULL) {
13261                 FCP_TRACE(fcp_logq, pptr->port_instbuf,
13262                     fcp_trace, FCP_BUF_LEVEL_3, 0,
13263                     "fcp_offline_child: plun->lun_cip is NULL: "
13264                     "plun: %p lun state: %x num: %d target state: %x",
13265                     plun, plun->lun_state, plun->lun_num,
13266                     plun->lun_tgt->tgt_port->port_state);
13267                 return (NDI_FAILURE);
13268         }
13269 
13270         /*
13271          * We will use this value twice. Make a copy to be sure we use
13272          * the same value in both places.
13273          */
13274         lun_mpxio = plun->lun_mpxio;
13275 
13276         if (lun_mpxio == 0) {
13277                 cdip = DIP(cip);
13278                 mutex_exit(&plun->lun_mutex);
13279                 mutex_exit(&pptr->port_mutex);
13280                 rval = ndi_devi_offline(DIP(cip), NDI_DEVFS_CLEAN | flags);
13281                 if (rval != NDI_SUCCESS) {
13282                         FCP_TRACE(fcp_logq, pptr->port_instbuf,
13283                             fcp_trace, FCP_BUF_LEVEL_3, 0,
13284                             "fcp_offline_child: ndi_devi_offline failed "
13285                             "rval=%x cip=%p", rval, cip);
13286                 }
13287         } else {
13288                 cdip = mdi_pi_get_client(PIP(cip));
13289                 mutex_exit(&plun->lun_mutex);
13290                 mutex_exit(&pptr->port_mutex);
13291 
13292                 /*
13293                  * Exit phci to avoid deadlock with power management code
13294                  * during mdi_pi_offline
13295                  */
13296                 mdi_hold_path(PIP(cip));
13297                 mdi_devi_exit_phci(pptr->port_dip, *circ);
13298 
13299                 rval = mdi_pi_offline(PIP(cip), flags);
13300