diff options
author | dhain <none@none> | 2005-10-26 16:23:44 -0700 |
---|---|---|
committer | dhain <none@none> | 2005-10-26 16:23:44 -0700 |
commit | 6d22b73346a02763769401e9f28b596670cc3d16 (patch) | |
tree | e7d7f39c1e781bfcbe0eabe6de0780f2eca0205c | |
parent | 595aa6e48d8a5812a3a42afa5f63ee6f772c7f4e (diff) | |
download | illumos-gate-6d22b73346a02763769401e9f28b596670cc3d16.tar.gz |
5107846 DR hangs on fcode_interpreter() running parallel DR.
5043347 PANIC with efcode probing of bad I/O hw in slot;
-rw-r--r-- | usr/src/lib/efcode/efdaemon/efdaemon.c | 19 | ||||
-rw-r--r-- | usr/src/lib/efcode/fcdriver/get_req.c | 10 | ||||
-rw-r--r-- | usr/src/lib/efcode/fcdriver/misc.c | 9 | ||||
-rw-r--r-- | usr/src/uts/sun4/io/efcode/fc_subr.c | 14 | ||||
-rw-r--r-- | usr/src/uts/sun4/io/efcode/fcode.c | 65 | ||||
-rw-r--r-- | usr/src/uts/sun4/sys/fcode.h | 25 | ||||
-rw-r--r-- | usr/src/uts/sun4u/io/pcicfg.e.c | 28 |
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); |