1
0
mirror of https://git.FreeBSD.org/src.git synced 2024-12-12 09:58:36 +00:00

Tweak the ia64 machine check handling code to not register new sysctl nodes

while holding a spin mutex.  Instead, it now shoves the machine check
records onto a queue that is later drained to add sysctl nodes for each
record.  While a routine to drain the queue is present, it is not currently
called.

Reviewed by:	marcel
This commit is contained in:
John Baldwin 2009-02-04 18:44:29 +00:00
parent c05bf25301
commit 148a5cf9e8
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=188119
2 changed files with 45 additions and 26 deletions

View File

@ -42,6 +42,16 @@
MALLOC_DEFINE(M_MCA, "MCA", "Machine Check Architecture");
struct mca_info {
STAILQ_ENTRY(mca_info) mi_link;
char mi_name[32];
size_t mi_recsz;
char mi_record[0];
};
static STAILQ_HEAD(, mca_info) mca_records =
STAILQ_HEAD_INITIALIZER(mca_records);
int64_t mca_info_size[SAL_INFO_TYPES];
vm_offset_t mca_info_block;
struct mtx mca_info_block_lock;
@ -75,15 +85,33 @@ mca_sysctl_handler(SYSCTL_HANDLER_ARGS)
return (error);
}
void
ia64_mca_populate(void)
{
struct mca_info *rec;
mtx_lock_spin(&mca_info_block_lock);
while (!STAILQ_EMPTY(&mca_records)) {
rec = STAILQ_FIRST(&mca_records);
STAILQ_REMOVE_HEAD(&mca_records, mi_link);
mtx_unlock_spin(&mca_info_block_lock);
(void)SYSCTL_ADD_PROC(NULL, SYSCTL_STATIC_CHILDREN(_hw_mca),
OID_AUTO, rec->mi_name, CTLTYPE_OPAQUE | CTLFLAG_RD,
rec->mi_record, rec->mi_recsz, mca_sysctl_handler, "S,MCA",
"Error record");
mtx_lock_spin(&mca_info_block_lock);
}
mtx_unlock_spin(&mca_info_block_lock);
}
void
ia64_mca_save_state(int type)
{
struct ia64_sal_result result;
struct mca_record_header *hdr;
struct sysctl_oid *oidp;
char *name, *state;
struct mca_info *rec;
uint64_t seqnr;
size_t recsz, totsz;
size_t recsz;
/*
* Don't try to get the state if we couldn't get the size of
@ -95,9 +123,8 @@ ia64_mca_save_state(int type)
if (mca_info_block == 0)
return;
mtx_lock_spin(&mca_info_block_lock);
while (1) {
mtx_lock_spin(&mca_info_block_lock);
result = ia64_sal_entry(SAL_GET_STATE_INFO, type, 0,
mca_info_block, 0, 0, 0, 0);
if (result.sal_status < 0) {
@ -111,11 +138,13 @@ ia64_mca_save_state(int type)
mtx_unlock_spin(&mca_info_block_lock);
totsz = sizeof(struct sysctl_oid) + recsz + 32;
oidp = malloc(totsz, M_MCA, M_NOWAIT|M_ZERO);
state = (char*)(oidp + 1);
name = state + recsz;
sprintf(name, "%lld", (long long)seqnr);
rec = malloc(sizeof(struct mca_info) + recsz, M_MCA,
M_NOWAIT | M_ZERO);
if (rec == NULL)
/* XXX: Not sure what to do. */
return;
sprintf(rec->mi_name, "%lld", (long long)seqnr);
mtx_lock_spin(&mca_info_block_lock);
@ -133,24 +162,14 @@ ia64_mca_save_state(int type)
mca_info_block, 0, 0, 0, 0);
if (seqnr != hdr->rh_seqnr) {
mtx_unlock_spin(&mca_info_block_lock);
free(oidp, M_MCA);
free(rec, M_MCA);
mtx_lock_spin(&mca_info_block_lock);
continue;
}
}
bcopy((char*)mca_info_block, state, recsz);
oidp->oid_parent = &sysctl__hw_mca_children;
oidp->oid_number = OID_AUTO;
oidp->oid_kind = CTLTYPE_OPAQUE|CTLFLAG_RD|CTLFLAG_DYN;
oidp->oid_arg1 = state;
oidp->oid_arg2 = recsz;
oidp->oid_name = name;
oidp->oid_handler = mca_sysctl_handler;
oidp->oid_fmt = "S,MCA";
oidp->oid_descr = "Error record";
sysctl_register_oid(oidp);
rec->mi_recsz = recsz;
bcopy((char*)mca_info_block, rec->mi_record, recsz);
if (mca_count > 0) {
if (seqnr < mca_first)
@ -161,6 +180,7 @@ ia64_mca_save_state(int type)
mca_first = mca_last = seqnr;
mca_count++;
STAILQ_INSERT_TAIL(&mca_records, rec, mi_link);
/*
* Clear the state so that we get any other records when
@ -168,8 +188,6 @@ ia64_mca_save_state(int type)
*/
result = ia64_sal_entry(SAL_CLEAR_STATE_INFO, type, 0, 0, 0,
0, 0, 0);
mtx_unlock_spin(&mca_info_block_lock);
}
}

View File

@ -239,6 +239,7 @@ struct mca_pcidev_reg {
#ifdef _KERNEL
void ia64_mca_init(void);
void ia64_mca_populate(void);
void ia64_mca_save_state(int);
#endif /* _KERNEL */