diff options
author | kellena <none@none> | 2007-04-25 14:13:55 -0700 |
---|---|---|
committer | kellena <none@none> | 2007-04-25 14:13:55 -0700 |
commit | e82e447ac83da0082df4f3e07829e533342ff9ef (patch) | |
tree | aafd494da87d2d26d170da4451db3766c77d9b41 /usr/src | |
parent | f05471646f8ccee9dbeb3d68f8bd68b50eec9c9d (diff) | |
download | illumos-gate-e82e447ac83da0082df4f3e07829e533342ff9ef.tar.gz |
6541014 ldmd fails to obtain the PRI via libpri and aborts
Diffstat (limited to 'usr/src')
-rw-r--r-- | usr/src/lib/libpri/common/pri.c | 49 | ||||
-rw-r--r-- | usr/src/uts/sun4v/io/ds.c | 5 | ||||
-rw-r--r-- | usr/src/uts/sun4v/io/ds_pri.c | 7 |
3 files changed, 42 insertions, 19 deletions
diff --git a/usr/src/lib/libpri/common/pri.c b/usr/src/lib/libpri/common/pri.c index d6785a3fef..479415aa9c 100644 --- a/usr/src/lib/libpri/common/pri.c +++ b/usr/src/lib/libpri/common/pri.c @@ -36,23 +36,43 @@ #include "sys/ds_pri.h" #include "pri.h" +static int pri_fd = -1; + + + /* - * Library init function - currently no-op. + * Library init function * Returns: Success (0), Failure (-1) */ int pri_init(void) { + int fd; + + if (pri_fd != -1) + return (-1); + + fd = open(DS_PRI_DRIVER, O_RDONLY); + if (fd < 0) + return (-1); + + pri_fd = fd; + return (0); } /* - * Library fini function - currently no-op. + * Library fini function * Returns: N/A */ void pri_fini(void) { + if (pri_fd < 0) + return; + + (void) close(pri_fd); + pri_fd = -1; } /* @@ -106,34 +126,34 @@ pri_fini(void) * Returns: * >0 if PRI is returned successfully (size of PRI buffer) * 0 if no PRI is available - * -1 if there is an error (errno contains the error code) + * -1 if there is an error (errno contains the error code + * provided) * */ ssize_t pri_get(uint8_t wait, uint64_t *token, uint64_t **buf, void *(*allocp)(size_t), void (*freep)(void *, size_t)) { - int fd; /* for device open */ uint64_t *bufp; /* buf holding PRI */ size_t size; /* sizeof PRI */ struct dspri_info pri_info; /* info about PRI */ struct dspri_info pri_info2; /* for PRI delta check */ - if ((fd = open(DS_PRI_DRIVER, O_RDONLY)) < 0) + if (pri_fd < 0) { + errno = EBADF; return (-1); + } if (wait == PRI_WAITGET) { /* wait until have new PRI with different token */ - if (ioctl(fd, DSPRI_WAIT, token) < 0) { - (void) close(fd); + if (ioctl(pri_fd, DSPRI_WAIT, token) < 0) { return (-1); } } do { /* get info on current PRI */ - if (ioctl(fd, DSPRI_GETINFO, &pri_info) < 0) { - (void) close(fd); + if (ioctl(pri_fd, DSPRI_GETINFO, &pri_info) < 0) { return (-1); } @@ -142,18 +162,17 @@ pri_get(uint8_t wait, uint64_t *token, uint64_t **buf, /* check to see if no PRI available yet */ if (size == 0) { *token = pri_info.token; - (void) close(fd); return (0); } /* allocate a buffer and read the PRI into it */ if ((bufp = (uint64_t *)allocp(size)) == NULL) { - (void) close(fd); + if (errno == 0) + errno = ENOMEM; return (-1); } - if (read(fd, bufp, size) < 0) { + if (read(pri_fd, bufp, size) < 0) { freep(bufp, size); - (void) close(fd); return (-1); } @@ -164,9 +183,8 @@ pri_get(uint8_t wait, uint64_t *token, uint64_t **buf, * tries to catch the above race condition; be sure * to not leak memory on retries. */ - if (ioctl(fd, DSPRI_GETINFO, &pri_info2) < 0) { + if (ioctl(pri_fd, DSPRI_GETINFO, &pri_info2) < 0) { freep(bufp, size); - (void) close(fd); return (-1); } if (pri_info2.token != pri_info.token) @@ -177,6 +195,5 @@ pri_get(uint8_t wait, uint64_t *token, uint64_t **buf, /* return the PRI, its token, and its size to the caller */ *buf = bufp; *token = pri_info.token; - (void) close(fd); return ((ssize_t)size); } diff --git a/usr/src/uts/sun4v/io/ds.c b/usr/src/uts/sun4v/io/ds.c index 2a8aea01dc..d014d7f6fb 100644 --- a/usr/src/uts/sun4v/io/ds.c +++ b/usr/src/uts/sun4v/io/ds.c @@ -290,7 +290,7 @@ static void ds_log_purge(void *arg); static struct modlmisc modlmisc = { &mod_miscops, - "Domain Services %I%" + "Domain Services 1.8" }; static struct modlinkage modlinkage = { @@ -311,6 +311,9 @@ _init(void) */ ds_init(); + /* force attach channel nexus */ + (void) i_ddi_attach_hw_nodes("cnex"); + if ((rv = ds_ports_init()) != 0) { cmn_err(CE_WARN, "Domain Services initialization failed"); ds_fini(); diff --git a/usr/src/uts/sun4v/io/ds_pri.c b/usr/src/uts/sun4v/io/ds_pri.c index 1c63c68f3f..e96f887d8a 100644 --- a/usr/src/uts/sun4v/io/ds_pri.c +++ b/usr/src/uts/sun4v/io/ds_pri.c @@ -410,10 +410,12 @@ ds_pri_open(dev_t *devp, int flag, int otyp, cred_t *credp) /* * If we're here and the state is DS_PRI_NO_SERVICE then this * means that ds hasn't yet called the registration callback. + * A while loop is necessary as we might have been woken up + * prematurely, e.g., due to a debugger or "pstack" etc. * Wait here and the callback will signal us when it has completed * its work. */ - if (sp->state == DS_PRI_NO_SERVICE) { + while (sp->state == DS_PRI_NO_SERVICE) { if (cv_wait_sig(&sp->cv, &sp->lock) == 0) { mutex_exit(&sp->lock); return (EINTR); @@ -421,7 +423,6 @@ ds_pri_open(dev_t *devp, int flag, int otyp, cred_t *credp) } sp->num_opens++; - mutex_exit(&sp->lock); /* @@ -628,6 +629,8 @@ loop:; while ((sp->state & DS_PRI_HAS_PRI) == 0 || gencount == sp->gencount) { + if ((sp->state & DS_PRI_HAS_PRI) == 0) + request_pri(sp); if (cv_wait_sig(&sp->cv, &sp->lock) == 0) { mutex_exit(&sp->lock); return (EINTR); |