17836SJohn.Forte@Sun.COM /*
27836SJohn.Forte@Sun.COM * CDDL HEADER START
37836SJohn.Forte@Sun.COM *
47836SJohn.Forte@Sun.COM * The contents of this file are subject to the terms of the
57836SJohn.Forte@Sun.COM * Common Development and Distribution License (the "License").
67836SJohn.Forte@Sun.COM * You may not use this file except in compliance with the License.
77836SJohn.Forte@Sun.COM *
87836SJohn.Forte@Sun.COM * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97836SJohn.Forte@Sun.COM * or http://www.opensolaris.org/os/licensing.
107836SJohn.Forte@Sun.COM * See the License for the specific language governing permissions
117836SJohn.Forte@Sun.COM * and limitations under the License.
127836SJohn.Forte@Sun.COM *
137836SJohn.Forte@Sun.COM * When distributing Covered Code, include this CDDL HEADER in each
147836SJohn.Forte@Sun.COM * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157836SJohn.Forte@Sun.COM * If applicable, add the following below this CDDL HEADER, with the
167836SJohn.Forte@Sun.COM * fields enclosed by brackets "[]" replaced with your own identifying
177836SJohn.Forte@Sun.COM * information: Portions Copyright [yyyy] [name of copyright owner]
187836SJohn.Forte@Sun.COM *
197836SJohn.Forte@Sun.COM * CDDL HEADER END
207836SJohn.Forte@Sun.COM */
217836SJohn.Forte@Sun.COM /*
22*9240SRaghuram.Prahlada@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
237836SJohn.Forte@Sun.COM * Use is subject to license terms.
247836SJohn.Forte@Sun.COM */
257836SJohn.Forte@Sun.COM
267836SJohn.Forte@Sun.COM
277836SJohn.Forte@Sun.COM #include "cfga_fp.h"
287836SJohn.Forte@Sun.COM
297836SJohn.Forte@Sun.COM /* define */
307836SJohn.Forte@Sun.COM #define ALL_APID_LUNS_UNUSABLE 0x10
317836SJohn.Forte@Sun.COM
327836SJohn.Forte@Sun.COM #define DEFAULT_LUN_COUNT 1024
337836SJohn.Forte@Sun.COM #define LUN_SIZE 8
347836SJohn.Forte@Sun.COM #define LUN_HEADER_SIZE 8
357836SJohn.Forte@Sun.COM #define DEFAULT_LUN_LENGTH DEFAULT_LUN_COUNT * \
367836SJohn.Forte@Sun.COM LUN_SIZE + \
377836SJohn.Forte@Sun.COM LUN_HEADER_SIZE
387836SJohn.Forte@Sun.COM
397836SJohn.Forte@Sun.COM /* Some forward declarations */
407836SJohn.Forte@Sun.COM static fpcfga_ret_t do_devctl_dev_create(apid_t *, char *, int,
417836SJohn.Forte@Sun.COM uchar_t, char **);
427836SJohn.Forte@Sun.COM static fpcfga_ret_t dev_rcm_online(apid_t *, int, cfga_flags_t, char **);
437836SJohn.Forte@Sun.COM static void dev_rcm_online_nonoperationalpath(apid_t *, cfga_flags_t, char **);
447836SJohn.Forte@Sun.COM static fpcfga_ret_t dev_rcm_offline(apid_t *, cfga_flags_t, char **);
457836SJohn.Forte@Sun.COM static fpcfga_ret_t dev_rcm_remove(apid_t *, cfga_flags_t, char **);
467836SJohn.Forte@Sun.COM static fpcfga_ret_t lun_unconf(char *, int, char *, char *, char **);
477836SJohn.Forte@Sun.COM static fpcfga_ret_t dev_unconf(apid_t *, char **, uchar_t *);
487836SJohn.Forte@Sun.COM static fpcfga_ret_t is_xport_phys_in_pathlist(apid_t *, char **);
497836SJohn.Forte@Sun.COM static void copy_pwwn_data_to_str(char *, const uchar_t *);
507836SJohn.Forte@Sun.COM static fpcfga_ret_t unconf_vhci_nodes(di_path_t, di_node_t, char *,
51*9240SRaghuram.Prahlada@Sun.COM char *, int, int *, int *, char **, cfga_flags_t);
527836SJohn.Forte@Sun.COM static fpcfga_ret_t unconf_non_vhci_nodes(di_node_t, char *, char *,
53*9240SRaghuram.Prahlada@Sun.COM int, int *, int *, char **, cfga_flags_t);
547836SJohn.Forte@Sun.COM static fpcfga_ret_t unconf_any_devinfo_nodes(apid_t *, cfga_flags_t, char **,
557836SJohn.Forte@Sun.COM int *, int *);
567836SJohn.Forte@Sun.COM static fpcfga_ret_t handle_devs(cfga_cmd_t, apid_t *, cfga_flags_t,
577836SJohn.Forte@Sun.COM char **, HBA_HANDLE, int, HBA_PORTATTRIBUTES);
587836SJohn.Forte@Sun.COM
597836SJohn.Forte@Sun.COM
607836SJohn.Forte@Sun.COM /*
617836SJohn.Forte@Sun.COM * This function initiates the creation of the new device node for a given
627836SJohn.Forte@Sun.COM * port WWN.
637836SJohn.Forte@Sun.COM * So, apidt->dyncomp CANNOT be NULL
647836SJohn.Forte@Sun.COM */
657836SJohn.Forte@Sun.COM static fpcfga_ret_t
do_devctl_dev_create(apid_t * apidt,char * dev_path,int pathlen,uchar_t dev_dtype,char ** errstring)667836SJohn.Forte@Sun.COM do_devctl_dev_create(apid_t *apidt, char *dev_path, int pathlen,
677836SJohn.Forte@Sun.COM uchar_t dev_dtype, char **errstring)
687836SJohn.Forte@Sun.COM {
697836SJohn.Forte@Sun.COM devctl_ddef_t ddef_hdl;
707836SJohn.Forte@Sun.COM devctl_hdl_t bus_hdl, dev_hdl;
717836SJohn.Forte@Sun.COM char *drvr_name = "dummy";
727836SJohn.Forte@Sun.COM la_wwn_t pwwn;
737836SJohn.Forte@Sun.COM
747836SJohn.Forte@Sun.COM *dev_path = NULL;
757836SJohn.Forte@Sun.COM if ((ddef_hdl = devctl_ddef_alloc(drvr_name, 0)) == NULL) {
767836SJohn.Forte@Sun.COM cfga_err(errstring, errno, ERRARG_DC_DDEF_ALLOC, drvr_name, 0);
777836SJohn.Forte@Sun.COM return (FPCFGA_LIB_ERR);
787836SJohn.Forte@Sun.COM }
797836SJohn.Forte@Sun.COM
807836SJohn.Forte@Sun.COM if (cvt_dyncomp_to_lawwn(apidt->dyncomp, &pwwn)) {
817836SJohn.Forte@Sun.COM devctl_ddef_free(ddef_hdl);
827836SJohn.Forte@Sun.COM cfga_err(errstring, 0, ERR_APID_INVAL, 0);
837836SJohn.Forte@Sun.COM return (FPCFGA_LIB_ERR);
847836SJohn.Forte@Sun.COM }
857836SJohn.Forte@Sun.COM
867836SJohn.Forte@Sun.COM if (devctl_ddef_byte_array(ddef_hdl, PORT_WWN_PROP, FC_WWN_SIZE,
877836SJohn.Forte@Sun.COM pwwn.raw_wwn) == -1) {
887836SJohn.Forte@Sun.COM devctl_ddef_free(ddef_hdl);
897836SJohn.Forte@Sun.COM cfga_err(errstring, errno, ERRARG_DC_BYTE_ARRAY,
907836SJohn.Forte@Sun.COM PORT_WWN_PROP, 0);
917836SJohn.Forte@Sun.COM return (FPCFGA_LIB_ERR);
927836SJohn.Forte@Sun.COM }
937836SJohn.Forte@Sun.COM
947836SJohn.Forte@Sun.COM if ((bus_hdl = devctl_bus_acquire(apidt->xport_phys, 0)) == NULL) {
957836SJohn.Forte@Sun.COM devctl_ddef_free(ddef_hdl);
967836SJohn.Forte@Sun.COM cfga_err(errstring, errno, ERRARG_DC_BUS_ACQUIRE,
977836SJohn.Forte@Sun.COM apidt->xport_phys, 0);
987836SJohn.Forte@Sun.COM return (FPCFGA_LIB_ERR);
997836SJohn.Forte@Sun.COM }
1007836SJohn.Forte@Sun.COM
1017836SJohn.Forte@Sun.COM /* Let driver handle creation of the new path */
1027836SJohn.Forte@Sun.COM if (devctl_bus_dev_create(bus_hdl, ddef_hdl, 0, &dev_hdl)) {
1037836SJohn.Forte@Sun.COM devctl_ddef_free(ddef_hdl);
1047836SJohn.Forte@Sun.COM devctl_release(bus_hdl);
1057836SJohn.Forte@Sun.COM if (dev_dtype == DTYPE_UNKNOWN) {
1067836SJohn.Forte@Sun.COM /*
1077836SJohn.Forte@Sun.COM * Unknown DTYPES are devices such as another system's
1087836SJohn.Forte@Sun.COM * FC HBA port. We have tried to configure it but
1097836SJohn.Forte@Sun.COM * have failed. Since devices with no device type
1107836SJohn.Forte@Sun.COM * or an unknown dtype cannot be configured, we will
1117836SJohn.Forte@Sun.COM * return an appropriate error message.
1127836SJohn.Forte@Sun.COM */
1137836SJohn.Forte@Sun.COM cfga_err(errstring, errno,
1147836SJohn.Forte@Sun.COM ERRARG_BUS_DEV_CREATE_UNKNOWN, apidt->dyncomp, 0);
1157836SJohn.Forte@Sun.COM } else {
1167836SJohn.Forte@Sun.COM cfga_err(errstring, errno, ERRARG_BUS_DEV_CREATE,
1177836SJohn.Forte@Sun.COM apidt->dyncomp, 0);
1187836SJohn.Forte@Sun.COM }
1197836SJohn.Forte@Sun.COM return (FPCFGA_LIB_ERR);
1207836SJohn.Forte@Sun.COM }
1217836SJohn.Forte@Sun.COM devctl_release(bus_hdl);
1227836SJohn.Forte@Sun.COM devctl_ddef_free(ddef_hdl);
1237836SJohn.Forte@Sun.COM
1247836SJohn.Forte@Sun.COM devctl_get_pathname(dev_hdl, dev_path, pathlen);
1257836SJohn.Forte@Sun.COM devctl_release(dev_hdl);
1267836SJohn.Forte@Sun.COM
1277836SJohn.Forte@Sun.COM return (FPCFGA_OK);
1287836SJohn.Forte@Sun.COM }
1297836SJohn.Forte@Sun.COM
1307836SJohn.Forte@Sun.COM /*
1317836SJohn.Forte@Sun.COM * Online, in RCM, all the LUNs for a particular device.
1327836SJohn.Forte@Sun.COM * Caller can specify the # of luns in the lunlist that have to be onlined
1337836SJohn.Forte@Sun.COM * by passing a count that is not -ve.
1347836SJohn.Forte@Sun.COM *
1357836SJohn.Forte@Sun.COM * INPUT :
1367836SJohn.Forte@Sun.COM * apidt - this is expected to have the list of luns for the device and so
1377836SJohn.Forte@Sun.COM * is assumed to be filled in prior to this call
1387836SJohn.Forte@Sun.COM * count - # of LUNs in the list that have to be onlined.
1397836SJohn.Forte@Sun.COM * errstring - If non-NULL, it will hold any error messages
1407836SJohn.Forte@Sun.COM *
1417836SJohn.Forte@Sun.COM * RETURNS :
1427836SJohn.Forte@Sun.COM * 0 on success
1437836SJohn.Forte@Sun.COM * non-zero otherwise
1447836SJohn.Forte@Sun.COM */
1457836SJohn.Forte@Sun.COM static fpcfga_ret_t
dev_rcm_online(apid_t * apidt,int count,cfga_flags_t flags,char ** errstring)1467836SJohn.Forte@Sun.COM dev_rcm_online(apid_t *apidt, int count, cfga_flags_t flags, char **errstring)
1477836SJohn.Forte@Sun.COM {
1487836SJohn.Forte@Sun.COM luninfo_list_t *lunlistp;
1497836SJohn.Forte@Sun.COM int i = 0, ret = 0;
1507836SJohn.Forte@Sun.COM fpcfga_ret_t retval = FPCFGA_OK;
1517836SJohn.Forte@Sun.COM
1527836SJohn.Forte@Sun.COM /* This check may be redundant, but safer this way */
1537836SJohn.Forte@Sun.COM if ((apidt->flags & FLAG_DISABLE_RCM) != 0) {
1547836SJohn.Forte@Sun.COM /* User has requested not to notify RCM framework */
1557836SJohn.Forte@Sun.COM return (FPCFGA_OK);
1567836SJohn.Forte@Sun.COM }
1577836SJohn.Forte@Sun.COM
1587836SJohn.Forte@Sun.COM lunlistp = apidt->lunlist;
1597836SJohn.Forte@Sun.COM
1607836SJohn.Forte@Sun.COM for (lunlistp = apidt->lunlist; lunlistp != NULL;
1617836SJohn.Forte@Sun.COM i++, lunlistp = lunlistp->next) {
1627836SJohn.Forte@Sun.COM if ((count >= 0) && (i >= count))
1637836SJohn.Forte@Sun.COM break;
1647836SJohn.Forte@Sun.COM if (fp_rcm_online(lunlistp->path, errstring, flags) !=
1657836SJohn.Forte@Sun.COM FPCFGA_OK) {
1667836SJohn.Forte@Sun.COM ret++;
1677836SJohn.Forte@Sun.COM }
1687836SJohn.Forte@Sun.COM }
1697836SJohn.Forte@Sun.COM
1707836SJohn.Forte@Sun.COM if (ret > 0)
1717836SJohn.Forte@Sun.COM retval = FPCFGA_LIB_ERR;
1727836SJohn.Forte@Sun.COM
1737836SJohn.Forte@Sun.COM return (retval);
1747836SJohn.Forte@Sun.COM }
1757836SJohn.Forte@Sun.COM
1767836SJohn.Forte@Sun.COM /*
1777836SJohn.Forte@Sun.COM * Online in RCM for devices which only have paths
1787836SJohn.Forte@Sun.COM * not in ONLINE/STANDBY state
1797836SJohn.Forte@Sun.COM */
1807836SJohn.Forte@Sun.COM void
dev_rcm_online_nonoperationalpath(apid_t * apidt,cfga_flags_t flags,char ** errstring)1817836SJohn.Forte@Sun.COM dev_rcm_online_nonoperationalpath(apid_t *apidt, cfga_flags_t flags,
1827836SJohn.Forte@Sun.COM char **errstring)
1837836SJohn.Forte@Sun.COM {
1847836SJohn.Forte@Sun.COM luninfo_list_t *lunlistp;
1857836SJohn.Forte@Sun.COM
1867836SJohn.Forte@Sun.COM if ((apidt->flags & FLAG_DISABLE_RCM) != 0) {
1877836SJohn.Forte@Sun.COM return;
1887836SJohn.Forte@Sun.COM }
1897836SJohn.Forte@Sun.COM
1907836SJohn.Forte@Sun.COM lunlistp = apidt->lunlist;
1917836SJohn.Forte@Sun.COM
1927836SJohn.Forte@Sun.COM for (lunlistp = apidt->lunlist; lunlistp != NULL;
1937836SJohn.Forte@Sun.COM lunlistp = lunlistp->next) {
1947836SJohn.Forte@Sun.COM if ((lunlistp->lun_flag & FLAG_SKIP_ONLINEOTHERS) != 0) {
1957836SJohn.Forte@Sun.COM continue;
1967836SJohn.Forte@Sun.COM }
1977836SJohn.Forte@Sun.COM (void) fp_rcm_online(lunlistp->path, errstring, flags);
1987836SJohn.Forte@Sun.COM }
1997836SJohn.Forte@Sun.COM }
2007836SJohn.Forte@Sun.COM
2017836SJohn.Forte@Sun.COM /*
2027836SJohn.Forte@Sun.COM * Offline, in RCM, all the LUNs for a particular device.
2037836SJohn.Forte@Sun.COM * This function should not be called for the MPXIO case.
2047836SJohn.Forte@Sun.COM *
2057836SJohn.Forte@Sun.COM * INPUT :
2067836SJohn.Forte@Sun.COM * apidt - this is expected to have the list of luns for the device and so
2077836SJohn.Forte@Sun.COM * is assumed to be filled in prior to this call
2087836SJohn.Forte@Sun.COM * errstring - If non-NULL, it will hold any error messages
2097836SJohn.Forte@Sun.COM *
2107836SJohn.Forte@Sun.COM * RETURNS :
2117836SJohn.Forte@Sun.COM * FPCFGA_OK on success
2127836SJohn.Forte@Sun.COM * error code otherwise
2137836SJohn.Forte@Sun.COM */
2147836SJohn.Forte@Sun.COM static fpcfga_ret_t
dev_rcm_offline(apid_t * apidt,cfga_flags_t flags,char ** errstring)2157836SJohn.Forte@Sun.COM dev_rcm_offline(apid_t *apidt, cfga_flags_t flags, char **errstring)
2167836SJohn.Forte@Sun.COM {
2177836SJohn.Forte@Sun.COM int count = 0;
2187836SJohn.Forte@Sun.COM luninfo_list_t *lunlistp;
2197836SJohn.Forte@Sun.COM
2207836SJohn.Forte@Sun.COM if ((apidt->flags & FLAG_DISABLE_RCM) != 0) {
2217836SJohn.Forte@Sun.COM /* User has requested not to notify RCM framework */
2227836SJohn.Forte@Sun.COM return (FPCFGA_OK);
2237836SJohn.Forte@Sun.COM }
2247836SJohn.Forte@Sun.COM
2257836SJohn.Forte@Sun.COM for (lunlistp = apidt->lunlist; lunlistp != NULL;
2267836SJohn.Forte@Sun.COM lunlistp = lunlistp->next) {
2277836SJohn.Forte@Sun.COM if ((lunlistp->lun_flag & FLAG_SKIP_RCMOFFLINE) != 0) {
2287836SJohn.Forte@Sun.COM continue;
2297836SJohn.Forte@Sun.COM }
2307836SJohn.Forte@Sun.COM if ((apidt->flags & FLAG_REMOVE_UNUSABLE_FCP_DEV) ==
2317836SJohn.Forte@Sun.COM FLAG_REMOVE_UNUSABLE_FCP_DEV) {
2327836SJohn.Forte@Sun.COM int ret = strncmp(lunlistp->path, SCSI_VHCI_ROOT,
2337836SJohn.Forte@Sun.COM strlen(SCSI_VHCI_ROOT));
2347836SJohn.Forte@Sun.COM
2357836SJohn.Forte@Sun.COM if (((ret == 0) &&
2367836SJohn.Forte@Sun.COM (lunlistp->node_state == DI_PATH_STATE_OFFLINE)) ||
2377836SJohn.Forte@Sun.COM ((ret != 0) &&
2387836SJohn.Forte@Sun.COM ((lunlistp->node_state & DI_DEVICE_OFFLINE) ==
2397836SJohn.Forte@Sun.COM DI_DEVICE_OFFLINE))) {
2407836SJohn.Forte@Sun.COM /* Offline the device through RCM */
2417836SJohn.Forte@Sun.COM if (fp_rcm_offline(lunlistp->path, errstring,
2427836SJohn.Forte@Sun.COM flags) != 0) {
2437836SJohn.Forte@Sun.COM /*
2447836SJohn.Forte@Sun.COM * Bring everything back online in
2457836SJohn.Forte@Sun.COM * rcm and return
2467836SJohn.Forte@Sun.COM */
2477836SJohn.Forte@Sun.COM (void) dev_rcm_online(apidt, count,
2487836SJohn.Forte@Sun.COM flags, NULL);
2497836SJohn.Forte@Sun.COM return (FPCFGA_LIB_ERR);
2507836SJohn.Forte@Sun.COM }
2517836SJohn.Forte@Sun.COM count++;
2527836SJohn.Forte@Sun.COM }
2537836SJohn.Forte@Sun.COM } else {
2547836SJohn.Forte@Sun.COM /* Offline the device through RCM */
2557836SJohn.Forte@Sun.COM if (fp_rcm_offline(lunlistp->path, errstring,
2567836SJohn.Forte@Sun.COM flags) != 0) {
2577836SJohn.Forte@Sun.COM /*
2587836SJohn.Forte@Sun.COM * Bring everything back online in
2597836SJohn.Forte@Sun.COM * rcm and return
2607836SJohn.Forte@Sun.COM */
2617836SJohn.Forte@Sun.COM (void) dev_rcm_online(apidt, count, flags,
2627836SJohn.Forte@Sun.COM NULL);
2637836SJohn.Forte@Sun.COM return (FPCFGA_LIB_ERR);
2647836SJohn.Forte@Sun.COM }
2657836SJohn.Forte@Sun.COM count++;
2667836SJohn.Forte@Sun.COM }
2677836SJohn.Forte@Sun.COM }
2687836SJohn.Forte@Sun.COM return (FPCFGA_OK);
2697836SJohn.Forte@Sun.COM }
2707836SJohn.Forte@Sun.COM
2717836SJohn.Forte@Sun.COM /*
2727836SJohn.Forte@Sun.COM * Remove, in RCM, all the LUNs for a particular device.
2737836SJohn.Forte@Sun.COM * This function should not be called for the MPXIO case.
2747836SJohn.Forte@Sun.COM *
2757836SJohn.Forte@Sun.COM * INPUT :
2767836SJohn.Forte@Sun.COM * apidt - this is expected to have the list of luns for the device and so
2777836SJohn.Forte@Sun.COM * is assumed to be filled in prior to this call
2787836SJohn.Forte@Sun.COM * errstring - If non-NULL, it will hold any error messages
2797836SJohn.Forte@Sun.COM *
2807836SJohn.Forte@Sun.COM * RETURNS :
2817836SJohn.Forte@Sun.COM * FPCFGA_OK on success
2827836SJohn.Forte@Sun.COM * error code otherwise
2837836SJohn.Forte@Sun.COM */
2847836SJohn.Forte@Sun.COM static fpcfga_ret_t
dev_rcm_remove(apid_t * apidt,cfga_flags_t flags,char ** errstring)2857836SJohn.Forte@Sun.COM dev_rcm_remove(apid_t *apidt, cfga_flags_t flags, char **errstring)
2867836SJohn.Forte@Sun.COM {
2877836SJohn.Forte@Sun.COM int count = 0;
2887836SJohn.Forte@Sun.COM luninfo_list_t *lunlistp;
2897836SJohn.Forte@Sun.COM
2907836SJohn.Forte@Sun.COM if ((apidt->flags & FLAG_DISABLE_RCM) != 0) {
2917836SJohn.Forte@Sun.COM /* User has requested not to notify RCM framework */
2927836SJohn.Forte@Sun.COM return (FPCFGA_OK);
2937836SJohn.Forte@Sun.COM }
2947836SJohn.Forte@Sun.COM
2957836SJohn.Forte@Sun.COM for (lunlistp = apidt->lunlist; lunlistp != NULL;
2967836SJohn.Forte@Sun.COM lunlistp = lunlistp->next) {
2977836SJohn.Forte@Sun.COM if ((lunlistp->lun_flag & FLAG_SKIP_RCMREMOVE) != 0)
2987836SJohn.Forte@Sun.COM continue;
2997836SJohn.Forte@Sun.COM if ((apidt->flags & FLAG_REMOVE_UNUSABLE_FCP_DEV) ==
3007836SJohn.Forte@Sun.COM FLAG_REMOVE_UNUSABLE_FCP_DEV) {
3017836SJohn.Forte@Sun.COM int ret = strncmp(lunlistp->path, SCSI_VHCI_ROOT,
3027836SJohn.Forte@Sun.COM strlen(SCSI_VHCI_ROOT));
3037836SJohn.Forte@Sun.COM
3047836SJohn.Forte@Sun.COM if (((ret == 0) &&
3057836SJohn.Forte@Sun.COM (lunlistp->node_state == DI_PATH_STATE_OFFLINE)) ||
3067836SJohn.Forte@Sun.COM ((ret != 0) &&
3077836SJohn.Forte@Sun.COM ((lunlistp->node_state & DI_DEVICE_OFFLINE) ==
3087836SJohn.Forte@Sun.COM DI_DEVICE_OFFLINE))) {
3097836SJohn.Forte@Sun.COM /* remove the device through RCM */
3107836SJohn.Forte@Sun.COM if (fp_rcm_remove(lunlistp->path, errstring,
3117836SJohn.Forte@Sun.COM flags) != 0) {
3127836SJohn.Forte@Sun.COM /*
3137836SJohn.Forte@Sun.COM * Bring everything back online in
3147836SJohn.Forte@Sun.COM * rcm and return
3157836SJohn.Forte@Sun.COM */
3167836SJohn.Forte@Sun.COM (void) dev_rcm_online(apidt, count,
3177836SJohn.Forte@Sun.COM flags, NULL);
3187836SJohn.Forte@Sun.COM return (FPCFGA_LIB_ERR);
3197836SJohn.Forte@Sun.COM }
3207836SJohn.Forte@Sun.COM count++;
3217836SJohn.Forte@Sun.COM }
3227836SJohn.Forte@Sun.COM } else {
3237836SJohn.Forte@Sun.COM /* remove the device through RCM */
3247836SJohn.Forte@Sun.COM if (fp_rcm_remove(lunlistp->path, errstring,
3257836SJohn.Forte@Sun.COM flags) != 0) {
3267836SJohn.Forte@Sun.COM /*
3277836SJohn.Forte@Sun.COM * Bring everything back online in rcm and
3287836SJohn.Forte@Sun.COM * return
3297836SJohn.Forte@Sun.COM */
3307836SJohn.Forte@Sun.COM (void) dev_rcm_online(apidt, count, flags,
3317836SJohn.Forte@Sun.COM NULL);
3327836SJohn.Forte@Sun.COM return (FPCFGA_LIB_ERR);
3337836SJohn.Forte@Sun.COM }
3347836SJohn.Forte@Sun.COM count++;
3357836SJohn.Forte@Sun.COM }
3367836SJohn.Forte@Sun.COM }
3377836SJohn.Forte@Sun.COM return (FPCFGA_OK);
3387836SJohn.Forte@Sun.COM }
3397836SJohn.Forte@Sun.COM
3407836SJohn.Forte@Sun.COM static fpcfga_ret_t
lun_unconf(char * path,int lunnum,char * xport_phys,char * dyncomp,char ** errstring)3417836SJohn.Forte@Sun.COM lun_unconf(char *path, int lunnum, char *xport_phys, char *dyncomp,
3427836SJohn.Forte@Sun.COM char **errstring)
3437836SJohn.Forte@Sun.COM {
3447836SJohn.Forte@Sun.COM devctl_hdl_t hdl;
3457836SJohn.Forte@Sun.COM char *ptr; /* To use as scratch/temp pointer */
3467836SJohn.Forte@Sun.COM char pathname[MAXPATHLEN];
3477836SJohn.Forte@Sun.COM
3487836SJohn.Forte@Sun.COM if (path == NULL)
3497836SJohn.Forte@Sun.COM return (FPCFGA_OK);
3507836SJohn.Forte@Sun.COM
3517836SJohn.Forte@Sun.COM if (strncmp(path, SCSI_VHCI_ROOT, strlen(SCSI_VHCI_ROOT)) == 0) {
3527836SJohn.Forte@Sun.COM /*
3537836SJohn.Forte@Sun.COM * We have an MPXIO managed device here.
3547836SJohn.Forte@Sun.COM * So, we have to concoct a path for the device.
3557836SJohn.Forte@Sun.COM *
3567836SJohn.Forte@Sun.COM * xport_phys looks like :
3577836SJohn.Forte@Sun.COM * /devices/pci@b,2000/pci@1/SUNW,qlc@5/fp@0,0:fc
3587836SJohn.Forte@Sun.COM */
3597836SJohn.Forte@Sun.COM (void) strlcpy(pathname, xport_phys, MAXPATHLEN);
3607836SJohn.Forte@Sun.COM if ((ptr = strrchr(pathname, ':')) != NULL) {
3617836SJohn.Forte@Sun.COM *ptr = '\0';
3627836SJohn.Forte@Sun.COM }
3637836SJohn.Forte@Sun.COM
3647836SJohn.Forte@Sun.COM /*
3657836SJohn.Forte@Sun.COM * Get pointer to driver name from VHCI path
3667836SJohn.Forte@Sun.COM * So, if lunlistp->path is
3677836SJohn.Forte@Sun.COM * /devices/scsi_vhci/ssd@g220000203707a417,
3687836SJohn.Forte@Sun.COM * we need a pointer to the last '/'
3697836SJohn.Forte@Sun.COM *
3707836SJohn.Forte@Sun.COM * Assumption:
3717836SJohn.Forte@Sun.COM * With MPXIO there will be only one entry per lun
3727836SJohn.Forte@Sun.COM * So, there will only be one entry in the linked list
3737836SJohn.Forte@Sun.COM * apidt->lunlist
3747836SJohn.Forte@Sun.COM */
3757836SJohn.Forte@Sun.COM if ((ptr = strrchr(path, '/')) == NULL) {
3767836SJohn.Forte@Sun.COM /* This shouldn't happen, but anyways ... */
3777836SJohn.Forte@Sun.COM cfga_err(errstring, 0, ERRARG_INVALID_PATH, path, 0);
3787836SJohn.Forte@Sun.COM return (FPCFGA_LIB_ERR);
3797836SJohn.Forte@Sun.COM }
3807836SJohn.Forte@Sun.COM
3817836SJohn.Forte@Sun.COM /*
3827836SJohn.Forte@Sun.COM * Make pathname to look something like :
3837836SJohn.Forte@Sun.COM * /devices/pci@x,xxxx/pci@x/SUNW,qlc@x/fp@x,x/ssd@w...
3847836SJohn.Forte@Sun.COM */
3857836SJohn.Forte@Sun.COM strcat(pathname, ptr);
3867836SJohn.Forte@Sun.COM
3877836SJohn.Forte@Sun.COM /*
3887836SJohn.Forte@Sun.COM * apidt_create() will make sure that lunlist->path
3897836SJohn.Forte@Sun.COM * has a "@<something>" at the end even if the driver
3907836SJohn.Forte@Sun.COM * state is "detached"
3917836SJohn.Forte@Sun.COM */
3927836SJohn.Forte@Sun.COM if ((ptr = strrchr(pathname, '@')) == NULL) {
3937836SJohn.Forte@Sun.COM /* This shouldn't happen, but anyways ... */
3947836SJohn.Forte@Sun.COM cfga_err(errstring, 0, ERRARG_INVALID_PATH,
3957836SJohn.Forte@Sun.COM pathname, 0);
3967836SJohn.Forte@Sun.COM return (FPCFGA_LIB_ERR);
3977836SJohn.Forte@Sun.COM }
3987836SJohn.Forte@Sun.COM *ptr = '\0';
3997836SJohn.Forte@Sun.COM
4007836SJohn.Forte@Sun.COM /* Now, concoct the path */
4017836SJohn.Forte@Sun.COM sprintf(&pathname[strlen(pathname)], "@w%s,%x",
4027836SJohn.Forte@Sun.COM dyncomp, lunnum);
4037836SJohn.Forte@Sun.COM ptr = pathname;
4047836SJohn.Forte@Sun.COM } else {
4057836SJohn.Forte@Sun.COM /*
4067836SJohn.Forte@Sun.COM * non-MPXIO path, use the path that is passed in
4077836SJohn.Forte@Sun.COM */
4087836SJohn.Forte@Sun.COM ptr = path;
4097836SJohn.Forte@Sun.COM }
4107836SJohn.Forte@Sun.COM
4117836SJohn.Forte@Sun.COM if ((hdl = devctl_device_acquire(ptr, 0)) == NULL) {
4127836SJohn.Forte@Sun.COM cfga_err(errstring, errno, ERRARG_DEV_ACQUIRE, ptr, 0);
4137836SJohn.Forte@Sun.COM return (FPCFGA_LIB_ERR);
4147836SJohn.Forte@Sun.COM }
4157836SJohn.Forte@Sun.COM
4167836SJohn.Forte@Sun.COM if (devctl_device_remove(hdl) != 0) {
4177836SJohn.Forte@Sun.COM devctl_release(hdl);
4187836SJohn.Forte@Sun.COM cfga_err(errstring, errno, ERRARG_DEV_REMOVE, ptr, 0);
4197836SJohn.Forte@Sun.COM return (FPCFGA_LIB_ERR);
4207836SJohn.Forte@Sun.COM }
4217836SJohn.Forte@Sun.COM devctl_release(hdl);
4227836SJohn.Forte@Sun.COM
4237836SJohn.Forte@Sun.COM return (FPCFGA_OK);
4247836SJohn.Forte@Sun.COM }
4257836SJohn.Forte@Sun.COM
4267836SJohn.Forte@Sun.COM static fpcfga_ret_t
dev_unconf(apid_t * apidt,char ** errstring,uchar_t * flag)4277836SJohn.Forte@Sun.COM dev_unconf(apid_t *apidt, char **errstring, uchar_t *flag)
4287836SJohn.Forte@Sun.COM {
4297836SJohn.Forte@Sun.COM luninfo_list_t *lunlistp;
4307836SJohn.Forte@Sun.COM fpcfga_ret_t ret = FPCFGA_OK;
4317836SJohn.Forte@Sun.COM int lun_cnt = 0, unusable_lun_cnt = 0;
4327836SJohn.Forte@Sun.COM
4337836SJohn.Forte@Sun.COM for (lunlistp = apidt->lunlist; lunlistp != NULL;
4347836SJohn.Forte@Sun.COM lunlistp = lunlistp->next) {
4357836SJohn.Forte@Sun.COM lun_cnt++;
4367836SJohn.Forte@Sun.COM /*
4377836SJohn.Forte@Sun.COM * Unconfigure each LUN.
4387836SJohn.Forte@Sun.COM * Note that for MPXIO devices, lunlistp->path will be a
4397836SJohn.Forte@Sun.COM * vHCI path
4407836SJohn.Forte@Sun.COM */
4417836SJohn.Forte@Sun.COM if ((apidt->flags & FLAG_REMOVE_UNUSABLE_FCP_DEV) ==
4427836SJohn.Forte@Sun.COM FLAG_REMOVE_UNUSABLE_FCP_DEV) {
4437836SJohn.Forte@Sun.COM if (strncmp(lunlistp->path, SCSI_VHCI_ROOT,
4447836SJohn.Forte@Sun.COM strlen(SCSI_VHCI_ROOT)) == 0) {
4457836SJohn.Forte@Sun.COM if (lunlistp->node_state ==
4467836SJohn.Forte@Sun.COM DI_PATH_STATE_OFFLINE) {
4477836SJohn.Forte@Sun.COM unusable_lun_cnt++;
4487836SJohn.Forte@Sun.COM if ((ret = lun_unconf(lunlistp->path,
4497836SJohn.Forte@Sun.COM lunlistp->lunnum, apidt->xport_phys,
4507836SJohn.Forte@Sun.COM apidt->dyncomp, errstring)) != FPCFGA_OK) {
4517836SJohn.Forte@Sun.COM return (ret);
4527836SJohn.Forte@Sun.COM }
4537836SJohn.Forte@Sun.COM }
4547836SJohn.Forte@Sun.COM } else {
4557836SJohn.Forte@Sun.COM if ((lunlistp->node_state & DI_DEVICE_OFFLINE) ==
4567836SJohn.Forte@Sun.COM DI_DEVICE_OFFLINE) {
4577836SJohn.Forte@Sun.COM unusable_lun_cnt++;
4587836SJohn.Forte@Sun.COM if ((ret = lun_unconf(lunlistp->path,
4597836SJohn.Forte@Sun.COM lunlistp->lunnum, apidt->xport_phys,
4607836SJohn.Forte@Sun.COM apidt->dyncomp, errstring)) != FPCFGA_OK) {
4617836SJohn.Forte@Sun.COM return (ret);
4627836SJohn.Forte@Sun.COM }
4637836SJohn.Forte@Sun.COM }
4647836SJohn.Forte@Sun.COM }
4657836SJohn.Forte@Sun.COM } else {
4667836SJohn.Forte@Sun.COM /*
4677836SJohn.Forte@Sun.COM * Unconfigure each LUN.
4687836SJohn.Forte@Sun.COM * Note that for MPXIO devices, lunlistp->path will be a
4697836SJohn.Forte@Sun.COM * vHCI path
4707836SJohn.Forte@Sun.COM */
4717836SJohn.Forte@Sun.COM if ((ret = lun_unconf(lunlistp->path, lunlistp->lunnum,
4727836SJohn.Forte@Sun.COM apidt->xport_phys, apidt->dyncomp,
4737836SJohn.Forte@Sun.COM errstring)) != FPCFGA_OK) {
4747836SJohn.Forte@Sun.COM return (ret);
4757836SJohn.Forte@Sun.COM }
4767836SJohn.Forte@Sun.COM }
4777836SJohn.Forte@Sun.COM }
4787836SJohn.Forte@Sun.COM
4797836SJohn.Forte@Sun.COM if ((apidt->flags & FLAG_REMOVE_UNUSABLE_FCP_DEV) ==
4807836SJohn.Forte@Sun.COM FLAG_REMOVE_UNUSABLE_FCP_DEV) {
4817836SJohn.Forte@Sun.COM /*
4827836SJohn.Forte@Sun.COM * when all luns are unconfigured
4837836SJohn.Forte@Sun.COM * indicate to remove repository entry.
4847836SJohn.Forte@Sun.COM */
4857836SJohn.Forte@Sun.COM if (lun_cnt == unusable_lun_cnt) {
4867836SJohn.Forte@Sun.COM *flag = ALL_APID_LUNS_UNUSABLE;
4877836SJohn.Forte@Sun.COM }
4887836SJohn.Forte@Sun.COM }
4897836SJohn.Forte@Sun.COM
4907836SJohn.Forte@Sun.COM return (ret);
4917836SJohn.Forte@Sun.COM }
4927836SJohn.Forte@Sun.COM
4937836SJohn.Forte@Sun.COM /*
4947836SJohn.Forte@Sun.COM * Check if the given physical path (the xport_phys) is part of the
4957836SJohn.Forte@Sun.COM * pHCI list and if the RCM should be done for a particular pHCI.
4967836SJohn.Forte@Sun.COM * Skip non-MPxIO dev node if any.
4977836SJohn.Forte@Sun.COM */
4987836SJohn.Forte@Sun.COM static fpcfga_ret_t
is_xport_phys_in_pathlist(apid_t * apidt,char ** errstring)4997836SJohn.Forte@Sun.COM is_xport_phys_in_pathlist(apid_t *apidt, char **errstring)
5007836SJohn.Forte@Sun.COM {
5017836SJohn.Forte@Sun.COM di_node_t root, vhci, node, phci;
5027836SJohn.Forte@Sun.COM di_path_t path = DI_PATH_NIL;
5037836SJohn.Forte@Sun.COM int num_active_paths, found = 0;
5047836SJohn.Forte@Sun.COM char *vhci_path_ptr, *pathname_ptr, pathname[MAXPATHLEN];
5057836SJohn.Forte@Sun.COM char *phci_path, *node_path;
5067836SJohn.Forte@Sun.COM char phci_addr[MAXPATHLEN];
5077836SJohn.Forte@Sun.COM char *xport_phys, *vhci_path, *dyncomp;
5087836SJohn.Forte@Sun.COM luninfo_list_t *lunlistp, *temp;
5097836SJohn.Forte@Sun.COM int non_operational_path_count;
5107836SJohn.Forte@Sun.COM
5117836SJohn.Forte@Sun.COM /* a safety check */
5127836SJohn.Forte@Sun.COM if ((apidt->dyncomp == NULL) || (*apidt->dyncomp == '\0')) {
5137836SJohn.Forte@Sun.COM return (FPCFGA_LIB_ERR);
5147836SJohn.Forte@Sun.COM }
5157836SJohn.Forte@Sun.COM
5167836SJohn.Forte@Sun.COM xport_phys = apidt->xport_phys;
5177836SJohn.Forte@Sun.COM dyncomp = apidt->dyncomp;
5187836SJohn.Forte@Sun.COM
5197836SJohn.Forte@Sun.COM lunlistp = apidt->lunlist;
5207836SJohn.Forte@Sun.COM for (lunlistp = apidt->lunlist; lunlistp != NULL;
5217836SJohn.Forte@Sun.COM lunlistp = lunlistp->next) {
5227836SJohn.Forte@Sun.COM
5237836SJohn.Forte@Sun.COM if (strncmp(lunlistp->path, SCSI_VHCI_ROOT,
5247836SJohn.Forte@Sun.COM strlen(SCSI_VHCI_ROOT)) != 0) {
5257836SJohn.Forte@Sun.COM lunlistp->lun_flag |= FLAG_SKIP_ONLINEOTHERS;
5267836SJohn.Forte@Sun.COM continue;
5277836SJohn.Forte@Sun.COM }
5287836SJohn.Forte@Sun.COM
5297836SJohn.Forte@Sun.COM vhci_path = lunlistp->path;
5307836SJohn.Forte@Sun.COM
5317836SJohn.Forte@Sun.COM num_active_paths = 0; /* # of paths in ONLINE/STANDBY */
5327836SJohn.Forte@Sun.COM non_operational_path_count = 0;
5337836SJohn.Forte@Sun.COM
5347836SJohn.Forte@Sun.COM if (xport_phys == NULL || vhci_path == NULL) {
5357836SJohn.Forte@Sun.COM cfga_err(errstring, 0, ERRARG_XPORT_NOT_IN_PHCI_LIST,
5367836SJohn.Forte@Sun.COM xport_phys, 0);
5377836SJohn.Forte@Sun.COM return (FPCFGA_LIB_ERR);
5387836SJohn.Forte@Sun.COM }
5397836SJohn.Forte@Sun.COM
5407836SJohn.Forte@Sun.COM (void) strlcpy(pathname, xport_phys, MAXPATHLEN);
5417836SJohn.Forte@Sun.COM if ((pathname_ptr = strrchr(pathname, ':')) != NULL) {
5427836SJohn.Forte@Sun.COM *pathname_ptr = '\0';
5437836SJohn.Forte@Sun.COM }
5447836SJohn.Forte@Sun.COM /* strip off the /devices/from the path */
5457836SJohn.Forte@Sun.COM pathname_ptr = pathname + strlen(DEVICES_DIR);
5467836SJohn.Forte@Sun.COM
5477836SJohn.Forte@Sun.COM root = di_init("/", DINFOCPYALL|DINFOPATH);
5487836SJohn.Forte@Sun.COM
5497836SJohn.Forte@Sun.COM if (root == DI_NODE_NIL) {
5507836SJohn.Forte@Sun.COM return (FPCFGA_LIB_ERR);
5517836SJohn.Forte@Sun.COM }
5527836SJohn.Forte@Sun.COM
5537836SJohn.Forte@Sun.COM vhci_path_ptr = vhci_path + strlen(DEVICES_DIR);
5547836SJohn.Forte@Sun.COM if ((vhci = di_drv_first_node(SCSI_VHCI_DRVR, root)) ==
5557836SJohn.Forte@Sun.COM DI_NODE_NIL) {
5567836SJohn.Forte@Sun.COM return (FPCFGA_LIB_ERR);
5577836SJohn.Forte@Sun.COM }
5587836SJohn.Forte@Sun.COM found = 0;
5597836SJohn.Forte@Sun.COM for (node = di_child_node(vhci); node != DI_NODE_NIL;
5607836SJohn.Forte@Sun.COM node = di_sibling_node(node)) {
5617836SJohn.Forte@Sun.COM if ((node_path = di_devfs_path(node)) != NULL) {
5627836SJohn.Forte@Sun.COM if (strncmp(vhci_path_ptr, node_path,
5637836SJohn.Forte@Sun.COM strlen(node_path)) != 0) {
5647836SJohn.Forte@Sun.COM di_devfs_path_free(node_path);
5657836SJohn.Forte@Sun.COM } else {
5667836SJohn.Forte@Sun.COM found = 1;
5677836SJohn.Forte@Sun.COM break;
5687836SJohn.Forte@Sun.COM }
5697836SJohn.Forte@Sun.COM }
5707836SJohn.Forte@Sun.COM }
5717836SJohn.Forte@Sun.COM if (found == 0) {
5727836SJohn.Forte@Sun.COM cfga_err(errstring, 0, ERRARG_XPORT_NOT_IN_PHCI_LIST,
5737836SJohn.Forte@Sun.COM xport_phys, 0);
5747836SJohn.Forte@Sun.COM di_fini(root);
5757836SJohn.Forte@Sun.COM return (FPCFGA_LIB_ERR);
5767836SJohn.Forte@Sun.COM }
5777836SJohn.Forte@Sun.COM /* found vhci_path we are looking for */
5787836SJohn.Forte@Sun.COM di_devfs_path_free(node_path);
5797836SJohn.Forte@Sun.COM found = 0;
5807836SJohn.Forte@Sun.COM for (path = di_path_next_phci(node, DI_PATH_NIL);
5817836SJohn.Forte@Sun.COM path != DI_PATH_NIL;
5827836SJohn.Forte@Sun.COM path = di_path_next_phci(node, path)) {
5837836SJohn.Forte@Sun.COM if ((phci = di_path_phci_node(path)) == DI_NODE_NIL) {
5847836SJohn.Forte@Sun.COM cfga_err(errstring, 0,
5857836SJohn.Forte@Sun.COM ERRARG_XPORT_NOT_IN_PHCI_LIST,
5867836SJohn.Forte@Sun.COM xport_phys, 0);
5877836SJohn.Forte@Sun.COM di_fini(root);
5887836SJohn.Forte@Sun.COM return (FPCFGA_LIB_ERR);
5897836SJohn.Forte@Sun.COM }
5907836SJohn.Forte@Sun.COM if ((phci_path = di_devfs_path(phci)) == NULL) {
5917836SJohn.Forte@Sun.COM cfga_err(errstring, 0,
5927836SJohn.Forte@Sun.COM ERRARG_XPORT_NOT_IN_PHCI_LIST,
5937836SJohn.Forte@Sun.COM xport_phys, 0);
5947836SJohn.Forte@Sun.COM di_fini(root);
5957836SJohn.Forte@Sun.COM return (FPCFGA_LIB_ERR);
5967836SJohn.Forte@Sun.COM }
5977836SJohn.Forte@Sun.COM (void) di_path_addr(path, (char *)phci_addr);
5987836SJohn.Forte@Sun.COM if ((phci_addr == NULL) || (*phci_addr == '\0')) {
5997836SJohn.Forte@Sun.COM cfga_err(errstring, 0,
6007836SJohn.Forte@Sun.COM ERRARG_XPORT_NOT_IN_PHCI_LIST,
6017836SJohn.Forte@Sun.COM xport_phys, 0);
6027836SJohn.Forte@Sun.COM di_devfs_path_free(phci_path);
6037836SJohn.Forte@Sun.COM di_fini(root);
6047836SJohn.Forte@Sun.COM return (FPCFGA_LIB_ERR);
6057836SJohn.Forte@Sun.COM }
6067836SJohn.Forte@Sun.COM /*
6077836SJohn.Forte@Sun.COM * Check if the phci path has the same
6087836SJohn.Forte@Sun.COM * xport addr and the target addr with current lun
6097836SJohn.Forte@Sun.COM */
6107836SJohn.Forte@Sun.COM if ((strncmp(phci_path, pathname_ptr,
6117836SJohn.Forte@Sun.COM strlen(pathname_ptr)) == 0) &&
6127836SJohn.Forte@Sun.COM (strstr(phci_addr, dyncomp) != NULL)) {
6137836SJohn.Forte@Sun.COM /* SUCCESS Found xport_phys */
6147836SJohn.Forte@Sun.COM found = 1;
6157836SJohn.Forte@Sun.COM } else if ((di_path_state(path) ==
6167836SJohn.Forte@Sun.COM DI_PATH_STATE_ONLINE) ||
6177836SJohn.Forte@Sun.COM (di_path_state(path) == DI_PATH_STATE_STANDBY)) {
6187836SJohn.Forte@Sun.COM num_active_paths++;
6197836SJohn.Forte@Sun.COM } else {
6207836SJohn.Forte@Sun.COM /*
6217836SJohn.Forte@Sun.COM * We have another path not in ONLINE/STANDBY
6227836SJohn.Forte@Sun.COM * state now, so should do a RCM online after
6237836SJohn.Forte@Sun.COM * the unconfiguration of current path.
6247836SJohn.Forte@Sun.COM */
6257836SJohn.Forte@Sun.COM non_operational_path_count++;
6267836SJohn.Forte@Sun.COM }
6277836SJohn.Forte@Sun.COM di_devfs_path_free(phci_path);
6287836SJohn.Forte@Sun.COM }
6297836SJohn.Forte@Sun.COM di_fini(root);
6307836SJohn.Forte@Sun.COM if (found == 1) {
6317836SJohn.Forte@Sun.COM if (num_active_paths != 0) {
6327836SJohn.Forte@Sun.COM /*
6337836SJohn.Forte@Sun.COM * There are other ONLINE/STANDBY paths,
6347836SJohn.Forte@Sun.COM * so no need to do the RCM
6357836SJohn.Forte@Sun.COM */
6367836SJohn.Forte@Sun.COM lunlistp->lun_flag |= FLAG_SKIP_RCMREMOVE;
6377836SJohn.Forte@Sun.COM lunlistp->lun_flag |= FLAG_SKIP_RCMOFFLINE;
6387836SJohn.Forte@Sun.COM }
6397836SJohn.Forte@Sun.COM if (non_operational_path_count == 0) {
6407836SJohn.Forte@Sun.COM lunlistp->lun_flag |= FLAG_SKIP_ONLINEOTHERS;
6417836SJohn.Forte@Sun.COM }
6427836SJohn.Forte@Sun.COM } else {
6437836SJohn.Forte@Sun.COM /*
6447836SJohn.Forte@Sun.COM * Fail all operations here
6457836SJohn.Forte@Sun.COM */
6467836SJohn.Forte@Sun.COM cfga_err(errstring, 0, ERRARG_XPORT_NOT_IN_PHCI_LIST,
6477836SJohn.Forte@Sun.COM xport_phys, 0);
6487836SJohn.Forte@Sun.COM return (FPCFGA_APID_NOEXIST);
6497836SJohn.Forte@Sun.COM }
6507836SJohn.Forte@Sun.COM }
6517836SJohn.Forte@Sun.COM
6527836SJohn.Forte@Sun.COM /* Mark duplicated paths for same vhci in the list */
6537836SJohn.Forte@Sun.COM for (lunlistp = apidt->lunlist; lunlistp != NULL;
6547836SJohn.Forte@Sun.COM lunlistp = lunlistp->next) {
6557836SJohn.Forte@Sun.COM if (strncmp(lunlistp->path, SCSI_VHCI_ROOT,
6567836SJohn.Forte@Sun.COM strlen(SCSI_VHCI_ROOT)) != 0) {
6577836SJohn.Forte@Sun.COM continue;
6587836SJohn.Forte@Sun.COM }
6597836SJohn.Forte@Sun.COM for (temp = lunlistp->next; temp != NULL;
6607836SJohn.Forte@Sun.COM temp = temp->next) {
6617836SJohn.Forte@Sun.COM if (strcmp(lunlistp->path, temp->path) == 0) {
6627836SJohn.Forte@Sun.COM /*
6637836SJohn.Forte@Sun.COM * don't do RCM for dup
6647836SJohn.Forte@Sun.COM */
6657836SJohn.Forte@Sun.COM lunlistp->lun_flag |= FLAG_SKIP_RCMREMOVE;
6667836SJohn.Forte@Sun.COM lunlistp->lun_flag |= FLAG_SKIP_RCMOFFLINE;
6677836SJohn.Forte@Sun.COM lunlistp->lun_flag |= FLAG_SKIP_ONLINEOTHERS;
6687836SJohn.Forte@Sun.COM }
6697836SJohn.Forte@Sun.COM }
6707836SJohn.Forte@Sun.COM }
6717836SJohn.Forte@Sun.COM return (FPCFGA_OK);
6727836SJohn.Forte@Sun.COM }
6737836SJohn.Forte@Sun.COM /*
6747836SJohn.Forte@Sun.COM * apidt->dyncomp has to be non-NULL by the time this routine is called
6757836SJohn.Forte@Sun.COM */
6767836SJohn.Forte@Sun.COM fpcfga_ret_t
dev_change_state(cfga_cmd_t state_change_cmd,apid_t * apidt,la_wwn_t * pwwn,cfga_flags_t flags,char ** errstring,HBA_HANDLE handle,HBA_PORTATTRIBUTES portAttrs)6777836SJohn.Forte@Sun.COM dev_change_state(cfga_cmd_t state_change_cmd, apid_t *apidt, la_wwn_t *pwwn,
6787836SJohn.Forte@Sun.COM cfga_flags_t flags, char **errstring, HBA_HANDLE handle,
6797836SJohn.Forte@Sun.COM HBA_PORTATTRIBUTES portAttrs)
6807836SJohn.Forte@Sun.COM {
6817836SJohn.Forte@Sun.COM char dev_path[MAXPATHLEN];
6827836SJohn.Forte@Sun.COM char *update_str, *t_apid;
6837836SJohn.Forte@Sun.COM int optflag = apidt->flags;
6847836SJohn.Forte@Sun.COM int no_config_attempt = 0;
6857836SJohn.Forte@Sun.COM fpcfga_ret_t ret;
6867836SJohn.Forte@Sun.COM apid_t my_apidt;
6877836SJohn.Forte@Sun.COM uchar_t unconf_flag = 0, peri_qual;
6887836SJohn.Forte@Sun.COM HBA_STATUS status;
6897836SJohn.Forte@Sun.COM HBA_PORTATTRIBUTES discPortAttrs;
6907836SJohn.Forte@Sun.COM uint64_t lun = 0;
6917836SJohn.Forte@Sun.COM struct scsi_inquiry inq;
6927836SJohn.Forte@Sun.COM struct scsi_extended_sense sense;
6937836SJohn.Forte@Sun.COM HBA_UINT8 scsiStatus;
6947836SJohn.Forte@Sun.COM uint32_t inquirySize = sizeof (inq),
6957836SJohn.Forte@Sun.COM senseSize = sizeof (sense);
6967836SJohn.Forte@Sun.COM report_lun_resp_t *resp_buf;
6977836SJohn.Forte@Sun.COM int i, l_errno, num_luns = 0;
6987836SJohn.Forte@Sun.COM uchar_t *lun_string;
6997836SJohn.Forte@Sun.COM
7007836SJohn.Forte@Sun.COM if ((apidt->dyncomp == NULL) || (*apidt->dyncomp == '\0')) {
7017836SJohn.Forte@Sun.COM /*
7027836SJohn.Forte@Sun.COM * No dynamic component specified. Just return success.
7037836SJohn.Forte@Sun.COM * Should not see this case. Just a safety check.
7047836SJohn.Forte@Sun.COM */
7057836SJohn.Forte@Sun.COM return (FPCFGA_OK);
7067836SJohn.Forte@Sun.COM }
7077836SJohn.Forte@Sun.COM
7087836SJohn.Forte@Sun.COM /* Now construct the string we are going to put in the repository */
7097836SJohn.Forte@Sun.COM if ((update_str = calloc(1, (strlen(apidt->xport_phys) +
7107836SJohn.Forte@Sun.COM strlen(DYN_SEP) + strlen(apidt->dyncomp) + 1))) == NULL) {
7117836SJohn.Forte@Sun.COM cfga_err(errstring, errno, ERR_MEM_ALLOC, 0);
7127836SJohn.Forte@Sun.COM return (FPCFGA_LIB_ERR);
7137836SJohn.Forte@Sun.COM }
7147836SJohn.Forte@Sun.COM strcpy(update_str, apidt->xport_phys);
7157836SJohn.Forte@Sun.COM strcat(update_str, DYN_SEP);
7167836SJohn.Forte@Sun.COM strcat(update_str, apidt->dyncomp);
7177836SJohn.Forte@Sun.COM
7187836SJohn.Forte@Sun.COM /* If force update of repository is sought, do it first */
7197836SJohn.Forte@Sun.COM if (optflag & FLAG_FORCE_UPDATE_REP) {
7207836SJohn.Forte@Sun.COM /* Ignore any failure in rep update */
7217836SJohn.Forte@Sun.COM (void) update_fabric_wwn_list(
7227836SJohn.Forte@Sun.COM ((state_change_cmd == CFGA_CMD_CONFIGURE) ?
7237836SJohn.Forte@Sun.COM ADD_ENTRY : REMOVE_ENTRY),
7247836SJohn.Forte@Sun.COM update_str, errstring);
7257836SJohn.Forte@Sun.COM }
7267836SJohn.Forte@Sun.COM
7277836SJohn.Forte@Sun.COM memset(&sense, 0, sizeof (sense));
7287836SJohn.Forte@Sun.COM if ((ret = get_report_lun_data(apidt->xport_phys, apidt->dyncomp,
7297836SJohn.Forte@Sun.COM &num_luns, &resp_buf, &sense, &l_errno)) != FPCFGA_OK) {
7307836SJohn.Forte@Sun.COM /*
7317836SJohn.Forte@Sun.COM * Checking the sense key data as well as the additional
7327836SJohn.Forte@Sun.COM * sense key. The SES Node is not required to repond
7337836SJohn.Forte@Sun.COM * to Report LUN. In the case of Minnow, the SES node
7347836SJohn.Forte@Sun.COM * returns with KEY_ILLEGAL_REQUEST and the additional
7357836SJohn.Forte@Sun.COM * sense key of 0x20. In this case we will blindly
7367836SJohn.Forte@Sun.COM * send the SCSI Inquiry call to lun 0
7377836SJohn.Forte@Sun.COM *
7387836SJohn.Forte@Sun.COM * if we get any other error we will set the inq_type
7397836SJohn.Forte@Sun.COM * appropriately
7407836SJohn.Forte@Sun.COM */
7417836SJohn.Forte@Sun.COM if ((sense.es_key == KEY_ILLEGAL_REQUEST) &&
7427836SJohn.Forte@Sun.COM (sense.es_add_code == 0x20)) {
7437836SJohn.Forte@Sun.COM lun = 0;
7447836SJohn.Forte@Sun.COM } else {
7457836SJohn.Forte@Sun.COM if (ret == FPCFGA_FCP_SEND_SCSI_DEV_NOT_TGT) {
7467836SJohn.Forte@Sun.COM inq.inq_dtype = DTYPE_UNKNOWN;
7477836SJohn.Forte@Sun.COM } else {
7487836SJohn.Forte@Sun.COM /*
7497836SJohn.Forte@Sun.COM * Failed to get the LUN data for the device
7507836SJohn.Forte@Sun.COM * If we find that there is a lunlist for this
7517836SJohn.Forte@Sun.COM * device it could mean that there are dangling
7527836SJohn.Forte@Sun.COM * devinfo nodes. So, we will go ahead and try
7537836SJohn.Forte@Sun.COM * to unconfigure them.
7547836SJohn.Forte@Sun.COM */
7557836SJohn.Forte@Sun.COM if ((apidt->lunlist == NULL) ||
7567836SJohn.Forte@Sun.COM (state_change_cmd == CFGA_CMD_CONFIGURE)) {
7577836SJohn.Forte@Sun.COM S_FREE(update_str);
7587836SJohn.Forte@Sun.COM status = getPortAttrsByWWN(handle,
7597836SJohn.Forte@Sun.COM *((HBA_WWN *)(pwwn)),
7607836SJohn.Forte@Sun.COM &discPortAttrs);
7617836SJohn.Forte@Sun.COM if (status ==
7627836SJohn.Forte@Sun.COM HBA_STATUS_ERROR_ILLEGAL_WWN) {
7637836SJohn.Forte@Sun.COM return (FPCFGA_APID_NOEXIST);
7647836SJohn.Forte@Sun.COM } else {
7657836SJohn.Forte@Sun.COM cfga_err(errstring, 0,
7667836SJohn.Forte@Sun.COM ERRARG_FC_REP_LUNS,
7677836SJohn.Forte@Sun.COM apidt->dyncomp, 0);
7687836SJohn.Forte@Sun.COM return (FPCFGA_LIB_ERR);
7697836SJohn.Forte@Sun.COM }
7707836SJohn.Forte@Sun.COM } else {
7717836SJohn.Forte@Sun.COM /* unconfig with lunlist not empty */
7727836SJohn.Forte@Sun.COM no_config_attempt++;
7737836SJohn.Forte@Sun.COM }
7747836SJohn.Forte@Sun.COM }
7757836SJohn.Forte@Sun.COM }
7767836SJohn.Forte@Sun.COM }
7777836SJohn.Forte@Sun.COM for (i = 0; i < num_luns; i++) {
7787836SJohn.Forte@Sun.COM /*
7797836SJohn.Forte@Sun.COM * issue the inquiry to the first valid lun found
7807836SJohn.Forte@Sun.COM * in the lun_string
7817836SJohn.Forte@Sun.COM */
7827836SJohn.Forte@Sun.COM lun_string = (uchar_t *)&(resp_buf->lun_string[i]);
7837836SJohn.Forte@Sun.COM memcpy(&lun, lun_string, sizeof (lun));
7847836SJohn.Forte@Sun.COM
7857836SJohn.Forte@Sun.COM memset(&sense, 0, sizeof (sense));
7867836SJohn.Forte@Sun.COM status = HBA_ScsiInquiryV2(handle, portAttrs.PortWWN,
7877836SJohn.Forte@Sun.COM *(HBA_WWN *)(pwwn), lun, 0, 0, &inq, &inquirySize,
7887836SJohn.Forte@Sun.COM &scsiStatus, &sense, &senseSize);
7897836SJohn.Forte@Sun.COM /*
7907836SJohn.Forte@Sun.COM * if Inquiry is returned correctly, check the
7917836SJohn.Forte@Sun.COM * peripheral qualifier for the lun. if it is non-zero
7927836SJohn.Forte@Sun.COM * then try the SCSI Inquiry on the next lun
7937836SJohn.Forte@Sun.COM */
7947836SJohn.Forte@Sun.COM if (status == HBA_STATUS_OK) {
7957836SJohn.Forte@Sun.COM peri_qual = inq.inq_dtype & FP_PERI_QUAL_MASK;
7967836SJohn.Forte@Sun.COM if (peri_qual == DPQ_POSSIBLE) {
7977836SJohn.Forte@Sun.COM break;
7987836SJohn.Forte@Sun.COM }
7997836SJohn.Forte@Sun.COM }
8007836SJohn.Forte@Sun.COM }
8017836SJohn.Forte@Sun.COM
8027836SJohn.Forte@Sun.COM if (ret == FPCFGA_OK)
8037836SJohn.Forte@Sun.COM S_FREE(resp_buf);
8047836SJohn.Forte@Sun.COM
8057836SJohn.Forte@Sun.COM /*
8067836SJohn.Forte@Sun.COM * If there are no luns on this target, we will attempt to send
8077836SJohn.Forte@Sun.COM * the SCSI Inquiry to lun 0
8087836SJohn.Forte@Sun.COM */
8097836SJohn.Forte@Sun.COM if (num_luns == 0) {
8107836SJohn.Forte@Sun.COM lun = 0;
8117836SJohn.Forte@Sun.COM status = HBA_ScsiInquiryV2(handle, portAttrs.PortWWN,
8127836SJohn.Forte@Sun.COM *(HBA_WWN *)(pwwn), lun, 0, 0, &inq, &inquirySize,
8137836SJohn.Forte@Sun.COM &scsiStatus, &sense, &senseSize);
8147836SJohn.Forte@Sun.COM }
8157836SJohn.Forte@Sun.COM
8167836SJohn.Forte@Sun.COM if (status != HBA_STATUS_OK) {
8177836SJohn.Forte@Sun.COM if (status == HBA_STATUS_ERROR_NOT_A_TARGET) {
8187836SJohn.Forte@Sun.COM inq.inq_dtype = DTYPE_UNKNOWN;
8197836SJohn.Forte@Sun.COM } else if (status == HBA_STATUS_ERROR_ILLEGAL_WWN) {
8207836SJohn.Forte@Sun.COM free(update_str);
8217836SJohn.Forte@Sun.COM return (FPCFGA_APID_NOEXIST);
8227836SJohn.Forte@Sun.COM } else {
8237836SJohn.Forte@Sun.COM /*
8247836SJohn.Forte@Sun.COM * Failed to get the inq_dtype of device
8257836SJohn.Forte@Sun.COM * If we find that there is a lunlist for this
8267836SJohn.Forte@Sun.COM * device it could mean that there dangling
8277836SJohn.Forte@Sun.COM * devinfo nodes. So, we will go ahead and try
8287836SJohn.Forte@Sun.COM * to unconfigure them. We'll just set the
8297836SJohn.Forte@Sun.COM * inq_dtype to some invalid value (0xFF)
8307836SJohn.Forte@Sun.COM */
8317836SJohn.Forte@Sun.COM if ((apidt->lunlist == NULL) ||
8327836SJohn.Forte@Sun.COM (state_change_cmd == CFGA_CMD_CONFIGURE)) {
8337836SJohn.Forte@Sun.COM cfga_err(errstring, 0,
8347836SJohn.Forte@Sun.COM ERRARG_FC_INQUIRY,
8357836SJohn.Forte@Sun.COM apidt->dyncomp, 0);
8367836SJohn.Forte@Sun.COM free(update_str);
8377836SJohn.Forte@Sun.COM return (FPCFGA_LIB_ERR);
8387836SJohn.Forte@Sun.COM } else {
8397836SJohn.Forte@Sun.COM /* unconfig with lunlist not empty */
8407836SJohn.Forte@Sun.COM no_config_attempt++;
8417836SJohn.Forte@Sun.COM }
8427836SJohn.Forte@Sun.COM }
8437836SJohn.Forte@Sun.COM }
8447836SJohn.Forte@Sun.COM switch (state_change_cmd) {
8457836SJohn.Forte@Sun.COM case CFGA_CMD_CONFIGURE:
8467836SJohn.Forte@Sun.COM if (portAttrs.PortType != HBA_PORTTYPE_NLPORT &&
8477836SJohn.Forte@Sun.COM portAttrs.PortType != HBA_PORTTYPE_NPORT) {
8487836SJohn.Forte@Sun.COM free(update_str);
8497836SJohn.Forte@Sun.COM return (FPCFGA_OK);
8507836SJohn.Forte@Sun.COM }
8517836SJohn.Forte@Sun.COM
8527836SJohn.Forte@Sun.COM if (((inq.inq_dtype & DTYPE_MASK) == DTYPE_UNKNOWN) &&
8537836SJohn.Forte@Sun.COM ((flags & CFGA_FLAG_FORCE) == 0)) {
8547836SJohn.Forte@Sun.COM /*
8557836SJohn.Forte@Sun.COM * We assume all DTYPE_UNKNOWNs are HBAs and we wont
8567836SJohn.Forte@Sun.COM * waste time trying to config them. If they are not
8577836SJohn.Forte@Sun.COM * HBAs, then there is something wrong since they should
8587836SJohn.Forte@Sun.COM * have had a valid dtype.
8597836SJohn.Forte@Sun.COM *
8607836SJohn.Forte@Sun.COM * However, if the force flag is set (cfgadm -f), we
8617836SJohn.Forte@Sun.COM * go ahead and try to configure.
8627836SJohn.Forte@Sun.COM *
8637836SJohn.Forte@Sun.COM * In this path, however, the force flag is not set.
8647836SJohn.Forte@Sun.COM */
8657836SJohn.Forte@Sun.COM free(update_str);
8667836SJohn.Forte@Sun.COM return (FPCFGA_OK);
8677836SJohn.Forte@Sun.COM }
8687836SJohn.Forte@Sun.COM
8697836SJohn.Forte@Sun.COM errno = 0;
8707836SJohn.Forte@Sun.COM /*
8717836SJohn.Forte@Sun.COM * We'll issue the devctl_bus_dev_create() call even if the
8727836SJohn.Forte@Sun.COM * path exists in the devinfo tree. This is to take care of
8737836SJohn.Forte@Sun.COM * the situation where the device may be in a state other
8747836SJohn.Forte@Sun.COM * than the online and attached state.
8757836SJohn.Forte@Sun.COM */
8767836SJohn.Forte@Sun.COM if ((ret = do_devctl_dev_create(apidt, dev_path, MAXPATHLEN,
8777836SJohn.Forte@Sun.COM inq.inq_dtype, errstring)) != FPCFGA_OK) {
8787836SJohn.Forte@Sun.COM /*
8797836SJohn.Forte@Sun.COM * Could not configure device. To provide a more
8807836SJohn.Forte@Sun.COM * meaningful error message, first see if the supplied port
8817836SJohn.Forte@Sun.COM * WWN is there on the fabric. Otherwise print the error
8827836SJohn.Forte@Sun.COM * message using the information received from the driver
8837836SJohn.Forte@Sun.COM */
8847836SJohn.Forte@Sun.COM status = getPortAttrsByWWN(handle, *((HBA_WWN *)(pwwn)),
8857836SJohn.Forte@Sun.COM &discPortAttrs);
8867836SJohn.Forte@Sun.COM S_FREE(update_str);
8877836SJohn.Forte@Sun.COM if (status == HBA_STATUS_ERROR_ILLEGAL_WWN) {
8887836SJohn.Forte@Sun.COM return (FPCFGA_APID_NOEXIST);
8897836SJohn.Forte@Sun.COM } else {
8907836SJohn.Forte@Sun.COM return (FPCFGA_LIB_ERR);
8917836SJohn.Forte@Sun.COM }
8927836SJohn.Forte@Sun.COM }
8937836SJohn.Forte@Sun.COM
8947836SJohn.Forte@Sun.COM if (((optflag & (FLAG_FORCE_UPDATE_REP|FLAG_NO_UPDATE_REP)) == 0) &&
8957836SJohn.Forte@Sun.COM update_fabric_wwn_list(ADD_ENTRY, update_str, errstring)) {
8967836SJohn.Forte@Sun.COM cfga_err(errstring, 0, ERR_CONF_OK_UPD_REP, 0);
8977836SJohn.Forte@Sun.COM }
8987836SJohn.Forte@Sun.COM
8997836SJohn.Forte@Sun.COM S_FREE(update_str);
9007836SJohn.Forte@Sun.COM
9017836SJohn.Forte@Sun.COM if ((apidt->flags & FLAG_DISABLE_RCM) == 0) {
9027836SJohn.Forte@Sun.COM /*
9037836SJohn.Forte@Sun.COM * There may be multiple LUNs associated with the
9047836SJohn.Forte@Sun.COM * WWN we created nodes for. So, we'll call
9057836SJohn.Forte@Sun.COM * apidt_create() again and let it build a list of
9067836SJohn.Forte@Sun.COM * all the LUNs for this WWN using the devinfo tree.
9077836SJohn.Forte@Sun.COM * We will then online all those devices in RCM
9087836SJohn.Forte@Sun.COM */
9097836SJohn.Forte@Sun.COM if ((t_apid = calloc(1, strlen(apidt->xport_phys) +
9107836SJohn.Forte@Sun.COM strlen(DYN_SEP) +
9117836SJohn.Forte@Sun.COM strlen(apidt->dyncomp) + 1)) == NULL) {
9127836SJohn.Forte@Sun.COM cfga_err(errstring, errno, ERR_MEM_ALLOC, 0);
9137836SJohn.Forte@Sun.COM return (FPCFGA_LIB_ERR);
9147836SJohn.Forte@Sun.COM }
9157836SJohn.Forte@Sun.COM sprintf(t_apid, "%s%s%s", apidt->xport_phys, DYN_SEP,
9167836SJohn.Forte@Sun.COM apidt->dyncomp);
9177836SJohn.Forte@Sun.COM if ((ret = apidt_create(t_apid, &my_apidt,
9187836SJohn.Forte@Sun.COM errstring)) != FPCFGA_OK) {
9197836SJohn.Forte@Sun.COM free(t_apid);
9207836SJohn.Forte@Sun.COM return (ret);
9217836SJohn.Forte@Sun.COM }
9227836SJohn.Forte@Sun.COM
9237836SJohn.Forte@Sun.COM my_apidt.flags = apidt->flags;
9247836SJohn.Forte@Sun.COM if ((ret = dev_rcm_online(&my_apidt, -1, flags,
9257836SJohn.Forte@Sun.COM NULL)) != FPCFGA_OK) {
9267836SJohn.Forte@Sun.COM cfga_err(errstring, 0, ERRARG_RCM_ONLINE,
9277836SJohn.Forte@Sun.COM apidt->lunlist->path, 0);
9287836SJohn.Forte@Sun.COM apidt_free(&my_apidt);
9297836SJohn.Forte@Sun.COM free(t_apid);
9307836SJohn.Forte@Sun.COM return (ret);
9317836SJohn.Forte@Sun.COM }
9327836SJohn.Forte@Sun.COM S_FREE(t_apid);
9337836SJohn.Forte@Sun.COM apidt_free(&my_apidt);
9347836SJohn.Forte@Sun.COM }
9357836SJohn.Forte@Sun.COM return (FPCFGA_OK);
9367836SJohn.Forte@Sun.COM
9377836SJohn.Forte@Sun.COM case CFGA_CMD_UNCONFIGURE:
9387836SJohn.Forte@Sun.COM if (portAttrs.PortType != HBA_PORTTYPE_NLPORT &&
9397836SJohn.Forte@Sun.COM portAttrs.PortType != HBA_PORTTYPE_NPORT) {
9407836SJohn.Forte@Sun.COM free(update_str);
9417836SJohn.Forte@Sun.COM return (FPCFGA_OPNOTSUPP);
9427836SJohn.Forte@Sun.COM }
9437836SJohn.Forte@Sun.COM
9447836SJohn.Forte@Sun.COM status = getPortAttrsByWWN(handle, *((HBA_WWN *)(pwwn)),
9457836SJohn.Forte@Sun.COM &discPortAttrs);
9467836SJohn.Forte@Sun.COM if (apidt->lunlist == NULL) {
9477836SJohn.Forte@Sun.COM /*
9487836SJohn.Forte@Sun.COM * But first, remove entry from the repository if it is
9497836SJohn.Forte@Sun.COM * there ... provided the force update flag is not set
9507836SJohn.Forte@Sun.COM * (in which case the update is already done) or if
9517836SJohn.Forte@Sun.COM * the no-update flag is not set.
9527836SJohn.Forte@Sun.COM */
9537836SJohn.Forte@Sun.COM if ((optflag &
9547836SJohn.Forte@Sun.COM (FLAG_FORCE_UPDATE_REP|FLAG_NO_UPDATE_REP)) == 0) {
9557836SJohn.Forte@Sun.COM if (update_fabric_wwn_list(REMOVE_ENTRY,
9567836SJohn.Forte@Sun.COM update_str, errstring)) {
9577836SJohn.Forte@Sun.COM free(update_str);
9587836SJohn.Forte@Sun.COM cfga_err(errstring, 0,
9597836SJohn.Forte@Sun.COM ERR_UNCONF_OK_UPD_REP, 0);
9607836SJohn.Forte@Sun.COM return
9617836SJohn.Forte@Sun.COM (FPCFGA_UNCONF_OK_UPD_REP_FAILED);
9627836SJohn.Forte@Sun.COM }
9637836SJohn.Forte@Sun.COM }
9647836SJohn.Forte@Sun.COM S_FREE(update_str);
9657836SJohn.Forte@Sun.COM if (status == HBA_STATUS_ERROR_ILLEGAL_WWN) {
9667836SJohn.Forte@Sun.COM return (FPCFGA_APID_NOEXIST);
9677836SJohn.Forte@Sun.COM }
9687836SJohn.Forte@Sun.COM return (FPCFGA_OK);
9697836SJohn.Forte@Sun.COM }
9707836SJohn.Forte@Sun.COM /*
9717836SJohn.Forte@Sun.COM * If there are multiple paths to the mpxio
9727836SJohn.Forte@Sun.COM * device, we will not check in RCM ONLY when there
9737836SJohn.Forte@Sun.COM * is atleast one other ONLINE/STANDBY path
9747836SJohn.Forte@Sun.COM */
9757836SJohn.Forte@Sun.COM if (is_xport_phys_in_pathlist(apidt, errstring) !=
9767836SJohn.Forte@Sun.COM FPCFGA_OK) {
9777836SJohn.Forte@Sun.COM free(update_str);
9787836SJohn.Forte@Sun.COM return (FPCFGA_XPORT_NOT_IN_PHCI_LIST);
9797836SJohn.Forte@Sun.COM }
9807836SJohn.Forte@Sun.COM
9817836SJohn.Forte@Sun.COM /*
9827836SJohn.Forte@Sun.COM * dev_rcm_offline() updates errstring
9837836SJohn.Forte@Sun.COM */
9847836SJohn.Forte@Sun.COM if ((ret = dev_rcm_offline(apidt, flags, errstring)) !=
9857836SJohn.Forte@Sun.COM FPCFGA_OK) {
9867836SJohn.Forte@Sun.COM free(update_str);
9877836SJohn.Forte@Sun.COM return (ret);
9887836SJohn.Forte@Sun.COM }
9897836SJohn.Forte@Sun.COM if ((ret = dev_unconf(apidt, errstring, &unconf_flag)) !=
9907836SJohn.Forte@Sun.COM FPCFGA_OK) {
9917836SJohn.Forte@Sun.COM /* when inq failed don't attempt to reconfigure */
9927836SJohn.Forte@Sun.COM if (!no_config_attempt) {
9937836SJohn.Forte@Sun.COM (void) do_devctl_dev_create(apidt, dev_path, MAXPATHLEN,
9947836SJohn.Forte@Sun.COM inq.inq_dtype, NULL);
9957836SJohn.Forte@Sun.COM (void) dev_rcm_online(apidt, -1, flags, NULL);
9967836SJohn.Forte@Sun.COM }
9977836SJohn.Forte@Sun.COM free(update_str);
9987836SJohn.Forte@Sun.COM return (ret);
9997836SJohn.Forte@Sun.COM }
10007836SJohn.Forte@Sun.COM if ((ret = dev_rcm_remove(apidt, flags, errstring)) !=
10017836SJohn.Forte@Sun.COM FPCFGA_OK) {
10027836SJohn.Forte@Sun.COM (void) do_devctl_dev_create(apidt, dev_path, MAXPATHLEN,
10037836SJohn.Forte@Sun.COM inq.inq_dtype, NULL);
10047836SJohn.Forte@Sun.COM (void) dev_rcm_online(apidt, -1, flags, NULL);
10057836SJohn.Forte@Sun.COM free(update_str);
10067836SJohn.Forte@Sun.COM return (ret);
10077836SJohn.Forte@Sun.COM }
10087836SJohn.Forte@Sun.COM /*
10097836SJohn.Forte@Sun.COM * If we offlined a lun in RCM when there are multiple paths but
10107836SJohn.Forte@Sun.COM * none of them are ONLINE/STANDBY, we have to online it back
10117836SJohn.Forte@Sun.COM * in RCM now. This is a try best, will not fail for it.
10127836SJohn.Forte@Sun.COM */
10137836SJohn.Forte@Sun.COM dev_rcm_online_nonoperationalpath(apidt, flags, NULL);
10147836SJohn.Forte@Sun.COM
10157836SJohn.Forte@Sun.COM /* Update the repository if we havent already done it */
10167836SJohn.Forte@Sun.COM if ((optflag &
10177836SJohn.Forte@Sun.COM (FLAG_FORCE_UPDATE_REP|FLAG_NO_UPDATE_REP)) == 0) {
10187836SJohn.Forte@Sun.COM if (((optflag & FLAG_REMOVE_UNUSABLE_FCP_DEV) !=
10197836SJohn.Forte@Sun.COM FLAG_REMOVE_UNUSABLE_FCP_DEV) ||
10207836SJohn.Forte@Sun.COM (((optflag & FLAG_REMOVE_UNUSABLE_FCP_DEV) ==
10217836SJohn.Forte@Sun.COM FLAG_REMOVE_UNUSABLE_FCP_DEV) &&
10227836SJohn.Forte@Sun.COM (unconf_flag == ALL_APID_LUNS_UNUSABLE))) {
10237836SJohn.Forte@Sun.COM if (update_fabric_wwn_list(REMOVE_ENTRY,
10247836SJohn.Forte@Sun.COM update_str, errstring)) {
10257836SJohn.Forte@Sun.COM free(update_str);
10267836SJohn.Forte@Sun.COM cfga_err(errstring, errno,
10277836SJohn.Forte@Sun.COM ERR_UNCONF_OK_UPD_REP, 0);
10287836SJohn.Forte@Sun.COM return (FPCFGA_UNCONF_OK_UPD_REP_FAILED);
10297836SJohn.Forte@Sun.COM }
10307836SJohn.Forte@Sun.COM }
10317836SJohn.Forte@Sun.COM }
10327836SJohn.Forte@Sun.COM free(update_str);
10337836SJohn.Forte@Sun.COM return (FPCFGA_OK);
10347836SJohn.Forte@Sun.COM
10357836SJohn.Forte@Sun.COM default:
10367836SJohn.Forte@Sun.COM free(update_str);
10377836SJohn.Forte@Sun.COM return (FPCFGA_OPNOTSUPP);
10387836SJohn.Forte@Sun.COM }
10397836SJohn.Forte@Sun.COM }
10407836SJohn.Forte@Sun.COM
10417836SJohn.Forte@Sun.COM /*
10427836SJohn.Forte@Sun.COM * This function copies a port_wwn got by reading the property on a device
10437836SJohn.Forte@Sun.COM * node (from_ptr in the function below) on to an array (to_ptr) so that it is
10447836SJohn.Forte@Sun.COM * readable.
10457836SJohn.Forte@Sun.COM *
10467836SJohn.Forte@Sun.COM * Caller responsible to allocate enough memory in "to_ptr"
10477836SJohn.Forte@Sun.COM */
10487836SJohn.Forte@Sun.COM static void
copy_pwwn_data_to_str(char * to_ptr,const uchar_t * from_ptr)10497836SJohn.Forte@Sun.COM copy_pwwn_data_to_str(char *to_ptr, const uchar_t *from_ptr)
10507836SJohn.Forte@Sun.COM {
10517836SJohn.Forte@Sun.COM if ((to_ptr == NULL) || (from_ptr == NULL))
10527836SJohn.Forte@Sun.COM return;
10537836SJohn.Forte@Sun.COM
10547836SJohn.Forte@Sun.COM (void) sprintf(to_ptr, "%1.2x%1.2x%1.2x%1.2x%1.2x%1.2x%1.2x%1.2x",
10557836SJohn.Forte@Sun.COM from_ptr[0], from_ptr[1], from_ptr[2], from_ptr[3],
10567836SJohn.Forte@Sun.COM from_ptr[4], from_ptr[5], from_ptr[6], from_ptr[7]);
10577836SJohn.Forte@Sun.COM }
10587836SJohn.Forte@Sun.COM
10597836SJohn.Forte@Sun.COM static fpcfga_ret_t
unconf_vhci_nodes(di_path_t pnode,di_node_t fp_node,char * xport_phys,char * dyncomp,int unusable_flag,int * num_devs,int * failure_count,char ** errstring,cfga_flags_t flags)10607836SJohn.Forte@Sun.COM unconf_vhci_nodes(di_path_t pnode, di_node_t fp_node, char *xport_phys,
1061*9240SRaghuram.Prahlada@Sun.COM char *dyncomp, int unusable_flag,
1062*9240SRaghuram.Prahlada@Sun.COM int *num_devs, int *failure_count, char **errstring,
10637836SJohn.Forte@Sun.COM cfga_flags_t flags)
10647836SJohn.Forte@Sun.COM {
10657836SJohn.Forte@Sun.COM int iret1, iret2, *lunnump;
10667836SJohn.Forte@Sun.COM char *ptr; /* scratch pad */
10677836SJohn.Forte@Sun.COM char *node_path, *vhci_path, *update_str;
10687836SJohn.Forte@Sun.COM char port_wwn[WWN_SIZE*2+1], pathname[MAXPATHLEN];
10697836SJohn.Forte@Sun.COM uchar_t *port_wwn_data = NULL;
10707836SJohn.Forte@Sun.COM di_node_t client_node;
10717836SJohn.Forte@Sun.COM
10727836SJohn.Forte@Sun.COM while (pnode != DI_PATH_NIL) {
10737836SJohn.Forte@Sun.COM
10747836SJohn.Forte@Sun.COM (*num_devs)++;
10757836SJohn.Forte@Sun.COM
10767836SJohn.Forte@Sun.COM
10777836SJohn.Forte@Sun.COM if ((node_path = di_devfs_path(fp_node)) == NULL) {
10787836SJohn.Forte@Sun.COM cfga_err(errstring, 0, ERRARG_DEVINFO,
10797836SJohn.Forte@Sun.COM xport_phys, 0);
10807836SJohn.Forte@Sun.COM (*failure_count)++;
10817836SJohn.Forte@Sun.COM pnode = di_path_next_client(fp_node, pnode);
10827836SJohn.Forte@Sun.COM continue;
10837836SJohn.Forte@Sun.COM }
10847836SJohn.Forte@Sun.COM
10857836SJohn.Forte@Sun.COM iret1 = di_path_prop_lookup_bytes(pnode, PORT_WWN_PROP,
10867836SJohn.Forte@Sun.COM &port_wwn_data);
10877836SJohn.Forte@Sun.COM
10887836SJohn.Forte@Sun.COM iret2 = di_path_prop_lookup_ints(pnode, LUN_PROP, &lunnump);
10897836SJohn.Forte@Sun.COM
10907836SJohn.Forte@Sun.COM if ((iret1 == -1) || (iret2 == -1)) {
10917836SJohn.Forte@Sun.COM cfga_err(errstring, 0, ERRARG_DI_GET_PROP,
10927836SJohn.Forte@Sun.COM node_path, 0);
10937836SJohn.Forte@Sun.COM di_devfs_path_free(node_path);
10947836SJohn.Forte@Sun.COM node_path = NULL;
10957836SJohn.Forte@Sun.COM (*failure_count)++;
10967836SJohn.Forte@Sun.COM pnode = di_path_next_client(fp_node, pnode);
10977836SJohn.Forte@Sun.COM continue;
10987836SJohn.Forte@Sun.COM }
10997836SJohn.Forte@Sun.COM
11007836SJohn.Forte@Sun.COM copy_pwwn_data_to_str(port_wwn, port_wwn_data);
11017836SJohn.Forte@Sun.COM
11027836SJohn.Forte@Sun.COM if ((client_node = di_path_client_node(pnode)) ==
11037836SJohn.Forte@Sun.COM DI_NODE_NIL) {
11047836SJohn.Forte@Sun.COM (*failure_count)++;
11057836SJohn.Forte@Sun.COM di_devfs_path_free(node_path);
11067836SJohn.Forte@Sun.COM node_path = NULL;
11077836SJohn.Forte@Sun.COM pnode = di_path_next_client(fp_node, pnode);
11087836SJohn.Forte@Sun.COM continue;
11097836SJohn.Forte@Sun.COM }
11107836SJohn.Forte@Sun.COM
11117836SJohn.Forte@Sun.COM if ((vhci_path = di_devfs_path(client_node)) == NULL) {
11127836SJohn.Forte@Sun.COM (*failure_count)++;
11137836SJohn.Forte@Sun.COM di_devfs_path_free(node_path);
11147836SJohn.Forte@Sun.COM node_path = NULL;
11157836SJohn.Forte@Sun.COM pnode = di_path_next_client(fp_node, pnode);
11167836SJohn.Forte@Sun.COM continue;
11177836SJohn.Forte@Sun.COM }
11187836SJohn.Forte@Sun.COM
11197836SJohn.Forte@Sun.COM if ((ptr = strrchr(vhci_path, '@')) != NULL) {
11207836SJohn.Forte@Sun.COM *ptr = '\0';
11217836SJohn.Forte@Sun.COM }
11227836SJohn.Forte@Sun.COM
11237836SJohn.Forte@Sun.COM if ((ptr = strrchr(vhci_path, '/')) == NULL) {
11247836SJohn.Forte@Sun.COM (*failure_count)++;
11257836SJohn.Forte@Sun.COM di_devfs_path_free(node_path);
11267836SJohn.Forte@Sun.COM node_path = NULL;
11277836SJohn.Forte@Sun.COM pnode = di_path_next_client(fp_node, pnode);
11287836SJohn.Forte@Sun.COM continue;
11297836SJohn.Forte@Sun.COM }
11307836SJohn.Forte@Sun.COM
11317836SJohn.Forte@Sun.COM sprintf(pathname, "%s%s/%s@w%s,%x", DEVICES_DIR, node_path,
11327836SJohn.Forte@Sun.COM ++ptr, port_wwn, *lunnump);
11337836SJohn.Forte@Sun.COM
11347836SJohn.Forte@Sun.COM di_devfs_path_free(node_path);
11357836SJohn.Forte@Sun.COM di_devfs_path_free(vhci_path);
11367836SJohn.Forte@Sun.COM node_path = vhci_path = NULL;
11377836SJohn.Forte@Sun.COM
11387836SJohn.Forte@Sun.COM /*
11397836SJohn.Forte@Sun.COM * Try to offline in RCM first and if that is successful,
11407836SJohn.Forte@Sun.COM * unconfigure the LUN. If offlining in RCM fails, then
11417836SJohn.Forte@Sun.COM * update the failure_count which gets passed back to caller
1142*9240SRaghuram.Prahlada@Sun.COM *
1143*9240SRaghuram.Prahlada@Sun.COM * Here we got to check if unusable_flag is set or not.
1144*9240SRaghuram.Prahlada@Sun.COM * If set, then unconfigure only those luns which are in
1145*9240SRaghuram.Prahlada@Sun.COM * node_state DI_PATH_STATE_OFFLINE. If not set, unconfigure
1146*9240SRaghuram.Prahlada@Sun.COM * all luns.
11477836SJohn.Forte@Sun.COM */
1148*9240SRaghuram.Prahlada@Sun.COM if ((unusable_flag & FLAG_REMOVE_UNUSABLE_FCP_DEV) ==
1149*9240SRaghuram.Prahlada@Sun.COM FLAG_REMOVE_UNUSABLE_FCP_DEV) {
1150*9240SRaghuram.Prahlada@Sun.COM if (pnode->path_state == DI_PATH_STATE_OFFLINE) {
1151*9240SRaghuram.Prahlada@Sun.COM if (fp_rcm_offline(pathname, errstring,
1152*9240SRaghuram.Prahlada@Sun.COM flags) != 0) {
1153*9240SRaghuram.Prahlada@Sun.COM (*failure_count)++;
1154*9240SRaghuram.Prahlada@Sun.COM pnode = di_path_next_client(fp_node,
1155*9240SRaghuram.Prahlada@Sun.COM pnode);
1156*9240SRaghuram.Prahlada@Sun.COM continue;
1157*9240SRaghuram.Prahlada@Sun.COM } else if (lun_unconf(pathname, *lunnump,
1158*9240SRaghuram.Prahlada@Sun.COM xport_phys,dyncomp, errstring)
1159*9240SRaghuram.Prahlada@Sun.COM != FPCFGA_OK) {
1160*9240SRaghuram.Prahlada@Sun.COM (void) fp_rcm_online(pathname,
1161*9240SRaghuram.Prahlada@Sun.COM NULL, flags);
1162*9240SRaghuram.Prahlada@Sun.COM (*failure_count)++;
1163*9240SRaghuram.Prahlada@Sun.COM pnode = di_path_next_client(fp_node,
1164*9240SRaghuram.Prahlada@Sun.COM pnode);
1165*9240SRaghuram.Prahlada@Sun.COM continue;
1166*9240SRaghuram.Prahlada@Sun.COM } else if (fp_rcm_remove(pathname, errstring,
1167*9240SRaghuram.Prahlada@Sun.COM flags) != 0) {
1168*9240SRaghuram.Prahlada@Sun.COM /*
1169*9240SRaghuram.Prahlada@Sun.COM * Bring everything back online
1170*9240SRaghuram.Prahlada@Sun.COM * in rcm and continue
1171*9240SRaghuram.Prahlada@Sun.COM */
1172*9240SRaghuram.Prahlada@Sun.COM (void) fp_rcm_online(pathname,
1173*9240SRaghuram.Prahlada@Sun.COM NULL, flags);
1174*9240SRaghuram.Prahlada@Sun.COM (*failure_count)++;
1175*9240SRaghuram.Prahlada@Sun.COM pnode = di_path_next_client(fp_node,
1176*9240SRaghuram.Prahlada@Sun.COM pnode);
1177*9240SRaghuram.Prahlada@Sun.COM continue;
1178*9240SRaghuram.Prahlada@Sun.COM }
1179*9240SRaghuram.Prahlada@Sun.COM } else {
1180*9240SRaghuram.Prahlada@Sun.COM pnode = di_path_next(fp_node, pnode);
1181*9240SRaghuram.Prahlada@Sun.COM continue;
1182*9240SRaghuram.Prahlada@Sun.COM }
1183*9240SRaghuram.Prahlada@Sun.COM } else {
1184*9240SRaghuram.Prahlada@Sun.COM if (fp_rcm_offline(pathname, errstring, flags) != 0) {
1185*9240SRaghuram.Prahlada@Sun.COM (*failure_count)++;
1186*9240SRaghuram.Prahlada@Sun.COM pnode = di_path_next_client(fp_node, pnode);
1187*9240SRaghuram.Prahlada@Sun.COM continue;
1188*9240SRaghuram.Prahlada@Sun.COM } else if (lun_unconf(pathname, *lunnump, xport_phys,
1189*9240SRaghuram.Prahlada@Sun.COM dyncomp, errstring) != FPCFGA_OK) {
1190*9240SRaghuram.Prahlada@Sun.COM (void) fp_rcm_online(pathname, NULL, flags);
1191*9240SRaghuram.Prahlada@Sun.COM (*failure_count)++;
1192*9240SRaghuram.Prahlada@Sun.COM pnode = di_path_next_client(fp_node, pnode);
1193*9240SRaghuram.Prahlada@Sun.COM continue;
1194*9240SRaghuram.Prahlada@Sun.COM } else if (fp_rcm_remove(pathname, errstring,
1195*9240SRaghuram.Prahlada@Sun.COM flags) != 0) {
1196*9240SRaghuram.Prahlada@Sun.COM /*
1197*9240SRaghuram.Prahlada@Sun.COM * Bring everything back online
1198*9240SRaghuram.Prahlada@Sun.COM * in rcm and continue
1199*9240SRaghuram.Prahlada@Sun.COM */
1200*9240SRaghuram.Prahlada@Sun.COM (void) fp_rcm_online(pathname, NULL, flags);
1201*9240SRaghuram.Prahlada@Sun.COM (*failure_count)++;
1202*9240SRaghuram.Prahlada@Sun.COM pnode = di_path_next_client(fp_node, pnode);
1203*9240SRaghuram.Prahlada@Sun.COM continue;
1204*9240SRaghuram.Prahlada@Sun.COM }
12057836SJohn.Forte@Sun.COM }
12067836SJohn.Forte@Sun.COM
12077836SJohn.Forte@Sun.COM /* Update the repository only on a successful unconfigure */
12087836SJohn.Forte@Sun.COM if ((update_str = calloc(1, strlen(xport_phys) +
12097836SJohn.Forte@Sun.COM strlen(DYN_SEP) +
12107836SJohn.Forte@Sun.COM strlen(port_wwn) + 1)) == NULL) {
12117836SJohn.Forte@Sun.COM cfga_err(errstring, errno, ERR_UNCONF_OK_UPD_REP, 0);
12127836SJohn.Forte@Sun.COM (*failure_count)++;
12137836SJohn.Forte@Sun.COM pnode = di_path_next_client(fp_node, pnode);
12147836SJohn.Forte@Sun.COM continue;
12157836SJohn.Forte@Sun.COM }
12167836SJohn.Forte@Sun.COM
12177836SJohn.Forte@Sun.COM /* Init the string to be removed from repository */
12187836SJohn.Forte@Sun.COM sprintf(update_str, "%s%s%s", xport_phys, DYN_SEP, port_wwn);
12197836SJohn.Forte@Sun.COM
12207836SJohn.Forte@Sun.COM if (update_fabric_wwn_list(REMOVE_ENTRY, update_str,
12217836SJohn.Forte@Sun.COM errstring)) {
12227836SJohn.Forte@Sun.COM S_FREE(update_str);
12237836SJohn.Forte@Sun.COM cfga_err(errstring, errno,
12247836SJohn.Forte@Sun.COM ERR_UNCONF_OK_UPD_REP, 0);
12257836SJohn.Forte@Sun.COM (*failure_count)++;
12267836SJohn.Forte@Sun.COM /* Cleanup and continue from here just for clarity */
12277836SJohn.Forte@Sun.COM pnode = di_path_next_client(fp_node, pnode);
12287836SJohn.Forte@Sun.COM continue;
12297836SJohn.Forte@Sun.COM }
12307836SJohn.Forte@Sun.COM
12317836SJohn.Forte@Sun.COM S_FREE(update_str);
12327836SJohn.Forte@Sun.COM pnode = di_path_next_client(fp_node, pnode);
12337836SJohn.Forte@Sun.COM }
12347836SJohn.Forte@Sun.COM
12357836SJohn.Forte@Sun.COM return (FPCFGA_OK);
12367836SJohn.Forte@Sun.COM }
12377836SJohn.Forte@Sun.COM
12387836SJohn.Forte@Sun.COM static fpcfga_ret_t
unconf_non_vhci_nodes(di_node_t dnode,char * xport_phys,char * dyncomp,int unusable_flag,int * num_devs,int * failure_count,char ** errstring,cfga_flags_t flags)12397836SJohn.Forte@Sun.COM unconf_non_vhci_nodes(di_node_t dnode, char *xport_phys, char *dyncomp,
1240*9240SRaghuram.Prahlada@Sun.COM int unusable_flag, int *num_devs, int *failure_count,
1241*9240SRaghuram.Prahlada@Sun.COM char **errstring, cfga_flags_t flags)
12427836SJohn.Forte@Sun.COM {
12437836SJohn.Forte@Sun.COM int ret1, ret2, *lunnump;
12447836SJohn.Forte@Sun.COM char pathname[MAXPATHLEN];
12457836SJohn.Forte@Sun.COM char *node_path, *update_str;
12467836SJohn.Forte@Sun.COM char port_wwn[WWN_SIZE*2+1];
12477836SJohn.Forte@Sun.COM uchar_t *port_wwn_data = NULL;
12487836SJohn.Forte@Sun.COM
12497836SJohn.Forte@Sun.COM while (dnode != DI_NODE_NIL) {
12507836SJohn.Forte@Sun.COM
12517836SJohn.Forte@Sun.COM (*num_devs)++;
12527836SJohn.Forte@Sun.COM
12537836SJohn.Forte@Sun.COM /* Get the physical path for this node */
12547836SJohn.Forte@Sun.COM if ((node_path = di_devfs_path(dnode)) == NULL) {
12557836SJohn.Forte@Sun.COM /*
12567836SJohn.Forte@Sun.COM * We don't try to offline in RCM here because we
12577836SJohn.Forte@Sun.COM * don't know the path to offline. Just continue to
12587836SJohn.Forte@Sun.COM * the next node.
12597836SJohn.Forte@Sun.COM */
12607836SJohn.Forte@Sun.COM cfga_err(errstring, 0, ERRARG_DEVINFO, xport_phys, 0);
12617836SJohn.Forte@Sun.COM (*failure_count)++;
12627836SJohn.Forte@Sun.COM dnode = di_sibling_node(dnode);
12637836SJohn.Forte@Sun.COM continue;
12647836SJohn.Forte@Sun.COM }
12657836SJohn.Forte@Sun.COM
12667836SJohn.Forte@Sun.COM /* Now get the LUN # of this device thru the property */
12677836SJohn.Forte@Sun.COM ret1 = di_prop_lookup_ints(DDI_DEV_T_ANY, dnode,
12687836SJohn.Forte@Sun.COM LUN_PROP, &lunnump);
12697836SJohn.Forte@Sun.COM
12707836SJohn.Forte@Sun.COM /* Next get the port WWN of the device */
12717836SJohn.Forte@Sun.COM ret2 = di_prop_lookup_bytes(DDI_DEV_T_ANY, dnode,
12727836SJohn.Forte@Sun.COM PORT_WWN_PROP, &port_wwn_data);
12737836SJohn.Forte@Sun.COM
12747836SJohn.Forte@Sun.COM /* A failure in any of the above is not good */
12757836SJohn.Forte@Sun.COM if ((ret1 == -1) || (ret2 == -1)) {
12767836SJohn.Forte@Sun.COM /*
12777836SJohn.Forte@Sun.COM * We don't try to offline in RCM here because we
12787836SJohn.Forte@Sun.COM * don't know the path to offline. Just continue to
12797836SJohn.Forte@Sun.COM * the next node.
12807836SJohn.Forte@Sun.COM */
12817836SJohn.Forte@Sun.COM cfga_err(errstring, 0,
12827836SJohn.Forte@Sun.COM ERRARG_DI_GET_PROP, node_path, 0);
12837836SJohn.Forte@Sun.COM di_devfs_path_free(node_path);
12847836SJohn.Forte@Sun.COM node_path = NULL;
12857836SJohn.Forte@Sun.COM (*failure_count)++;
12867836SJohn.Forte@Sun.COM dnode = di_sibling_node(dnode);
12877836SJohn.Forte@Sun.COM continue;
12887836SJohn.Forte@Sun.COM }
12897836SJohn.Forte@Sun.COM
12907836SJohn.Forte@Sun.COM /* Prepend the "/devices" prefix to the path and copy it */
12917836SJohn.Forte@Sun.COM sprintf(pathname, "%s%s", DEVICES_DIR, node_path);
12927836SJohn.Forte@Sun.COM di_devfs_path_free(node_path);
12937836SJohn.Forte@Sun.COM node_path = NULL;
12947836SJohn.Forte@Sun.COM
12957836SJohn.Forte@Sun.COM copy_pwwn_data_to_str(port_wwn, port_wwn_data);
12967836SJohn.Forte@Sun.COM
12977836SJohn.Forte@Sun.COM if (strstr(pathname, "@w") == NULL) {
12987836SJohn.Forte@Sun.COM /*
12997836SJohn.Forte@Sun.COM * If the driver is detached, some part of the path
13007836SJohn.Forte@Sun.COM * may be missing and so we'll manually construct it
13017836SJohn.Forte@Sun.COM */
13027836SJohn.Forte@Sun.COM sprintf(&pathname[strlen(pathname)], "@w%s,%x",
13037836SJohn.Forte@Sun.COM port_wwn, *lunnump);
13047836SJohn.Forte@Sun.COM }
13057836SJohn.Forte@Sun.COM
13067836SJohn.Forte@Sun.COM /*
13077836SJohn.Forte@Sun.COM * Try to offline in RCM first and if that is successful,
13087836SJohn.Forte@Sun.COM * unconfigure the LUN. If offlining in RCM fails, then
13097836SJohn.Forte@Sun.COM * update the failure count
1310*9240SRaghuram.Prahlada@Sun.COM *
1311*9240SRaghuram.Prahlada@Sun.COM * Here we got to check if unusable_flag is set or not.
1312*9240SRaghuram.Prahlada@Sun.COM * If set, then unconfigure only those luns which are in
1313*9240SRaghuram.Prahlada@Sun.COM * node_state DI_DEVICE_OFFLINE or DI_DEVICE_DOWN.
1314*9240SRaghuram.Prahlada@Sun.COM * If not set, unconfigure all luns.
13157836SJohn.Forte@Sun.COM */
1316*9240SRaghuram.Prahlada@Sun.COM if ((unusable_flag & FLAG_REMOVE_UNUSABLE_FCP_DEV) ==
1317*9240SRaghuram.Prahlada@Sun.COM FLAG_REMOVE_UNUSABLE_FCP_DEV) {
1318*9240SRaghuram.Prahlada@Sun.COM if ((dnode->node_state == DI_DEVICE_OFFLINE) ||
1319*9240SRaghuram.Prahlada@Sun.COM (dnode->node_state == DI_DEVICE_DOWN)) {
1320*9240SRaghuram.Prahlada@Sun.COM if (fp_rcm_offline(pathname, errstring,
1321*9240SRaghuram.Prahlada@Sun.COM flags) != 0) {
1322*9240SRaghuram.Prahlada@Sun.COM (*failure_count)++;
1323*9240SRaghuram.Prahlada@Sun.COM dnode = di_sibling_node(dnode);
1324*9240SRaghuram.Prahlada@Sun.COM continue;
1325*9240SRaghuram.Prahlada@Sun.COM } else if (lun_unconf(pathname, *lunnump,
1326*9240SRaghuram.Prahlada@Sun.COM xport_phys,dyncomp, errstring)
1327*9240SRaghuram.Prahlada@Sun.COM != FPCFGA_OK) {
1328*9240SRaghuram.Prahlada@Sun.COM (void) fp_rcm_online(pathname,
1329*9240SRaghuram.Prahlada@Sun.COM NULL, flags);
1330*9240SRaghuram.Prahlada@Sun.COM (*failure_count)++;
1331*9240SRaghuram.Prahlada@Sun.COM dnode = di_sibling_node(dnode);
1332*9240SRaghuram.Prahlada@Sun.COM continue;
1333*9240SRaghuram.Prahlada@Sun.COM } else if (fp_rcm_remove(pathname, errstring,
1334*9240SRaghuram.Prahlada@Sun.COM flags) != 0) {
1335*9240SRaghuram.Prahlada@Sun.COM /*
1336*9240SRaghuram.Prahlada@Sun.COM * Bring everything back online
1337*9240SRaghuram.Prahlada@Sun.COM * in rcm and continue
1338*9240SRaghuram.Prahlada@Sun.COM */
1339*9240SRaghuram.Prahlada@Sun.COM (void) fp_rcm_online(pathname,
1340*9240SRaghuram.Prahlada@Sun.COM NULL, flags);
1341*9240SRaghuram.Prahlada@Sun.COM (*failure_count)++;
1342*9240SRaghuram.Prahlada@Sun.COM dnode = di_sibling_node(dnode);
1343*9240SRaghuram.Prahlada@Sun.COM continue;
1344*9240SRaghuram.Prahlada@Sun.COM }
1345*9240SRaghuram.Prahlada@Sun.COM } else {
1346*9240SRaghuram.Prahlada@Sun.COM dnode = di_sibling_node(dnode);
1347*9240SRaghuram.Prahlada@Sun.COM continue;
1348*9240SRaghuram.Prahlada@Sun.COM }
1349*9240SRaghuram.Prahlada@Sun.COM } else {
1350*9240SRaghuram.Prahlada@Sun.COM if (fp_rcm_offline(pathname, errstring, flags) != 0) {
1351*9240SRaghuram.Prahlada@Sun.COM (*failure_count)++;
1352*9240SRaghuram.Prahlada@Sun.COM dnode = di_sibling_node(dnode);
1353*9240SRaghuram.Prahlada@Sun.COM continue;
1354*9240SRaghuram.Prahlada@Sun.COM } else if (lun_unconf(pathname, *lunnump, xport_phys,
1355*9240SRaghuram.Prahlada@Sun.COM dyncomp, errstring) != FPCFGA_OK) {
1356*9240SRaghuram.Prahlada@Sun.COM (void) fp_rcm_online(pathname, NULL, flags);
1357*9240SRaghuram.Prahlada@Sun.COM (*failure_count)++;
1358*9240SRaghuram.Prahlada@Sun.COM dnode = di_sibling_node(dnode);
1359*9240SRaghuram.Prahlada@Sun.COM continue;
1360*9240SRaghuram.Prahlada@Sun.COM } else if (fp_rcm_remove(pathname, errstring,
1361*9240SRaghuram.Prahlada@Sun.COM flags) != 0) {
1362*9240SRaghuram.Prahlada@Sun.COM /*
1363*9240SRaghuram.Prahlada@Sun.COM * Bring everything back online
1364*9240SRaghuram.Prahlada@Sun.COM * in rcm and continue
1365*9240SRaghuram.Prahlada@Sun.COM */
1366*9240SRaghuram.Prahlada@Sun.COM (void) fp_rcm_online(pathname, NULL, flags);
1367*9240SRaghuram.Prahlada@Sun.COM (*failure_count)++;
1368*9240SRaghuram.Prahlada@Sun.COM dnode = di_sibling_node(dnode);
1369*9240SRaghuram.Prahlada@Sun.COM continue;
1370*9240SRaghuram.Prahlada@Sun.COM }
13717836SJohn.Forte@Sun.COM }
13727836SJohn.Forte@Sun.COM
13737836SJohn.Forte@Sun.COM /* Update the repository only on a successful unconfigure */
13747836SJohn.Forte@Sun.COM if ((update_str = calloc(1, strlen(xport_phys) +
13757836SJohn.Forte@Sun.COM strlen(DYN_SEP) +
13767836SJohn.Forte@Sun.COM strlen(port_wwn) + 1)) == NULL) {
13777836SJohn.Forte@Sun.COM cfga_err(errstring, errno, ERR_UNCONF_OK_UPD_REP, 0);
13787836SJohn.Forte@Sun.COM (*failure_count)++;
13797836SJohn.Forte@Sun.COM dnode = di_sibling_node(dnode);
13807836SJohn.Forte@Sun.COM continue;
13817836SJohn.Forte@Sun.COM }
13827836SJohn.Forte@Sun.COM
13837836SJohn.Forte@Sun.COM /* Init the string to be removed from repository */
13847836SJohn.Forte@Sun.COM sprintf(update_str, "%s%s%s", xport_phys, DYN_SEP, port_wwn);
13857836SJohn.Forte@Sun.COM
13867836SJohn.Forte@Sun.COM if (update_fabric_wwn_list(REMOVE_ENTRY, update_str,
13877836SJohn.Forte@Sun.COM errstring)) {
13887836SJohn.Forte@Sun.COM S_FREE(update_str);
13897836SJohn.Forte@Sun.COM cfga_err(errstring, errno, ERR_UNCONF_OK_UPD_REP, 0);
13907836SJohn.Forte@Sun.COM (*failure_count)++;
13917836SJohn.Forte@Sun.COM dnode = di_sibling_node(dnode);
13927836SJohn.Forte@Sun.COM continue;
13937836SJohn.Forte@Sun.COM }
13947836SJohn.Forte@Sun.COM
13957836SJohn.Forte@Sun.COM S_FREE(update_str);
13967836SJohn.Forte@Sun.COM dnode = di_sibling_node(dnode);
13977836SJohn.Forte@Sun.COM }
13987836SJohn.Forte@Sun.COM
13997836SJohn.Forte@Sun.COM return (FPCFGA_OK);
14007836SJohn.Forte@Sun.COM }
14017836SJohn.Forte@Sun.COM
14027836SJohn.Forte@Sun.COM /*
14037836SJohn.Forte@Sun.COM * INPUT:
14047836SJohn.Forte@Sun.COM * apidt - Pointer to apid_t structure with data filled in
14057836SJohn.Forte@Sun.COM * flags - Flags for special handling
14067836SJohn.Forte@Sun.COM *
14077836SJohn.Forte@Sun.COM * OUTPUT:
14087836SJohn.Forte@Sun.COM * errstring - Applicable only on a failure from plugin
14097836SJohn.Forte@Sun.COM * num_devs - Incremented per lun
14107836SJohn.Forte@Sun.COM * failure_count - Incremented on any failed operation on lun
14117836SJohn.Forte@Sun.COM *
14127836SJohn.Forte@Sun.COM * RETURNS:
14137836SJohn.Forte@Sun.COM * non-FPCFGA_OK on any validation check error. If this value is returned, no
14147836SJohn.Forte@Sun.COM * devices were handled. Consequently num_devs and failure_count
14157836SJohn.Forte@Sun.COM * will not be incremented.
14167836SJohn.Forte@Sun.COM * FPCFGA_OK This return value doesn't mean that all devices were successfully
14177836SJohn.Forte@Sun.COM * unconfigured, you have to check failure_count.
14187836SJohn.Forte@Sun.COM */
14197836SJohn.Forte@Sun.COM static fpcfga_ret_t
unconf_any_devinfo_nodes(apid_t * apidt,cfga_flags_t flags,char ** errstring,int * num_devs,int * failure_count)14207836SJohn.Forte@Sun.COM unconf_any_devinfo_nodes(apid_t *apidt, cfga_flags_t flags, char **errstring,
14217836SJohn.Forte@Sun.COM int *num_devs, int *failure_count)
14227836SJohn.Forte@Sun.COM {
14237836SJohn.Forte@Sun.COM char *node_path = NULL;
14247836SJohn.Forte@Sun.COM char pathname[MAXPATHLEN], *ptr; /* scratch pad */
14257836SJohn.Forte@Sun.COM di_node_t root_node, direct_node, fp_node;
14267836SJohn.Forte@Sun.COM di_path_t path_node = DI_PATH_NIL;
14277836SJohn.Forte@Sun.COM
14287836SJohn.Forte@Sun.COM /*
14297836SJohn.Forte@Sun.COM * apidt->xport_phys is something like :
14307836SJohn.Forte@Sun.COM * /devices/pci@.../SUNW,qlc@../fp@0,0:fc
14317836SJohn.Forte@Sun.COM * Make sure we copy both the devinfo and pathinfo nodes
14327836SJohn.Forte@Sun.COM */
14337836SJohn.Forte@Sun.COM (void) strlcpy(pathname, apidt->xport_phys, MAXPATHLEN);
14347836SJohn.Forte@Sun.COM
14357836SJohn.Forte@Sun.COM /* Now get rid of the ':' at the end */
14367836SJohn.Forte@Sun.COM if ((ptr = strstr(pathname, MINOR_SEP)) != NULL)
14377836SJohn.Forte@Sun.COM *ptr = '\0';
14387836SJohn.Forte@Sun.COM
14397836SJohn.Forte@Sun.COM if (strncmp(pathname, DEVICES_DIR, strlen(DEVICES_DIR))) {
14407836SJohn.Forte@Sun.COM cfga_err(errstring, 0, ERRARG_INVALID_PATH, pathname, 0);
14417836SJohn.Forte@Sun.COM return (FPCFGA_INVALID_PATH);
14427836SJohn.Forte@Sun.COM }
14437836SJohn.Forte@Sun.COM
14447836SJohn.Forte@Sun.COM if ((root_node = di_init("/", DINFOCPYALL | DINFOPATH)) ==
14457836SJohn.Forte@Sun.COM DI_NODE_NIL) {
14467836SJohn.Forte@Sun.COM cfga_err(errstring, errno, ERRARG_DEVINFO,
14477836SJohn.Forte@Sun.COM apidt->xport_phys, 0);
14487836SJohn.Forte@Sun.COM return (FPCFGA_LIB_ERR);
14497836SJohn.Forte@Sun.COM }
14507836SJohn.Forte@Sun.COM
14517836SJohn.Forte@Sun.COM if ((fp_node = di_drv_first_node("fp", root_node)) == DI_NODE_NIL) {
14527836SJohn.Forte@Sun.COM cfga_err(errstring, errno, ERRARG_DEVINFO,
14537836SJohn.Forte@Sun.COM apidt->xport_phys, 0);
14547836SJohn.Forte@Sun.COM di_fini(root_node);
14557836SJohn.Forte@Sun.COM return (FPCFGA_LIB_ERR);
14567836SJohn.Forte@Sun.COM }
14577836SJohn.Forte@Sun.COM
14587836SJohn.Forte@Sun.COM /*
14597836SJohn.Forte@Sun.COM * Search all the fp nodes to see if any match the one we are trying
14607836SJohn.Forte@Sun.COM * to unconfigure
14617836SJohn.Forte@Sun.COM */
14627836SJohn.Forte@Sun.COM
14637836SJohn.Forte@Sun.COM /* Skip the "/devices" prefix */
14647836SJohn.Forte@Sun.COM ptr = pathname + strlen(DEVICES_DIR);
14657836SJohn.Forte@Sun.COM
14667836SJohn.Forte@Sun.COM while (fp_node != DI_NODE_NIL) {
14677836SJohn.Forte@Sun.COM node_path = di_devfs_path(fp_node);
14687836SJohn.Forte@Sun.COM if (strcmp(node_path, ptr) == 0) {
14697836SJohn.Forte@Sun.COM /* Found the fp node. 'pathname' has the full path */
14707836SJohn.Forte@Sun.COM di_devfs_path_free(node_path);
14717836SJohn.Forte@Sun.COM node_path = NULL;
14727836SJohn.Forte@Sun.COM break;
14737836SJohn.Forte@Sun.COM }
14747836SJohn.Forte@Sun.COM fp_node = di_drv_next_node(fp_node);
14757836SJohn.Forte@Sun.COM di_devfs_path_free(node_path);
14767836SJohn.Forte@Sun.COM }
14777836SJohn.Forte@Sun.COM
14787836SJohn.Forte@Sun.COM if (fp_node == DI_NODE_NIL) {
14797836SJohn.Forte@Sun.COM cfga_err(errstring, 0, ERRARG_NOT_IN_DEVINFO,
14807836SJohn.Forte@Sun.COM apidt->xport_phys, 0);
14817836SJohn.Forte@Sun.COM di_fini(root_node);
14827836SJohn.Forte@Sun.COM return (FPCFGA_LIB_ERR);
14837836SJohn.Forte@Sun.COM }
14847836SJohn.Forte@Sun.COM
14857836SJohn.Forte@Sun.COM direct_node = di_child_node(fp_node);
14867836SJohn.Forte@Sun.COM path_node = di_path_next_client(fp_node, path_node);
14877836SJohn.Forte@Sun.COM
14887836SJohn.Forte@Sun.COM if ((direct_node == DI_NODE_NIL) && (path_node == DI_PATH_NIL)) {
14897836SJohn.Forte@Sun.COM /* No devinfo or pathinfo nodes. Great ! Just return success */
14907836SJohn.Forte@Sun.COM di_fini(root_node);
14917836SJohn.Forte@Sun.COM return (FPCFGA_OK);
14927836SJohn.Forte@Sun.COM }
14937836SJohn.Forte@Sun.COM
14947836SJohn.Forte@Sun.COM /* First unconfigure any non-MPXIO nodes */
14957836SJohn.Forte@Sun.COM unconf_non_vhci_nodes(direct_node, apidt->xport_phys, apidt->dyncomp,
1496*9240SRaghuram.Prahlada@Sun.COM apidt->flags, num_devs, failure_count, errstring, flags);
14977836SJohn.Forte@Sun.COM
14987836SJohn.Forte@Sun.COM /*
14997836SJohn.Forte@Sun.COM * Now we will traverse any path info nodes that are there
15007836SJohn.Forte@Sun.COM *
15017836SJohn.Forte@Sun.COM * Only MPXIO devices have pathinfo nodes
15027836SJohn.Forte@Sun.COM */
15037836SJohn.Forte@Sun.COM unconf_vhci_nodes(path_node, fp_node, apidt->xport_phys, apidt->dyncomp,
1504*9240SRaghuram.Prahlada@Sun.COM apidt->flags, num_devs, failure_count, errstring, flags);
15057836SJohn.Forte@Sun.COM
15067836SJohn.Forte@Sun.COM di_fini(root_node);
15077836SJohn.Forte@Sun.COM
15087836SJohn.Forte@Sun.COM /*
15097836SJohn.Forte@Sun.COM * We don't want to check the return value of unconf_non_vhci_nodes()
15107836SJohn.Forte@Sun.COM * and unconf_vhci_nodes(). But instead, we are interested only in
15117836SJohn.Forte@Sun.COM * consistently incrementing num_devs and failure_count so that we can
15127836SJohn.Forte@Sun.COM * compare them.
15137836SJohn.Forte@Sun.COM */
15147836SJohn.Forte@Sun.COM return (FPCFGA_OK);
15157836SJohn.Forte@Sun.COM }
15167836SJohn.Forte@Sun.COM
15177836SJohn.Forte@Sun.COM /*
15187836SJohn.Forte@Sun.COM * This function handles configuring/unconfiguring all the devices w.r.t
15197836SJohn.Forte@Sun.COM * the FCA port specified by apidt.
15207836SJohn.Forte@Sun.COM *
15217836SJohn.Forte@Sun.COM * In the unconfigure case, it first unconfigures all the devices that are
15227836SJohn.Forte@Sun.COM * seen through the given port at that moment and then unconfigures all the
15237836SJohn.Forte@Sun.COM * devices that still (somehow) have devinfo nodes on the system for that FCA
15247836SJohn.Forte@Sun.COM * port.
15257836SJohn.Forte@Sun.COM *
15267836SJohn.Forte@Sun.COM * INPUT:
15277836SJohn.Forte@Sun.COM * cmd - CFGA_CMD_CONFIGURE or CFGA_CMD_UNCONFIGURE
15287836SJohn.Forte@Sun.COM * apidt - Pointer to apid_t structure with data filled in
15297836SJohn.Forte@Sun.COM * flags - Flags for special handling
15307836SJohn.Forte@Sun.COM *
15317836SJohn.Forte@Sun.COM * OUTPUT:
15327836SJohn.Forte@Sun.COM * errstring - Applicable only on a failure from plugin
15337836SJohn.Forte@Sun.COM *
15347836SJohn.Forte@Sun.COM * RETURNS:
15357836SJohn.Forte@Sun.COM * FPCFGA_OK on success
15367836SJohn.Forte@Sun.COM * non-FPCFGA_OK otherwise
15377836SJohn.Forte@Sun.COM */
15387836SJohn.Forte@Sun.COM static fpcfga_ret_t
handle_devs(cfga_cmd_t cmd,apid_t * apidt,cfga_flags_t flags,char ** errstring,HBA_HANDLE handle,int portIndex,HBA_PORTATTRIBUTES portAttrs)15397836SJohn.Forte@Sun.COM handle_devs(cfga_cmd_t cmd, apid_t *apidt, cfga_flags_t flags,
15407836SJohn.Forte@Sun.COM char **errstring, HBA_HANDLE handle, int portIndex,
15417836SJohn.Forte@Sun.COM HBA_PORTATTRIBUTES portAttrs)
15427836SJohn.Forte@Sun.COM {
15437836SJohn.Forte@Sun.COM int num_devs = 0, dev_cs_failed = 0;
15447836SJohn.Forte@Sun.COM char port_wwn[WWN_S_LEN];
15457836SJohn.Forte@Sun.COM la_wwn_t pwwn;
15467836SJohn.Forte@Sun.COM apid_t my_apidt = {NULL};
15477836SJohn.Forte@Sun.COM char *my_apid;
15487836SJohn.Forte@Sun.COM HBA_PORTATTRIBUTES discPortAttrs;
15497836SJohn.Forte@Sun.COM int discIndex;
15507836SJohn.Forte@Sun.COM fpcfga_ret_t rval = FPCFGA_OK;
15517836SJohn.Forte@Sun.COM
15527836SJohn.Forte@Sun.COM if ((my_apid = calloc(
15537836SJohn.Forte@Sun.COM 1, strlen(apidt->xport_phys) + strlen(DYN_SEP) +
15547836SJohn.Forte@Sun.COM (2 * FC_WWN_SIZE) + 1)) == NULL) {
15557836SJohn.Forte@Sun.COM cfga_err(errstring, errno, ERR_MEM_ALLOC, 0);
15567836SJohn.Forte@Sun.COM return (FPCFGA_LIB_ERR);
15577836SJohn.Forte@Sun.COM }
15587836SJohn.Forte@Sun.COM
15597836SJohn.Forte@Sun.COM num_devs = portAttrs.NumberofDiscoveredPorts;
15607836SJohn.Forte@Sun.COM for (discIndex = 0; discIndex < portAttrs.NumberofDiscoveredPorts;
15617836SJohn.Forte@Sun.COM discIndex++) {
15627836SJohn.Forte@Sun.COM if (getDiscPortAttrs(handle, portIndex,
15637836SJohn.Forte@Sun.COM discIndex, &discPortAttrs)) {
15647836SJohn.Forte@Sun.COM dev_cs_failed++;
15657836SJohn.Forte@Sun.COM /* Move on to the next target */
15667836SJohn.Forte@Sun.COM continue;
15677836SJohn.Forte@Sun.COM }
15687836SJohn.Forte@Sun.COM (void) sprintf(port_wwn, "%016llx",
15697836SJohn.Forte@Sun.COM wwnConversion(discPortAttrs.PortWWN.wwn));
15707836SJohn.Forte@Sun.COM /*
15717836SJohn.Forte@Sun.COM * Construct a fake apid string similar to the one the
15727836SJohn.Forte@Sun.COM * plugin gets from the framework and have apidt_create()
15737836SJohn.Forte@Sun.COM * fill in the apid_t structure.
15747836SJohn.Forte@Sun.COM */
15757836SJohn.Forte@Sun.COM strcpy(my_apid, apidt->xport_phys);
15767836SJohn.Forte@Sun.COM strcat(my_apid, DYN_SEP);
15777836SJohn.Forte@Sun.COM strcat(my_apid, port_wwn);
15787836SJohn.Forte@Sun.COM if (apidt_create(my_apid, &my_apidt, errstring) != FPCFGA_OK) {
15797836SJohn.Forte@Sun.COM dev_cs_failed++;
15807836SJohn.Forte@Sun.COM continue;
15817836SJohn.Forte@Sun.COM }
15827836SJohn.Forte@Sun.COM my_apidt.flags = apidt->flags;
15837836SJohn.Forte@Sun.COM
15847836SJohn.Forte@Sun.COM memcpy(&pwwn, &(discPortAttrs.PortWWN), sizeof (la_wwn_t));
15857836SJohn.Forte@Sun.COM if (dev_change_state(cmd, &my_apidt, &pwwn,
15867836SJohn.Forte@Sun.COM flags, errstring, handle, portAttrs) != FPCFGA_OK) {
15877836SJohn.Forte@Sun.COM dev_cs_failed++;
15887836SJohn.Forte@Sun.COM }
15897836SJohn.Forte@Sun.COM apidt_free(&my_apidt);
15907836SJohn.Forte@Sun.COM }
15917836SJohn.Forte@Sun.COM
15927836SJohn.Forte@Sun.COM S_FREE(my_apid);
15937836SJohn.Forte@Sun.COM
15947836SJohn.Forte@Sun.COM /*
15957836SJohn.Forte@Sun.COM * We have now handled all the devices that are currently visible
15967836SJohn.Forte@Sun.COM * through the given FCA port. But, it is possible that there are
15977836SJohn.Forte@Sun.COM * some devinfo nodes hanging around. For the unconfigure operation,
15987836SJohn.Forte@Sun.COM * this has to be looked into too.
15997836SJohn.Forte@Sun.COM */
16007836SJohn.Forte@Sun.COM if (cmd == CFGA_CMD_UNCONFIGURE) {
16017836SJohn.Forte@Sun.COM /* dev_cs_failed will be updated to indicate any failures */
16027836SJohn.Forte@Sun.COM rval = unconf_any_devinfo_nodes(apidt, flags, errstring,
16037836SJohn.Forte@Sun.COM &num_devs, &dev_cs_failed);
16047836SJohn.Forte@Sun.COM }
16057836SJohn.Forte@Sun.COM
16067836SJohn.Forte@Sun.COM if (rval == FPCFGA_OK) {
16077836SJohn.Forte@Sun.COM if (dev_cs_failed == 0)
16087836SJohn.Forte@Sun.COM return (FPCFGA_OK);
16097836SJohn.Forte@Sun.COM
16107836SJohn.Forte@Sun.COM /*
16117836SJohn.Forte@Sun.COM * For the discovered ports, num_devs is counted on target
16127836SJohn.Forte@Sun.COM * basis, but for invisible targets, num_devs is counted on
16137836SJohn.Forte@Sun.COM * lun basis.
16147836SJohn.Forte@Sun.COM *
16157836SJohn.Forte@Sun.COM * But if dev_cs_failed and num_devs are incremented
16167836SJohn.Forte@Sun.COM * consistently, comparation of these two counters is still
16177836SJohn.Forte@Sun.COM * meaningful.
16187836SJohn.Forte@Sun.COM */
16197836SJohn.Forte@Sun.COM if (dev_cs_failed == num_devs) {
16207836SJohn.Forte@Sun.COM /* Failed on all devices seen through this FCA port */
16217836SJohn.Forte@Sun.COM cfga_err(errstring, 0,
16227836SJohn.Forte@Sun.COM ((cmd == CFGA_CMD_CONFIGURE) ?
16237836SJohn.Forte@Sun.COM ERR_FCA_CONFIGURE : ERR_FCA_UNCONFIGURE), 0);
16247836SJohn.Forte@Sun.COM return (FPCFGA_LIB_ERR);
16257836SJohn.Forte@Sun.COM } else {
16267836SJohn.Forte@Sun.COM /* Failed only on some of the devices */
16277836SJohn.Forte@Sun.COM cfga_err(errstring, 0, ERR_PARTIAL_SUCCESS, 0);
16287836SJohn.Forte@Sun.COM return (FPCFGA_LIB_ERR);
16297836SJohn.Forte@Sun.COM }
16307836SJohn.Forte@Sun.COM } else {
16317836SJohn.Forte@Sun.COM if (dev_cs_failed == num_devs) {
16327836SJohn.Forte@Sun.COM /* Failed on all devices seen through this FCA port */
16337836SJohn.Forte@Sun.COM cfga_err(errstring, 0,
16347836SJohn.Forte@Sun.COM ((cmd == CFGA_CMD_CONFIGURE) ?
16357836SJohn.Forte@Sun.COM ERR_FCA_CONFIGURE : ERR_FCA_UNCONFIGURE), 0);
16367836SJohn.Forte@Sun.COM return (FPCFGA_LIB_ERR);
16377836SJohn.Forte@Sun.COM } else {
16387836SJohn.Forte@Sun.COM /* Failed only on some of the devices */
16397836SJohn.Forte@Sun.COM cfga_err(errstring, 0, ERR_PARTIAL_SUCCESS, 0);
16407836SJohn.Forte@Sun.COM return (FPCFGA_LIB_ERR);
16417836SJohn.Forte@Sun.COM }
16427836SJohn.Forte@Sun.COM }
16437836SJohn.Forte@Sun.COM
16447836SJohn.Forte@Sun.COM /*
16457836SJohn.Forte@Sun.COM * Should never get here
16467836SJohn.Forte@Sun.COM */
16477836SJohn.Forte@Sun.COM }
16487836SJohn.Forte@Sun.COM
16497836SJohn.Forte@Sun.COM fpcfga_ret_t
fca_change_state(cfga_cmd_t state_change_cmd,apid_t * apidt,cfga_flags_t flags,char ** errstring)16507836SJohn.Forte@Sun.COM fca_change_state(cfga_cmd_t state_change_cmd, apid_t *apidt,
16517836SJohn.Forte@Sun.COM cfga_flags_t flags, char **errstring)
16527836SJohn.Forte@Sun.COM {
16537836SJohn.Forte@Sun.COM fpcfga_ret_t ret;
16547836SJohn.Forte@Sun.COM HBA_HANDLE handle;
16557836SJohn.Forte@Sun.COM HBA_PORTATTRIBUTES portAttrs;
16567836SJohn.Forte@Sun.COM int portIndex;
16577836SJohn.Forte@Sun.COM
16587836SJohn.Forte@Sun.COM if ((ret = findMatchingAdapterPort(apidt->xport_phys, &handle,
16597836SJohn.Forte@Sun.COM &portIndex, &portAttrs, errstring)) != FPCFGA_OK) {
16607836SJohn.Forte@Sun.COM return (ret);
16617836SJohn.Forte@Sun.COM }
16627836SJohn.Forte@Sun.COM
16637836SJohn.Forte@Sun.COM /*
16647836SJohn.Forte@Sun.COM * Bail out if not fabric/public loop
16657836SJohn.Forte@Sun.COM */
16667836SJohn.Forte@Sun.COM switch (state_change_cmd) {
16677836SJohn.Forte@Sun.COM case CFGA_CMD_CONFIGURE:
16687836SJohn.Forte@Sun.COM if (portAttrs.PortType != HBA_PORTTYPE_NLPORT &&
16697836SJohn.Forte@Sun.COM portAttrs.PortType != HBA_PORTTYPE_NPORT) {
16707836SJohn.Forte@Sun.COM HBA_CloseAdapter(handle);
16717836SJohn.Forte@Sun.COM HBA_FreeLibrary();
16727836SJohn.Forte@Sun.COM return (FPCFGA_OK);
16737836SJohn.Forte@Sun.COM }
16747836SJohn.Forte@Sun.COM break;
16757836SJohn.Forte@Sun.COM
16767836SJohn.Forte@Sun.COM case CFGA_CMD_UNCONFIGURE:
16777836SJohn.Forte@Sun.COM if (portAttrs.PortType != HBA_PORTTYPE_NLPORT &&
16787836SJohn.Forte@Sun.COM portAttrs.PortType != HBA_PORTTYPE_NPORT) {
16797836SJohn.Forte@Sun.COM HBA_CloseAdapter(handle);
16807836SJohn.Forte@Sun.COM HBA_FreeLibrary();
16817836SJohn.Forte@Sun.COM return (FPCFGA_OPNOTSUPP);
16827836SJohn.Forte@Sun.COM }
16837836SJohn.Forte@Sun.COM break;
16847836SJohn.Forte@Sun.COM default:
16857836SJohn.Forte@Sun.COM HBA_CloseAdapter(handle);
16867836SJohn.Forte@Sun.COM HBA_FreeLibrary();
16877836SJohn.Forte@Sun.COM return (FPCFGA_LIB_ERR);
16887836SJohn.Forte@Sun.COM }
16897836SJohn.Forte@Sun.COM ret = (handle_devs(state_change_cmd, apidt, flags, errstring,
16907836SJohn.Forte@Sun.COM handle, portIndex, portAttrs));
16917836SJohn.Forte@Sun.COM HBA_CloseAdapter(handle);
16927836SJohn.Forte@Sun.COM HBA_FreeLibrary();
16937836SJohn.Forte@Sun.COM return (ret);
16947836SJohn.Forte@Sun.COM }
1695