summaryrefslogtreecommitdiff
path: root/usr
diff options
context:
space:
mode:
authorSebastien Roy <Sebastien.Roy@Sun.COM>2009-11-06 14:51:38 -0500
committerSebastien Roy <Sebastien.Roy@Sun.COM>2009-11-06 14:51:38 -0500
commitee94b1c37a34b758315666dcd0bc7c46d1aea15c (patch)
tree7147932421cadffc3fd7a58eef1c94eda4128ddc /usr
parent70ab5741638f3af9101ada693c7aa7aeeefb73bb (diff)
downloadillumos-gate-ee94b1c37a34b758315666dcd0bc7c46d1aea15c.tar.gz
6896138 GLDv3 thwarted by broken getinfo() routines
Diffstat (limited to 'usr')
-rw-r--r--usr/src/uts/common/io/mac/mac.c19
-rw-r--r--usr/src/uts/common/io/mac/mac_provider.c10
-rw-r--r--usr/src/uts/common/io/softmac/softmac_dev.c1
-rw-r--r--usr/src/uts/common/io/softmac/softmac_main.c51
4 files changed, 53 insertions, 28 deletions
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);