summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--usr/src/lib/efcode/efdaemon/efdaemon.c19
-rw-r--r--usr/src/lib/efcode/fcdriver/get_req.c10
-rw-r--r--usr/src/lib/efcode/fcdriver/misc.c9
-rw-r--r--usr/src/uts/sun4/io/efcode/fc_subr.c14
-rw-r--r--usr/src/uts/sun4/io/efcode/fcode.c65
-rw-r--r--usr/src/uts/sun4/sys/fcode.h25
-rw-r--r--usr/src/uts/sun4u/io/pcicfg.e.c28
7 files changed, 144 insertions, 26 deletions
diff --git a/usr/src/lib/efcode/efdaemon/efdaemon.c b/usr/src/lib/efcode/efdaemon/efdaemon.c
index 7aba030848..2450d2d1fa 100644
--- a/usr/src/lib/efcode/efdaemon/efdaemon.c
+++ b/usr/src/lib/efcode/efdaemon/efdaemon.c
@@ -20,7 +20,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2000-2002 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -42,6 +42,7 @@
#include <syslog.h>
#include <errno.h>
#include <sys/wait.h>
+#include <sys/fcode.h>
char efcode_sh_file[] = "/usr/lib/efcode/efcode.sh";
char dev_fcode_file[] = "/dev/fcode";
@@ -57,6 +58,7 @@ main(int argc, char **argv)
char tc;
pid_t pid, tpid;
long nerr = 0;
+ int error;
openlog("efdaemon", LOG_PID|LOG_CONS, LOG_DAEMON);
@@ -160,10 +162,21 @@ main(int argc, char **argv)
else if (pid != tpid)
syslog(LOG_ERR, "Wait error, expect pid: %d"
" got %d, status: %x\n", pid, tpid, status);
- else if (status)
+ else if (status) {
syslog(LOG_ERR, "Wait pid: %d status: %x\n",
pid, status);
- else if (debug)
+ if (WIFEXITED(status) &&
+ (WEXITSTATUS(status) == 1)) {
+ error = FC_FCODE_ABORT;
+ } else {
+ error = FC_EXEC_FAILED;
+ }
+ if (ioctl(fd, FC_SET_FCODE_ERROR, &error) < 0) {
+ syslog(LOG_ERR,
+ "ioctl(FC_SET_FCODE_ERROR)"
+ " failed\n");
+ }
+ } else if (debug)
syslog(LOG_DEBUG, "Wait: pid: %d\n", pid);
close(fd);
continue;
diff --git a/usr/src/lib/efcode/fcdriver/get_req.c b/usr/src/lib/efcode/fcdriver/get_req.c
index 6a87b375d5..1423524a5d 100644
--- a/usr/src/lib/efcode/fcdriver/get_req.c
+++ b/usr/src/lib/efcode/fcdriver/get_req.c
@@ -20,7 +20,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -252,7 +252,9 @@ void
find_fcode(fcode_env_t *env)
{
fstack_t *dp = env->ds;
+ common_data_t *cdp = env->private;
static char func_name[] = "find_fcode";
+ int error;
my_unit(env);
push_a_string(env, "device-id");
@@ -300,7 +302,13 @@ find_fcode(fcode_env_t *env)
func_name, TOS);
return;
}
+
debug_msg(DEBUG_FIND_FCODE, "%s: not found\n", func_name);
+ error = FC_NO_FCODE;
+ if (ioctl(cdp->fcode_fd, FC_SET_FCODE_ERROR, &error) < 0) {
+ log_perror(MSG_FATAL, "ioctl(FC_SET_FCODE_ERROR) failed");
+ return;
+ }
}
int
diff --git a/usr/src/lib/efcode/fcdriver/misc.c b/usr/src/lib/efcode/fcdriver/misc.c
index 4e62b11e03..b2ea8a9e00 100644
--- a/usr/src/lib/efcode/fcdriver/misc.c
+++ b/usr/src/lib/efcode/fcdriver/misc.c
@@ -20,8 +20,8 @@
* CDDL HEADER END
*/
/*
- * Copyright (c) 2000 by Sun Microsystems, Inc.
- * All rights reserved.
+ * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
@@ -54,9 +54,8 @@ fc_reg_read(fcode_env_t *env, char *service, fstack_t virt, int *errp)
/* Don't report error on peeks */
*errp = error;
else if (error) {
- log_message(MSG_ERROR, "fc_read_reg: ERROR: cookie: %llx"
+ forth_abort(env, "fc_read_reg: ERROR: cookie: %llx"
" virt: %llx\n", (uint64_t)virt, (uint64_t)virtaddr);
- data = 0;
}
return (data);
}
@@ -81,7 +80,7 @@ fc_reg_write(fcode_env_t *env, char *service, fstack_t virt, fc_cell_t data,
/* Don't report error on pokes */
*errp = error;
else if (error) {
- log_message(MSG_ERROR, "fc_write_reg: ERROR: cookie: %llx"
+ forth_abort(env, "fc_write_reg: ERROR: cookie: %llx"
" virt: %llx\n", (uint64_t)virt, (uint64_t)virtaddr);
}
}
diff --git a/usr/src/uts/sun4/io/efcode/fc_subr.c b/usr/src/uts/sun4/io/efcode/fc_subr.c
index 834e82db4c..a49ad53b4d 100644
--- a/usr/src/uts/sun4/io/efcode/fc_subr.c
+++ b/usr/src/uts/sun4/io/efcode/fc_subr.c
@@ -20,8 +20,8 @@
* CDDL HEADER END
*/
/*
- * Copyright (c) 2000-2001 by Sun Microsystems, Inc.
- * All rights reserved.
+ * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
@@ -245,6 +245,16 @@ fcode_timer(void *arg)
mutex_exit(&fc_request_lock);
cv_broadcast(&fc_request_cv);
return;
+ } else if (fp->error != FC_SUCCESS) {
+ /*
+ * An error was detected, but didn't close the driver.
+ * This will allow the process to error out, returning
+ * the interpreter error code instead of FC_TIMEOUT.
+ */
+ fp->busy = FC_R_DONE;
+ cv_broadcast(&fc_request_cv);
+ mutex_exit(&fc_request_lock);
+ return;
} else {
cmn_err(CE_WARN, "fcode_timer: Timeout waiting for "
"interpreter - Interpreter is executing request\n");
diff --git a/usr/src/uts/sun4/io/efcode/fcode.c b/usr/src/uts/sun4/io/efcode/fcode.c
index 0f0b4b54f1..f98ed8db01 100644
--- a/usr/src/uts/sun4/io/efcode/fcode.c
+++ b/usr/src/uts/sun4/io/efcode/fcode.c
@@ -20,7 +20,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -59,6 +59,7 @@ static struct fc_state {
#define FC_STATE_READ_DONE 2 /* blocking read done */
#define FC_STATE_IN_PROGRESS 3 /* FC_GET_PARAMETERS done, active */
#define FC_STATE_VALIDATED 4 /* FC_VALIDATE done, active */
+#define FC_STATE_ERROR_SET 5 /* FC_SET_FCODE_ERROR done, active */
#define FC_STATE_ACTIVE(s) ((s) != 0)
#define FC_STATE_AVAILABLE(s) ((s) == FC_STATE_INACTIVE)
@@ -79,6 +80,7 @@ static int fc_get_my_args(dev_t, intptr_t, int, cred_t *, int *);
static int fc_run_priv(dev_t, intptr_t, int, cred_t *, int *);
static int fc_validate(dev_t, intptr_t, int, cred_t *, int *);
static int fc_get_fcode(dev_t, intptr_t, int, cred_t *, int *);
+static int fc_set_fcode_error(dev_t, intptr_t, int, cred_t *, int *);
static struct cb_ops fc_cb_ops = {
fc_open, /* open */
@@ -335,7 +337,13 @@ fc_close(dev_t dev, int flag, int otype, cred_t *cred_p)
"fc_close: Send invalidate cmd\n");
cp->svc_name = fc_ptr2cell(FC_SVC_INVALIDATE);
(void) fp->ap_ops(fp->ap_dip, fp->handle, cp);
- fp->error = FC_ERROR;
+ if ((st->state != FC_STATE_ERROR_SET) ||
+ (fp->error == FC_SUCCESS)) {
+ fp->error = FC_ERROR;
+ }
+ /*
+ * else - fp->error already set by userland interpreter
+ */
}
bzero(cp, sizeof (struct fc_client_interface));
@@ -464,6 +472,12 @@ fc_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *credp, int *rvalp)
*/
return (fc_get_fcode(dev, arg, mode, credp, rvalp));
+
+ case FC_SET_FCODE_ERROR:
+ /*
+ * Copy in interpreter error status
+ */
+ return (fc_set_fcode_error(dev, arg, mode, credp, rvalp));
}
/*
* Invalid ioctl command
@@ -859,3 +873,50 @@ fc_get_fcode(dev_t dev, intptr_t arg, int mode, cred_t *credp, int *rvalp)
return (0);
}
+
+/*
+ * fc_set_fcode_error: Copy in fcode error.
+ * The input 'arg' is a pointer to int which
+ * should have the appropriate error code set.
+ */
+
+/*ARGSUSED*/
+static int
+fc_set_fcode_error(dev_t dev, intptr_t arg, int mode, cred_t *credp, int *rvalp)
+{
+ struct fc_state *st;
+ struct fc_request *fp;
+ int m = (int)getminor(dev) - 1;
+ int status;
+
+ st = fc_states + m;
+ ASSERT(m < fc_max_opens && FC_STATE_ACTIVE(st->state));
+
+ ASSERT(st->req != NULL);
+ fp = st->req;
+
+ FC_DEBUG1(3, CE_CONT, "fc_ioctl: fc_set_fcode_error fp: %p\n", fp);
+
+ /*
+ * Get the error code from userland.
+ * We expect these to be negative values to denote
+ * interpreter errors.
+ */
+ if (copyin((void *)arg, &status, sizeof (int))) {
+ FC_DEBUG1(1, CE_CONT, "fc_ioctl: fc_set_fcode_error "
+ "fault copying in status from %p\n", arg);
+ return (EFAULT);
+ }
+
+ if (!FC_ERROR_VALID(status)) {
+ FC_DEBUG1(1, CE_CONT, "fc_ioctl: fc_set_fcode_error "
+ "invalid error code specified %i\n", status);
+ return (EINVAL);
+ }
+ fp->error = status;
+ mutex_enter(&fc_open_lock);
+ st->state = FC_STATE_ERROR_SET;
+ mutex_exit(&fc_open_lock);
+
+ return (0);
+}
diff --git a/usr/src/uts/sun4/sys/fcode.h b/usr/src/uts/sun4/sys/fcode.h
index 30d83bee1a..280bf6e94e 100644
--- a/usr/src/uts/sun4/sys/fcode.h
+++ b/usr/src/uts/sun4/sys/fcode.h
@@ -20,7 +20,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -71,6 +71,7 @@ extern "C" {
#define FC_VALIDATE (FCIOC | 3)
#define FC_GET_MY_ARGS (FCIOC | 4)
#define FC_GET_FCODE_DATA (FCIOC | 5)
+#define FC_SET_FCODE_ERROR (FCIOC | 6)
#define FC_GET_MY_ARGS_BUFLEN 256 /* Max my-args length */
@@ -295,6 +296,21 @@ typedef struct fc_fcode_info {
#define FC_GET_FCODE "sunos,get-fcode"
/*
+ * Values for fc_request 'error'. This has been moved from the _KERNEL
+ * area to allow the FC_SET_FCODE_ERROR ioctl to use these values to
+ * signal the kernel as to the disposition of the userland interpreter.
+ * NOTE: Positive values are used to indicate a kernel error,
+ * negative values are used to identify userland interpreter errors.
+ */
+#define FC_SUCCESS 0 /* FCode interpreted successfully */
+#define FC_TIMEOUT 1 /* Timer expired */
+#define FC_ERROR -1 /* Interpreter error */
+#define FC_EXEC_FAILED -2 /* Interpreter failed to exec */
+#define FC_NO_FCODE -3 /* Interpreter couldn't find fcode */
+#define FC_FCODE_ABORT -4 /* Interpreter called exit(1) */
+#define FC_ERROR_VALID(s) ((s) >= FC_FCODE_ABORT) && ((s) <= FC_TIMEOUT)
+
+/*
* kernel internal data structures and interfaces
* for the fcode interpreter.
*/
@@ -550,13 +566,6 @@ struct fc_request {
#define FC_R_DONE 2 /* request is done and may be deq'd */
/*
- * Values for 'error'.
- */
-#define FC_SUCCESS 0 /* FCode interpreted successfully */
-#define FC_TIMEOUT 1 /* Timer expired */
-#define FC_ERROR -1 /* Interpreter error */
-
-/*
* Function to call to invoke the fcode interpreter.
*
* This function will wait and return when the interpreter either
diff --git a/usr/src/uts/sun4u/io/pcicfg.e.c b/usr/src/uts/sun4u/io/pcicfg.e.c
index 83397fe6a2..1109623f9e 100644
--- a/usr/src/uts/sun4u/io/pcicfg.e.c
+++ b/usr/src/uts/sun4u/io/pcicfg.e.c
@@ -1098,7 +1098,7 @@ pcicfg_ntbridge_unconfigure_child(dev_info_t *new_device, uint_t devno)
}
if (pcicfg_config_setup(new_ntbridgechild, &config_handle)
- != DDI_SUCCESS) {
+ != DDI_SUCCESS) {
cmn_err(CE_WARN,
"pcicfg: Cannot map ntbridge child %x\n", devno);
(void) ndi_devi_free(new_ntbridgechild);
@@ -3787,15 +3787,23 @@ pcicfg_fcode_probe(dev_info_t *parent, uint_t bus,
(void) ndi_devi_bind_driver(new_child, 0);
return (PCICFG_SUCCESS);
+ } else if ((error != FC_NO_FCODE) &&
+ (pcicfg_dont_interpret == 0)) {
+ /*
+ * The interpreter located fcode, but had an error in
+ * processing. Cleanup and fail the operation.
+ */
+ DEBUG0("Interpreter detected fcode failure\n");
+ (void) pcicfg_free_resources(new_child);
+ goto failed;
} else {
/*
- * Either the interpreter failed or the we chose
- * not to run the interpreter (pcicfg_dont_interpret).
+ * Either the interpreter failed with FC_NO_FCODE or we
+ * chose not to run the interpreter
+ * (pcicfg_dont_interpret).
*
* If the interpreter failed because there was no
* dropin, then we need to probe the device ourself.
- * Otherwise we will probably just fail the
- * configuration.
*/
/*
@@ -3864,6 +3872,16 @@ pcicfg_fcode_probe(dev_info_t *parent, uint_t bus,
ret = pcicfg_configure_ntbridge(new_child,
bus, device);
}
+ if (ret != PCICFG_SUCCESS) {
+ /*
+ * Bridge configure failed. Free up the self
+ * probed entry. The bus resource allocation
+ * maps need to be cleaned up to prevent
+ * warnings on retries of the failed configure.
+ */
+ (void) pcicfg_ntbridge_unconfigure(new_child);
+ (void) pcicfg_teardown_device(new_child);
+ }
#endif
return (ret);