From ee94b1c37a34b758315666dcd0bc7c46d1aea15c Mon Sep 17 00:00:00 2001 From: Sebastien Roy Date: Fri, 6 Nov 2009 14:51:38 -0500 Subject: 6896138 GLDv3 thwarted by broken getinfo() routines --- usr/src/uts/common/io/mac/mac.c | 19 ++++++++++- usr/src/uts/common/io/mac/mac_provider.c | 10 +++--- usr/src/uts/common/io/softmac/softmac_dev.c | 1 + usr/src/uts/common/io/softmac/softmac_main.c | 51 ++++++++++++++++------------ 4 files changed, 53 insertions(+), 28 deletions(-) (limited to 'usr') diff --git a/usr/src/uts/common/io/mac/mac.c b/usr/src/uts/common/io/mac/mac.c index bb9f2ea62a..92d1542efd 100644 --- a/usr/src/uts/common/io/mac/mac.c +++ b/usr/src/uts/common/io/mac/mac.c @@ -462,10 +462,27 @@ mac_fini(void) return (0); } +/* + * Initialize a GLDv3 driver's device ops. A driver that manages its own ops + * (e.g. softmac) may pass in a NULL ops argument. + */ void mac_init_ops(struct dev_ops *ops, const char *name) { - dld_init_ops(ops, name); + major_t major = ddi_name_to_major((char *)name); + + /* + * By returning on error below, we are not letting the driver continue + * in an undefined context. The mac_register() function will faill if + * DN_GLDV3_DRIVER isn't set. + */ + if (major == DDI_MAJOR_T_NONE) + return; + LOCK_DEV_OPS(&devnamesp[major].dn_lock); + devnamesp[major].dn_flags |= (DN_GLDV3_DRIVER | DN_NETWORK_DRIVER); + UNLOCK_DEV_OPS(&devnamesp[major].dn_lock); + if (ops != NULL) + dld_init_ops(ops, name); } void diff --git a/usr/src/uts/common/io/mac/mac_provider.c b/usr/src/uts/common/io/mac/mac_provider.c index 090de162b5..b752d2577a 100644 --- a/usr/src/uts/common/io/mac/mac_provider.c +++ b/usr/src/uts/common/io/mac/mac_provider.c @@ -128,6 +128,10 @@ mac_register(mac_register_t *mregp, mac_handle_t *mhp) char *driver; minor_t minor = 0; + /* A successful call to mac_init_ops() sets the DN_GLDV3_DRIVER flag. */ + if (!GLDV3_DRV(ddi_driver_major(mregp->m_dip))) + return (EINVAL); + /* Find the required MAC-Type plugin. */ if ((mtype = mactype_getplugin(mregp->m_type_ident)) == NULL) return (EINVAL); @@ -397,12 +401,6 @@ mac_register(mac_register_t *mregp, mac_handle_t *mhp) /* Zero out any properties. */ bzero(&mip->mi_resource_props, sizeof (mac_resource_props_t)); - /* set the gldv3 flag in dn_flags */ - dnp = &devnamesp[ddi_driver_major(mip->mi_dip)]; - LOCK_DEV_OPS(&dnp->dn_lock); - dnp->dn_flags |= (DN_GLDV3_DRIVER | DN_NETWORK_DRIVER); - UNLOCK_DEV_OPS(&dnp->dn_lock); - if (mip->mi_minor <= MAC_MAX_MINOR) { /* Create a style-2 DLPI device */ if (ddi_create_minor_node(mip->mi_dip, driver, S_IFCHR, 0, diff --git a/usr/src/uts/common/io/softmac/softmac_dev.c b/usr/src/uts/common/io/softmac/softmac_dev.c index 317a89360c..23f43ced0b 100644 --- a/usr/src/uts/common/io/softmac/softmac_dev.c +++ b/usr/src/uts/common/io/softmac/softmac_dev.c @@ -196,6 +196,7 @@ _init(void) { int err; + mac_init_ops(NULL, SOFTMAC_DEV_NAME); softmac_init(); softmac_upper_cachep = kmem_cache_create("softmac_upper_cache", diff --git a/usr/src/uts/common/io/softmac/softmac_main.c b/usr/src/uts/common/io/softmac/softmac_main.c index b0853602cb..9e33c31b7b 100644 --- a/usr/src/uts/common/io/softmac/softmac_main.c +++ b/usr/src/uts/common/io/softmac/softmac_main.c @@ -1501,46 +1501,55 @@ int softmac_hold_device(dev_t dev, dls_dev_handle_t *ddhp) { dev_info_t *dip; - const char *drvname; char devname[MAXNAMELEN]; softmac_t *softmac; - int ppa, err, inst; + major_t major; + int ppa, err = 0, inst; - drvname = ddi_major_to_name(getmajor(dev)); + major = getmajor(dev); + ppa = getminor(dev) - 1; /* - * We have to lookup the device instance using getinfo(9e). + * For GLDv3 devices, look up the device instance using getinfo(9e). + * Otherwise, fall back to the old assumption that inst == ppa. The + * GLDV3_DRV() macro depends on the driver module being loaded, hence + * the call to ddi_hold_driver(). */ - inst = dev_to_instance(dev); - if (inst < 0) - return (ENOENT); - - if ((ppa = getminor(dev) - 1) > DLS_MAX_PPA) - return (ENOENT); + if (ddi_hold_driver(major) == NULL) + return (ENXIO); + if (GLDV3_DRV(major)) { + if ((inst = dev_to_instance(dev)) < 0) + err = ENOENT; + } else { + inst = ppa; + } + ddi_rele_driver(major); + if (err != 0) + return (err); /* - * First try to hold this device instance to force the MAC - * to be registered. + * First try to hold this device instance to force device to attach + * and ensure that the softmac entry gets created in net_postattach(). */ - if ((dip = ddi_hold_devi_by_instance(getmajor(dev), inst, 0)) == NULL) + if ((dip = ddi_hold_devi_by_instance(major, inst, 0)) == NULL) return (ENOENT); /* * Exclude non-physical network device instances, for example, aggr0. * Note: this check *must* occur after the dip is held, or else - * NETWORK_PHYSDRV might return false incorrectly. (Essentially, the - * driver needs to be loaded to populate the dev_ops structure - * that NETWORK_PHYSDRV checks.) + * NETWORK_PHYSDRV might return false incorrectly. The + * DN_NETWORK_PHYSDRIVER flag used by NETWORK_PHYSDRV() gets set if + * ddi_create_minor_node() is called during the device's attach + * phase. */ - if (!NETWORK_PHYSDRV(getmajor(dev))) { + if (!NETWORK_PHYSDRV(major)) { ddi_release_devi(dip); return (ENOENT); } - /* - * This is a network device; wait for its softmac to be registered. - */ - (void) snprintf(devname, MAXNAMELEN, "%s%d", drvname, ppa); + /* Now wait for its softmac to be created. */ + (void) snprintf(devname, MAXNAMELEN, "%s%d", ddi_major_to_name(major), + ppa); again: rw_enter(&softmac_hash_lock, RW_READER); -- cgit v1.2.3