diff options
author | cth <none@none> | 2007-05-01 05:33:55 -0700 |
---|---|---|
committer | cth <none@none> | 2007-05-01 05:33:55 -0700 |
commit | f4da9be01648d6afa604495d9b9956dddeb92a8c (patch) | |
tree | e3730f62fe03f317264d5c836fe4e6710acc729f | |
parent | 75c7619736838143dd41b3c5c9d7adec4683488f (diff) | |
download | illumos-joyent-f4da9be01648d6afa604495d9b9956dddeb92a8c.tar.gz |
PSARC 2007/176 path-oriented driver alias
6536151 path-oriented driver alias
-rw-r--r-- | usr/src/cmd/mdb/common/modules/genunix/devinfo.c | 36 | ||||
-rw-r--r-- | usr/src/cmd/mdb/common/modules/mdb_ks/mdb_ks.c | 7 | ||||
-rw-r--r-- | usr/src/cmd/mdb/i86pc/modules/uppc/uppc.c | 2 | ||||
-rw-r--r-- | usr/src/cmd/modload/add_drv.c | 15 | ||||
-rw-r--r-- | usr/src/cmd/modload/addrem.h | 12 | ||||
-rw-r--r-- | usr/src/cmd/modload/drvsubr.c | 117 | ||||
-rw-r--r-- | usr/src/cmd/modload/errmsg.h | 9 | ||||
-rw-r--r-- | usr/src/cmd/modload/rem_drv.c | 9 | ||||
-rw-r--r-- | usr/src/cmd/modload/update_drv.c | 20 | ||||
-rw-r--r-- | usr/src/uts/common/os/autoconf.c | 9 | ||||
-rw-r--r-- | usr/src/uts/common/os/devcfg.c | 341 | ||||
-rw-r--r-- | usr/src/uts/common/os/modsysfile.c | 4 | ||||
-rw-r--r-- | usr/src/uts/common/os/sunddi.c | 16 | ||||
-rw-r--r-- | usr/src/uts/common/os/swapgeneric.c | 84 | ||||
-rw-r--r-- | usr/src/uts/common/sys/ddi_impldefs.h | 10 | ||||
-rw-r--r-- | usr/src/uts/common/sys/ndi_impldefs.h | 13 |
16 files changed, 546 insertions, 158 deletions
diff --git a/usr/src/cmd/mdb/common/modules/genunix/devinfo.c b/usr/src/cmd/mdb/common/modules/genunix/devinfo.c index adab304cdb..296fa0c414 100644 --- a/usr/src/cmd/mdb/common/modules/genunix/devinfo.c +++ b/usr/src/cmd/mdb/common/modules/genunix/devinfo.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -1072,7 +1072,7 @@ devinfo(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) { char tmpstr[MODMAXNAMELEN]; char nodename[MODMAXNAMELEN]; - char bindname[MODMAXNAMELEN]; + char bindname[MAXPATHLEN]; int size, length; struct dev_info devi; devinfo_node_t din; @@ -1082,6 +1082,7 @@ devinfo(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) { "DEVICE_OFFLINE", DEVI_DEVICE_OFFLINE, DEVI_DEVICE_OFFLINE }, { "DEVICE_DOWN", DEVI_DEVICE_DOWN, DEVI_DEVICE_DOWN }, { "DEVICE_DEGRADED", DEVI_DEVICE_DEGRADED, DEVI_DEVICE_DEGRADED }, + { "DEVICE_REMOVED", DEVI_DEVICE_REMOVED, DEVI_DEVICE_REMOVED }, { "BUS_QUIESCED", DEVI_BUS_QUIESCED, DEVI_BUS_QUIESCED }, { "BUS_DOWN", DEVI_BUS_DOWN, DEVI_BUS_DOWN }, { "NDI_CONFIG", DEVI_NDI_CONFIG, DEVI_NDI_CONFIG }, @@ -1096,6 +1097,7 @@ devinfo(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) { "S_REPORT", DEVI_S_REPORT, DEVI_S_REPORT }, { "S_EVADD", DEVI_S_EVADD, DEVI_S_EVADD }, { "S_EVREMOVE", DEVI_S_EVREMOVE, DEVI_S_EVREMOVE }, + { "S_NEED_RESET", DEVI_S_NEED_RESET, DEVI_S_NEED_RESET }, { NULL, 0, 0 } }; @@ -1105,6 +1107,13 @@ devinfo(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) { "ATTACHED_CHILDREN", DEVI_ATTACHED_CHILDREN, DEVI_ATTACHED_CHILDREN}, { "BRANCH_HELD", DEVI_BRANCH_HELD, DEVI_BRANCH_HELD }, + { "NO_BIND", DEVI_NO_BIND, DEVI_NO_BIND }, + { "DEVI_REGISTERED_DEVID", + DEVI_REGISTERED_DEVID, DEVI_REGISTERED_DEVID }, + { "PHCI_SIGNALS_VHCI", + DEVI_PHCI_SIGNALS_VHCI, + DEVI_PHCI_SIGNALS_VHCI }, + { "REBIND", DEVI_REBIND, DEVI_REBIND }, { NULL, 0, 0 } }; @@ -1716,9 +1725,8 @@ binding_hash_entry(uintptr_t addr, uint_t flags, int argc, { struct bind bind; /* Arbitrary lengths based on output format below */ - char name[25] = "???"; - char bind_name[32] = "<null>"; - + char name[MAXPATHLEN] = "???"; + char bind_name[MAXPATHLEN] = "<null>"; if ((flags & DCMD_ADDRSPEC) == NULL) return (DCMD_USAGE); @@ -1733,18 +1741,22 @@ binding_hash_entry(uintptr_t addr, uint_t flags, int argc, } if (DCMD_HDRSPEC(flags)) { - mdb_printf("%<u>%-32s %-5s %-?s%</u>\n", - "NAME", "MAJOR", "NEXT"); + mdb_printf("%<u>%?s% %-5s %s%</u>\n", + "NEXT", "MAJOR", "NAME(S)"); } if (mdb_readstr(name, sizeof (name), (uintptr_t)bind.b_name) == -1) mdb_warn("failed to read 'name'"); - /* There may be no binding name for a driver, so this may fail */ - (void) mdb_readstr(bind_name, sizeof (bind_name), - (uintptr_t)bind.b_bind_name); - - mdb_printf("%-32s %3d %?p\n", name, bind.b_num, bind.b_next); + /* There may be bind_name, so this may fail */ + if (mdb_readstr(bind_name, sizeof (bind_name), + (uintptr_t)bind.b_bind_name) == -1) { + mdb_printf("%?p %5d %s\n", + bind.b_next, bind.b_num, name); + } else { + mdb_printf("%?p %5d %s %s\n", + bind.b_next, bind.b_num, name, bind_name); + } return (DCMD_OK); } diff --git a/usr/src/cmd/mdb/common/modules/mdb_ks/mdb_ks.c b/usr/src/cmd/mdb/common/modules/mdb_ks/mdb_ks.c index 869c58c6e0..3d7537a1d6 100644 --- a/usr/src/cmd/mdb/common/modules/mdb_ks/mdb_ks.c +++ b/usr/src/cmd/mdb/common/modules/mdb_ks/mdb_ks.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -863,8 +863,7 @@ find_mbind(const char *name, uintptr_t *hashtab) int hashndx; uintptr_t mb; struct bind mb_local; - char node_name[MODMAXNAMELEN + 1]; - + char node_name[MAXPATHLEN + 1]; hashndx = nm_hash(name); mb = hashtab[hashndx]; @@ -944,7 +943,7 @@ int mdb_devinfo2driver(uintptr_t dip_addr, char *drivername, size_t namebufsize) { struct dev_info devinfo; - char bind_name[MODMAXNAMELEN + 1]; + char bind_name[MAXPATHLEN + 1]; major_t major; const char *namestr; diff --git a/usr/src/cmd/mdb/i86pc/modules/uppc/uppc.c b/usr/src/cmd/mdb/i86pc/modules/uppc/uppc.c index fee48b58f5..0bd87f8a65 100644 --- a/usr/src/cmd/mdb/i86pc/modules/uppc/uppc.c +++ b/usr/src/cmd/mdb/i86pc/modules/uppc/uppc.c @@ -33,7 +33,7 @@ static uint16_t shared_tbl[MAX_ISA_IRQ + 1]; static char * interrupt_print_bus(uintptr_t dip_addr) { - char bind_name[MODMAXNAMELEN + 1]; + char bind_name[MAXPATHLEN + 1]; struct dev_info dev_info; if (mdb_vread(&dev_info, sizeof (dev_info), dip_addr) == -1) { diff --git a/usr/src/cmd/modload/add_drv.c b/usr/src/cmd/modload/add_drv.c index d40eec2902..62da6d8796 100644 --- a/usr/src/cmd/modload/add_drv.c +++ b/usr/src/cmd/modload/add_drv.c @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -525,7 +524,7 @@ update_driver_classes( { /* make call to update the classes file */ return (append_to_file(driver_name, classes, driver_classes, - ' ', "\t")); + ' ', "\t", 0)); } static int @@ -533,7 +532,8 @@ update_minor_perm( char *driver_name, char *perm_list) { - return (append_to_file(driver_name, perm_list, minor_perm, ',', ":")); + return (append_to_file(driver_name, perm_list, minor_perm, + ',', ":", 0)); } @@ -567,7 +567,8 @@ update_extra_privs( char *driver_name, char *privlist) { - return (append_to_file(driver_name, privlist, extra_privs, ',', ":")); + return (append_to_file(driver_name, privlist, extra_privs, + ',', ":", 0)); } /* diff --git a/usr/src/cmd/modload/addrem.h b/usr/src/cmd/modload/addrem.h index e4b70bea10..c1763c760d 100644 --- a/usr/src/cmd/modload/addrem.h +++ b/usr/src/cmd/modload/addrem.h @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -125,9 +124,9 @@ extern int check_name_to_major(int); extern void enter_lock(void); extern void err_exit(void); extern void exit_unlock(void); -extern char *get_entry(char *, char *, char); +extern char *get_entry(char *, char *, char, int); extern int build_filenames(char *); -extern int append_to_file(char *, char *, char *, char, char *); +extern int append_to_file(char *, char *, char *, char, char *, int); extern int get_major_no(char *, char *); extern int get_driver_name(int, char *, char *); extern int delete_entry(char *, char *, char *, char *); @@ -139,6 +138,7 @@ extern int update_name_to_major(char *, major_t *, int); extern int do_the_update(char *, char *); extern int fill_n2m_array(char *, char **, int *); extern int aliases_unique(char *); +extern int aliases_paths_exist(char *); extern int update_driver_aliases(char *, char *); extern int unique_driver_name(char *, char *, int *); extern int unique_drv_alias(char *); diff --git a/usr/src/cmd/modload/drvsubr.c b/usr/src/cmd/modload/drvsubr.c index f1fb38add3..37daeaf6f7 100644 --- a/usr/src/cmd/modload/drvsubr.c +++ b/usr/src/cmd/modload/drvsubr.c @@ -106,7 +106,8 @@ append_to_file( char *entry_list, char *filename, char list_separator, - char *entry_separator) + char *entry_separator, + int quoted) { int i, len; int fpint; @@ -153,12 +154,16 @@ append_to_file( line[i] = 0; current_head = get_entry(previous_head, one_entry, - list_separator); + list_separator, quoted); previous_head = current_head; (void) strcpy(line, driver_name); (void) strcat(line, entry_separator); + if (quoted) + (void) strcat(line, "\""); (void) strcat(line, one_entry); + if (quoted) + (void) strcat(line, "\""); (void) strcat(line, "\n"); if ((fputs(line, fp)) == EOF) { @@ -615,16 +620,20 @@ get_name_to_major_entry(int *major_no, char *driver_name, char *file_name) } /* - * given pointer to member n in space separated list, return pointer - * to member n+1, return member n + * Given pointer to begining of member 'n' in a space (or separator) + * separated list, return pointer to member 'n+1', and establish member 'n' + * in *current_entry. If unquote, then we skip a leading quote and treat + * the trailing quote as a separator (and skip). */ char * get_entry( char *prev_member, char *current_entry, - char separator) + char separator, + int unquote) { - char *ptr; + char *ptr; + int quoted = 0; ptr = prev_member; @@ -632,14 +641,25 @@ get_entry( while (*ptr == '\t' || *ptr == ' ') ptr++; - /* read thru the current entry */ - while (*ptr != separator && *ptr != '\0') { + /* if unquote skip leading quote */ + if (unquote && *ptr == '"') { + quoted++; + ptr++; + } + + /* read thru the current entry looking for end, separator, or unquote */ + while (*ptr && + (*ptr != separator) && + ((separator != ' ') || (*ptr != '\t')) && + (!quoted || (*ptr != '"'))) { *current_entry++ = *ptr++; } *current_entry = '\0'; - if ((separator == ',') && (*ptr == separator)) - ptr++; /* skip over comma */ + if (separator && (*ptr == separator)) + ptr++; /* skip over separator */ + if (quoted && (*ptr == '"')) + ptr++; /* skip over trailing quote */ /* skip white space */ while (*ptr == '\t' || *ptr == ' ') { @@ -1003,7 +1023,7 @@ config_driver( return (ERROR); } current = get_entry(previous, - cmdline[n++], ' '); + cmdline[n++], ' ', 0); previous = current; } while (*current != '\0'); @@ -1395,7 +1415,7 @@ check_perm_opts(char *perm_list) for (i = 0; i <= len; i++) one_entry[i] = 0; - current_head = get_entry(previous_head, one_entry, ','); + current_head = get_entry(previous_head, one_entry, ',', 0); previous_head = current_head; scan_stat = sscanf(one_entry, "%s%s%s%s%s", minor, perm, own, @@ -1453,7 +1473,7 @@ aliases_unique(char *aliases) for (i = 0; i <= len; i++) one_entry[i] = 0; - current_head = get_entry(previous_head, one_entry, ' '); + current_head = get_entry(previous_head, one_entry, ' ', 1); previous_head = current_head; if ((unique_driver_name(one_entry, name_to_major, @@ -1490,14 +1510,66 @@ aliases_unique(char *aliases) } +/* + * check each alias : + * if path-oriented alias, path exists + */ +int +aliases_paths_exist(char *aliases) +{ + char *current_head; + char *previous_head; + char *one_entry; + int i, len; + char path[MAXPATHLEN]; + struct stat buf; + + len = strlen(aliases); + + one_entry = calloc(len + 1, 1); + if (one_entry == NULL) { + (void) fprintf(stderr, gettext(ERR_NO_MEM)); + return (ERROR); + } + + previous_head = aliases; + + do { + for (i = 0; i <= len; i++) + one_entry[i] = 0; + + current_head = get_entry(previous_head, one_entry, ' ', 1); + previous_head = current_head; + + /* if the alias is a path, ensure that the path exists */ + if (*one_entry != '/') + continue; + (void) snprintf(path, sizeof (path), "/devices/%s", one_entry); + if (stat(path, &buf) == 0) + continue; + + /* no device at specified path-oriented alias path */ + (void) fprintf(stderr, gettext(ERR_PATH_ORIENTED_ALIAS), + one_entry); + free(one_entry); + return (ERROR); + + } while (*current_head != '\0'); + + free(one_entry); + + return (NOERR); +} + + int update_driver_aliases( char *driver_name, char *aliases) { /* make call to update the aliases file */ - return (append_to_file(driver_name, aliases, driver_aliases, ' ', " ")); - + return (append_to_file(driver_name, aliases, driver_aliases, + ' ', " ", 1)); } @@ -1508,6 +1580,7 @@ unique_drv_alias(char *drv_alias) char drv[FILENAME_MAX + 1]; char line[MAX_N2M_ALIAS_LINE + 1], *cp; char alias[FILENAME_MAX + 1]; + char *a; int status = NOERR; fp = fopen(driver_aliases, "r"); @@ -1526,8 +1599,16 @@ unique_drv_alias(char *drv_alias) (void) fprintf(stderr, gettext(ERR_BAD_LINE), driver_aliases, line); + /* unquote for compare */ + if ((*alias == '"') && + (*(alias + strlen(alias) - 1) == '"')) { + a = &alias[1]; + alias[strlen(alias) - 1] = '\0'; + } else + a = alias; + if ((strcmp(drv_alias, drv) == 0) || - (strcmp(drv_alias, alias) == 0)) { + (strcmp(drv_alias, a) == 0)) { (void) fprintf(stderr, gettext(ERR_ALIAS_IN_USE), drv_alias); @@ -1656,7 +1737,7 @@ update_name_to_major(char *driver_name, major_t *major_num, int server) "%d", is_unique); if (append_to_file(driver_name, major, - name_to_major, ' ', " ") == ERROR) { + name_to_major, ' ', " ", 0) == ERROR) { (void) fprintf(stderr, gettext(ERR_NO_UPDATE), name_to_major); @@ -1857,7 +1938,7 @@ int do_the_update(char *driver_name, char *major_number) { return (append_to_file(driver_name, major_number, name_to_major, - ' ', " ")); + ' ', " ", 0)); } /* diff --git a/usr/src/cmd/modload/errmsg.h b/usr/src/cmd/modload/errmsg.h index 6412f4d24b..a29f866cd9 100644 --- a/usr/src/cmd/modload/errmsg.h +++ b/usr/src/cmd/modload/errmsg.h @@ -56,8 +56,10 @@ extern "C" { #define ERR_INSTALL_FAIL "Error: Could not install driver (%s).\n" #define ERR_DRVNAME_TOO_LONG "Error: driver name must not exceed (%d)" \ " characters; driver name too long (%s)\n" -#define ERR_ALIAS_IN_NAM_MAJ "Alias (%s) already in use as driver name.\n" -#define ERR_ALIAS_IN_USE "(%s) already in use as a driver or alias.\n" +#define ERR_ALIAS_IN_NAM_MAJ \ +"Alias (\"%s\") already in use as driver name.\n" +#define ERR_ALIAS_IN_USE \ +"(\"%s\") already in use as a driver or alias.\n" #define ERR_CANT_ACCESS_FILE "Cannot access file (%s).\n" #define ERR_BAD_PATH "Bad syntax for pathname : (%s)\n" #define ERR_FORK_FAIL "Fork failed; cannot exec : %s\n" @@ -171,6 +173,9 @@ Use octal escape sequence \"\\040\".\n" #define ERR_REMDRV_CLEANUP \ "post-rem_drv devfs cleanup for driver %s failed (%d)\n" +#define ERR_PATH_ORIENTED_ALIAS \ + "no device at specified path-oriented alias \"%s\"\n" + #ifdef __cplusplus } #endif diff --git a/usr/src/cmd/modload/rem_drv.c b/usr/src/cmd/modload/rem_drv.c index 189cc5e9d9..761c52b60c 100644 --- a/usr/src/cmd/modload/rem_drv.c +++ b/usr/src/cmd/modload/rem_drv.c @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -169,7 +168,7 @@ main(int argc, char *argv[]) (void) sprintf(maj_num, "%d", found); if (append_to_file(driver_name, maj_num, - rem_name_to_major, ' ', " ") == ERROR) { + rem_name_to_major, ' ', " ", 0) == ERROR) { (void) fprintf(stderr, gettext(ERR_NO_UPDATE), rem_name_to_major); err_exit(); diff --git a/usr/src/cmd/modload/update_drv.c b/usr/src/cmd/modload/update_drv.c index 6b49f43a5f..8efbc6d7e9 100644 --- a/usr/src/cmd/modload/update_drv.c +++ b/usr/src/cmd/modload/update_drv.c @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -270,7 +269,7 @@ main(int argc, char *argv[]) if (priv != NULL) { (void) append_to_file(driver_name, priv, extra_privs, - ',', ":"); + ',', ":", 0); cleanup_flag |= CLEAN_DRV_PRIV; } @@ -306,6 +305,17 @@ main(int argc, char *argv[]) return (error); } + /* + * unless force_flag is specified check that + * path-oriented aliases we are adding exist + */ + if ((force_flag == 0) && + ((error = aliases_paths_exist(aliases)) == ERROR)) { + exit_unlock(); + + return (error); + } + /* update the file */ if ((error = update_driver_aliases(driver_name, aliases)) == ERROR) { diff --git a/usr/src/uts/common/os/autoconf.c b/usr/src/uts/common/os/autoconf.c index 95c236cff6..2adffdd7b0 100644 --- a/usr/src/uts/common/os/autoconf.c +++ b/usr/src/uts/common/os/autoconf.c @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -403,8 +402,6 @@ create_devinfo_tree(void) void i_ddi_init_root() { - extern int i_ndi_make_spec_children(dev_info_t *, uint_t); - #ifdef DDI_PROP_DEBUG (void) ddi_prop_debug(1); /* Enable property debugging */ #endif /* DDI_PROP_DEBUG */ diff --git a/usr/src/uts/common/os/devcfg.c b/usr/src/uts/common/os/devcfg.c index 9a2b6b745f..5e8eeca828 100644 --- a/usr/src/uts/common/os/devcfg.c +++ b/usr/src/uts/common/os/devcfg.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -144,6 +144,9 @@ int di_cache_debug = 0; /* For ddvis, which needs pseudo children under PCI */ int pci_allow_pseudo_children = 0; +/* Allow path-oriented alias driver binding on driver.conf enumerated nodes */ +int driver_conf_allow_path_alias = 1; + /* * The following switch is for service people, in case a * 3rd party driver depends on identify(9e) being called. @@ -187,6 +190,7 @@ ndi_devi_config_obp_args(dev_info_t *parent, char *devnm, static void i_link_vhci_node(dev_info_t *); static void ndi_devi_exit_and_wait(dev_info_t *dip, int circular, clock_t end_time); +static int ndi_devi_unbind_driver(dev_info_t *dip); /* * dev_info cache and node management @@ -233,9 +237,10 @@ i_ddi_alloc_node(dev_info_t *pdip, char *node_name, pnode_t nodeid, if ((devi->devi_node_name = i_ddi_strdup(node_name, flag)) == NULL) goto fail; + /* default binding name is node name */ devi->devi_binding_name = devi->devi_node_name; - devi->devi_major = (major_t)-1; /* unbound by default */ + devi->devi_major = (major_t)-1; /* unbound by default */ /* * Make a copy of system property @@ -369,6 +374,9 @@ i_ddi_free_node(dev_info_t *dip) if (DEVI(dip)->devi_compat_names) kmem_free(DEVI(dip)->devi_compat_names, DEVI(dip)->devi_compat_length); + if (DEVI(dip)->devi_rebinding_name) + kmem_free(DEVI(dip)->devi_rebinding_name, + strlen(DEVI(dip)->devi_rebinding_name) + 1); ddi_prop_remove_all(dip); /* remove driver properties */ if (devi->devi_sys_prop_ptr) @@ -573,13 +581,13 @@ link_node(dev_info_t *dip) * Extending the workaround to IB Nexus/VHCI * driver also. */ - if (strcmp(devi->devi_name, "scsi_vhci") == 0) { + if (strcmp(devi->devi_binding_name, "scsi_vhci") == 0) { /* Add scsi_vhci to beginning of list */ ASSERT((dev_info_t *)parent == top_devinfo); /* scsi_vhci under rootnex */ devi->devi_sibling = parent->devi_child; parent->devi_child = devi; - } else if (strcmp(devi->devi_name, "ib") == 0) { + } else if (strcmp(devi->devi_binding_name, "ib") == 0) { i_link_vhci_node(dip); } else { /* Add to end of list */ @@ -732,7 +740,9 @@ unbind_node(dev_info_t *dip) (void *)dip, ddi_node_name(dip))); unlink_from_driver_list(dip); + DEVI(dip)->devi_major = (major_t)-1; + DEVI(dip)->devi_binding_name = DEVI(dip)->devi_node_name; return (DDI_SUCCESS); } @@ -749,6 +759,7 @@ init_node(dev_info_t *dip) dev_info_t *pdip = ddi_get_parent(dip); int (*f)(dev_info_t *, dev_info_t *, ddi_ctl_enum_t, void *, void *); char *path; + major_t major; ASSERT(i_ddi_node_state(dip) == DS_BOUND); @@ -789,14 +800,14 @@ init_node(dev_info_t *dip) ndi_hold_devi(pdip); - /* check for duplicate nodes */ - if (find_duplicate_child(pdip, dip) != NULL) { - /* recompute path after initchild for @addr information */ - (void) ddi_pathname(dip, path); + /* recompute path after initchild for @addr information */ + (void) ddi_pathname(dip, path); + /* Check for duplicate nodes */ + if (find_duplicate_child(pdip, dip) != NULL) { /* * uninit_node() the duplicate - a successful uninit_node() - * does a ndi_rele_devi + * does a ndi_rele_devi. */ if ((error = uninit_node(dip)) != DDI_SUCCESS) { ndi_rele_devi(pdip); @@ -811,13 +822,100 @@ init_node(dev_info_t *dip) } /* + * Check to see if we have a path-oriented driver alias that overrides + * the current driver binding. If so, we need to rebind. This check + * needs to be delayed until after a successful DDI_CTLOPS_INITCHILD, + * so the unit-address is established on the last component of the path. + * + * NOTE: Allowing a path-oriented alias to change the driver binding + * of a driver.conf node results in non-intuitive property behavior. + * We provide a tunable (driver_conf_allow_path_alias) to control + * this behavior. See uninit_node() for more details. + * + * NOTE: If you are adding a path-oriented alias for the boot device, + * and there is mismatch between OBP and the kernel in regard to + * generic name use, like "disk" .vs. "ssd", then you will need + * to add a path-oriented alias for both paths. + */ + major = ddi_name_to_major(path); + if ((major != (major_t)-1) && + !(devnamesp[major].dn_flags & DN_DRIVER_REMOVED) && + (major != DEVI(dip)->devi_major) && + (ndi_dev_is_persistent_node(dip) || driver_conf_allow_path_alias)) { + + /* Mark node for rebind processing. */ + mutex_enter(&DEVI(dip)->devi_lock); + DEVI(dip)->devi_flags |= DEVI_REBIND; + mutex_exit(&DEVI(dip)->devi_lock); + + /* + * uninit_node() current binding - a successful uninit_node() + * does a ndi_rele_devi. + */ + if ((error = uninit_node(dip)) != DDI_SUCCESS) { + ndi_rele_devi(pdip); + cmn_err(CE_WARN, "init_node: uninit for rebind " + "of node %s failed", path); + goto out; + } + + /* Unbind: demote the node back to DS_LINKED. */ + if ((error = ndi_devi_unbind_driver(dip)) != DDI_SUCCESS) { + cmn_err(CE_WARN, "init_node: unbind for rebind " + "of node %s failed", path); + goto out; + } + + /* establish rebinding name */ + if (DEVI(dip)->devi_rebinding_name == NULL) + DEVI(dip)->devi_rebinding_name = + i_ddi_strdup(path, KM_SLEEP); + + /* + * Now that we are demoted and marked for rebind, repromote. + * We need to do this in steps, instead of just calling + * ddi_initchild, so that we can redo the merge operation + * after we are rebound to the path-bound driver. + * + * Start by rebinding node to the path-bound driver. + */ + if ((error = ndi_devi_bind_driver(dip, 0)) != DDI_SUCCESS) { + cmn_err(CE_WARN, "init_node: rebind " + "of node %s failed", path); + goto out; + } + + /* + * If the node is not a driver.conf node then merge + * driver.conf properties from new path-bound driver.conf. + */ + if (ndi_dev_is_persistent_node(dip)) + (void) i_ndi_make_spec_children(pdip, 0); + + /* + * Now that we have taken care of merge, repromote back + * to DS_INITIALIZED. + */ + error = ddi_initchild(pdip, dip); + NDI_CONFIG_DEBUG((CE_CONT, "init_node: rebind " + "%s 0x%p\n", path, (void *)dip)); + goto out; + } + + /* * Apply multi-parent/deep-nexus optimization to the new node */ DEVI(dip)->devi_instance = e_ddi_assign_instance(dip); ddi_optimize_dtree(dip); error = DDI_SUCCESS; -out: kmem_free(path, MAXPATHLEN); +out: if (error != DDI_SUCCESS) { + /* On failure ensure that DEVI_REBIND is cleared */ + mutex_enter(&DEVI(dip)->devi_lock); + DEVI(dip)->devi_flags &= ~DEVI_REBIND; + mutex_exit(&DEVI(dip)->devi_lock); + } + kmem_free(path, MAXPATHLEN); return (error); } @@ -888,7 +986,33 @@ uninit_node(dev_info_t *dip) ndi_rele_devi(pdip); remove_global_props(dip); - e_ddi_prop_remove_all(dip); + + /* + * NOTE: The decision on whether to allow a path-oriented + * rebind of a driver.conf enumerated node is made by + * init_node() based on driver_conf_allow_path_alias. The + * rebind code below prevents deletion of system properties + * on driver.conf nodes. + * + * When driver_conf_allow_path_alias is set, property behavior + * on rebound driver.conf file is non-intuitive. For a + * driver.conf node, the unit-address properties come from + * the driver.conf file as system properties. Removing system + * properties from a driver.conf node makes the node + * useless (we get node without unit-address properties) - so + * we leave system properties in place. The result is a node + * where system properties come from the node being rebound, + * and global properties come from the driver.conf file + * of the driver we are rebinding to. If we could determine + * that the path-oriented alias driver.conf file defined a + * node at the same unit address, it would be best to use + * that node and avoid the non-intuitive property behavior. + * Unfortunately, the current "merge" code does not support + * this, so we live with the non-intuitive property behavior. + */ + if (!((ndi_dev_is_persistent_node(dip) == 0) && + (DEVI(dip)->devi_flags & DEVI_REBIND))) + e_ddi_prop_remove_all(dip); } else { NDI_CONFIG_DEBUG((CE_CONT, "uninit_node failed: 0x%p(%s%d)\n", (void *)dip, ddi_driver_name(dip), ddi_get_instance(dip))); @@ -1301,6 +1425,7 @@ i_ndi_config_node(dev_info_t *dip, ddi_node_state_t state, uint_t flag) */ if ((rv = bind_node(dip)) == DDI_SUCCESS) i_ddi_set_node_state(dip, DS_BOUND); + break; case DS_BOUND: /* @@ -1874,11 +1999,15 @@ i_ddi_devi_attached(dev_info_t *dip) * By default, name is matched with devi_node_name. The following * alternative match strategies are supported: * - * FIND_NAME_BY_DRIVER: A match on driver name bound to node is conducted. + * FIND_NODE_BY_NODENAME: Match on node name - typical use. + * FIND_NODE_BY_DRIVER: A match on driver name bound to node is conducted. * This support is used for support of OBP generic names and - * for the conversion from driver names to generic names. When + * for the conversion from driver names to generic names. When * more consistency in the generic name environment is achieved * (and not needed for upgrade) this support can be removed. + * FIND_NODE_BY_ADDR: Match on just the addr. + * This support is only used/needed during boot to match + * a node bound via a path-based driver alias. * * If a child is not named (dev_addr == NULL), there are three * possible actions: @@ -1887,7 +2016,9 @@ i_ddi_devi_attached(dev_info_t *dip) * (2) FIND_ADDR_BY_INIT: bring child to DS_INITIALIZED state * (3) FIND_ADDR_BY_CALLBACK: use a caller-supplied callback function */ -#define FIND_NAME_BY_DRIVER 0x01 +#define FIND_NODE_BY_NODENAME 0x01 +#define FIND_NODE_BY_DRIVER 0x02 +#define FIND_NODE_BY_ADDR 0x04 #define FIND_ADDR_BY_INIT 0x10 #define FIND_ADDR_BY_CALLBACK 0x20 @@ -1898,12 +2029,18 @@ find_sibling(dev_info_t *head, char *cname, char *caddr, uint_t flag, dev_info_t *dip; char *addr, *buf; major_t major; + uint_t by; + + /* only one way to find a node */ + by = flag & + (FIND_NODE_BY_DRIVER | FIND_NODE_BY_NODENAME | FIND_NODE_BY_ADDR); + ASSERT(by && BIT_ONLYONESET(by)); /* only one way to name a node */ ASSERT(((flag & FIND_ADDR_BY_INIT) == 0) || ((flag & FIND_ADDR_BY_CALLBACK) == 0)); - if (flag & FIND_NAME_BY_DRIVER) { + if (by == FIND_NODE_BY_DRIVER) { major = ddi_name_to_major(cname); if (major == (major_t)-1) return (NULL); @@ -1918,14 +2055,14 @@ find_sibling(dev_info_t *head, char *cname, char *caddr, uint_t flag, */ for (dip = head; dip; dip = ddi_get_next_sibling(dip)) { - if (flag & FIND_NAME_BY_DRIVER) { - /* match driver major */ - if (DEVI(dip)->devi_major != major) - continue; - } else { + if (by == FIND_NODE_BY_NODENAME) { /* match node name */ if (strcmp(cname, DEVI(dip)->devi_node_name) != 0) continue; + } else if (by == FIND_NODE_BY_DRIVER) { + /* match driver major */ + if (DEVI(dip)->devi_major != major) + continue; } if ((addr = DEVI(dip)->devi_addr) == NULL) { @@ -1968,7 +2105,8 @@ find_duplicate_child(dev_info_t *pdip, dev_info_t *dip) char *caddr = DEVI(dip)->devi_addr; /* search nodes before dip */ - dup = find_sibling(ddi_get_child(pdip), cname, caddr, 0, NULL); + dup = find_sibling(ddi_get_child(pdip), cname, caddr, + FIND_NODE_BY_NODENAME, NULL); if (dup != dip) return (dup); @@ -1976,7 +2114,7 @@ find_duplicate_child(dev_info_t *pdip, dev_info_t *dip) * search nodes after dip; normally this is not needed, */ return (find_sibling(ddi_get_next_sibling(dip), cname, caddr, - 0, NULL)); + FIND_NODE_BY_NODENAME, NULL)); } /* @@ -1988,7 +2126,7 @@ find_child_by_callback(dev_info_t *pdip, char *cname, char *caddr, int (*name_node)(dev_info_t *, char *, int)) { return (find_sibling(ddi_get_child(pdip), cname, caddr, - FIND_NAME_BY_DRIVER|FIND_ADDR_BY_CALLBACK, name_node)); + FIND_NODE_BY_DRIVER|FIND_ADDR_BY_CALLBACK, name_node)); } /* @@ -2000,13 +2138,14 @@ find_child_by_name(dev_info_t *pdip, char *cname, char *caddr) { dev_info_t *dip; - /* attempt search without changing state of preceeding siblings */ - dip = find_sibling(ddi_get_child(pdip), cname, caddr, 0, NULL); + /* attempt search without changing state of preceding siblings */ + dip = find_sibling(ddi_get_child(pdip), cname, caddr, + FIND_NODE_BY_NODENAME, NULL); if (dip) return (dip); return (find_sibling(ddi_get_child(pdip), cname, caddr, - FIND_ADDR_BY_INIT, NULL)); + FIND_NODE_BY_NODENAME|FIND_ADDR_BY_INIT, NULL)); } /* @@ -2018,14 +2157,41 @@ find_child_by_driver(dev_info_t *pdip, char *cname, char *caddr) { dev_info_t *dip; - /* attempt search without changing state of preceeding siblings */ + /* attempt search without changing state of preceding siblings */ dip = find_sibling(ddi_get_child(pdip), cname, caddr, - FIND_NAME_BY_DRIVER, NULL); + FIND_NODE_BY_DRIVER, NULL); if (dip) return (dip); return (find_sibling(ddi_get_child(pdip), cname, caddr, - FIND_NAME_BY_DRIVER|FIND_ADDR_BY_INIT, NULL)); + FIND_NODE_BY_DRIVER|FIND_ADDR_BY_INIT, NULL)); +} + +/* + * Find a child of a given address, invoking initchild to name + * unnamed children. cname is the node name. + * + * NOTE: This function is only used during boot. One would hope that + * unique sibling unit-addresses on hardware branches of the tree would + * be a requirement to avoid two drivers trying to control the same + * piece of hardware. Unfortunately there are some cases where this + * situation exists (/ssm@0,0/pci@1c,700000 /ssm@0,0/sghsc@1c,700000). + * Until unit-address uniqueness of siblings is guaranteed, use of this + * interface for purposes other than boot should be avoided. + */ +static dev_info_t * +find_child_by_addr(dev_info_t *pdip, char *caddr) +{ + dev_info_t *dip; + + /* attempt search without changing state of preceding siblings */ + dip = find_sibling(ddi_get_child(pdip), NULL, caddr, + FIND_NODE_BY_ADDR, NULL); + if (dip) + return (dip); + + return (find_sibling(ddi_get_child(pdip), NULL, caddr, + FIND_NODE_BY_ADDR|FIND_ADDR_BY_INIT, NULL)); } /* @@ -2425,6 +2591,34 @@ ddi_compatible_driver_major(dev_info_t *dip, char **formp) if (formp) *formp = NULL; + /* + * Highest precedence binding is a path-oriented alias. Since this + * requires a 'path', this type of binding occurs via more obtuse + * 'rebind'. The need for a path-oriented alias 'rebind' is detected + * after a successful DDI_CTLOPS_INITCHILD to another driver: this is + * is the first point at which the unit-address (or instance) of the + * last component of the path is available (even though the path is + * bound to the wrong driver at this point). + */ + if (devi->devi_flags & DEVI_REBIND) { + p = devi->devi_rebinding_name; + major = ddi_name_to_major(p); + if ((major != (major_t)-1) && + !(devnamesp[major].dn_flags & DN_DRIVER_REMOVED)) { + if (formp) + *formp = p; + return (major); + } + + /* + * If for some reason devi_rebinding_name no longer resolves + * to a proper driver then clear DEVI_REBIND. + */ + mutex_enter(&devi->devi_lock); + devi->devi_flags &= ~DEVI_REBIND; + mutex_exit(&devi->devi_lock); + } + /* look up compatible property */ (void) lookup_compatible(dip, KM_SLEEP); compat = (void *)(devi->devi_compat_names); @@ -3727,6 +3921,38 @@ static int bind_dip(dev_info_t *dip, void *arg) { _NOTE(ARGUNUSED(arg)) + char *path; + major_t major, pmajor; + + /* + * If the node is currently bound to the wrong driver, try to unbind + * so that we can rebind to the correct driver. + */ + if (i_ddi_node_state(dip) >= DS_BOUND) { + major = ddi_compatible_driver_major(dip, NULL); + if ((DEVI(dip)->devi_major == major) && + (i_ddi_node_state(dip) >= DS_INITIALIZED)) { + /* + * Check for a path-oriented driver alias that + * takes precedence over current driver binding. + */ + path = kmem_alloc(MAXPATHLEN, KM_SLEEP); + (void) ddi_pathname(dip, path); + pmajor = ddi_name_to_major(path); + if ((pmajor != (major_t)-1) && + !(devnamesp[pmajor].dn_flags & DN_DRIVER_REMOVED)) + major = pmajor; + kmem_free(path, MAXPATHLEN); + } + + /* attempt unbind if current driver is incorrect */ + if ((major != (major_t)-1) && + !(devnamesp[major].dn_flags & DN_DRIVER_REMOVED) && + (major != DEVI(dip)->devi_major)) + (void) ndi_devi_unbind_driver(dip); + } + + /* If unbound, try to bind to a driver */ if (i_ddi_node_state(dip) < DS_BOUND) (void) ndi_devi_bind_driver(dip, 0); @@ -3736,6 +3962,9 @@ bind_dip(dev_info_t *dip, void *arg) void i_ddi_bind_devs(void) { + /* flush devfs so that ndi_devi_unbind_driver will work when possible */ + (void) devfs_clean(top_devinfo, NULL, 0); + ddi_walk_devs(top_devinfo, bind_dip, (void *)NULL); } @@ -4627,6 +4856,7 @@ devi_config_one(dev_info_t *pdip, char *devnm, dev_info_t **cdipp, { dev_info_t *vdip = NULL; char *drivername = NULL; + int find_by_addr = 0; char *name, *addr; int v_circ, p_circ; clock_t end_time; /* 60 sec */ @@ -4656,8 +4886,10 @@ devi_config_one(dev_info_t *pdip, char *devnm, dev_info_t **cdipp, * drivername. This allows an implementation to supply a genericly * named boot path (disk) and locate drivename nodes (sd). */ - if (flags & NDI_PROMNAME) + if (flags & NDI_PROMNAME) { drivername = child_path_to_driver(pdip, name, addr); + find_by_addr = 1; + } /* * Determine end_time: This routine should *not* be called with a @@ -4698,13 +4930,16 @@ devi_config_one(dev_info_t *pdip, char *devnm, dev_info_t **cdipp, * Search for child by name, if not found then search * for a node bound to the drivername driver with the * specified "@addr". Break out of for(;;) loop if - * child found. + * child found. To support path-oriented aliases + * binding on boot-device, we do a search_by_addr too. */ again: (void) i_ndi_make_spec_children(pdip, flags); cdip = find_child_by_name(pdip, name, addr); if ((cdip == NULL) && drivername) cdip = find_child_by_driver(pdip, drivername, addr); + if ((cdip == NULL) && find_by_addr) + cdip = find_child_by_addr(pdip, addr); if (cdip) break; @@ -4823,7 +5058,7 @@ ndi_devi_config_one(dev_info_t *dip, char *devnm, dev_info_t **dipp, int flags) } /* - * DR usage ((i.e. call with NDI_CONFIG) recursively configures + * DR usage (i.e. call with NDI_CONFIG) recursively configures * grandchildren, performing a BUS_CONFIG_ALL from the node attached * by the BUS_CONFIG_ONE. */ @@ -5585,7 +5820,8 @@ ndi_devi_find(dev_info_t *pdip, char *cname, char *caddr) return ((dev_info_t *)NULL); ndi_devi_enter(pdip, &circ); - child = find_sibling(ddi_get_child(pdip), cname, caddr, 0, NULL); + child = find_sibling(ddi_get_child(pdip), cname, caddr, + FIND_NODE_BY_NODENAME, NULL); ndi_devi_exit(pdip, circ); return (child); } @@ -5611,7 +5847,8 @@ ndi_devi_findchild(dev_info_t *pdip, char *devname) return ((dev_info_t *)NULL); } - child = find_sibling(ddi_get_child(pdip), cname, caddr, 0, NULL); + child = find_sibling(ddi_get_child(pdip), cname, caddr, + FIND_NODE_BY_NODENAME, NULL); kmem_free(devstr, strlen(devname)+1); return (child); } @@ -5671,7 +5908,16 @@ path_to_major(char *path) dev_info_t *dip; char *p, *q; pnode_t nodeid; - major_t maj; + major_t major; + + /* check for path-oriented alias */ + major = ddi_name_to_major(path); + if ((major != (major_t)-1) && + !(devnamesp[major].dn_flags & DN_DRIVER_REMOVED)) { + NDI_CONFIG_DEBUG((CE_NOTE, "path_to_major: %s path bound %s\n", + path, ddi_major_to_name(major))); + return (major); + } /* * Get the nodeid of the given pathname, if such a mapping exists. @@ -5702,11 +5948,11 @@ path_to_major(char *path) NDI_CONFIG_DEBUG((CE_NOTE, "path_to_major: %s bound to %s\n", path, p)); - maj = ddi_name_to_major(p); + major = ddi_name_to_major(p); - ndi_rele_devi(dip); /* release node held during walk */ + ndi_rele_devi(dip); /* release e_ddi_nodeid_to_dip hold */ - return (maj); + return (major); } /* @@ -6837,25 +7083,10 @@ i_ddi_di_cache_invalidate(int kmflag) static void i_bind_vhci_node(dev_info_t *dip) { - char *node_name; - - node_name = i_ddi_strdup(ddi_node_name(dip), KM_SLEEP); - i_ddi_set_binding_name(dip, node_name); - DEVI(dip)->devi_major = ddi_name_to_major(node_name); + DEVI(dip)->devi_major = ddi_name_to_major(ddi_node_name(dip)); i_ddi_set_node_state(dip, DS_BOUND); } - -static void -i_free_vhci_bind_name(dev_info_t *dip) -{ - if (DEVI(dip)->devi_binding_name) { - kmem_free(DEVI(dip)->devi_binding_name, - sizeof (ddi_node_name(dip))); - } -} - - static char vhci_node_addr[2]; static int @@ -6938,7 +7169,6 @@ ndi_devi_config_vhci(char *drvname, int flags) i_ddi_add_devimap(dip); i_bind_vhci_node(dip); if (i_init_vhci_node(dip) == -1) { - i_free_vhci_bind_name(dip); ndi_rele_devi(dip); (void) ndi_devi_free(dip); return (NULL); @@ -6951,7 +7181,6 @@ ndi_devi_config_vhci(char *drvname, int flags) if (devi_attach(dip, DDI_ATTACH) != DDI_SUCCESS) { cmn_err(CE_CONT, "Could not attach %s driver", drvname); e_ddi_free_instance(dip, vhci_node_addr); - i_free_vhci_bind_name(dip); ndi_rele_devi(dip); (void) ndi_devi_free(dip); return (NULL); diff --git a/usr/src/uts/common/os/modsysfile.c b/usr/src/uts/common/os/modsysfile.c index d1538a3f9d..690491d8ba 100644 --- a/usr/src/uts/common/os/modsysfile.c +++ b/usr/src/uts/common/os/modsysfile.c @@ -2147,8 +2147,8 @@ make_aliases(struct bind **bhash) } state; struct _buf *file; - char tokbuf[MAXNAMELEN]; - char drvbuf[MAXNAMELEN]; + char tokbuf[MAXPATHLEN]; + char drvbuf[MAXPATHLEN]; token_t token; major_t major; int done = 0; diff --git a/usr/src/uts/common/os/sunddi.c b/usr/src/uts/common/os/sunddi.c index 8c6bcefe06..e9fd930d22 100644 --- a/usr/src/uts/common/os/sunddi.c +++ b/usr/src/uts/common/os/sunddi.c @@ -20,7 +20,7 @@ */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -6350,10 +6350,22 @@ ddi_deviname(dev_info_t *dip, char *name) return (name); } - if (i_ddi_node_state(dip) < DS_INITIALIZED) { + if (i_ddi_node_state(dip) < DS_BOUND) { addrname = &none; } else { + /* + * Use ddi_get_name_addr() without checking state so we get + * a unit-address if we are called after ddi_set_name_addr() + * by nexus DDI_CTL_INITCHILD code, but before completing + * node promotion to DS_INITIALIZED. We currently have + * two situations where we are called in this state: + * o For framework processing of a path-oriented alias. + * o If a SCSA nexus driver calls ddi_devid_register() + * from it's tran_tgt_init(9E) implementation. + */ addrname = ddi_get_name_addr(dip); + if (addrname == NULL) + addrname = &none; } if (*addrname == '\0') { diff --git a/usr/src/uts/common/os/swapgeneric.c b/usr/src/uts/common/os/swapgeneric.c index b1c9d5e7b0..72ea7572e7 100644 --- a/usr/src/uts/common/os/swapgeneric.c +++ b/usr/src/uts/common/os/swapgeneric.c @@ -20,7 +20,7 @@ */ /* ONC_PLUS EXTRACT START */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -718,16 +718,34 @@ load_boot_driver(char *drv) * For a given instance, load that driver and its parents */ static int -load_parent_drivers(dev_info_t *dip) +load_parent_drivers(dev_info_t *dip, char *path) { int rval = 0; + major_t major = (major_t)-1; char *drv; + char *p; while (dip) { - drv = ddi_get_name(dip); + /* check for path-oriented alias */ + if (path) + major = ddi_name_to_major(path); + else + major = (major_t)-1; + + if (major != (major_t)-1) + drv = ddi_major_to_name(major); + else + drv = ddi_binding_name(dip); + if (load_boot_driver(drv) != 0) rval = -1; + dip = ddi_get_parent(dip); + if (path) { + p = strrchr(path, '/'); + if (p) + *p = 0; + } } return (rval); @@ -741,14 +759,21 @@ load_parent_drivers(dev_info_t *dip) static int load_bootpath_drivers(char *bootpath) { - dev_info_t *dip; + dev_info_t *dip; + char *pathcopy; + int pathcopy_len; + int rval; + char *p; if (bootpath == NULL || *bootpath == 0) return (-1); BMDPRINTF(("load_bootpath_drivers: %s\n", bootpath)); - dip = path_to_devinfo(bootpath); + pathcopy = i_ddi_strdup(bootpath, KM_SLEEP); + pathcopy_len = strlen(pathcopy) + 1; + + dip = path_to_devinfo(pathcopy); #if defined(__i386) || defined(__amd64) /* @@ -758,44 +783,40 @@ load_bootpath_drivers(char *bootpath) * which we go ahead and load here. */ if (dip == NULL) { - char *pathcopy, *leaf, *p; - int len, rval; - - len = strlen(bootpath) + 1; - pathcopy = kmem_zalloc(len, KM_SLEEP); - (void) strcpy(pathcopy, bootpath); + char *leaf; /* - * Work backward to the last slash to build the - * full path of the parent of the boot device + * Find last slash to build the full path to the + * parent of the leaf boot device */ - for (p = pathcopy + len - 2; *p != '/'; p--) - ; + p = strrchr(pathcopy, '/'); *p++ = 0; /* * Now isolate the driver name of the leaf device */ - for (leaf = p; *p && *p != '@'; p++) - ; + leaf = p; + p = strchr(leaf, '@'); *p = 0; BMDPRINTF(("load_bootpath_drivers: parent=%s leaf=%s\n", - pathcopy, leaf)); + bootpath, leaf)); dip = path_to_devinfo(pathcopy); - - rval = load_boot_driver(leaf); - kmem_free(pathcopy, len); - if (rval == -1) - return (NULL); - + if (leaf) { + rval = load_boot_driver(leaf, NULL); + if (rval == -1) { + kmem_free(pathcopy, pathcopy_len); + return (NULL); + } + } } #endif if (dip == NULL) { cmn_err(CE_WARN, "can't bind driver for boot path <%s>", bootpath); + kmem_free(pathcopy, pathcopy_len); return (NULL); } @@ -811,10 +832,21 @@ load_bootpath_drivers(char *bootpath) if (netboot_over_ib(bootpath) && modloadonly("drv", "ibd") == -1) { cmn_err(CE_CONT, "ibd: cannot load platform driver\n"); + kmem_free(pathcopy, pathcopy_len); return (NULL); } - return (load_parent_drivers(dip)); + /* get rid of minor node at end of copy (if not already done above) */ + p = strrchr(pathcopy, '/'); + if (p) { + p = strchr(p, ':'); + if (p) + *p = 0; + } + + rval = load_parent_drivers(dip, pathcopy); + kmem_free(pathcopy, pathcopy_len); + return (rval); } @@ -866,7 +898,7 @@ load_boot_platform_modules(char *drv) } } else { while (dip) { - if (load_parent_drivers(dip) != 0) + if (load_parent_drivers(dip, NULL) != 0) rval = -1; dip = ddi_get_next(dip); } diff --git a/usr/src/uts/common/sys/ddi_impldefs.h b/usr/src/uts/common/sys/ddi_impldefs.h index 0a1bcf9cde..3b99c60997 100644 --- a/usr/src/uts/common/sys/ddi_impldefs.h +++ b/usr/src/uts/common/sys/ddi_impldefs.h @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -80,7 +80,10 @@ struct dev_info { struct dev_info *devi_child; /* my child list head */ struct dev_info *devi_sibling; /* next element on my level */ - char *devi_binding_name; /* name used to bind driver */ + char *devi_binding_name; /* name used to bind driver: */ + /* shared storage, points to */ + /* devi_node_name, devi_compat_names */ + /* or devi_rebinding_name */ char *devi_addr; /* address part of name */ @@ -189,6 +192,8 @@ struct dev_info { void *devi_nex_pm; /* nexus PM private */ char *devi_addr_buf; /* buffer for devi_addr */ + + char *devi_rebinding_name; /* binding_name of rebind */ }; #define DEVI(dev_info_type) ((struct dev_info *)(dev_info_type)) @@ -497,6 +502,7 @@ void i_devi_exit(dev_info_t *, uint_t c_mask, int has_lock); #define DEVI_NO_BIND 0x00000010 /* prevent driver binding */ #define DEVI_REGISTERED_DEVID 0x00000020 /* device registered a devid */ #define DEVI_PHCI_SIGNALS_VHCI 0x00000040 /* pHCI ndi_devi_exit signals vHCI */ +#define DEVI_REBIND 0x00000080 /* post initchild driver rebind */ #define DEVI_BUSY_CHANGING(dip) (DEVI(dip)->devi_flags & DEVI_BUSY) #define DEVI_BUSY_OWNED(dip) (DEVI_BUSY_CHANGING(dip) && \ diff --git a/usr/src/uts/common/sys/ndi_impldefs.h b/usr/src/uts/common/sys/ndi_impldefs.h index 2f36500d01..0d450e2db0 100644 --- a/usr/src/uts/common/sys/ndi_impldefs.h +++ b/usr/src/uts/common/sys/ndi_impldefs.h @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 1998-2003 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -126,6 +125,12 @@ void i_ndi_set_node_attributes(dev_info_t *, int); */ void i_ndi_set_nodeid(dev_info_t *, int); +/* + * Make driver.conf children. + * (Intended for the ddi framework use only.) + */ +int i_ndi_make_spec_children(dev_info_t *, uint_t); + #ifdef __cplusplus } #endif |