MFC
This commit is contained in:
commit
b2e0423c48
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/projects/random_number_generator/; revision=254782
@ -495,14 +495,10 @@ waitcmdloop(struct job *job)
|
||||
in_waitcmd++;
|
||||
do {
|
||||
if (job != NULL) {
|
||||
if (job->state) {
|
||||
if (job->state == JOBDONE) {
|
||||
status = job->ps[job->nprocs - 1].status;
|
||||
if (WIFEXITED(status))
|
||||
retval = WEXITSTATUS(status);
|
||||
#if JOBS
|
||||
else if (WIFSTOPPED(status))
|
||||
retval = WSTOPSIG(status) + 128;
|
||||
#endif
|
||||
else
|
||||
retval = WTERMSIG(status) + 128;
|
||||
if (! iflag || ! job->changed)
|
||||
|
@ -25,6 +25,7 @@
|
||||
* Copyright (c) 2012 by Delphix. All rights reserved.
|
||||
* Copyright (c) 2012 by Frederik Wessels. All rights reserved.
|
||||
* Copyright (c) 2012 Martin Matuska <mm@FreeBSD.org>. All rights reserved.
|
||||
* Copyright (c) 2013 by Prasad Joshi (sTec). All rights reserved.
|
||||
*/
|
||||
|
||||
#include <solaris.h>
|
||||
@ -2128,8 +2129,10 @@ zpool_do_import(int argc, char **argv)
|
||||
|
||||
errno = 0;
|
||||
searchguid = strtoull(argv[0], &endptr, 10);
|
||||
if (errno != 0 || *endptr != '\0')
|
||||
if (errno != 0 || *endptr != '\0') {
|
||||
searchname = argv[0];
|
||||
searchguid = 0;
|
||||
}
|
||||
found_config = NULL;
|
||||
|
||||
/*
|
||||
|
@ -24,13 +24,15 @@
|
||||
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*/
|
||||
|
||||
#pragma ident "%Z%%M% %I% %E% SMI"
|
||||
/*
|
||||
* Copyright (c) 2013, Joyent, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <sys/sysmacros.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/mman.h>
|
||||
#include <ctf_impl.h>
|
||||
#include <sys/debug.h>
|
||||
|
||||
/*
|
||||
* This static string is used as the template for initially populating a
|
||||
@ -166,6 +168,51 @@ ctf_copy_membnames(ctf_dtdef_t *dtd, uchar_t *s)
|
||||
return (s);
|
||||
}
|
||||
|
||||
/*
|
||||
* Only types of dyanmic CTF containers contain reference counts. These
|
||||
* containers are marked RD/WR. Because of that we basically make this a no-op
|
||||
* for compatability with non-dynamic CTF sections. This is also a no-op for
|
||||
* types which are not dynamic types. It is the responsibility of the caller to
|
||||
* make sure it is a valid type. We help that caller out on debug builds.
|
||||
*
|
||||
* Note that the reference counts are not maintained for types that are not
|
||||
* within this container. In other words if we have a type in a parent, that
|
||||
* will not have its reference count increased. On the flip side, the parent
|
||||
* will not be allowed to remove dynamic types if it has children.
|
||||
*/
|
||||
static void
|
||||
ctf_ref_inc(ctf_file_t *fp, ctf_id_t tid)
|
||||
{
|
||||
ctf_dtdef_t *dtd = ctf_dtd_lookup(fp, tid);
|
||||
|
||||
if (dtd == NULL)
|
||||
return;
|
||||
|
||||
if (!(fp->ctf_flags & LCTF_RDWR))
|
||||
return;
|
||||
|
||||
dtd->dtd_ref++;
|
||||
}
|
||||
|
||||
/*
|
||||
* Just as with ctf_ref_inc, this is a no-op on non-writeable containers and the
|
||||
* caller should ensure that this is already a valid type.
|
||||
*/
|
||||
static void
|
||||
ctf_ref_dec(ctf_file_t *fp, ctf_id_t tid)
|
||||
{
|
||||
ctf_dtdef_t *dtd = ctf_dtd_lookup(fp, tid);
|
||||
|
||||
if (dtd == NULL)
|
||||
return;
|
||||
|
||||
if (!(fp->ctf_flags & LCTF_RDWR))
|
||||
return;
|
||||
|
||||
ASSERT(dtd->dtd_ref >= 1);
|
||||
dtd->dtd_ref--;
|
||||
}
|
||||
|
||||
/*
|
||||
* If the specified CTF container is writable and has been modified, reload
|
||||
* this container with the updated type definitions. In order to make this
|
||||
@ -180,6 +227,10 @@ ctf_copy_membnames(ctf_dtdef_t *dtd, uchar_t *s)
|
||||
* ctf_bufopen() will return a new ctf_file_t, but we want to keep the fp
|
||||
* constant for the caller, so after ctf_bufopen() returns, we use bcopy to
|
||||
* swap the interior of the old and new ctf_file_t's, and then free the old.
|
||||
*
|
||||
* Note that the lists of dynamic types stays around and the resulting container
|
||||
* is still writeable. Furthermore, the reference counts that are on the dtd's
|
||||
* are still valid.
|
||||
*/
|
||||
int
|
||||
ctf_update(ctf_file_t *fp)
|
||||
@ -432,6 +483,7 @@ ctf_dtd_delete(ctf_file_t *fp, ctf_dtdef_t *dtd)
|
||||
ctf_dtdef_t *p, **q = &fp->ctf_dthash[h];
|
||||
ctf_dmdef_t *dmd, *nmd;
|
||||
size_t len;
|
||||
int kind, i;
|
||||
|
||||
for (p = *q; p != NULL; p = p->dtd_hash) {
|
||||
if (p != dtd)
|
||||
@ -443,7 +495,8 @@ ctf_dtd_delete(ctf_file_t *fp, ctf_dtdef_t *dtd)
|
||||
if (p != NULL)
|
||||
*q = p->dtd_hash;
|
||||
|
||||
switch (CTF_INFO_KIND(dtd->dtd_data.ctt_info)) {
|
||||
kind = CTF_INFO_KIND(dtd->dtd_data.ctt_info);
|
||||
switch (kind) {
|
||||
case CTF_K_STRUCT:
|
||||
case CTF_K_UNION:
|
||||
case CTF_K_ENUM:
|
||||
@ -454,14 +507,33 @@ ctf_dtd_delete(ctf_file_t *fp, ctf_dtdef_t *dtd)
|
||||
ctf_free(dmd->dmd_name, len);
|
||||
fp->ctf_dtstrlen -= len;
|
||||
}
|
||||
if (kind != CTF_K_ENUM)
|
||||
ctf_ref_dec(fp, dmd->dmd_type);
|
||||
nmd = ctf_list_next(dmd);
|
||||
ctf_free(dmd, sizeof (ctf_dmdef_t));
|
||||
}
|
||||
break;
|
||||
case CTF_K_FUNCTION:
|
||||
ctf_ref_dec(fp, dtd->dtd_data.ctt_type);
|
||||
for (i = 0; i < CTF_INFO_VLEN(dtd->dtd_data.ctt_info); i++)
|
||||
if (dtd->dtd_u.dtu_argv[i] != 0)
|
||||
ctf_ref_dec(fp, dtd->dtd_u.dtu_argv[i]);
|
||||
ctf_free(dtd->dtd_u.dtu_argv, sizeof (ctf_id_t) *
|
||||
CTF_INFO_VLEN(dtd->dtd_data.ctt_info));
|
||||
break;
|
||||
case CTF_K_ARRAY:
|
||||
ctf_ref_dec(fp, dtd->dtd_u.dtu_arr.ctr_contents);
|
||||
ctf_ref_dec(fp, dtd->dtd_u.dtu_arr.ctr_index);
|
||||
break;
|
||||
case CTF_K_TYPEDEF:
|
||||
ctf_ref_dec(fp, dtd->dtd_data.ctt_type);
|
||||
break;
|
||||
case CTF_K_POINTER:
|
||||
case CTF_K_VOLATILE:
|
||||
case CTF_K_CONST:
|
||||
case CTF_K_RESTRICT:
|
||||
ctf_ref_dec(fp, dtd->dtd_data.ctt_type);
|
||||
break;
|
||||
}
|
||||
|
||||
if (dtd->dtd_name) {
|
||||
@ -495,7 +567,9 @@ ctf_dtd_lookup(ctf_file_t *fp, ctf_id_t type)
|
||||
* Discard all of the dynamic type definitions that have been added to the
|
||||
* container since the last call to ctf_update(). We locate such types by
|
||||
* scanning the list and deleting elements that have type IDs greater than
|
||||
* ctf_dtoldid, which is set by ctf_update(), above.
|
||||
* ctf_dtoldid, which is set by ctf_update(), above. Note that to work properly
|
||||
* with our reference counting schemes, we must delete the dynamic list in
|
||||
* reverse.
|
||||
*/
|
||||
int
|
||||
ctf_discard(ctf_file_t *fp)
|
||||
@ -508,11 +582,11 @@ ctf_discard(ctf_file_t *fp)
|
||||
if (!(fp->ctf_flags & LCTF_DIRTY))
|
||||
return (0); /* no update required */
|
||||
|
||||
for (dtd = ctf_list_next(&fp->ctf_dtdefs); dtd != NULL; dtd = ntd) {
|
||||
for (dtd = ctf_list_prev(&fp->ctf_dtdefs); dtd != NULL; dtd = ntd) {
|
||||
if (dtd->dtd_type <= fp->ctf_dtoldid)
|
||||
continue; /* skip types that have been committed */
|
||||
|
||||
ntd = ctf_list_next(dtd);
|
||||
ntd = ctf_list_prev(dtd);
|
||||
ctf_dtd_delete(fp, dtd);
|
||||
}
|
||||
|
||||
@ -614,6 +688,8 @@ ctf_add_reftype(ctf_file_t *fp, uint_t flag, ctf_id_t ref, uint_t kind)
|
||||
if ((type = ctf_add_generic(fp, flag, NULL, &dtd)) == CTF_ERR)
|
||||
return (CTF_ERR); /* errno is set for us */
|
||||
|
||||
ctf_ref_inc(fp, ref);
|
||||
|
||||
dtd->dtd_data.ctt_info = CTF_TYPE_INFO(kind, flag, 0);
|
||||
dtd->dtd_data.ctt_type = (ushort_t)ref;
|
||||
|
||||
@ -645,16 +721,29 @@ ctf_add_array(ctf_file_t *fp, uint_t flag, const ctf_arinfo_t *arp)
|
||||
{
|
||||
ctf_dtdef_t *dtd;
|
||||
ctf_id_t type;
|
||||
ctf_file_t *fpd;
|
||||
|
||||
if (arp == NULL)
|
||||
return (ctf_set_errno(fp, EINVAL));
|
||||
|
||||
fpd = fp;
|
||||
if (ctf_lookup_by_id(&fpd, arp->ctr_contents) == NULL &&
|
||||
ctf_dtd_lookup(fp, arp->ctr_contents) == NULL)
|
||||
return (ctf_set_errno(fp, ECTF_BADID));
|
||||
|
||||
fpd = fp;
|
||||
if (ctf_lookup_by_id(&fpd, arp->ctr_index) == NULL &&
|
||||
ctf_dtd_lookup(fp, arp->ctr_index) == NULL)
|
||||
return (ctf_set_errno(fp, ECTF_BADID));
|
||||
|
||||
if ((type = ctf_add_generic(fp, flag, NULL, &dtd)) == CTF_ERR)
|
||||
return (CTF_ERR); /* errno is set for us */
|
||||
|
||||
dtd->dtd_data.ctt_info = CTF_TYPE_INFO(CTF_K_ARRAY, flag, 0);
|
||||
dtd->dtd_data.ctt_size = 0;
|
||||
dtd->dtd_u.dtu_arr = *arp;
|
||||
ctf_ref_inc(fp, arp->ctr_contents);
|
||||
ctf_ref_inc(fp, arp->ctr_index);
|
||||
|
||||
return (type);
|
||||
}
|
||||
@ -662,6 +751,7 @@ ctf_add_array(ctf_file_t *fp, uint_t flag, const ctf_arinfo_t *arp)
|
||||
int
|
||||
ctf_set_array(ctf_file_t *fp, ctf_id_t type, const ctf_arinfo_t *arp)
|
||||
{
|
||||
ctf_file_t *fpd;
|
||||
ctf_dtdef_t *dtd = ctf_dtd_lookup(fp, type);
|
||||
|
||||
if (!(fp->ctf_flags & LCTF_RDWR))
|
||||
@ -670,8 +760,22 @@ ctf_set_array(ctf_file_t *fp, ctf_id_t type, const ctf_arinfo_t *arp)
|
||||
if (dtd == NULL || CTF_INFO_KIND(dtd->dtd_data.ctt_info) != CTF_K_ARRAY)
|
||||
return (ctf_set_errno(fp, ECTF_BADID));
|
||||
|
||||
fpd = fp;
|
||||
if (ctf_lookup_by_id(&fpd, arp->ctr_contents) == NULL &&
|
||||
ctf_dtd_lookup(fp, arp->ctr_contents) == NULL)
|
||||
return (ctf_set_errno(fp, ECTF_BADID));
|
||||
|
||||
fpd = fp;
|
||||
if (ctf_lookup_by_id(&fpd, arp->ctr_index) == NULL &&
|
||||
ctf_dtd_lookup(fp, arp->ctr_index) == NULL)
|
||||
return (ctf_set_errno(fp, ECTF_BADID));
|
||||
|
||||
ctf_ref_dec(fp, dtd->dtd_u.dtu_arr.ctr_contents);
|
||||
ctf_ref_dec(fp, dtd->dtd_u.dtu_arr.ctr_index);
|
||||
fp->ctf_flags |= LCTF_DIRTY;
|
||||
dtd->dtd_u.dtu_arr = *arp;
|
||||
ctf_ref_inc(fp, arp->ctr_contents);
|
||||
ctf_ref_inc(fp, arp->ctr_index);
|
||||
|
||||
return (0);
|
||||
}
|
||||
@ -683,7 +787,9 @@ ctf_add_function(ctf_file_t *fp, uint_t flag,
|
||||
ctf_dtdef_t *dtd;
|
||||
ctf_id_t type;
|
||||
uint_t vlen;
|
||||
int i;
|
||||
ctf_id_t *vdat = NULL;
|
||||
ctf_file_t *fpd;
|
||||
|
||||
if (ctc == NULL || (ctc->ctc_flags & ~CTF_FUNC_VARARG) != 0 ||
|
||||
(ctc->ctc_argc != 0 && argv == NULL))
|
||||
@ -696,6 +802,18 @@ ctf_add_function(ctf_file_t *fp, uint_t flag,
|
||||
if (vlen > CTF_MAX_VLEN)
|
||||
return (ctf_set_errno(fp, EOVERFLOW));
|
||||
|
||||
fpd = fp;
|
||||
if (ctf_lookup_by_id(&fpd, ctc->ctc_return) == NULL &&
|
||||
ctf_dtd_lookup(fp, ctc->ctc_return) == NULL)
|
||||
return (ctf_set_errno(fp, ECTF_BADID));
|
||||
|
||||
for (i = 0; i < ctc->ctc_argc; i++) {
|
||||
fpd = fp;
|
||||
if (ctf_lookup_by_id(&fpd, argv[i]) == NULL &&
|
||||
ctf_dtd_lookup(fp, argv[i]) == NULL)
|
||||
return (ctf_set_errno(fp, ECTF_BADID));
|
||||
}
|
||||
|
||||
if (vlen != 0 && (vdat = ctf_alloc(sizeof (ctf_id_t) * vlen)) == NULL)
|
||||
return (ctf_set_errno(fp, EAGAIN));
|
||||
|
||||
@ -707,6 +825,10 @@ ctf_add_function(ctf_file_t *fp, uint_t flag,
|
||||
dtd->dtd_data.ctt_info = CTF_TYPE_INFO(CTF_K_FUNCTION, flag, vlen);
|
||||
dtd->dtd_data.ctt_type = (ushort_t)ctc->ctc_return;
|
||||
|
||||
ctf_ref_inc(fp, ctc->ctc_return);
|
||||
for (i = 0; i < ctc->ctc_argc; i++)
|
||||
ctf_ref_inc(fp, argv[i]);
|
||||
|
||||
bcopy(argv, vdat, sizeof (ctf_id_t) * ctc->ctc_argc);
|
||||
if (ctc->ctc_flags & CTF_FUNC_VARARG)
|
||||
vdat[vlen - 1] = 0; /* add trailing zero to indicate varargs */
|
||||
@ -825,8 +947,11 @@ ctf_add_typedef(ctf_file_t *fp, uint_t flag, const char *name, ctf_id_t ref)
|
||||
{
|
||||
ctf_dtdef_t *dtd;
|
||||
ctf_id_t type;
|
||||
ctf_file_t *fpd;
|
||||
|
||||
if (ref == CTF_ERR || ref < 0 || ref > CTF_MAX_TYPE)
|
||||
fpd = fp;
|
||||
if (ref == CTF_ERR || (ctf_lookup_by_id(&fpd, ref) == NULL &&
|
||||
ctf_dtd_lookup(fp, ref) == NULL))
|
||||
return (ctf_set_errno(fp, EINVAL));
|
||||
|
||||
if ((type = ctf_add_generic(fp, flag, name, &dtd)) == CTF_ERR)
|
||||
@ -834,6 +959,7 @@ ctf_add_typedef(ctf_file_t *fp, uint_t flag, const char *name, ctf_id_t ref)
|
||||
|
||||
dtd->dtd_data.ctt_info = CTF_TYPE_INFO(CTF_K_TYPEDEF, flag, 0);
|
||||
dtd->dtd_data.ctt_type = (ushort_t)ref;
|
||||
ctf_ref_inc(fp, ref);
|
||||
|
||||
return (type);
|
||||
}
|
||||
@ -1008,6 +1134,45 @@ ctf_add_member(ctf_file_t *fp, ctf_id_t souid, const char *name, ctf_id_t type)
|
||||
if (s != NULL)
|
||||
fp->ctf_dtstrlen += strlen(s) + 1;
|
||||
|
||||
ctf_ref_inc(fp, type);
|
||||
fp->ctf_flags |= LCTF_DIRTY;
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* This removes a type from the dynamic section. This will fail if the type is
|
||||
* referenced by another type. Note that the CTF ID is never reused currently by
|
||||
* CTF. Note that if this container is a parent container then we just outright
|
||||
* refuse to remove the type. There currently is no notion of searching for the
|
||||
* ctf_dtdef_t in parent containers. If there is, then this constraint could
|
||||
* become finer grained.
|
||||
*/
|
||||
int
|
||||
ctf_delete_type(ctf_file_t *fp, ctf_id_t type)
|
||||
{
|
||||
ctf_file_t *fpd;
|
||||
ctf_dtdef_t *dtd = ctf_dtd_lookup(fp, type);
|
||||
|
||||
if (!(fp->ctf_flags & LCTF_RDWR))
|
||||
return (ctf_set_errno(fp, ECTF_RDONLY));
|
||||
|
||||
/*
|
||||
* We want to give as useful an errno as possible. That means that we
|
||||
* want to distinguish between a type which does not exist and one for
|
||||
* which the type is not dynamic.
|
||||
*/
|
||||
fpd = fp;
|
||||
if (ctf_lookup_by_id(&fpd, type) == NULL &&
|
||||
ctf_dtd_lookup(fp, type) == NULL)
|
||||
return (CTF_ERR); /* errno is set for us */
|
||||
|
||||
if (dtd == NULL)
|
||||
return (ctf_set_errno(fp, ECTF_NOTDYN));
|
||||
|
||||
if (dtd->dtd_ref != 0 || fp->ctf_refcnt > 1)
|
||||
return (ctf_set_errno(fp, ECTF_REFERENCED));
|
||||
|
||||
ctf_dtd_delete(fp, dtd);
|
||||
fp->ctf_flags |= LCTF_DIRTY;
|
||||
return (0);
|
||||
}
|
||||
@ -1103,6 +1268,9 @@ ctf_add_type(ctf_file_t *dst_fp, ctf_file_t *src_fp, ctf_id_t src_type)
|
||||
ctf_hash_t *hp;
|
||||
ctf_helem_t *hep;
|
||||
|
||||
if (dst_fp == src_fp)
|
||||
return (src_type);
|
||||
|
||||
if (!(dst_fp->ctf_flags & LCTF_RDWR))
|
||||
return (ctf_set_errno(dst_fp, ECTF_RDONLY));
|
||||
|
||||
@ -1313,6 +1481,14 @@ ctf_add_type(ctf_file_t *dst_fp, ctf_file_t *src_fp, ctf_id_t src_type)
|
||||
|
||||
if (errs)
|
||||
return (CTF_ERR); /* errno is set for us */
|
||||
|
||||
/*
|
||||
* Now that we know that we can't fail, we go through and bump
|
||||
* all the reference counts on the member types.
|
||||
*/
|
||||
for (dmd = ctf_list_next(&dtd->dtd_u.dtu_members);
|
||||
dmd != NULL; dmd = ctf_list_next(dmd))
|
||||
ctf_ref_inc(dst_fp, dmd->dmd_type);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -23,8 +23,9 @@
|
||||
* Copyright 2003 Sun Microsystems, Inc. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*/
|
||||
|
||||
#pragma ident "%Z%%M% %I% %E% SMI"
|
||||
/*
|
||||
* Copyright (c) 2012, Joyent, Inc.
|
||||
*/
|
||||
|
||||
#include <ctf_impl.h>
|
||||
|
||||
@ -73,6 +74,8 @@ static const char *const _ctf_errlist[] = {
|
||||
"Limit on number of dynamic types reached", /* ECTF_FULL */
|
||||
"Duplicate member name definition", /* ECTF_DUPMEMBER */
|
||||
"Conflicting type is already defined", /* ECTF_CONFLICT */
|
||||
"Type has outstanding references", /* ECTF_REFERENCED */
|
||||
"Type is not a dynamic type" /* ECTF_NOTDYN */
|
||||
};
|
||||
|
||||
static const int _ctf_nerr = sizeof (_ctf_errlist) / sizeof (_ctf_errlist[0]);
|
||||
|
@ -24,12 +24,13 @@
|
||||
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 2012, Joyent, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _CTF_IMPL_H
|
||||
#define _CTF_IMPL_H
|
||||
|
||||
#pragma ident "%Z%%M% %I% %E% SMI"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/errno.h>
|
||||
#include <sys/sysmacros.h>
|
||||
@ -149,6 +150,7 @@ typedef struct ctf_dtdef {
|
||||
char *dtd_name; /* name associated with definition (if any) */
|
||||
ctf_id_t dtd_type; /* type identifier for this definition */
|
||||
ctf_type_t dtd_data; /* type node (see <sys/ctf.h>) */
|
||||
int dtd_ref; /* recfount for dyanmic types */
|
||||
union {
|
||||
ctf_list_t dtu_members; /* struct, union, or enum */
|
||||
ctf_arinfo_t dtu_arr; /* array */
|
||||
@ -269,7 +271,9 @@ enum {
|
||||
ECTF_DTFULL, /* CTF type is full (no more members allowed) */
|
||||
ECTF_FULL, /* CTF container is full */
|
||||
ECTF_DUPMEMBER, /* duplicate member name definition */
|
||||
ECTF_CONFLICT /* conflicting type definition present */
|
||||
ECTF_CONFLICT, /* conflicting type definition present */
|
||||
ECTF_REFERENCED, /* type has outstanding references */
|
||||
ECTF_NOTDYN /* type is not a dynamic type */
|
||||
};
|
||||
|
||||
extern ssize_t ctf_get_ctt_size(const ctf_file_t *, const ctf_type_t *,
|
||||
|
@ -24,8 +24,9 @@
|
||||
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*/
|
||||
|
||||
#pragma ident "%Z%%M% %I% %E% SMI"
|
||||
/*
|
||||
* Copyright (c) 2012, Joyent, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <ctf_impl.h>
|
||||
#include <sys/mman.h>
|
||||
@ -810,8 +811,12 @@ ctf_close(ctf_file_t *fp)
|
||||
if (fp->ctf_parent != NULL)
|
||||
ctf_close(fp->ctf_parent);
|
||||
|
||||
for (dtd = ctf_list_next(&fp->ctf_dtdefs); dtd != NULL; dtd = ntd) {
|
||||
ntd = ctf_list_next(dtd);
|
||||
/*
|
||||
* Note, to work properly with reference counting on the dynamic
|
||||
* section, we must delete the list in reverse.
|
||||
*/
|
||||
for (dtd = ctf_list_prev(&fp->ctf_dtdefs); dtd != NULL; dtd = ntd) {
|
||||
ntd = ctf_list_prev(dtd);
|
||||
ctf_dtd_delete(fp, dtd);
|
||||
}
|
||||
|
||||
|
@ -216,6 +216,7 @@ ctf_fdopen(int fd, int *errp)
|
||||
{
|
||||
ctf_sect_t ctfsect, symsect, strsect;
|
||||
ctf_file_t *fp = NULL;
|
||||
size_t shstrndx, shnum;
|
||||
|
||||
struct stat64 st;
|
||||
ssize_t nbytes;
|
||||
@ -278,11 +279,10 @@ ctf_fdopen(int fd, int *errp)
|
||||
#else
|
||||
uchar_t order = ELFDATA2LSB;
|
||||
#endif
|
||||
GElf_Half i, n;
|
||||
GElf_Shdr *sp;
|
||||
|
||||
void *strs_map;
|
||||
size_t strs_mapsz;
|
||||
size_t strs_mapsz, i;
|
||||
char *strs;
|
||||
|
||||
if (hdr.e32.e_ident[EI_DATA] != order)
|
||||
@ -298,11 +298,38 @@ ctf_fdopen(int fd, int *errp)
|
||||
ehdr_to_gelf(&e32, &hdr.e64);
|
||||
}
|
||||
|
||||
if (hdr.e64.e_shstrndx >= hdr.e64.e_shnum)
|
||||
shnum = hdr.e64.e_shnum;
|
||||
shstrndx = hdr.e64.e_shstrndx;
|
||||
|
||||
/* Extended ELF sections */
|
||||
if ((shstrndx == SHN_XINDEX) || (shnum == 0)) {
|
||||
if (hdr.e32.e_ident[EI_CLASS] == ELFCLASS32) {
|
||||
Elf32_Shdr x32;
|
||||
|
||||
if (pread64(fd, &x32, sizeof (x32),
|
||||
hdr.e64.e_shoff) != sizeof (x32))
|
||||
return (ctf_set_open_errno(errp,
|
||||
errno));
|
||||
|
||||
shnum = x32.sh_size;
|
||||
shstrndx = x32.sh_link;
|
||||
} else {
|
||||
Elf64_Shdr x64;
|
||||
|
||||
if (pread64(fd, &x64, sizeof (x64),
|
||||
hdr.e64.e_shoff) != sizeof (x64))
|
||||
return (ctf_set_open_errno(errp,
|
||||
errno));
|
||||
|
||||
shnum = x64.sh_size;
|
||||
shstrndx = x64.sh_link;
|
||||
}
|
||||
}
|
||||
|
||||
if (shstrndx >= shnum)
|
||||
return (ctf_set_open_errno(errp, ECTF_CORRUPT));
|
||||
|
||||
n = hdr.e64.e_shnum;
|
||||
nbytes = sizeof (GElf_Shdr) * n;
|
||||
nbytes = sizeof (GElf_Shdr) * shnum;
|
||||
|
||||
if ((sp = malloc(nbytes)) == NULL)
|
||||
return (ctf_set_open_errno(errp, errno));
|
||||
@ -314,7 +341,7 @@ ctf_fdopen(int fd, int *errp)
|
||||
if (hdr.e32.e_ident[EI_CLASS] == ELFCLASS32) {
|
||||
Elf32_Shdr *sp32;
|
||||
|
||||
nbytes = sizeof (Elf32_Shdr) * n;
|
||||
nbytes = sizeof (Elf32_Shdr) * shnum;
|
||||
|
||||
if ((sp32 = malloc(nbytes)) == NULL || pread64(fd,
|
||||
sp32, nbytes, hdr.e64.e_shoff) != nbytes) {
|
||||
@ -322,7 +349,7 @@ ctf_fdopen(int fd, int *errp)
|
||||
return (ctf_set_open_errno(errp, errno));
|
||||
}
|
||||
|
||||
for (i = 0; i < n; i++)
|
||||
for (i = 0; i < shnum; i++)
|
||||
shdr_to_gelf(&sp32[i], &sp[i]);
|
||||
|
||||
free(sp32);
|
||||
@ -336,14 +363,14 @@ ctf_fdopen(int fd, int *errp)
|
||||
* Now mmap the section header strings section so that we can
|
||||
* perform string comparison on the section names.
|
||||
*/
|
||||
strs_mapsz = sp[hdr.e64.e_shstrndx].sh_size +
|
||||
(sp[hdr.e64.e_shstrndx].sh_offset & ~_PAGEMASK);
|
||||
strs_mapsz = sp[shstrndx].sh_size +
|
||||
(sp[shstrndx].sh_offset & ~_PAGEMASK);
|
||||
|
||||
strs_map = mmap64(NULL, strs_mapsz, PROT_READ, MAP_PRIVATE,
|
||||
fd, sp[hdr.e64.e_shstrndx].sh_offset & _PAGEMASK);
|
||||
fd, sp[shstrndx].sh_offset & _PAGEMASK);
|
||||
|
||||
strs = (char *)strs_map +
|
||||
(sp[hdr.e64.e_shstrndx].sh_offset & ~_PAGEMASK);
|
||||
(sp[shstrndx].sh_offset & ~_PAGEMASK);
|
||||
|
||||
if (strs_map == MAP_FAILED) {
|
||||
free(sp);
|
||||
@ -354,15 +381,15 @@ ctf_fdopen(int fd, int *errp)
|
||||
* Iterate over the section header array looking for the CTF
|
||||
* section and symbol table. The strtab is linked to symtab.
|
||||
*/
|
||||
for (i = 0; i < n; i++) {
|
||||
for (i = 0; i < shnum; i++) {
|
||||
const GElf_Shdr *shp = &sp[i];
|
||||
const GElf_Shdr *lhp = &sp[shp->sh_link];
|
||||
|
||||
if (shp->sh_link >= hdr.e64.e_shnum)
|
||||
if (shp->sh_link >= shnum)
|
||||
continue; /* corrupt sh_link field */
|
||||
|
||||
if (shp->sh_name >= sp[hdr.e64.e_shstrndx].sh_size ||
|
||||
lhp->sh_name >= sp[hdr.e64.e_shstrndx].sh_size)
|
||||
if (shp->sh_name >= sp[shstrndx].sh_size ||
|
||||
lhp->sh_name >= sp[shstrndx].sh_size)
|
||||
continue; /* corrupt sh_name field */
|
||||
|
||||
if (shp->sh_type == SHT_PROGBITS &&
|
||||
|
@ -21,10 +21,10 @@
|
||||
|
||||
/*
|
||||
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright 2010 Nexenta Systems, Inc. All rights reserved.
|
||||
* Copyright (c) 2012 by Delphix. All rights reserved.
|
||||
* Copyright (c) 2012 Pawel Jakub Dawidek <pawel@dawidek.net>.
|
||||
* All rights reserved.
|
||||
* Copyright 2013 Nexenta Systems, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
@ -452,8 +452,12 @@ iter_dependents_cb(zfs_handle_t *zhp, void *arg)
|
||||
}
|
||||
ida->stack = isf.next;
|
||||
}
|
||||
|
||||
if (!first && err == 0)
|
||||
err = ida->func(zhp, ida->data);
|
||||
else
|
||||
zfs_close(zhp);
|
||||
|
||||
return (err);
|
||||
}
|
||||
|
||||
|
@ -336,19 +336,45 @@ class IRExecutionUnit : public IRMemoryMap
|
||||
/// @return
|
||||
/// True in case of failure, false in case of success.
|
||||
//------------------------------------------------------------------
|
||||
virtual bool finalizeMemory(std::string *ErrMsg) {
|
||||
// TODO: Ensure that the instruction cache is flushed because
|
||||
// relocations are updated by dy-load. See:
|
||||
// sys::Memory::InvalidateInstructionCache
|
||||
// llvm::SectionMemoryManager
|
||||
return false;
|
||||
}
|
||||
bool applyPermissions(std::string *ErrMsg) { return false; }
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Passthrough interface stub
|
||||
//------------------------------------------------------------------
|
||||
virtual void deallocateFunctionBody(void *Body);
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Passthrough interface stub
|
||||
//------------------------------------------------------------------
|
||||
virtual uint8_t* startExceptionTable(const llvm::Function* F,
|
||||
uintptr_t &ActualSize);
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Complete the exception table for a function, and add it to the
|
||||
/// m_exception_tables map
|
||||
///
|
||||
/// @param[in] F
|
||||
/// The function whose exception table is being written.
|
||||
///
|
||||
/// @param[in] TableStart
|
||||
/// The first byte of the exception table.
|
||||
///
|
||||
/// @param[in] TableEnd
|
||||
/// The last byte of the exception table.
|
||||
///
|
||||
/// @param[in] FrameRegister
|
||||
/// I don't know what this does, but it's passed through.
|
||||
//------------------------------------------------------------------
|
||||
virtual void endExceptionTable(const llvm::Function *F,
|
||||
uint8_t *TableStart,
|
||||
uint8_t *TableEnd,
|
||||
uint8_t* FrameRegister);
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Passthrough interface stub
|
||||
//------------------------------------------------------------------
|
||||
virtual void deallocateExceptionTable(void *ET);
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Passthrough interface stub
|
||||
//------------------------------------------------------------------
|
||||
|
@ -52,7 +52,7 @@
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/ExecutionEngine/ExecutionEngine.h"
|
||||
#include "llvm/Support/Debug.h"
|
||||
#include "llvm/Support/FileSystem.h"
|
||||
#include "llvm/Support/PathV1.h"
|
||||
#include "llvm/Support/TargetSelect.h"
|
||||
|
||||
#if defined(__FreeBSD__)
|
||||
@ -81,16 +81,19 @@ using namespace lldb_private;
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
std::string GetBuiltinIncludePath(const char *Argv0) {
|
||||
SmallString<128> P(llvm::sys::fs::getMainExecutable(
|
||||
Argv0, (void *)(intptr_t) GetBuiltinIncludePath));
|
||||
|
||||
if (!P.empty()) {
|
||||
llvm::sys::path::remove_filename(P); // Remove /clang from foo/bin/clang
|
||||
llvm::sys::path::remove_filename(P); // Remove /bin from foo/bin
|
||||
|
||||
llvm::sys::Path P =
|
||||
llvm::sys::Path::GetMainExecutable(Argv0,
|
||||
(void*)(intptr_t) GetBuiltinIncludePath);
|
||||
|
||||
if (!P.isEmpty()) {
|
||||
P.eraseComponent(); // Remove /clang from foo/bin/clang
|
||||
P.eraseComponent(); // Remove /bin from foo/bin
|
||||
|
||||
// Get foo/lib/clang/<version>/include
|
||||
llvm::sys::path::append(P, "lib", "clang", CLANG_VERSION_STRING,
|
||||
"include");
|
||||
P.appendComponent("lib");
|
||||
P.appendComponent("clang");
|
||||
P.appendComponent(CLANG_VERSION_STRING);
|
||||
P.appendComponent("include");
|
||||
}
|
||||
|
||||
return P.str();
|
||||
|
@ -563,6 +563,28 @@ IRExecutionUnit::MemoryManager::deallocateFunctionBody(void *Body)
|
||||
m_default_mm_ap->deallocateFunctionBody(Body);
|
||||
}
|
||||
|
||||
uint8_t*
|
||||
IRExecutionUnit::MemoryManager::startExceptionTable(const llvm::Function* F,
|
||||
uintptr_t &ActualSize)
|
||||
{
|
||||
return m_default_mm_ap->startExceptionTable(F, ActualSize);
|
||||
}
|
||||
|
||||
void
|
||||
IRExecutionUnit::MemoryManager::endExceptionTable(const llvm::Function *F,
|
||||
uint8_t *TableStart,
|
||||
uint8_t *TableEnd,
|
||||
uint8_t* FrameRegister)
|
||||
{
|
||||
m_default_mm_ap->endExceptionTable(F, TableStart, TableEnd, FrameRegister);
|
||||
}
|
||||
|
||||
void
|
||||
IRExecutionUnit::MemoryManager::deallocateExceptionTable(void *ET)
|
||||
{
|
||||
m_default_mm_ap->deallocateExceptionTable (ET);
|
||||
}
|
||||
|
||||
lldb::addr_t
|
||||
IRExecutionUnit::GetRemoteAddressForLocal (lldb::addr_t local_address)
|
||||
{
|
||||
|
@ -553,8 +553,9 @@ FileSpec::ResolveExecutableLocation ()
|
||||
if (file_cstr)
|
||||
{
|
||||
const std::string file_str (file_cstr);
|
||||
std::string path = llvm::sys::FindProgramByName (file_str);
|
||||
llvm::StringRef dir_ref = llvm::sys::path::parent_path(path);
|
||||
llvm::sys::Path path = llvm::sys::Program::FindProgramByName (file_str);
|
||||
const std::string &path_str = path.str();
|
||||
llvm::StringRef dir_ref = llvm::sys::path::parent_path(path_str);
|
||||
//llvm::StringRef dir_ref = path.getDirname();
|
||||
if (! dir_ref.empty())
|
||||
{
|
||||
|
@ -10,7 +10,6 @@
|
||||
#include "DisassemblerLLVMC.h"
|
||||
|
||||
#include "llvm-c/Disassembler.h"
|
||||
#include "llvm/ADT/OwningPtr.h"
|
||||
#include "llvm/MC/MCAsmInfo.h"
|
||||
#include "llvm/MC/MCContext.h"
|
||||
#include "llvm/MC/MCDisassembler.h"
|
||||
@ -18,7 +17,6 @@
|
||||
#include "llvm/MC/MCInstPrinter.h"
|
||||
#include "llvm/MC/MCInstrInfo.h"
|
||||
#include "llvm/MC/MCRegisterInfo.h"
|
||||
#include "llvm/MC/MCRelocationInfo.h"
|
||||
#include "llvm/MC/MCSubtargetInfo.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
#include "llvm/Support/MemoryObject.h"
|
||||
@ -442,30 +440,23 @@ DisassemblerLLVMC::LLVMCDisassembler::LLVMCDisassembler (const char *triple, uns
|
||||
m_subtarget_info_ap.reset(curr_target->createMCSubtargetInfo(triple, "",
|
||||
features_str));
|
||||
|
||||
m_asm_info_ap.reset(curr_target->createMCAsmInfo(*curr_target->createMCRegInfo(triple), triple));
|
||||
|
||||
m_asm_info_ap.reset(curr_target->createMCAsmInfo(triple));
|
||||
|
||||
if (m_instr_info_ap.get() == NULL || m_reg_info_ap.get() == NULL || m_subtarget_info_ap.get() == NULL || m_asm_info_ap.get() == NULL)
|
||||
{
|
||||
m_is_valid = false;
|
||||
return;
|
||||
}
|
||||
|
||||
m_context_ap.reset(new llvm::MCContext(m_asm_info_ap.get(), m_reg_info_ap.get(), 0));
|
||||
m_context_ap.reset(new llvm::MCContext(*m_asm_info_ap.get(), *(m_reg_info_ap.get()), 0));
|
||||
|
||||
m_disasm_ap.reset(curr_target->createMCDisassembler(*m_subtarget_info_ap.get()));
|
||||
if (m_disasm_ap.get() && m_context_ap.get())
|
||||
if (m_disasm_ap.get())
|
||||
{
|
||||
llvm::OwningPtr<llvm::MCRelocationInfo> RelInfo(curr_target->createMCRelocationInfo(triple, *m_context_ap.get()));
|
||||
if (!RelInfo)
|
||||
{
|
||||
m_is_valid = false;
|
||||
return;
|
||||
}
|
||||
m_disasm_ap->setupForSymbolicDisassembly(NULL,
|
||||
DisassemblerLLVMC::SymbolLookupCallback,
|
||||
(void *) &owner,
|
||||
m_context_ap.get(),
|
||||
RelInfo);
|
||||
DisassemblerLLVMC::SymbolLookupCallback,
|
||||
(void *) &owner,
|
||||
m_context_ap.get());
|
||||
|
||||
unsigned asm_printer_variant;
|
||||
if (flavor == ~0U)
|
||||
|
@ -25,7 +25,7 @@
|
||||
#include "Utility/ARM_DWARF_Registers.h"
|
||||
|
||||
#include "llvm/Support/MathExtras.h" // for SignExtend32 template function
|
||||
// and countTrailingZeros function
|
||||
// and CountTrailingZeros_32 function
|
||||
|
||||
using namespace lldb;
|
||||
using namespace lldb_private;
|
||||
@ -47,7 +47,7 @@ using namespace lldb_private;
|
||||
static uint32_t
|
||||
CountITSize (uint32_t ITMask) {
|
||||
// First count the trailing zeros of the IT mask.
|
||||
uint32_t TZ = llvm::countTrailingZeros(ITMask);
|
||||
uint32_t TZ = llvm::CountTrailingZeros_32(ITMask);
|
||||
if (TZ > 3)
|
||||
{
|
||||
#ifdef LLDB_CONFIGURATION_DEBUG
|
||||
|
@ -661,9 +661,9 @@ ipv4_down()
|
||||
for _inet in $inetList ; do
|
||||
# get rid of extraneous line
|
||||
case $_inet in
|
||||
"") break ;;
|
||||
inet\ *) ;;
|
||||
*) continue ;;
|
||||
"") break ;;
|
||||
\ inet\ *|inet\ *) ;;
|
||||
*) continue ;;
|
||||
esac
|
||||
[ -z "$_inet" ] && break
|
||||
|
||||
|
@ -539,6 +539,7 @@ MAN= aac.4 \
|
||||
${_virtio_scsi.4} \
|
||||
vkbd.4 \
|
||||
vlan.4 \
|
||||
${_vmx.4} \
|
||||
vpo.4 \
|
||||
vr.4 \
|
||||
vte.4 \
|
||||
@ -706,6 +707,7 @@ MLINKS+=ural.4 if_ural.4
|
||||
MLINKS+=${_urtw.4} ${_if_urtw.4}
|
||||
MLINKS+=vge.4 if_vge.4
|
||||
MLINKS+=vlan.4 if_vlan.4
|
||||
MLINKS+=${_vmx.4} ${_if_vmx.4}
|
||||
MLINKS+=vpo.4 imm.4
|
||||
MLINKS+=vr.4 if_vr.4
|
||||
MLINKS+=vte.4 if_vte.4
|
||||
@ -758,6 +760,7 @@ _if_nfe.4= if_nfe.4
|
||||
_if_nve.4= if_nve.4
|
||||
_if_nxge.4= if_nxge.4
|
||||
_if_urtw.4= if_urtw.4
|
||||
_if_vmx.4= if_vmx.4
|
||||
_if_vtnet.4= if_vtnet.4
|
||||
_if_vxge.4= if_vxge.4
|
||||
_if_wpi.4= if_wpi.4
|
||||
@ -777,6 +780,7 @@ _virtio.4= virtio.4
|
||||
_virtio_balloon.4=virtio_balloon.4
|
||||
_virtio_blk.4= virtio_blk.4
|
||||
_virtio_scsi.4= virtio_scsi.4
|
||||
_vmx.4= vmx.4
|
||||
_vtnet.4= vtnet.4
|
||||
_vxge.4= vxge.4
|
||||
_padlock.4= padlock.4
|
||||
|
@ -25,7 +25,7 @@
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd June 6, 1999
|
||||
.Dd August 23, 2013
|
||||
.Dt SA 4
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -159,6 +159,70 @@ of 0.
|
||||
(As above, if the file mark is never read, it remains for the next
|
||||
process to read if in no-rewind mode.)
|
||||
.El
|
||||
.Sh BLOCK SIZES
|
||||
By default, the driver will NOT accept reads or writes to a tape device that
|
||||
are larger than may be written to or read from the mounted tape using a single
|
||||
write or read request.
|
||||
Because of this, the application author may have confidence that his wishes
|
||||
are respected in terms of the block size written to tape.
|
||||
For example, if the user tries to write a 256KB block to the tape, but the
|
||||
controller can handle no more than 128KB, the write will fail.
|
||||
The previous
|
||||
.Fx
|
||||
behavior, prior to
|
||||
.Fx
|
||||
10.0,
|
||||
was to break up large reads or writes into smaller blocks when going to the
|
||||
tape.
|
||||
The problem with that behavior, though, is that it hides the actual on-tape
|
||||
block size from the application writer, at least in variable block mode.
|
||||
.Pp
|
||||
If the user would like his large reads and writes broken up into separate
|
||||
pieces, he may set the following loader tunables.
|
||||
Note that these tunables WILL GO AWAY in
|
||||
.Fx 11.0 .
|
||||
They are provided for transition purposes only.
|
||||
.Bl -tag -width 12
|
||||
.It kern.cam.sa.allow_io_split
|
||||
.Pp
|
||||
This variable, when set to 1, will configure all
|
||||
.Nm
|
||||
devices to split large buffers into smaller pieces when needed.
|
||||
.It kern.cam.sa.%d.allow_io_split
|
||||
.Pp
|
||||
This variable, when set to 1, will configure the given
|
||||
.Nm
|
||||
unit to split large buffers into multiple pieces.
|
||||
This will override the global setting, if it exists.
|
||||
.El
|
||||
.Pp
|
||||
There are several
|
||||
.Xr sysctl 8
|
||||
variables available to view block handling parameters:
|
||||
.Bl -tag -width 12
|
||||
.It kern.cam.sa.%d.allow_io_split
|
||||
.Pp
|
||||
This variable allows the user to see, but not modify, the current I/O split
|
||||
setting.
|
||||
The user is not permitted to modify this setting so that there is no chance
|
||||
of behavior changing for the application while a tape is mounted.
|
||||
.It kern.cam.sa.%d.maxio
|
||||
.Pp
|
||||
This variable shows the maximum I/O size in bytes that is allowed by the
|
||||
combination of kernel tuning parameters (MAXPHYS, DFLTPHYS) and the
|
||||
capabilities of the controller that is attached to the tape drive.
|
||||
Applications may look at this value for a guide on how large an I/O may be
|
||||
permitted, but should keep in mind that the actual maximum may be
|
||||
restricted further by the tape drive via the
|
||||
.Tn SCSI
|
||||
READ BLOCK LIMITS command.
|
||||
.It kern.cam.sa.%d.cpi_maxio
|
||||
.Pp
|
||||
This variable shows the maximum I/O size supported by the controller, in
|
||||
bytes, that is reported via the CAM Path Inquiry CCB (XPT_PATH_INQ).
|
||||
If this is 0, that means that the controller has not reported a maximum I/O
|
||||
size.
|
||||
.El
|
||||
.Sh FILE MARK HANDLING
|
||||
The handling of file marks on write is automatic.
|
||||
If the user has
|
||||
|
112
share/man/man4/vmx.4
Normal file
112
share/man/man4/vmx.4
Normal file
@ -0,0 +1,112 @@
|
||||
.\"
|
||||
.\" Copyright (c) 2006,2013 Reyk Floeter <reyk@openbsd.org>
|
||||
.\"
|
||||
.\" Permission to use, copy, modify, and distribute this software for any
|
||||
.\" purpose with or without fee is hereby granted, provided that the above
|
||||
.\" copyright notice and this permission notice appear in all copies.
|
||||
.\"
|
||||
.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
.\"
|
||||
.\" $OpenBSD: src/share/man/man4/vmx.4,v 1.1 2013/05/31 20:18:44 reyk Exp $
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd August 4, 2013
|
||||
.Dt VMX 4
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm vmx
|
||||
.Nd VMware VMXNET3 Virtual Interface Controller device
|
||||
.Sh SYNOPSIS
|
||||
To compile this driver into the kernel,
|
||||
place the following line in your
|
||||
kernel configuration file:
|
||||
.Bd -ragged -offset indent
|
||||
.Cd "device vmx"
|
||||
.Ed
|
||||
.Pp
|
||||
Alternatively, to load the driver as a
|
||||
module at boot time, place the following line in
|
||||
.Xr loader.conf 5 :
|
||||
.Bd -literal -offset indent
|
||||
if_vmx_load="YES"
|
||||
.Ed
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm
|
||||
driver provides support for the VMXNET3 virtual NIC available in virtual
|
||||
machines by VMware.
|
||||
It appears as a simple Ethernet device but is actually a virtual network
|
||||
interface to the underlying host operating system.
|
||||
.Pp
|
||||
This driver supports the
|
||||
.Ic VMXNET3
|
||||
driver protocol, as an alternative to the emulated
|
||||
.Xr pcn 4 ,
|
||||
.Xr em 4
|
||||
interfaces also available in the VMware environment.
|
||||
The
|
||||
.Nm
|
||||
driver is optimized for the virtual machine, it can provide advanced
|
||||
capabilities depending on the underlying host operating system and
|
||||
the physical network interface controller of the host.
|
||||
The
|
||||
.Nm
|
||||
driver supports features like multiqueue support, IPv6
|
||||
checksum offloading, MSI/MSI-X support and hardware VLAN tagging in
|
||||
VMware's VLAN Guest Tagging (VGT) mode.
|
||||
.Pp
|
||||
The
|
||||
.Nm
|
||||
driver supports VMXNET3 VMware virtual NICs provided by the virtual
|
||||
machine hardware version 7 or newer, as provided by the following
|
||||
products:
|
||||
.Pp
|
||||
.Bl -bullet -compact -offset indent
|
||||
.It
|
||||
VMware ESX/ESXi 4.0 and newer
|
||||
.It
|
||||
VMware Server 2.0 and newer
|
||||
.It
|
||||
VMware Workstation 6.5 and newer
|
||||
.It
|
||||
VMware Fusion 2.0 and newer
|
||||
.El
|
||||
.Pp
|
||||
For more information on configuring this device, see
|
||||
.Xr ifconfig 8 .
|
||||
.Sh EXAMPLES
|
||||
The following entry must be added to the VMware configuration file
|
||||
to provide the
|
||||
.Nm
|
||||
device:
|
||||
.Bd -literal -offset indent
|
||||
ethernet0.virtualDev = "vmxnet3"
|
||||
.Ed
|
||||
.Sh SEE ALSO
|
||||
.Xr altq 4 ,
|
||||
.Xr arp 4 ,
|
||||
.Xr em 4 ,
|
||||
.Xr netintro 4 ,
|
||||
.Xr ng_ether 4 ,
|
||||
.Xr pcn 4 ,
|
||||
.Xr vlan 4 ,
|
||||
.Xr ifconfig 8
|
||||
.Sh AUTHORS
|
||||
.An -nosplit
|
||||
The
|
||||
.Nm
|
||||
driver was ported from
|
||||
.Ox
|
||||
by
|
||||
.An Bryan Venteicher Aq bryanv@freebsd.org .
|
||||
The
|
||||
.Ox
|
||||
driver was written by
|
||||
.An Tsubai Masanari .
|
@ -28,7 +28,7 @@
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd October 22, 2012
|
||||
.Dd August 23, 2013
|
||||
.Dt PFIL 9
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -36,7 +36,6 @@
|
||||
.Nm pfil_head_register ,
|
||||
.Nm pfil_head_unregister ,
|
||||
.Nm pfil_head_get ,
|
||||
.Nm pfil_hook_get ,
|
||||
.Nm pfil_add_hook ,
|
||||
.Nm pfil_remove_hook ,
|
||||
.Nm pfil_run_hooks ,
|
||||
@ -50,20 +49,18 @@
|
||||
.In sys/mbuf.h
|
||||
.In net/if.h
|
||||
.In net/pfil.h
|
||||
.Bd -literal
|
||||
typedef int (*pfil_func_t)(void *arg, struct mbuf **mp, struct ifnet *, int dir, struct inpcb);
|
||||
.Ft int
|
||||
.Fn pfil_head_register "struct pfil_head *head"
|
||||
.Ft int
|
||||
.Fn pfil_head_unregister "struct pfil_head *head"
|
||||
.Ft "struct pfil_head *"
|
||||
.Fn pfil_head_get "int af" "u_long dlt"
|
||||
.Ft "struct packet_filter_hook *"
|
||||
.Fn pfil_hook_get "int dir" "struct pfil_head *head"
|
||||
.Ft void
|
||||
.Fn pfil_add_hook "int (*func)()" "void *arg" "int flags" "struct pfil_head *"
|
||||
.Fn pfil_add_hook "pfil_func_t" "void *arg" "int flags" "struct pfil_head *"
|
||||
.Ft void
|
||||
.Fn pfil_remove_hook "int (*func)()" "void *arg" "int flags" "struct pfil_head *"
|
||||
.Ft int
|
||||
.Fn (*func) "void *arg" "struct mbuf **mp" "struct ifnet *" "int dir" "struct inpcb *"
|
||||
.Fn pfil_remove_hook "pfil_func_t" "void *arg" "int flags" "struct pfil_head *"
|
||||
.Ft int
|
||||
.Fn pfil_run_hooks "struct pfil_head *head" "struct mbuf **mp" "struct ifnet *" "int dir" "struct inpcb *"
|
||||
.Ft void
|
||||
@ -245,11 +242,7 @@ lock export was added in
|
||||
.Fx 10.0 .
|
||||
.Sh BUGS
|
||||
The
|
||||
.Fn pfil_hook_get
|
||||
function
|
||||
is only safe for internal use.
|
||||
.Pp
|
||||
When a
|
||||
.Fn When a
|
||||
.Vt pfil_head
|
||||
is being modified, no traffic is diverted
|
||||
(to avoid deadlock).
|
||||
|
@ -61,7 +61,7 @@ biosacpi_detect(void)
|
||||
return;
|
||||
|
||||
/* export values from the RSDP */
|
||||
sprintf(buf, "%u", VTOP(rsdp));
|
||||
sprintf(buf, "0x%08x", VTOP(rsdp));
|
||||
setenv("hint.acpi.0.rsdp", buf, 1);
|
||||
revision = rsdp->Revision;
|
||||
if (revision == 0)
|
||||
|
@ -1091,7 +1091,8 @@ xpt_getattr(char *buf, size_t len, const char *attr, struct cam_path *path)
|
||||
cdai.buftype = CDAI_TYPE_SERIAL_NUM;
|
||||
else if (!strcmp(attr, "GEOM::physpath"))
|
||||
cdai.buftype = CDAI_TYPE_PHYS_PATH;
|
||||
else if (!strcmp(attr, "GEOM::lunid")) {
|
||||
else if (strcmp(attr, "GEOM::lunid") == 0 ||
|
||||
strcmp(attr, "GEOM::lunname") == 0) {
|
||||
cdai.buftype = CDAI_TYPE_SCSI_DEVID;
|
||||
cdai.bufsiz = CAM_SCSI_DEVID_MAXLEN;
|
||||
} else
|
||||
@ -1108,11 +1109,14 @@ xpt_getattr(char *buf, size_t len, const char *attr, struct cam_path *path)
|
||||
if (cdai.provsiz == 0)
|
||||
goto out;
|
||||
if (cdai.buftype == CDAI_TYPE_SCSI_DEVID) {
|
||||
idd = scsi_get_devid((struct scsi_vpd_device_id *)cdai.buf,
|
||||
cdai.provsiz, scsi_devid_is_lun_naa);
|
||||
if (idd == NULL)
|
||||
if (strcmp(attr, "GEOM::lunid") == 0) {
|
||||
idd = scsi_get_devid((struct scsi_vpd_device_id *)cdai.buf,
|
||||
cdai.provsiz, scsi_devid_is_lun_eui64);
|
||||
cdai.provsiz, scsi_devid_is_lun_naa);
|
||||
if (idd == NULL)
|
||||
idd = scsi_get_devid((struct scsi_vpd_device_id *)cdai.buf,
|
||||
cdai.provsiz, scsi_devid_is_lun_eui64);
|
||||
} else
|
||||
idd = NULL;
|
||||
if (idd == NULL)
|
||||
idd = scsi_get_devid((struct scsi_vpd_device_id *)cdai.buf,
|
||||
cdai.provsiz, scsi_devid_is_lun_t10);
|
||||
|
@ -894,8 +894,13 @@ ctl_isc_event_handler(ctl_ha_channel channel, ctl_ha_event event, int param)
|
||||
struct ctl_lun *lun;
|
||||
struct ctl_page_index *page_index;
|
||||
struct copan_aps_subpage *current_sp;
|
||||
uint32_t targ_lun;
|
||||
|
||||
lun = ctl_softc->ctl_luns[msg_info.hdr.nexus.targ_lun];
|
||||
targ_lun = msg_info.hdr.nexus.targ_lun;
|
||||
if (msg_info.hdr.nexus.lun_map_fn != NULL)
|
||||
targ_lun = msg_info.hdr.nexus.lun_map_fn(msg_info.hdr.nexus.lun_map_arg, targ_lun);
|
||||
|
||||
lun = ctl_softc->ctl_luns[targ_lun];
|
||||
page_index = &lun->mode_pages.index[index_to_aps_page];
|
||||
current_sp = (struct copan_aps_subpage *)
|
||||
(page_index->page_data +
|
||||
@ -1098,7 +1103,8 @@ ctl_init(void)
|
||||
mtx_unlock(&softc->ctl_lock);
|
||||
return (error);
|
||||
}
|
||||
printf("ctl: CAM Target Layer loaded\n");
|
||||
if (bootverbose)
|
||||
printf("ctl: CAM Target Layer loaded\n");
|
||||
|
||||
/*
|
||||
* Initialize the initiator and portname mappings
|
||||
@ -1194,7 +1200,8 @@ ctl_shutdown(void)
|
||||
free(control_softc, M_DEVBUF);
|
||||
control_softc = NULL;
|
||||
|
||||
printf("ctl: CAM Target Layer unloaded\n");
|
||||
if (bootverbose)
|
||||
printf("ctl: CAM Target Layer unloaded\n");
|
||||
}
|
||||
|
||||
static int
|
||||
@ -1678,12 +1685,16 @@ ctl_serialize_other_sc_cmd(struct ctl_scsiio *ctsio, int have_lock)
|
||||
union ctl_ha_msg msg_info;
|
||||
struct ctl_lun *lun;
|
||||
int retval = 0;
|
||||
uint32_t targ_lun;
|
||||
|
||||
ctl_softc = control_softc;
|
||||
if (have_lock == 0)
|
||||
mtx_lock(&ctl_softc->ctl_lock);
|
||||
|
||||
lun = ctl_softc->ctl_luns[ctsio->io_hdr.nexus.targ_lun];
|
||||
targ_lun = ctsio->io_hdr.nexus.targ_lun;
|
||||
if (ctsio->io_hdr.nexus.lun_map_fn != NULL)
|
||||
targ_lun = ctsio->io_hdr.nexus.lun_map_fn(ctsio->io_hdr.nexus.lun_map_arg, targ_lun);
|
||||
lun = ctl_softc->ctl_luns[targ_lun];
|
||||
if (lun==NULL)
|
||||
{
|
||||
/*
|
||||
@ -2980,6 +2991,7 @@ ctl_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag,
|
||||
struct sbuf *sb;
|
||||
struct ctl_lun *lun;
|
||||
struct ctl_lun_list *list;
|
||||
struct ctl_be_lun_option *opt;
|
||||
|
||||
list = (struct ctl_lun_list *)addr;
|
||||
|
||||
@ -3097,17 +3109,16 @@ ctl_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag,
|
||||
if (retval != 0)
|
||||
break;
|
||||
|
||||
if (lun->backend->lun_info == NULL) {
|
||||
retval = sbuf_printf(sb, "</lun>\n");
|
||||
if (lun->backend->lun_info != NULL) {
|
||||
retval = lun->backend->lun_info(lun->be_lun->be_lun, sb);
|
||||
if (retval != 0)
|
||||
break;
|
||||
}
|
||||
STAILQ_FOREACH(opt, &lun->be_lun->options, links) {
|
||||
retval = sbuf_printf(sb, "<%s>%s</%s>", opt->name, opt->value, opt->name);
|
||||
if (retval != 0)
|
||||
break;
|
||||
continue;
|
||||
}
|
||||
|
||||
retval =lun->backend->lun_info(lun->be_lun->be_lun, sb);
|
||||
|
||||
if (retval != 0)
|
||||
break;
|
||||
|
||||
retval = sbuf_printf(sb, "</lun>\n");
|
||||
|
||||
@ -4432,9 +4443,14 @@ ctl_free_lun(struct ctl_lun *lun)
|
||||
*/
|
||||
for (io = (union ctl_io *)STAILQ_FIRST(&softc->rtr_queue); io != NULL;
|
||||
io = next_io) {
|
||||
uint32_t targ_lun;
|
||||
|
||||
next_io = (union ctl_io *)STAILQ_NEXT(&io->io_hdr, links);
|
||||
targ_lun = io->io_hdr.nexus.targ_lun;
|
||||
if (io->io_hdr.nexus.lun_map_fn != NULL)
|
||||
targ_lun = io->io_hdr.nexus.lun_map_fn(io->io_hdr.nexus.lun_map_arg, targ_lun);
|
||||
if ((io->io_hdr.nexus.targ_target.id == lun->target.id)
|
||||
&& (io->io_hdr.nexus.targ_lun == lun->lun))
|
||||
&& (targ_lun == lun->lun))
|
||||
STAILQ_REMOVE(&softc->rtr_queue, &io->io_hdr,
|
||||
ctl_io_hdr, links);
|
||||
}
|
||||
@ -8247,12 +8263,16 @@ ctl_hndl_per_res_out_on_other_sc(union ctl_ha_msg *msg)
|
||||
struct ctl_lun *lun;
|
||||
struct ctl_softc *softc;
|
||||
int i;
|
||||
uint32_t targ_lun;
|
||||
|
||||
softc = control_softc;
|
||||
|
||||
mtx_lock(&softc->ctl_lock);
|
||||
|
||||
lun = softc->ctl_luns[msg->hdr.nexus.targ_lun];
|
||||
targ_lun = msg->hdr.nexus.targ_lun;
|
||||
if (msg->hdr.nexus.lun_map_fn != NULL)
|
||||
targ_lun = msg->hdr.nexus.lun_map_fn(msg->hdr.nexus.lun_map_arg, targ_lun);
|
||||
lun = softc->ctl_luns[targ_lun];
|
||||
switch(msg->pr.pr_info.action) {
|
||||
case CTL_PR_REG_KEY:
|
||||
if (!lun->per_res[msg->pr.pr_info.residx].registered) {
|
||||
@ -8601,7 +8621,7 @@ ctl_report_luns(struct ctl_scsiio *ctsio)
|
||||
int num_luns, retval;
|
||||
uint32_t alloc_len, lun_datalen;
|
||||
int num_filled, well_known;
|
||||
uint32_t initidx;
|
||||
uint32_t initidx, targ_lun_id, lun_id;
|
||||
|
||||
retval = CTL_RETVAL_COMPLETE;
|
||||
well_known = 0;
|
||||
@ -8662,63 +8682,47 @@ ctl_report_luns(struct ctl_scsiio *ctsio)
|
||||
lun_data = (struct scsi_report_luns_data *)ctsio->kern_data_ptr;
|
||||
ctsio->kern_sg_entries = 0;
|
||||
|
||||
if (lun_datalen < alloc_len) {
|
||||
ctsio->residual = alloc_len - lun_datalen;
|
||||
ctsio->kern_data_len = lun_datalen;
|
||||
ctsio->kern_total_len = lun_datalen;
|
||||
} else {
|
||||
ctsio->residual = 0;
|
||||
ctsio->kern_data_len = alloc_len;
|
||||
ctsio->kern_total_len = alloc_len;
|
||||
}
|
||||
ctsio->kern_data_resid = 0;
|
||||
ctsio->kern_rel_offset = 0;
|
||||
ctsio->kern_sg_entries = 0;
|
||||
|
||||
initidx = ctl_get_initindex(&ctsio->io_hdr.nexus);
|
||||
|
||||
/*
|
||||
* We set this to the actual data length, regardless of how much
|
||||
* space we actually have to return results. If the user looks at
|
||||
* this value, he'll know whether or not he allocated enough space
|
||||
* and reissue the command if necessary. We don't support well
|
||||
* known logical units, so if the user asks for that, return none.
|
||||
*/
|
||||
scsi_ulto4b(lun_datalen - 8, lun_data->length);
|
||||
|
||||
mtx_lock(&control_softc->ctl_lock);
|
||||
for (num_filled = 0, lun = STAILQ_FIRST(&control_softc->lun_list);
|
||||
(lun != NULL) && (num_filled < num_luns);
|
||||
lun = STAILQ_NEXT(lun, links)) {
|
||||
for (targ_lun_id = 0, num_filled = 0; targ_lun_id < CTL_MAX_LUNS && num_filled < num_luns; targ_lun_id++) {
|
||||
lun_id = targ_lun_id;
|
||||
if (ctsio->io_hdr.nexus.lun_map_fn != NULL)
|
||||
lun_id = ctsio->io_hdr.nexus.lun_map_fn(ctsio->io_hdr.nexus.lun_map_arg, lun_id);
|
||||
if (lun_id >= CTL_MAX_LUNS)
|
||||
continue;
|
||||
lun = control_softc->ctl_luns[lun_id];
|
||||
if (lun == NULL)
|
||||
continue;
|
||||
|
||||
if (lun->lun <= 0xff) {
|
||||
if (targ_lun_id <= 0xff) {
|
||||
/*
|
||||
* Peripheral addressing method, bus number 0.
|
||||
*/
|
||||
lun_data->luns[num_filled].lundata[0] =
|
||||
RPL_LUNDATA_ATYP_PERIPH;
|
||||
lun_data->luns[num_filled].lundata[1] = lun->lun;
|
||||
lun_data->luns[num_filled].lundata[1] = targ_lun_id;
|
||||
num_filled++;
|
||||
} else if (lun->lun <= 0x3fff) {
|
||||
} else if (targ_lun_id <= 0x3fff) {
|
||||
/*
|
||||
* Flat addressing method.
|
||||
*/
|
||||
lun_data->luns[num_filled].lundata[0] =
|
||||
RPL_LUNDATA_ATYP_FLAT |
|
||||
(lun->lun & RPL_LUNDATA_FLAT_LUN_MASK);
|
||||
(targ_lun_id & RPL_LUNDATA_FLAT_LUN_MASK);
|
||||
#ifdef OLDCTLHEADERS
|
||||
(SRLD_ADDR_FLAT << SRLD_ADDR_SHIFT) |
|
||||
(lun->lun & SRLD_BUS_LUN_MASK);
|
||||
(targ_lun_id & SRLD_BUS_LUN_MASK);
|
||||
#endif
|
||||
lun_data->luns[num_filled].lundata[1] =
|
||||
#ifdef OLDCTLHEADERS
|
||||
lun->lun >> SRLD_BUS_LUN_BITS;
|
||||
targ_lun_id >> SRLD_BUS_LUN_BITS;
|
||||
#endif
|
||||
lun->lun >> RPL_LUNDATA_FLAT_LUN_BITS;
|
||||
targ_lun_id >> RPL_LUNDATA_FLAT_LUN_BITS;
|
||||
num_filled++;
|
||||
} else {
|
||||
printf("ctl_report_luns: bogus LUN number %jd, "
|
||||
"skipping\n", (intmax_t)lun->lun);
|
||||
"skipping\n", (intmax_t)targ_lun_id);
|
||||
}
|
||||
/*
|
||||
* According to SPC-3, rev 14 section 6.21:
|
||||
@ -8742,6 +8746,35 @@ ctl_report_luns(struct ctl_scsiio *ctsio)
|
||||
}
|
||||
mtx_unlock(&control_softc->ctl_lock);
|
||||
|
||||
/*
|
||||
* It's quite possible that we've returned fewer LUNs than we allocated
|
||||
* space for. Trim it.
|
||||
*/
|
||||
lun_datalen = sizeof(*lun_data) +
|
||||
(num_filled * sizeof(struct scsi_report_luns_lundata));
|
||||
|
||||
if (lun_datalen < alloc_len) {
|
||||
ctsio->residual = alloc_len - lun_datalen;
|
||||
ctsio->kern_data_len = lun_datalen;
|
||||
ctsio->kern_total_len = lun_datalen;
|
||||
} else {
|
||||
ctsio->residual = 0;
|
||||
ctsio->kern_data_len = alloc_len;
|
||||
ctsio->kern_total_len = alloc_len;
|
||||
}
|
||||
ctsio->kern_data_resid = 0;
|
||||
ctsio->kern_rel_offset = 0;
|
||||
ctsio->kern_sg_entries = 0;
|
||||
|
||||
/*
|
||||
* We set this to the actual data length, regardless of how much
|
||||
* space we actually have to return results. If the user looks at
|
||||
* this value, he'll know whether or not he allocated enough space
|
||||
* and reissue the command if necessary. We don't support well
|
||||
* known logical units, so if the user asks for that, return none.
|
||||
*/
|
||||
scsi_ulto4b(lun_datalen - 8, lun_data->length);
|
||||
|
||||
/*
|
||||
* We can only return SCSI_STATUS_CHECK_COND when we can't satisfy
|
||||
* this request.
|
||||
@ -9077,6 +9110,14 @@ ctl_inquiry_evpd_devid(struct ctl_scsiio *ctsio, int alloc_len)
|
||||
int devid_len;
|
||||
|
||||
ctl_softc = control_softc;
|
||||
|
||||
mtx_lock(&ctl_softc->ctl_lock);
|
||||
fe = ctl_softc->ctl_ports[ctl_port_idx(ctsio->io_hdr.nexus.targ_port)];
|
||||
mtx_unlock(&ctl_softc->ctl_lock);
|
||||
|
||||
if (fe->devid != NULL)
|
||||
return ((fe->devid)(ctsio, alloc_len));
|
||||
|
||||
lun = (struct ctl_lun *)ctsio->io_hdr.ctl_private[CTL_PRIV_LUN].ptr;
|
||||
|
||||
devid_len = sizeof(struct scsi_vpd_device_id) +
|
||||
@ -9130,8 +9171,6 @@ ctl_inquiry_evpd_devid(struct ctl_scsiio *ctsio, int alloc_len)
|
||||
|
||||
mtx_lock(&ctl_softc->ctl_lock);
|
||||
|
||||
fe = ctl_softc->ctl_ports[ctl_port_idx(ctsio->io_hdr.nexus.targ_port)];
|
||||
|
||||
/*
|
||||
* For Fibre channel,
|
||||
*/
|
||||
@ -10350,7 +10389,7 @@ ctl_scsiio_precheck(struct ctl_softc *ctl_softc, struct ctl_scsiio *ctsio)
|
||||
struct ctl_lun *lun;
|
||||
struct ctl_cmd_entry *entry;
|
||||
uint8_t opcode;
|
||||
uint32_t initidx;
|
||||
uint32_t initidx, targ_lun;
|
||||
int retval;
|
||||
|
||||
retval = 0;
|
||||
@ -10361,9 +10400,12 @@ ctl_scsiio_precheck(struct ctl_softc *ctl_softc, struct ctl_scsiio *ctsio)
|
||||
|
||||
mtx_lock(&ctl_softc->ctl_lock);
|
||||
|
||||
if ((ctsio->io_hdr.nexus.targ_lun < CTL_MAX_LUNS)
|
||||
&& (ctl_softc->ctl_luns[ctsio->io_hdr.nexus.targ_lun] != NULL)) {
|
||||
lun = ctl_softc->ctl_luns[ctsio->io_hdr.nexus.targ_lun];
|
||||
targ_lun = ctsio->io_hdr.nexus.targ_lun;
|
||||
if (ctsio->io_hdr.nexus.lun_map_fn != NULL)
|
||||
targ_lun = ctsio->io_hdr.nexus.lun_map_fn(ctsio->io_hdr.nexus.lun_map_arg, targ_lun);
|
||||
if ((targ_lun < CTL_MAX_LUNS)
|
||||
&& (ctl_softc->ctl_luns[targ_lun] != NULL)) {
|
||||
lun = ctl_softc->ctl_luns[targ_lun];
|
||||
/*
|
||||
* If the LUN is invalid, pretend that it doesn't exist.
|
||||
* It will go away as soon as all pending I/O has been
|
||||
@ -10403,6 +10445,7 @@ ctl_scsiio_precheck(struct ctl_softc *ctl_softc, struct ctl_scsiio *ctsio)
|
||||
ctl_set_unsupported_lun(ctsio);
|
||||
mtx_unlock(&ctl_softc->ctl_lock);
|
||||
ctl_done((union ctl_io *)ctsio);
|
||||
CTL_DEBUG_PRINT(("ctl_scsiio_precheck: bailing out due to invalid LUN\n"));
|
||||
goto bailout;
|
||||
} else {
|
||||
/*
|
||||
@ -10769,6 +10812,7 @@ ctl_abort_task(union ctl_io *io)
|
||||
char printbuf[128];
|
||||
#endif
|
||||
int found;
|
||||
uint32_t targ_lun;
|
||||
|
||||
ctl_softc = control_softc;
|
||||
found = 0;
|
||||
@ -10776,9 +10820,12 @@ ctl_abort_task(union ctl_io *io)
|
||||
/*
|
||||
* Look up the LUN.
|
||||
*/
|
||||
if ((io->io_hdr.nexus.targ_lun < CTL_MAX_LUNS)
|
||||
&& (ctl_softc->ctl_luns[io->io_hdr.nexus.targ_lun] != NULL))
|
||||
lun = ctl_softc->ctl_luns[io->io_hdr.nexus.targ_lun];
|
||||
targ_lun = io->io_hdr.nexus.targ_lun;
|
||||
if (io->io_hdr.nexus.lun_map_fn != NULL)
|
||||
targ_lun = io->io_hdr.nexus.lun_map_fn(io->io_hdr.nexus.lun_map_arg, targ_lun);
|
||||
if ((targ_lun < CTL_MAX_LUNS)
|
||||
&& (ctl_softc->ctl_luns[targ_lun] != NULL))
|
||||
lun = ctl_softc->ctl_luns[targ_lun];
|
||||
else
|
||||
goto bailout;
|
||||
|
||||
@ -10968,6 +11015,8 @@ ctl_run_task_queue(struct ctl_softc *ctl_softc)
|
||||
int retval;
|
||||
|
||||
targ_lun = io->io_hdr.nexus.targ_lun;
|
||||
if (io->io_hdr.nexus.lun_map_fn != NULL)
|
||||
targ_lun = io->io_hdr.nexus.lun_map_fn(io->io_hdr.nexus.lun_map_arg, targ_lun);
|
||||
|
||||
if ((targ_lun < CTL_MAX_LUNS)
|
||||
&& (ctl_softc->ctl_luns[targ_lun] != NULL))
|
||||
@ -11042,7 +11091,7 @@ ctl_run_task_queue(struct ctl_softc *ctl_softc)
|
||||
(uintmax_t)io->io_hdr.nexus.initid.id,
|
||||
io->io_hdr.nexus.targ_port,
|
||||
(uintmax_t)io->io_hdr.nexus.targ_target.id,
|
||||
io->io_hdr.nexus.targ_lun,
|
||||
io->io_hdr.nexus.targ_lun /* XXX */,
|
||||
(io->io_hdr.io_type == CTL_IO_TASK) ?
|
||||
io->taskio.tag_num : io->scsiio.tag_num);
|
||||
STAILQ_REMOVE(&ctl_softc->task_queue, &io->io_hdr,
|
||||
@ -11066,10 +11115,14 @@ ctl_handle_isc(union ctl_io *io)
|
||||
int free_io;
|
||||
struct ctl_lun *lun;
|
||||
struct ctl_softc *ctl_softc;
|
||||
uint32_t targ_lun;
|
||||
|
||||
ctl_softc = control_softc;
|
||||
|
||||
lun = ctl_softc->ctl_luns[io->io_hdr.nexus.targ_lun];
|
||||
targ_lun = io->io_hdr.nexus.targ_lun;
|
||||
if (io->io_hdr.nexus.lun_map_fn != NULL)
|
||||
targ_lun = io->io_hdr.nexus.lun_map_fn(io->io_hdr.nexus.lun_map_arg, targ_lun);
|
||||
lun = ctl_softc->ctl_luns[targ_lun];
|
||||
|
||||
switch (io->io_hdr.msg_type) {
|
||||
case CTL_MSG_SERIALIZE:
|
||||
@ -12625,7 +12678,7 @@ ctl_queue_sense(union ctl_io *io)
|
||||
{
|
||||
struct ctl_lun *lun;
|
||||
struct ctl_softc *ctl_softc;
|
||||
uint32_t initidx;
|
||||
uint32_t initidx, targ_lun;
|
||||
|
||||
ctl_softc = control_softc;
|
||||
|
||||
@ -12644,9 +12697,12 @@ ctl_queue_sense(union ctl_io *io)
|
||||
* If we don't have a LUN for this, just toss the sense
|
||||
* information.
|
||||
*/
|
||||
if ((io->io_hdr.nexus.targ_lun < CTL_MAX_LUNS)
|
||||
&& (ctl_softc->ctl_luns[io->io_hdr.nexus.targ_lun] != NULL))
|
||||
lun = ctl_softc->ctl_luns[io->io_hdr.nexus.targ_lun];
|
||||
targ_lun = io->io_hdr.nexus.targ_lun;
|
||||
if (io->io_hdr.nexus.lun_map_fn != NULL)
|
||||
targ_lun = io->io_hdr.nexus.lun_map_fn(io->io_hdr.nexus.lun_map_arg, targ_lun);
|
||||
if ((targ_lun < CTL_MAX_LUNS)
|
||||
&& (ctl_softc->ctl_luns[targ_lun] != NULL))
|
||||
lun = ctl_softc->ctl_luns[targ_lun];
|
||||
else
|
||||
goto bailout;
|
||||
|
||||
@ -13047,6 +13103,8 @@ ctl_isc_start(struct ctl_ha_component *c, ctl_ha_state state)
|
||||
{
|
||||
ctl_ha_comp_status ret = CTL_HA_COMP_STATUS_OK;
|
||||
|
||||
printf("%s: go\n", __func__);
|
||||
|
||||
// UNKNOWN->HA or UNKNOWN->SINGLE (bootstrap)
|
||||
if (c->state == CTL_HA_STATE_UNKNOWN ) {
|
||||
ctl_is_single = 0;
|
||||
|
@ -52,6 +52,7 @@ typedef enum {
|
||||
CTL_PORT_SCSI = 0x02,
|
||||
CTL_PORT_IOCTL = 0x04,
|
||||
CTL_PORT_INTERNAL = 0x08,
|
||||
CTL_PORT_ISCSI = 0x10,
|
||||
CTL_PORT_ALL = 0xff,
|
||||
CTL_PORT_ISC = 0x100 // FC port for inter-shelf communication
|
||||
} ctl_port_type;
|
||||
|
@ -173,6 +173,12 @@ typedef void (*be_lun_config_t)(void *be_lun,
|
||||
* The links field is for CTL internal use only, and should not be used by
|
||||
* the backend.
|
||||
*/
|
||||
struct ctl_be_lun_option {
|
||||
STAILQ_ENTRY(ctl_be_lun_option) links;
|
||||
char *name;
|
||||
char *value;
|
||||
};
|
||||
|
||||
struct ctl_be_lun {
|
||||
uint8_t lun_type; /* passed to CTL */
|
||||
ctl_backend_lun_flags flags; /* passed to CTL */
|
||||
@ -187,6 +193,7 @@ struct ctl_be_lun {
|
||||
be_lun_config_t lun_config_status; /* passed to CTL */
|
||||
struct ctl_backend_driver *be; /* passed to CTL */
|
||||
void *ctl_lun; /* used by CTL */
|
||||
STAILQ_HEAD(, ctl_be_lun_option) options; /* passed to CTL */
|
||||
STAILQ_ENTRY(ctl_be_lun) links; /* used by CTL */
|
||||
};
|
||||
|
||||
|
@ -1639,6 +1639,7 @@ ctl_be_block_create(struct ctl_be_block_softc *softc, struct ctl_lun_req *req)
|
||||
STAILQ_INIT(&be_lun->input_queue);
|
||||
STAILQ_INIT(&be_lun->config_write_queue);
|
||||
STAILQ_INIT(&be_lun->datamove_queue);
|
||||
STAILQ_INIT(&be_lun->ctl_be_lun.options);
|
||||
sprintf(be_lun->lunname, "cblk%d", softc->num_luns);
|
||||
mtx_init(&be_lun->lock, be_lun->lunname, NULL, MTX_DEF);
|
||||
|
||||
@ -1740,6 +1741,16 @@ ctl_be_block_create(struct ctl_be_block_softc *softc, struct ctl_lun_req *req)
|
||||
}
|
||||
|
||||
num_threads = tmp_num_threads;
|
||||
} else if (strcmp(req->kern_be_args[i].kname, "file") != 0 &&
|
||||
strcmp(req->kern_be_args[i].kname, "dev") != 0) {
|
||||
struct ctl_be_lun_option *opt;
|
||||
|
||||
opt = malloc(sizeof(*opt), M_CTLBLK, M_WAITOK);
|
||||
opt->name = malloc(strlen(req->kern_be_args[i].kname) + 1, M_CTLBLK, M_WAITOK);
|
||||
strcpy(opt->name, req->kern_be_args[i].kname);
|
||||
opt->value = malloc(strlen(req->kern_be_args[i].kvalue) + 1, M_CTLBLK, M_WAITOK);
|
||||
strcpy(opt->value, req->kern_be_args[i].kvalue);
|
||||
STAILQ_INSERT_TAIL(&be_lun->ctl_be_lun.options, opt, links);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -491,7 +491,7 @@ ctl_backend_ramdisk_create(struct ctl_be_ramdisk_softc *softc,
|
||||
struct ctl_lun_create_params *params;
|
||||
uint32_t blocksize;
|
||||
char tmpstr[32];
|
||||
int retval;
|
||||
int i, retval;
|
||||
|
||||
retval = 0;
|
||||
params = &req->reqdata.create;
|
||||
@ -509,6 +509,7 @@ ctl_backend_ramdisk_create(struct ctl_be_ramdisk_softc *softc,
|
||||
sizeof(*be_lun));
|
||||
goto bailout_error;
|
||||
}
|
||||
STAILQ_INIT(&be_lun->ctl_be_lun.options);
|
||||
|
||||
if (params->flags & CTL_LUN_FLAG_DEV_TYPE)
|
||||
be_lun->ctl_be_lun.lun_type = params->device_type;
|
||||
@ -545,6 +546,17 @@ ctl_backend_ramdisk_create(struct ctl_be_ramdisk_softc *softc,
|
||||
|
||||
be_lun->softc = softc;
|
||||
|
||||
for (i = 0; i < req->num_be_args; i++) {
|
||||
struct ctl_be_lun_option *opt;
|
||||
|
||||
opt = malloc(sizeof(*opt), M_RAMDISK, M_WAITOK);
|
||||
opt->name = malloc(strlen(req->kern_be_args[i].kname) + 1, M_RAMDISK, M_WAITOK);
|
||||
strcpy(opt->name, req->kern_be_args[i].kname);
|
||||
opt->value = malloc(strlen(req->kern_be_args[i].kvalue) + 1, M_RAMDISK, M_WAITOK);
|
||||
strcpy(opt->value, req->kern_be_args[i].kvalue);
|
||||
STAILQ_INSERT_TAIL(&be_lun->ctl_be_lun.options, opt, links);
|
||||
}
|
||||
|
||||
be_lun->flags = CTL_BE_RAMDISK_LUN_UNCONFIGURED;
|
||||
be_lun->ctl_be_lun.flags = CTL_LUN_FLAG_PRIMARY;
|
||||
be_lun->ctl_be_lun.be_lun = be_lun;
|
||||
|
@ -49,6 +49,9 @@ typedef enum {
|
||||
typedef void (*port_func_t)(void *onoff_arg);
|
||||
typedef int (*targ_func_t)(void *arg, struct ctl_id targ_id);
|
||||
typedef int (*lun_func_t)(void *arg, struct ctl_id targ_id, int lun_id);
|
||||
typedef int (*fe_ioctl_t)(struct cdev *dev, u_long cmd, caddr_t addr, int flag,
|
||||
struct thread *td);
|
||||
typedef int (*fe_devid_t)(struct ctl_scsiio *ctsio, int alloc_len);
|
||||
|
||||
/*
|
||||
* The ctl_frontend structure is the registration mechanism between a FETD
|
||||
@ -213,6 +216,8 @@ struct ctl_frontend {
|
||||
targ_func_t targ_disable; /* passed to CTL */
|
||||
lun_func_t lun_enable; /* passed to CTL */
|
||||
lun_func_t lun_disable; /* passed to CTL */
|
||||
fe_ioctl_t ioctl; /* passed to CTL */
|
||||
fe_devid_t devid; /* passed to CTL */
|
||||
void *targ_lun_arg; /* passed to CTL */
|
||||
void (*fe_datamove)(union ctl_io *io); /* passed to CTL */
|
||||
void (*fe_done)(union ctl_io *io); /* passed to CTL */
|
||||
|
@ -204,6 +204,8 @@ struct ctl_nexus {
|
||||
uint32_t targ_port; /* Target port, filled in by PORT */
|
||||
struct ctl_id targ_target; /* Destination target */
|
||||
uint32_t targ_lun; /* Destination lun */
|
||||
uint32_t (*lun_map_fn)(void *arg, uint32_t lun);
|
||||
void *lun_map_arg;
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
|
@ -43,6 +43,8 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/mtio.h>
|
||||
#ifdef _KERNEL
|
||||
#include <sys/conf.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/taskqueue.h>
|
||||
#endif
|
||||
#include <sys/fcntl.h>
|
||||
#include <sys/devicestat.h>
|
||||
@ -223,6 +225,8 @@ struct sa_softc {
|
||||
u_int32_t max_blk;
|
||||
u_int32_t min_blk;
|
||||
u_int32_t maxio;
|
||||
u_int32_t cpi_maxio;
|
||||
int allow_io_split;
|
||||
u_int32_t comp_algorithm;
|
||||
u_int32_t saved_comp_algorithm;
|
||||
u_int32_t media_blksize;
|
||||
@ -268,6 +272,10 @@ struct sa_softc {
|
||||
open_rdonly : 1, /* open read-only */
|
||||
open_pending_mount : 1, /* open pending mount */
|
||||
ctrl_mode : 1; /* control device open */
|
||||
|
||||
struct task sysctl_task;
|
||||
struct sysctl_ctx_list sysctl_ctx;
|
||||
struct sysctl_oid *sysctl_tree;
|
||||
};
|
||||
|
||||
struct sa_quirk_entry {
|
||||
@ -426,6 +434,22 @@ static int sardpos(struct cam_periph *periph, int, u_int32_t *);
|
||||
static int sasetpos(struct cam_periph *periph, int, u_int32_t *);
|
||||
|
||||
|
||||
#ifndef SA_DEFAULT_IO_SPLIT
|
||||
#define SA_DEFAULT_IO_SPLIT 0
|
||||
#endif
|
||||
|
||||
static int sa_allow_io_split = SA_DEFAULT_IO_SPLIT;
|
||||
|
||||
/*
|
||||
* Tunable to allow the user to set a global allow_io_split value. Note
|
||||
* that this WILL GO AWAY in FreeBSD 11.0. Silently splitting the I/O up
|
||||
* is bad behavior, because it hides the true tape block size from the
|
||||
* application.
|
||||
*/
|
||||
TUNABLE_INT("kern.cam.sa.allow_io_split", &sa_allow_io_split);
|
||||
static SYSCTL_NODE(_kern_cam, OID_AUTO, sa, CTLFLAG_RD, 0,
|
||||
"CAM Sequential Access Tape Driver");
|
||||
|
||||
static struct periph_driver sadriver =
|
||||
{
|
||||
sainit, "sa",
|
||||
@ -1448,6 +1472,49 @@ saasync(void *callback_arg, u_int32_t code,
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
sasysctlinit(void *context, int pending)
|
||||
{
|
||||
struct cam_periph *periph;
|
||||
struct sa_softc *softc;
|
||||
char tmpstr[80], tmpstr2[80];
|
||||
|
||||
periph = (struct cam_periph *)context;
|
||||
/*
|
||||
* If the periph is invalid, no need to setup the sysctls.
|
||||
*/
|
||||
if (periph->flags & CAM_PERIPH_INVALID)
|
||||
goto bailout;
|
||||
|
||||
softc = (struct sa_softc *)periph->softc;
|
||||
|
||||
snprintf(tmpstr, sizeof(tmpstr), "CAM SA unit %d", periph->unit_number);
|
||||
snprintf(tmpstr2, sizeof(tmpstr2), "%u", periph->unit_number);
|
||||
|
||||
sysctl_ctx_init(&softc->sysctl_ctx);
|
||||
softc->sysctl_tree = SYSCTL_ADD_NODE(&softc->sysctl_ctx,
|
||||
SYSCTL_STATIC_CHILDREN(_kern_cam_sa), OID_AUTO, tmpstr2,
|
||||
CTLFLAG_RD, 0, tmpstr);
|
||||
if (softc->sysctl_tree == NULL)
|
||||
goto bailout;
|
||||
|
||||
SYSCTL_ADD_INT(&softc->sysctl_ctx, SYSCTL_CHILDREN(softc->sysctl_tree),
|
||||
OID_AUTO, "allow_io_split", CTLTYPE_INT | CTLFLAG_RDTUN,
|
||||
&softc->allow_io_split, 0, "Allow Splitting I/O");
|
||||
SYSCTL_ADD_INT(&softc->sysctl_ctx, SYSCTL_CHILDREN(softc->sysctl_tree),
|
||||
OID_AUTO, "maxio", CTLTYPE_INT | CTLFLAG_RD,
|
||||
&softc->maxio, 0, "Maximum I/O size");
|
||||
SYSCTL_ADD_INT(&softc->sysctl_ctx, SYSCTL_CHILDREN(softc->sysctl_tree),
|
||||
OID_AUTO, "cpi_maxio", CTLTYPE_INT | CTLFLAG_RD,
|
||||
&softc->cpi_maxio, 0, "Maximum Controller I/O size");
|
||||
|
||||
bailout:
|
||||
/*
|
||||
* Release the reference that was held when this task was enqueued.
|
||||
*/
|
||||
cam_periph_release(periph);
|
||||
}
|
||||
|
||||
static cam_status
|
||||
saregister(struct cam_periph *periph, void *arg)
|
||||
{
|
||||
@ -1455,6 +1522,7 @@ saregister(struct cam_periph *periph, void *arg)
|
||||
struct ccb_getdev *cgd;
|
||||
struct ccb_pathinq cpi;
|
||||
caddr_t match;
|
||||
char tmpstr[80];
|
||||
int i;
|
||||
|
||||
cgd = (struct ccb_getdev *)arg;
|
||||
@ -1509,21 +1577,55 @@ saregister(struct cam_periph *periph, void *arg)
|
||||
XPORT_DEVSTAT_TYPE(cpi.transport), DEVSTAT_PRIORITY_TAPE);
|
||||
|
||||
/*
|
||||
* If maxio isn't set, we fall back to DFLTPHYS. If it is set, we
|
||||
* take it whether or not it's larger than MAXPHYS. physio will
|
||||
* break it down into pieces small enough to fit in a buffer.
|
||||
* Load the default value that is either compiled in, or loaded
|
||||
* in the global kern.cam.sa.allow_io_split tunable.
|
||||
*/
|
||||
softc->allow_io_split = sa_allow_io_split;
|
||||
|
||||
/*
|
||||
* Load a per-instance tunable, if it exists. NOTE that this
|
||||
* tunable WILL GO AWAY in FreeBSD 11.0.
|
||||
*/
|
||||
snprintf(tmpstr, sizeof(tmpstr), "kern.cam.sa.%u.allow_io_split",
|
||||
periph->unit_number);
|
||||
TUNABLE_INT_FETCH(tmpstr, &softc->allow_io_split);
|
||||
|
||||
/*
|
||||
* If maxio isn't set, we fall back to DFLTPHYS. Otherwise we take
|
||||
* the smaller of cpi.maxio or MAXPHYS.
|
||||
*/
|
||||
if (cpi.maxio == 0)
|
||||
softc->maxio = DFLTPHYS;
|
||||
else if (cpi.maxio > MAXPHYS)
|
||||
softc->maxio = MAXPHYS;
|
||||
else
|
||||
softc->maxio = cpi.maxio;
|
||||
|
||||
/*
|
||||
* Record the controller's maximum I/O size so we can report it to
|
||||
* the user later.
|
||||
*/
|
||||
softc->cpi_maxio = cpi.maxio;
|
||||
|
||||
/*
|
||||
* By default we tell physio that we do not want our I/O split.
|
||||
* The user needs to have a 1:1 mapping between the size of his
|
||||
* write to a tape character device and the size of the write
|
||||
* that actually goes down to the drive.
|
||||
*/
|
||||
if (softc->allow_io_split == 0)
|
||||
softc->si_flags = SI_NOSPLIT;
|
||||
else
|
||||
softc->si_flags = 0;
|
||||
|
||||
TASK_INIT(&softc->sysctl_task, 0, sasysctlinit, periph);
|
||||
|
||||
/*
|
||||
* If the SIM supports unmapped I/O, let physio know that we can
|
||||
* handle unmapped buffers.
|
||||
*/
|
||||
if (cpi.hba_misc & PIM_UNMAPPED)
|
||||
softc->si_flags = SI_UNMAPPED;
|
||||
softc->si_flags |= SI_UNMAPPED;
|
||||
|
||||
softc->devs.ctl_dev = make_dev(&sa_cdevsw, SAMINOR(SA_CTLDEV,
|
||||
0, SA_ATYPE_R), UID_ROOT, GID_OPERATOR,
|
||||
@ -1585,6 +1687,13 @@ saregister(struct cam_periph *periph, void *arg)
|
||||
}
|
||||
cam_periph_lock(periph);
|
||||
|
||||
/*
|
||||
* Bump the peripheral refcount for the sysctl thread, in case we
|
||||
* get invalidated before the thread has a chance to run.
|
||||
*/
|
||||
cam_periph_acquire(periph);
|
||||
taskqueue_enqueue(taskqueue_thread, &softc->sysctl_task);
|
||||
|
||||
/*
|
||||
* Add an async callback so that we get
|
||||
* notified if this device goes away.
|
||||
|
@ -40,6 +40,12 @@
|
||||
#include <sys/sa.h>
|
||||
#include <sys/sa_impl.h>
|
||||
|
||||
/*
|
||||
* Number of times that zfs_free_range() took the slow path while doing
|
||||
* a zfs receive. A nonzero value indicates a potential performance problem.
|
||||
*/
|
||||
uint64_t zfs_free_range_recv_miss;
|
||||
|
||||
static void dbuf_destroy(dmu_buf_impl_t *db);
|
||||
static boolean_t dbuf_undirty(dmu_buf_impl_t *db, dmu_tx_t *tx);
|
||||
static void dbuf_write(dbuf_dirty_record_t *dr, arc_buf_t *data, dmu_tx_t *tx);
|
||||
@ -819,20 +825,22 @@ dbuf_free_range(dnode_t *dn, uint64_t start, uint64_t end, dmu_tx_t *tx)
|
||||
}
|
||||
dprintf_dnode(dn, "start=%llu end=%llu\n", start, end);
|
||||
|
||||
if (dmu_objset_is_receiving(dn->dn_objset)) {
|
||||
/*
|
||||
* When processing a free record from a zfs receive,
|
||||
* there should have been no previous modifications to the
|
||||
* data in this range. Therefore there should be no dbufs
|
||||
* in the range. Searching dn_dbufs for these non-existent
|
||||
* dbufs can be very expensive, so simply ignore this.
|
||||
*/
|
||||
VERIFY3P(dbuf_find(dn, 0, start), ==, NULL);
|
||||
VERIFY3P(dbuf_find(dn, 0, end), ==, NULL);
|
||||
mutex_enter(&dn->dn_dbufs_mtx);
|
||||
if (start >= dn->dn_unlisted_l0_blkid * dn->dn_datablksz) {
|
||||
/* There can't be any dbufs in this range; no need to search. */
|
||||
mutex_exit(&dn->dn_dbufs_mtx);
|
||||
return;
|
||||
} else if (dmu_objset_is_receiving(dn->dn_objset)) {
|
||||
/*
|
||||
* If we are receiving, we expect there to be no dbufs in
|
||||
* the range to be freed, because receive modifies each
|
||||
* block at most once, and in offset order. If this is
|
||||
* not the case, it can lead to performance problems,
|
||||
* so note that we unexpectedly took the slow path.
|
||||
*/
|
||||
atomic_inc_64(&zfs_free_range_recv_miss);
|
||||
}
|
||||
|
||||
mutex_enter(&dn->dn_dbufs_mtx);
|
||||
for (db = list_head(&dn->dn_dbufs); db; db = db_next) {
|
||||
db_next = list_next(&dn->dn_dbufs, db);
|
||||
ASSERT(db->db_blkid != DMU_BONUS_BLKID);
|
||||
@ -1720,6 +1728,9 @@ dbuf_create(dnode_t *dn, uint8_t level, uint64_t blkid,
|
||||
return (odb);
|
||||
}
|
||||
list_insert_head(&dn->dn_dbufs, db);
|
||||
if (db->db_level == 0 && db->db_blkid >=
|
||||
dn->dn_unlisted_l0_blkid)
|
||||
dn->dn_unlisted_l0_blkid = db->db_blkid + 1;
|
||||
db->db_state = DB_UNCACHED;
|
||||
mutex_exit(&dn->dn_dbufs_mtx);
|
||||
arc_space_consume(sizeof (dmu_buf_impl_t), ARC_SPACE_OTHER);
|
||||
|
@ -575,98 +575,93 @@ dmu_prefetch(objset_t *os, uint64_t object, uint64_t offset, uint64_t len)
|
||||
* the end so that the file gets shorter over time (if we crashes in the
|
||||
* middle, this will leave us in a better state). We find allocated file
|
||||
* data by simply searching the allocated level 1 indirects.
|
||||
*
|
||||
* On input, *start should be the first offset that does not need to be
|
||||
* freed (e.g. "offset + length"). On return, *start will be the first
|
||||
* offset that should be freed.
|
||||
*/
|
||||
static int
|
||||
get_next_chunk(dnode_t *dn, uint64_t *start, uint64_t limit)
|
||||
get_next_chunk(dnode_t *dn, uint64_t *start, uint64_t minimum)
|
||||
{
|
||||
uint64_t len = *start - limit;
|
||||
uint64_t blkcnt = 0;
|
||||
uint64_t maxblks = DMU_MAX_ACCESS / (1ULL << (dn->dn_indblkshift + 1));
|
||||
uint64_t maxblks = DMU_MAX_ACCESS >> (dn->dn_indblkshift + 1);
|
||||
/* bytes of data covered by a level-1 indirect block */
|
||||
uint64_t iblkrange =
|
||||
dn->dn_datablksz * EPB(dn->dn_indblkshift, SPA_BLKPTRSHIFT);
|
||||
|
||||
ASSERT(limit <= *start);
|
||||
ASSERT3U(minimum, <=, *start);
|
||||
|
||||
if (len <= iblkrange * maxblks) {
|
||||
*start = limit;
|
||||
if (*start - minimum <= iblkrange * maxblks) {
|
||||
*start = minimum;
|
||||
return (0);
|
||||
}
|
||||
ASSERT(ISP2(iblkrange));
|
||||
|
||||
while (*start > limit && blkcnt < maxblks) {
|
||||
for (uint64_t blks = 0; *start > minimum && blks < maxblks; blks++) {
|
||||
int err;
|
||||
|
||||
/* find next allocated L1 indirect */
|
||||
/*
|
||||
* dnode_next_offset(BACKWARDS) will find an allocated L1
|
||||
* indirect block at or before the input offset. We must
|
||||
* decrement *start so that it is at the end of the region
|
||||
* to search.
|
||||
*/
|
||||
(*start)--;
|
||||
err = dnode_next_offset(dn,
|
||||
DNODE_FIND_BACKWARDS, start, 2, 1, 0);
|
||||
|
||||
/* if there are no more, then we are done */
|
||||
/* if there are no indirect blocks before start, we are done */
|
||||
if (err == ESRCH) {
|
||||
*start = limit;
|
||||
return (0);
|
||||
} else if (err) {
|
||||
*start = minimum;
|
||||
break;
|
||||
} else if (err != 0) {
|
||||
return (err);
|
||||
}
|
||||
blkcnt += 1;
|
||||
|
||||
/* reset offset to end of "next" block back */
|
||||
/* set start to the beginning of this L1 indirect */
|
||||
*start = P2ALIGN(*start, iblkrange);
|
||||
if (*start <= limit)
|
||||
*start = limit;
|
||||
else
|
||||
*start -= 1;
|
||||
}
|
||||
if (*start < minimum)
|
||||
*start = minimum;
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
dmu_free_long_range_impl(objset_t *os, dnode_t *dn, uint64_t offset,
|
||||
uint64_t length, boolean_t free_dnode)
|
||||
uint64_t length)
|
||||
{
|
||||
dmu_tx_t *tx;
|
||||
uint64_t object_size, start, end, len;
|
||||
boolean_t trunc = (length == DMU_OBJECT_END);
|
||||
int align, err;
|
||||
uint64_t object_size = (dn->dn_maxblkid + 1) * dn->dn_datablksz;
|
||||
int err;
|
||||
|
||||
align = 1 << dn->dn_datablkshift;
|
||||
ASSERT(align > 0);
|
||||
object_size = align == 1 ? dn->dn_datablksz :
|
||||
(dn->dn_maxblkid + 1) << dn->dn_datablkshift;
|
||||
|
||||
end = offset + length;
|
||||
if (trunc || end > object_size)
|
||||
end = object_size;
|
||||
if (end <= offset)
|
||||
if (offset >= object_size)
|
||||
return (0);
|
||||
length = end - offset;
|
||||
|
||||
while (length) {
|
||||
start = end;
|
||||
/* assert(offset <= start) */
|
||||
err = get_next_chunk(dn, &start, offset);
|
||||
if (length == DMU_OBJECT_END || offset + length > object_size)
|
||||
length = object_size - offset;
|
||||
|
||||
while (length != 0) {
|
||||
uint64_t chunk_end, chunk_begin;
|
||||
|
||||
chunk_end = chunk_begin = offset + length;
|
||||
|
||||
/* move chunk_begin backwards to the beginning of this chunk */
|
||||
err = get_next_chunk(dn, &chunk_begin, offset);
|
||||
if (err)
|
||||
return (err);
|
||||
len = trunc ? DMU_OBJECT_END : end - start;
|
||||
ASSERT3U(chunk_begin, >=, offset);
|
||||
ASSERT3U(chunk_begin, <=, chunk_end);
|
||||
|
||||
tx = dmu_tx_create(os);
|
||||
dmu_tx_hold_free(tx, dn->dn_object, start, len);
|
||||
dmu_tx_t *tx = dmu_tx_create(os);
|
||||
dmu_tx_hold_free(tx, dn->dn_object,
|
||||
chunk_begin, chunk_end - chunk_begin);
|
||||
err = dmu_tx_assign(tx, TXG_WAIT);
|
||||
if (err) {
|
||||
dmu_tx_abort(tx);
|
||||
return (err);
|
||||
}
|
||||
|
||||
dnode_free_range(dn, start, trunc ? -1 : len, tx);
|
||||
|
||||
if (start == 0 && free_dnode) {
|
||||
ASSERT(trunc);
|
||||
dnode_free(dn, tx);
|
||||
}
|
||||
|
||||
length -= end - start;
|
||||
|
||||
dnode_free_range(dn, chunk_begin, chunk_end - chunk_begin, tx);
|
||||
dmu_tx_commit(tx);
|
||||
end = start;
|
||||
|
||||
length -= chunk_end - chunk_begin;
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
@ -681,38 +676,32 @@ dmu_free_long_range(objset_t *os, uint64_t object,
|
||||
err = dnode_hold(os, object, FTAG, &dn);
|
||||
if (err != 0)
|
||||
return (err);
|
||||
err = dmu_free_long_range_impl(os, dn, offset, length, FALSE);
|
||||
err = dmu_free_long_range_impl(os, dn, offset, length);
|
||||
dnode_rele(dn, FTAG);
|
||||
return (err);
|
||||
}
|
||||
|
||||
int
|
||||
dmu_free_object(objset_t *os, uint64_t object)
|
||||
dmu_free_long_object(objset_t *os, uint64_t object)
|
||||
{
|
||||
dnode_t *dn;
|
||||
dmu_tx_t *tx;
|
||||
int err;
|
||||
|
||||
err = dnode_hold_impl(os, object, DNODE_MUST_BE_ALLOCATED,
|
||||
FTAG, &dn);
|
||||
err = dmu_free_long_range(os, object, 0, DMU_OBJECT_END);
|
||||
if (err != 0)
|
||||
return (err);
|
||||
if (dn->dn_nlevels == 1) {
|
||||
tx = dmu_tx_create(os);
|
||||
dmu_tx_hold_bonus(tx, object);
|
||||
dmu_tx_hold_free(tx, dn->dn_object, 0, DMU_OBJECT_END);
|
||||
err = dmu_tx_assign(tx, TXG_WAIT);
|
||||
if (err == 0) {
|
||||
dnode_free_range(dn, 0, DMU_OBJECT_END, tx);
|
||||
dnode_free(dn, tx);
|
||||
dmu_tx_commit(tx);
|
||||
} else {
|
||||
dmu_tx_abort(tx);
|
||||
}
|
||||
|
||||
tx = dmu_tx_create(os);
|
||||
dmu_tx_hold_bonus(tx, object);
|
||||
dmu_tx_hold_free(tx, object, 0, DMU_OBJECT_END);
|
||||
err = dmu_tx_assign(tx, TXG_WAIT);
|
||||
if (err == 0) {
|
||||
err = dmu_object_free(os, object, tx);
|
||||
dmu_tx_commit(tx);
|
||||
} else {
|
||||
err = dmu_free_long_range_impl(os, dn, 0, DMU_OBJECT_END, TRUE);
|
||||
dmu_tx_abort(tx);
|
||||
}
|
||||
dnode_rele(dn, FTAG);
|
||||
|
||||
return (err);
|
||||
}
|
||||
|
||||
|
@ -1286,7 +1286,7 @@ restore_freeobjects(struct restorearg *ra, objset_t *os,
|
||||
if (dmu_object_info(os, obj, NULL) != 0)
|
||||
continue;
|
||||
|
||||
err = dmu_free_object(os, obj);
|
||||
err = dmu_free_long_object(os, obj);
|
||||
if (err != 0)
|
||||
return (err);
|
||||
}
|
||||
|
@ -615,7 +615,8 @@ dmu_tx_hold_free(dmu_tx_t *tx, uint64_t object, uint64_t off, uint64_t len)
|
||||
* if they are blocksize-aligned.
|
||||
*/
|
||||
if (dn->dn_datablkshift == 0) {
|
||||
dmu_tx_count_write(txh, off, len);
|
||||
if (off != 0 || len < dn->dn_datablksz)
|
||||
dmu_tx_count_write(txh, off, len);
|
||||
} else {
|
||||
/* first block will be modified if it is not aligned */
|
||||
if (!IS_P2ALIGNED(off, 1 << dn->dn_datablkshift))
|
||||
|
@ -117,6 +117,7 @@ dnode_cons(void *arg, void *unused, int kmflag)
|
||||
dn->dn_id_flags = 0;
|
||||
|
||||
dn->dn_dbufs_count = 0;
|
||||
dn->dn_unlisted_l0_blkid = 0;
|
||||
list_create(&dn->dn_dbufs, sizeof (dmu_buf_impl_t),
|
||||
offsetof(dmu_buf_impl_t, db_link));
|
||||
|
||||
@ -170,6 +171,7 @@ dnode_dest(void *arg, void *unused)
|
||||
ASSERT0(dn->dn_id_flags);
|
||||
|
||||
ASSERT0(dn->dn_dbufs_count);
|
||||
ASSERT0(dn->dn_unlisted_l0_blkid);
|
||||
list_destroy(&dn->dn_dbufs);
|
||||
}
|
||||
|
||||
@ -475,6 +477,7 @@ dnode_destroy(dnode_t *dn)
|
||||
dn->dn_newuid = 0;
|
||||
dn->dn_newgid = 0;
|
||||
dn->dn_id_flags = 0;
|
||||
dn->dn_unlisted_l0_blkid = 0;
|
||||
|
||||
dmu_zfetch_rele(&dn->dn_zfetch);
|
||||
kmem_cache_free(dnode_cache, dn);
|
||||
@ -705,6 +708,7 @@ dnode_move_impl(dnode_t *odn, dnode_t *ndn)
|
||||
ASSERT(list_is_empty(&ndn->dn_dbufs));
|
||||
list_move_tail(&ndn->dn_dbufs, &odn->dn_dbufs);
|
||||
ndn->dn_dbufs_count = odn->dn_dbufs_count;
|
||||
ndn->dn_unlisted_l0_blkid = odn->dn_unlisted_l0_blkid;
|
||||
ndn->dn_bonus = odn->dn_bonus;
|
||||
ndn->dn_have_spill = odn->dn_have_spill;
|
||||
ndn->dn_zio = odn->dn_zio;
|
||||
@ -739,6 +743,7 @@ dnode_move_impl(dnode_t *odn, dnode_t *ndn)
|
||||
list_create(&odn->dn_dbufs, sizeof (dmu_buf_impl_t),
|
||||
offsetof(dmu_buf_impl_t, db_link));
|
||||
odn->dn_dbufs_count = 0;
|
||||
odn->dn_unlisted_l0_blkid = 0;
|
||||
odn->dn_bonus = NULL;
|
||||
odn->dn_zfetch.zf_dnode = NULL;
|
||||
|
||||
@ -1528,7 +1533,7 @@ dnode_free_range(dnode_t *dn, uint64_t off, uint64_t len, dmu_tx_t *tx)
|
||||
blkshift = dn->dn_datablkshift;
|
||||
epbs = dn->dn_indblkshift - SPA_BLKPTRSHIFT;
|
||||
|
||||
if (len == -1ULL) {
|
||||
if (len == DMU_OBJECT_END) {
|
||||
len = UINT64_MAX - off;
|
||||
trunc = TRUE;
|
||||
}
|
||||
|
@ -101,9 +101,8 @@ dsl_dataset_block_born(dsl_dataset_t *ds, const blkptr_t *bp, dmu_tx_t *tx)
|
||||
used, compressed, uncompressed);
|
||||
return;
|
||||
}
|
||||
dmu_buf_will_dirty(ds->ds_dbuf, tx);
|
||||
|
||||
mutex_enter(&ds->ds_dir->dd_lock);
|
||||
dmu_buf_will_dirty(ds->ds_dbuf, tx);
|
||||
mutex_enter(&ds->ds_lock);
|
||||
delta = parent_delta(ds, used);
|
||||
ds->ds_phys->ds_referenced_bytes += used;
|
||||
@ -115,7 +114,6 @@ dsl_dataset_block_born(dsl_dataset_t *ds, const blkptr_t *bp, dmu_tx_t *tx)
|
||||
compressed, uncompressed, tx);
|
||||
dsl_dir_transfer_space(ds->ds_dir, used - delta,
|
||||
DD_USED_REFRSRV, DD_USED_HEAD, tx);
|
||||
mutex_exit(&ds->ds_dir->dd_lock);
|
||||
}
|
||||
|
||||
int
|
||||
@ -150,7 +148,6 @@ dsl_dataset_block_kill(dsl_dataset_t *ds, const blkptr_t *bp, dmu_tx_t *tx,
|
||||
dprintf_bp(bp, "freeing ds=%llu", ds->ds_object);
|
||||
dsl_free(tx->tx_pool, tx->tx_txg, bp);
|
||||
|
||||
mutex_enter(&ds->ds_dir->dd_lock);
|
||||
mutex_enter(&ds->ds_lock);
|
||||
ASSERT(ds->ds_phys->ds_unique_bytes >= used ||
|
||||
!DS_UNIQUE_IS_ACCURATE(ds));
|
||||
@ -161,7 +158,6 @@ dsl_dataset_block_kill(dsl_dataset_t *ds, const blkptr_t *bp, dmu_tx_t *tx,
|
||||
delta, -compressed, -uncompressed, tx);
|
||||
dsl_dir_transfer_space(ds->ds_dir, -used - delta,
|
||||
DD_USED_REFRSRV, DD_USED_HEAD, tx);
|
||||
mutex_exit(&ds->ds_dir->dd_lock);
|
||||
} else {
|
||||
dprintf_bp(bp, "putting on dead list: %s", "");
|
||||
if (async) {
|
||||
@ -596,31 +592,6 @@ dsl_dataset_name(dsl_dataset_t *ds, char *name)
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
dsl_dataset_namelen(dsl_dataset_t *ds)
|
||||
{
|
||||
int result;
|
||||
|
||||
if (ds == NULL) {
|
||||
result = 3; /* "mos" */
|
||||
} else {
|
||||
result = dsl_dir_namelen(ds->ds_dir);
|
||||
VERIFY0(dsl_dataset_get_snapname(ds));
|
||||
if (ds->ds_snapname[0]) {
|
||||
++result; /* adding one for the @-sign */
|
||||
if (!MUTEX_HELD(&ds->ds_lock)) {
|
||||
mutex_enter(&ds->ds_lock);
|
||||
result += strlen(ds->ds_snapname);
|
||||
mutex_exit(&ds->ds_lock);
|
||||
} else {
|
||||
result += strlen(ds->ds_snapname);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (result);
|
||||
}
|
||||
|
||||
void
|
||||
dsl_dataset_rele(dsl_dataset_t *ds, void *tag)
|
||||
{
|
||||
|
@ -896,7 +896,7 @@ dsl_destroy_head(const char *name)
|
||||
for (uint64_t obj = 0; error == 0;
|
||||
error = dmu_object_next(os, &obj, FALSE,
|
||||
prev_snap_txg))
|
||||
(void) dmu_free_object(os, obj);
|
||||
(void) dmu_free_long_object(os, obj);
|
||||
/* sync out all frees */
|
||||
txg_wait_synced(dmu_objset_pool(os), 0);
|
||||
dmu_objset_disown(os, FTAG);
|
||||
|
@ -845,11 +845,21 @@ dsl_dir_diduse_space(dsl_dir_t *dd, dd_used_t type,
|
||||
int64_t used, int64_t compressed, int64_t uncompressed, dmu_tx_t *tx)
|
||||
{
|
||||
int64_t accounted_delta;
|
||||
|
||||
/*
|
||||
* dsl_dataset_set_refreservation_sync_impl() calls this with
|
||||
* dd_lock held, so that it can atomically update
|
||||
* ds->ds_reserved and the dsl_dir accounting, so that
|
||||
* dsl_dataset_check_quota() can see dataset and dir accounting
|
||||
* consistently.
|
||||
*/
|
||||
boolean_t needlock = !MUTEX_HELD(&dd->dd_lock);
|
||||
|
||||
ASSERT(dmu_tx_is_syncing(tx));
|
||||
ASSERT(type < DD_USED_NUM);
|
||||
|
||||
dmu_buf_will_dirty(dd->dd_dbuf, tx);
|
||||
|
||||
if (needlock)
|
||||
mutex_enter(&dd->dd_lock);
|
||||
accounted_delta = parent_delta(dd, dd->dd_phys->dd_used_bytes, used);
|
||||
@ -858,7 +868,6 @@ dsl_dir_diduse_space(dsl_dir_t *dd, dd_used_t type,
|
||||
dd->dd_phys->dd_compressed_bytes >= -compressed);
|
||||
ASSERT(uncompressed >= 0 ||
|
||||
dd->dd_phys->dd_uncompressed_bytes >= -uncompressed);
|
||||
dmu_buf_will_dirty(dd->dd_dbuf, tx);
|
||||
dd->dd_phys->dd_used_bytes += used;
|
||||
dd->dd_phys->dd_uncompressed_bytes += uncompressed;
|
||||
dd->dd_phys->dd_compressed_bytes += compressed;
|
||||
@ -891,8 +900,6 @@ void
|
||||
dsl_dir_transfer_space(dsl_dir_t *dd, int64_t delta,
|
||||
dd_used_t oldtype, dd_used_t newtype, dmu_tx_t *tx)
|
||||
{
|
||||
boolean_t needlock = !MUTEX_HELD(&dd->dd_lock);
|
||||
|
||||
ASSERT(dmu_tx_is_syncing(tx));
|
||||
ASSERT(oldtype < DD_USED_NUM);
|
||||
ASSERT(newtype < DD_USED_NUM);
|
||||
@ -900,17 +907,15 @@ dsl_dir_transfer_space(dsl_dir_t *dd, int64_t delta,
|
||||
if (delta == 0 || !(dd->dd_phys->dd_flags & DD_FLAG_USED_BREAKDOWN))
|
||||
return;
|
||||
|
||||
if (needlock)
|
||||
mutex_enter(&dd->dd_lock);
|
||||
dmu_buf_will_dirty(dd->dd_dbuf, tx);
|
||||
mutex_enter(&dd->dd_lock);
|
||||
ASSERT(delta > 0 ?
|
||||
dd->dd_phys->dd_used_breakdown[oldtype] >= delta :
|
||||
dd->dd_phys->dd_used_breakdown[newtype] >= -delta);
|
||||
ASSERT(dd->dd_phys->dd_used_bytes >= ABS(delta));
|
||||
dmu_buf_will_dirty(dd->dd_dbuf, tx);
|
||||
dd->dd_phys->dd_used_breakdown[oldtype] -= delta;
|
||||
dd->dd_phys->dd_used_breakdown[newtype] += delta;
|
||||
if (needlock)
|
||||
mutex_exit(&dd->dd_lock);
|
||||
mutex_exit(&dd->dd_lock);
|
||||
}
|
||||
|
||||
typedef struct dsl_dir_set_qr_arg {
|
||||
|
@ -21,7 +21,7 @@
|
||||
|
||||
/*
|
||||
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2012 by Delphix. All rights reserved.
|
||||
* Copyright (c) 2013 by Delphix. All rights reserved.
|
||||
* Copyright 2011 Nexenta Systems, Inc. All rights reserved.
|
||||
* Copyright (c) 2012, Joyent, Inc. All rights reserved.
|
||||
*/
|
||||
@ -583,7 +583,7 @@ int dmu_free_range(objset_t *os, uint64_t object, uint64_t offset,
|
||||
uint64_t size, dmu_tx_t *tx);
|
||||
int dmu_free_long_range(objset_t *os, uint64_t object, uint64_t offset,
|
||||
uint64_t size);
|
||||
int dmu_free_object(objset_t *os, uint64_t object);
|
||||
int dmu_free_long_object(objset_t *os, uint64_t object);
|
||||
|
||||
/*
|
||||
* Convenience functions.
|
||||
|
@ -20,7 +20,7 @@
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2012 by Delphix. All rights reserved.
|
||||
* Copyright (c) 2013 by Delphix. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _SYS_DNODE_H
|
||||
@ -188,6 +188,8 @@ typedef struct dnode {
|
||||
|
||||
/* protected by dn_dbufs_mtx; declared here to fill 32-bit hole */
|
||||
uint32_t dn_dbufs_count; /* count of dn_dbufs */
|
||||
/* There are no level-0 blocks of this blkid or higher in dn_dbufs */
|
||||
uint64_t dn_unlisted_l0_blkid;
|
||||
|
||||
/* protected by os_lock: */
|
||||
list_node_t dn_dirty_link[TXG_SIZE]; /* next on dataset's dirty */
|
||||
|
@ -23,6 +23,9 @@
|
||||
* Copyright 2005 Sun Microsystems, Inc. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 2012, Joyent, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This header file defines the interfaces available from the CTF debugger
|
||||
@ -40,8 +43,6 @@
|
||||
#ifndef _CTF_API_H
|
||||
#define _CTF_API_H
|
||||
|
||||
#pragma ident "%Z%%M% %I% %E% SMI"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/elf.h>
|
||||
@ -227,6 +228,8 @@ extern int ctf_add_member(ctf_file_t *, ctf_id_t, const char *, ctf_id_t);
|
||||
|
||||
extern int ctf_set_array(ctf_file_t *, ctf_id_t, const ctf_arinfo_t *);
|
||||
|
||||
extern int ctf_delete_type(ctf_file_t *, ctf_id_t);
|
||||
|
||||
extern int ctf_update(ctf_file_t *);
|
||||
extern int ctf_discard(ctf_file_t *);
|
||||
extern int ctf_write(ctf_file_t *, int);
|
||||
|
@ -304,6 +304,7 @@ dev/tpm/tpm_acpi.c optional tpm acpi
|
||||
dev/tpm/tpm_isa.c optional tpm isa
|
||||
dev/uart/uart_cpu_x86.c optional uart
|
||||
dev/viawd/viawd.c optional viawd
|
||||
dev/vmware/vmxnet3/if_vmx.c optional vmx
|
||||
dev/wbwd/wbwd.c optional wbwd
|
||||
dev/wpi/if_wpi.c optional wpi
|
||||
dev/isci/isci.c optional isci
|
||||
|
@ -267,6 +267,7 @@ dev/tpm/tpm_acpi.c optional tpm acpi
|
||||
dev/tpm/tpm_isa.c optional tpm isa
|
||||
dev/uart/uart_cpu_x86.c optional uart
|
||||
dev/viawd/viawd.c optional viawd
|
||||
dev/vmware/vmxnet3/if_vmx.c optional vmx
|
||||
dev/acpica/acpi_if.m standard
|
||||
dev/acpi_support/acpi_wmi_if.m standard
|
||||
dev/wbwd/wbwd.c optional wbwd
|
||||
|
@ -21,7 +21,7 @@ stripdirs="generate libraries tests tools"
|
||||
stripfiles="Makefile README accygwin.h acefi.h achaiku.h acintel.h \
|
||||
aclinux.h acmacosx.h acmsvc.h acnetbsd.h acos2.h acwin.h \
|
||||
acwin64.h new_table.txt osfreebsdtbl.c oslinuxtbl.c osunixdir.c \
|
||||
oswindir.c oswintbl.c oswinxf.c readme.txt utclib.c"
|
||||
osunixmap.c oswindir.c oswintbl.c oswinxf.c readme.txt utclib.c"
|
||||
|
||||
# include files to canonify
|
||||
src_headers="acapps.h acbuffer.h accommon.h acconfig.h acdebug.h \
|
||||
|
@ -1,3 +1,87 @@
|
||||
----------------------------------------
|
||||
23 August 2013. Summary of changes for version 20130823:
|
||||
|
||||
1) ACPICA kernel-resident subsystem:
|
||||
|
||||
Implemented support for host-installed System Control Interrupt (SCI)
|
||||
handlers. Certain ACPI functionality requires the host to handle raw
|
||||
SCIs. For example, the "SCI Doorbell" that is defined for memory power
|
||||
state support requires the host device driver to handle SCIs to examine
|
||||
if the doorbell has been activated. Multiple SCI handlers can be
|
||||
installed to allow for future expansion. New external interfaces are
|
||||
AcpiInstallSciHandler, AcpiRemoveSciHandler; see the ACPICA reference for
|
||||
details. Lv Zheng, Bob Moore. ACPICA BZ 1032.
|
||||
|
||||
Operation region support: Never locally free the handler "context"
|
||||
pointer. This change removes some dangerous code that attempts to free
|
||||
the handler context pointer in some (rare) circumstances. The owner of
|
||||
the handler owns this pointer and the ACPICA code should never touch it.
|
||||
Although not seen to be an issue in any kernel, it did show up as a
|
||||
problem (fault) under AcpiExec. Also, set the internal storage field for
|
||||
the context pointer to zero when the region is deactivated, simply for
|
||||
sanity. David Box. ACPICA BZ 1039.
|
||||
|
||||
AcpiRead: On error, do not modify the return value target location. If an
|
||||
error happens in the middle of a split 32/32 64-bit I/O operation, do not
|
||||
modify the target of the return value pointer. Makes the code consistent
|
||||
with the rest of ACPICA. Bjorn Helgaas.
|
||||
|
||||
Example Code and Data Size: These are the sizes for the OS-independent
|
||||
acpica.lib produced by the Microsoft Visual C++ 9.0 32-bit compiler. The
|
||||
debug version of the code includes the debug output trace mechanism and
|
||||
has a much larger code and data size.
|
||||
|
||||
Current Release:
|
||||
Non-Debug Version: 96.7K Code, 27.1K Data, 123.9K Total
|
||||
Debug Version: 184.4K Code, 76.8K Data, 261.2K Total
|
||||
Previous Release:
|
||||
Non-Debug Version: 96.2K Code, 27.1K Data, 123.3K Total
|
||||
Debug Version: 185.4K Code, 77.1K Data, 262.5K Total
|
||||
|
||||
|
||||
2) iASL Compiler/Disassembler and Tools:
|
||||
|
||||
AcpiDump: Implemented several new features and fixed some problems:
|
||||
1) Added support to dump the RSDP, RSDT, and XSDT tables.
|
||||
2) Added support for multiple table instances (SSDT, UEFI).
|
||||
3) Added option to dump "customized" (overridden) tables (-c).
|
||||
4) Fixed a problem where some table filenames were improperly
|
||||
constructed.
|
||||
5) Improved some error messages, removed some unnecessary messages.
|
||||
|
||||
iASL: Implemented additional support for disassembly of ACPI tables that
|
||||
contain invocations of external control methods. The -fe<file> option
|
||||
allows the import of a file that specifies the external methods along
|
||||
with the required number of arguments for each -- allowing for the
|
||||
correct disassembly of the table. This is a workaround for a limitation
|
||||
of AML code where the disassembler often cannot determine the number of
|
||||
arguments required for an external control method and generates incorrect
|
||||
ASL code. See the iASL reference for details. ACPICA BZ 1030.
|
||||
|
||||
Debugger: Implemented a new command (paths) that displays the full
|
||||
pathnames (namepaths) and object types of all objects in the namespace.
|
||||
This is an alternative to the namespace command.
|
||||
|
||||
Debugger: Implemented a new command (sci) that invokes the SCI dispatch
|
||||
mechanism and any installed handlers.
|
||||
|
||||
iASL: Fixed a possible segfault for "too many parent prefixes" condition.
|
||||
This can occur if there are too many parent prefixes in a namepath (for
|
||||
example, ^^^^^^PCI0.ECRD). ACPICA BZ 1035.
|
||||
|
||||
Application OSLs: Set the return value for the PCI read functions. These
|
||||
functions simply return AE_OK, but should set the return value to zero
|
||||
also. This change implements this. ACPICA BZ 1038.
|
||||
|
||||
Debugger: Prevent possible command line buffer overflow. Increase the
|
||||
size of a couple of the debugger line buffers, and ensure that overflow
|
||||
cannot happen. ACPICA BZ 1037.
|
||||
|
||||
iASL: Changed to abort immediately on serious errors during the parsing
|
||||
phase. Due to the nature of ASL, there is no point in attempting to
|
||||
compile these types of errors, and they typically end up causing a
|
||||
cascade of hundreds of errors which obscure the original problem.
|
||||
|
||||
----------------------------------------
|
||||
25 July 2013. Summary of changes for version 20130725:
|
||||
|
||||
|
@ -341,6 +341,10 @@ AdAmlDisassemble (
|
||||
{
|
||||
AcpiDmClearExternalList ();
|
||||
}
|
||||
|
||||
/* Load any externals defined in the optional external ref file */
|
||||
|
||||
AcpiDmGetExternalsFromFile ();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -373,10 +373,18 @@ AcpiDmDumpDescending (
|
||||
switch (Op->Common.AmlOpcode)
|
||||
{
|
||||
case AML_BYTE_OP:
|
||||
|
||||
AcpiOsPrintf ("%2.2X", (UINT32) Op->Common.Value.Integer);
|
||||
break;
|
||||
|
||||
case AML_WORD_OP:
|
||||
|
||||
AcpiOsPrintf ("%4.4X", (UINT32) Op->Common.Value.Integer);
|
||||
break;
|
||||
|
||||
case AML_DWORD_OP:
|
||||
|
||||
AcpiOsPrintf ("%X", (UINT32) Op->Common.Value.Integer);
|
||||
AcpiOsPrintf ("%8.8X", (UINT32) Op->Common.Value.Integer);
|
||||
break;
|
||||
|
||||
case AML_QWORD_OP:
|
||||
|
@ -46,7 +46,9 @@
|
||||
#include <contrib/dev/acpica/include/amlcode.h>
|
||||
#include <contrib/dev/acpica/include/acnamesp.h>
|
||||
#include <contrib/dev/acpica/include/acdisasm.h>
|
||||
#include <contrib/dev/acpica/compiler/aslcompiler.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
|
||||
|
||||
/*
|
||||
@ -87,6 +89,8 @@ static const char *AcpiGbl_DmTypeNames[] =
|
||||
/* 19 */ ", FieldUnitObj"
|
||||
};
|
||||
|
||||
#define METHOD_SEPARATORS " \t,()\n"
|
||||
|
||||
|
||||
/* Local prototypes */
|
||||
|
||||
@ -99,6 +103,12 @@ AcpiDmNormalizeParentPrefix (
|
||||
ACPI_PARSE_OBJECT *Op,
|
||||
char *Path);
|
||||
|
||||
static void
|
||||
AcpiDmAddToExternalListFromFile (
|
||||
char *Path,
|
||||
UINT8 Type,
|
||||
UINT32 Value);
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
@ -444,7 +454,7 @@ AcpiDmAddToExternalList (
|
||||
(NextExternal->Value != Value))
|
||||
{
|
||||
ACPI_ERROR ((AE_INFO,
|
||||
"Argument count mismatch for method %s %u %u",
|
||||
"External method arg count mismatch %s: Current %u, attempted %u",
|
||||
NextExternal->Path, NextExternal->Value, Value));
|
||||
}
|
||||
|
||||
@ -534,6 +544,275 @@ AcpiDmAddToExternalList (
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: AcpiDmGetExternalsFromFile
|
||||
*
|
||||
* PARAMETERS: None
|
||||
*
|
||||
* RETURN: None
|
||||
*
|
||||
* DESCRIPTION: Process the optional external reference file.
|
||||
*
|
||||
* Each line in the file should be of the form:
|
||||
* External (<Method namepath>, MethodObj, <ArgCount>)
|
||||
*
|
||||
* Example:
|
||||
* External (_SB_.PCI0.XHC_.PS0X, MethodObj, 4)
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
void
|
||||
AcpiDmGetExternalsFromFile (
|
||||
void)
|
||||
{
|
||||
FILE *ExternalRefFile;
|
||||
char *Token;
|
||||
char *MethodName;
|
||||
UINT32 ArgCount;
|
||||
UINT32 ImportCount = 0;
|
||||
|
||||
|
||||
if (!Gbl_ExternalRefFilename)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* Open the file */
|
||||
|
||||
ExternalRefFile = fopen (Gbl_ExternalRefFilename, "r");
|
||||
if (!ExternalRefFile)
|
||||
{
|
||||
fprintf (stderr, "Could not open external reference file \"%s\"\n",
|
||||
Gbl_ExternalRefFilename);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Each line defines a method */
|
||||
|
||||
while (fgets (StringBuffer, ASL_MSG_BUFFER_SIZE, ExternalRefFile))
|
||||
{
|
||||
Token = strtok (StringBuffer, METHOD_SEPARATORS); /* "External" */
|
||||
if (!Token) continue;
|
||||
if (strcmp (Token, "External")) continue;
|
||||
|
||||
MethodName = strtok (NULL, METHOD_SEPARATORS); /* Method namepath */
|
||||
if (!MethodName) continue;
|
||||
|
||||
Token = strtok (NULL, METHOD_SEPARATORS); /* "MethodObj" */
|
||||
if (!Token) continue;
|
||||
if (strcmp (Token, "MethodObj")) continue;
|
||||
|
||||
Token = strtok (NULL, METHOD_SEPARATORS); /* Arg count */
|
||||
if (!Token) continue;
|
||||
|
||||
/* Convert arg count string to an integer */
|
||||
|
||||
errno = 0;
|
||||
ArgCount = strtoul (Token, NULL, 0);
|
||||
if (errno)
|
||||
{
|
||||
fprintf (stderr, "Invalid argument count (%s)\n", Token);
|
||||
continue;
|
||||
}
|
||||
if (ArgCount > 7)
|
||||
{
|
||||
fprintf (stderr, "Invalid argument count (%u)\n", ArgCount);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Add this external to the global list */
|
||||
|
||||
AcpiOsPrintf ("%s: Importing method external (%u arguments) %s\n",
|
||||
Gbl_ExternalRefFilename, ArgCount, MethodName);
|
||||
|
||||
AcpiDmAddToExternalListFromFile (MethodName, ACPI_TYPE_METHOD, ArgCount | 0x80);
|
||||
ImportCount++;
|
||||
}
|
||||
|
||||
if (!ImportCount)
|
||||
{
|
||||
fprintf (stderr, "Did not find any external methods in reference file \"%s\"\n",
|
||||
Gbl_ExternalRefFilename);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Add the external(s) to the namespace */
|
||||
|
||||
AcpiDmAddExternalsToNamespace ();
|
||||
|
||||
AcpiOsPrintf ("%s: Imported %u external method definitions\n",
|
||||
Gbl_ExternalRefFilename, ImportCount);
|
||||
}
|
||||
|
||||
fclose (ExternalRefFile);
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: AcpiDmAddToExternalListFromFile
|
||||
*
|
||||
* PARAMETERS: Path - Internal (AML) path to the object
|
||||
* Type - ACPI object type to be added
|
||||
* Value - Arg count if adding a Method object
|
||||
*
|
||||
* RETURN: None
|
||||
*
|
||||
* DESCRIPTION: Insert a new name into the global list of Externals which
|
||||
* will in turn be later emitted as an External() declaration
|
||||
* in the disassembled output.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
static void
|
||||
AcpiDmAddToExternalListFromFile (
|
||||
char *Path,
|
||||
UINT8 Type,
|
||||
UINT32 Value)
|
||||
{
|
||||
char *InternalPath;
|
||||
char *ExternalPath;
|
||||
ACPI_EXTERNAL_LIST *NewExternal;
|
||||
ACPI_EXTERNAL_LIST *NextExternal;
|
||||
ACPI_EXTERNAL_LIST *PrevExternal = NULL;
|
||||
ACPI_STATUS Status;
|
||||
BOOLEAN Resolved = FALSE;
|
||||
|
||||
|
||||
if (!Path)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* TBD: Add a flags parameter */
|
||||
|
||||
if (Type == ACPI_TYPE_METHOD)
|
||||
{
|
||||
if (Value & 0x80)
|
||||
{
|
||||
Resolved = TRUE;
|
||||
}
|
||||
Value &= 0x07;
|
||||
}
|
||||
|
||||
/*
|
||||
* We don't want External() statements to contain a leading '\'.
|
||||
* This prevents duplicate external statements of the form:
|
||||
*
|
||||
* External (\ABCD)
|
||||
* External (ABCD)
|
||||
*
|
||||
* This would cause a compile time error when the disassembled
|
||||
* output file is recompiled.
|
||||
*/
|
||||
if ((*Path == AML_ROOT_PREFIX) && (Path[1]))
|
||||
{
|
||||
Path++;
|
||||
}
|
||||
|
||||
/* Check all existing externals to ensure no duplicates */
|
||||
|
||||
NextExternal = AcpiGbl_ExternalList;
|
||||
while (NextExternal)
|
||||
{
|
||||
if (!ACPI_STRCMP (Path, NextExternal->Path))
|
||||
{
|
||||
/* Duplicate method, check that the Value (ArgCount) is the same */
|
||||
|
||||
if ((NextExternal->Type == ACPI_TYPE_METHOD) &&
|
||||
(NextExternal->Value != Value))
|
||||
{
|
||||
ACPI_ERROR ((AE_INFO,
|
||||
"(File) External method arg count mismatch %s: Current %u, override to %u",
|
||||
NextExternal->Path, NextExternal->Value, Value));
|
||||
|
||||
/* Override, since new value came from external reference file */
|
||||
|
||||
NextExternal->Value = Value;
|
||||
}
|
||||
|
||||
/* Allow upgrade of type from ANY */
|
||||
|
||||
else if (NextExternal->Type == ACPI_TYPE_ANY)
|
||||
{
|
||||
NextExternal->Type = Type;
|
||||
NextExternal->Value = Value;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
NextExternal = NextExternal->Next;
|
||||
}
|
||||
|
||||
/* Get the internal pathname (AML format) */
|
||||
|
||||
Status = AcpiNsInternalizeName (Path, &InternalPath);
|
||||
if (ACPI_FAILURE (Status))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* Allocate and init a new External() descriptor */
|
||||
|
||||
NewExternal = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EXTERNAL_LIST));
|
||||
if (!NewExternal)
|
||||
{
|
||||
ACPI_FREE (InternalPath);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Must copy and normalize the input path */
|
||||
|
||||
AcpiNsExternalizeName (ACPI_UINT32_MAX, InternalPath, NULL, &ExternalPath);
|
||||
|
||||
NewExternal->Path = ExternalPath;
|
||||
NewExternal->Type = Type;
|
||||
NewExternal->Value = Value;
|
||||
NewExternal->Resolved = Resolved;
|
||||
NewExternal->Length = (UINT16) ACPI_STRLEN (Path);
|
||||
NewExternal->InternalPath = InternalPath;
|
||||
|
||||
/* Set flag to indicate External->InternalPath needs to be freed */
|
||||
|
||||
NewExternal->Flags |= ACPI_IPATH_ALLOCATED | ACPI_FROM_REFERENCE_FILE;
|
||||
|
||||
/* Link the new descriptor into the global list, alphabetically ordered */
|
||||
|
||||
NextExternal = AcpiGbl_ExternalList;
|
||||
while (NextExternal)
|
||||
{
|
||||
if (AcpiUtStricmp (NewExternal->Path, NextExternal->Path) < 0)
|
||||
{
|
||||
if (PrevExternal)
|
||||
{
|
||||
PrevExternal->Next = NewExternal;
|
||||
}
|
||||
else
|
||||
{
|
||||
AcpiGbl_ExternalList = NewExternal;
|
||||
}
|
||||
|
||||
NewExternal->Next = NextExternal;
|
||||
return;
|
||||
}
|
||||
|
||||
PrevExternal = NextExternal;
|
||||
NextExternal = NextExternal->Next;
|
||||
}
|
||||
|
||||
if (PrevExternal)
|
||||
{
|
||||
PrevExternal->Next = NewExternal;
|
||||
}
|
||||
else
|
||||
{
|
||||
AcpiGbl_ExternalList = NewExternal;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: AcpiDmAddExternalsToNamespace
|
||||
@ -563,7 +842,7 @@ AcpiDmAddExternalsToNamespace (
|
||||
|
||||
Status = AcpiNsLookup (NULL, External->InternalPath, External->Type,
|
||||
ACPI_IMODE_LOAD_PASS1,
|
||||
ACPI_NS_EXTERNAL | ACPI_NS_DONT_OPEN_SCOPE,
|
||||
ACPI_NS_ERROR_IF_FOUND | ACPI_NS_EXTERNAL | ACPI_NS_DONT_OPEN_SCOPE,
|
||||
NULL, &Node);
|
||||
|
||||
if (ACPI_FAILURE (Status))
|
||||
@ -731,7 +1010,8 @@ AcpiDmEmitExternals (
|
||||
NextExternal->Path,
|
||||
AcpiDmGetObjectTypeName (NextExternal->Type));
|
||||
|
||||
AcpiOsPrintf (") // Warning: Unresolved Method, "
|
||||
AcpiOsPrintf (
|
||||
") // Warning: Unresolved Method, "
|
||||
"guessing %u arguments (may be incorrect, see warning above)\n",
|
||||
NextExternal->Value);
|
||||
|
||||
@ -743,9 +1023,45 @@ AcpiDmEmitExternals (
|
||||
|
||||
AcpiOsPrintf ("\n");
|
||||
|
||||
|
||||
/* Emit externals that were imported from a file */
|
||||
|
||||
if (Gbl_ExternalRefFilename)
|
||||
{
|
||||
AcpiOsPrintf (
|
||||
" /*\n * External declarations that were imported from\n"
|
||||
" * the reference file [%s]\n */\n",
|
||||
Gbl_ExternalRefFilename);
|
||||
|
||||
NextExternal = AcpiGbl_ExternalList;
|
||||
while (NextExternal)
|
||||
{
|
||||
if (!NextExternal->Emitted && (NextExternal->Flags & ACPI_FROM_REFERENCE_FILE))
|
||||
{
|
||||
AcpiOsPrintf (" External (%s%s",
|
||||
NextExternal->Path,
|
||||
AcpiDmGetObjectTypeName (NextExternal->Type));
|
||||
|
||||
if (NextExternal->Type == ACPI_TYPE_METHOD)
|
||||
{
|
||||
AcpiOsPrintf (") // %u Arguments\n",
|
||||
NextExternal->Value);
|
||||
}
|
||||
else
|
||||
{
|
||||
AcpiOsPrintf (")\n");
|
||||
}
|
||||
NextExternal->Emitted = TRUE;
|
||||
}
|
||||
|
||||
NextExternal = NextExternal->Next;
|
||||
}
|
||||
|
||||
AcpiOsPrintf ("\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* Walk the list of externals (unresolved references)
|
||||
* found during the AML parsing
|
||||
* Walk the list of externals found during the AML parsing
|
||||
*/
|
||||
while (AcpiGbl_ExternalList)
|
||||
{
|
||||
|
@ -446,7 +446,7 @@ AcpiDmDumpDataTable (
|
||||
Length = Table->Length;
|
||||
AcpiDmDumpTable (Length, 0, Table, 0, AcpiDmTableInfoFacs);
|
||||
}
|
||||
else if (ACPI_COMPARE_NAME (Table->Signature, ACPI_SIG_RSDP))
|
||||
else if (ACPI_VALIDATE_RSDP_SIG (Table->Signature))
|
||||
{
|
||||
Length = AcpiDmDumpRsdp (Table);
|
||||
}
|
||||
|
@ -593,10 +593,15 @@ CmDoCompile (
|
||||
AslCompilerparse();
|
||||
UtEndEvent (Event);
|
||||
|
||||
/* Flush out any remaining source after parse tree is complete */
|
||||
/* Check for parse errors */
|
||||
|
||||
Event = UtBeginEvent ("Flush source input");
|
||||
CmFlushSourceCode ();
|
||||
Status = AslCheckForErrorExit ();
|
||||
if (ACPI_FAILURE (Status))
|
||||
{
|
||||
fprintf (stderr, "Compiler aborting due to parser-detected syntax error(s)\n");
|
||||
LsDumpParseTree ();
|
||||
goto ErrorExit;
|
||||
}
|
||||
|
||||
/* Did the parse tree get successfully constructed? */
|
||||
|
||||
@ -606,16 +611,18 @@ CmDoCompile (
|
||||
* If there are no errors, then we have some sort of
|
||||
* internal problem.
|
||||
*/
|
||||
Status = AslCheckForErrorExit ();
|
||||
if (Status == AE_OK)
|
||||
{
|
||||
AslError (ASL_ERROR, ASL_MSG_COMPILER_INTERNAL,
|
||||
NULL, "- Could not resolve parse tree root node");
|
||||
}
|
||||
AslError (ASL_ERROR, ASL_MSG_COMPILER_INTERNAL,
|
||||
NULL, "- Could not resolve parse tree root node");
|
||||
|
||||
goto ErrorExit;
|
||||
}
|
||||
|
||||
|
||||
/* Flush out any remaining source after parse tree is complete */
|
||||
|
||||
Event = UtBeginEvent ("Flush source input");
|
||||
CmFlushSourceCode ();
|
||||
|
||||
/* Optional parse tree dump, compiler debug output only */
|
||||
|
||||
LsDumpParseTree ();
|
||||
|
@ -186,6 +186,7 @@ ASL_EXTERN char ASL_INIT_GLOBAL (*Gbl_IncludeFilename, NULL)
|
||||
ASL_EXTERN char ASL_INIT_GLOBAL (*Gbl_OutputFilenamePrefix, NULL);
|
||||
ASL_EXTERN ASL_INCLUDE_DIR ASL_INIT_GLOBAL (*Gbl_IncludeDirList, NULL);
|
||||
ASL_EXTERN char *Gbl_CurrentInputFilename;
|
||||
ASL_EXTERN char ASL_INIT_GLOBAL (*Gbl_ExternalRefFilename, NULL);
|
||||
|
||||
ASL_EXTERN BOOLEAN ASL_INIT_GLOBAL (Gbl_HasIncludeFiles, FALSE);
|
||||
|
||||
|
@ -487,6 +487,10 @@ LdNamespace1Begin (
|
||||
ACPI_TYPE_LOCAL_SCOPE,
|
||||
ACPI_IMODE_LOAD_PASS1, Flags,
|
||||
WalkState, &(Node));
|
||||
if (ACPI_FAILURE (Status))
|
||||
{
|
||||
return_ACPI_STATUS (Status);
|
||||
}
|
||||
|
||||
/*
|
||||
* However, this is an error -- primarily because the MS
|
||||
|
@ -138,6 +138,7 @@ Usage (
|
||||
ACPI_OPTION ("-dc <f1,f2>", "Disassemble AML and immediately compile it");
|
||||
ACPI_OPTION ("", " (Obtain DSDT from current system if no input file)");
|
||||
ACPI_OPTION ("-e <f1,f2>", "Include ACPI table(s) for external symbol resolution");
|
||||
ACPI_OPTION ("-fe <file>", "Specify external symbol declaration file");
|
||||
ACPI_OPTION ("-g", "Get ACPI tables and write to files (*.dat)");
|
||||
ACPI_OPTION ("-in", "Ignore NoOp opcodes");
|
||||
ACPI_OPTION ("-vt", "Dump binary table data in hex format within output file");
|
||||
|
@ -68,7 +68,7 @@ AslDoResponseFile (
|
||||
|
||||
|
||||
#define ASL_TOKEN_SEPARATORS " \t\n"
|
||||
#define ASL_SUPPORTED_OPTIONS "@:b|c|d^D:e:fgh^i|I:l^m:no|p:P^r:s|t|T+G^v^w|x:z"
|
||||
#define ASL_SUPPORTED_OPTIONS "@:b|c|d^D:e:f^gh^i|I:l^m:no|p:P^r:s|t|T+G^v^w|x:z"
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
@ -136,8 +136,7 @@ AslCommandLine (
|
||||
|
||||
if (BadCommandLine)
|
||||
{
|
||||
printf ("\n");
|
||||
Usage ();
|
||||
printf ("Use -h option for help information\n");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
@ -276,9 +275,30 @@ AslDoOptions (
|
||||
}
|
||||
break;
|
||||
|
||||
case 'f': /* Ignore errors and force creation of aml file */
|
||||
case 'f':
|
||||
|
||||
Gbl_IgnoreErrors = TRUE;
|
||||
switch (AcpiGbl_Optarg[0])
|
||||
{
|
||||
case '^': /* Ignore errors and force creation of aml file */
|
||||
|
||||
Gbl_IgnoreErrors = TRUE;
|
||||
break;
|
||||
|
||||
case 'e': /* Disassembler: Get external declaration file */
|
||||
|
||||
if (AcpiGetoptArgument (argc, argv))
|
||||
{
|
||||
return (-1);
|
||||
}
|
||||
|
||||
Gbl_ExternalRefFilename = AcpiGbl_Optarg;
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
printf ("Unknown option: -f%s\n", AcpiGbl_Optarg);
|
||||
return (-1);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'G':
|
||||
|
@ -317,7 +317,7 @@ DtCompileDataTable (
|
||||
DtSetTableLength ();
|
||||
return (Status);
|
||||
}
|
||||
else if (ACPI_COMPARE_NAME (Signature, ACPI_SIG_RSDP))
|
||||
else if (ACPI_VALIDATE_RSDP_SIG (Signature))
|
||||
{
|
||||
Status = DtCompileRsdp (FieldList);
|
||||
return (Status);
|
||||
|
@ -1211,6 +1211,14 @@ AcpiDbGenerateGpe (
|
||||
|
||||
(void) AcpiEvGpeDispatch (NULL, GpeEventInfo, GpeNumber);
|
||||
}
|
||||
|
||||
void
|
||||
AcpiDbGenerateSci (
|
||||
void)
|
||||
{
|
||||
AcpiEvSciDispatch ();
|
||||
}
|
||||
|
||||
#endif /* !ACPI_REDUCED_HARDWARE */
|
||||
|
||||
#endif /* ACPI_DEBUGGER */
|
||||
|
@ -142,7 +142,8 @@ AcpiDbOpenDebugFile (
|
||||
}
|
||||
|
||||
AcpiOsPrintf ("Debug output file %s opened\n", Name);
|
||||
ACPI_STRCPY (AcpiGbl_DbDebugFilename, Name);
|
||||
ACPI_STRNCPY (AcpiGbl_DbDebugFilename, Name,
|
||||
sizeof (AcpiGbl_DbDebugFilename));
|
||||
AcpiGbl_DbOutputToFile = TRUE;
|
||||
|
||||
#endif
|
||||
@ -274,11 +275,9 @@ AcpiDbReadTable (
|
||||
|
||||
fseek (fp, 0, SEEK_SET);
|
||||
|
||||
/* The RSDT, FACS and S3PT tables do not have standard ACPI headers */
|
||||
/* The RSDP table does not have standard ACPI header */
|
||||
|
||||
if (ACPI_COMPARE_NAME (TableHeader.Signature, "RSD ") ||
|
||||
ACPI_COMPARE_NAME (TableHeader.Signature, "FACS") ||
|
||||
ACPI_COMPARE_NAME (TableHeader.Signature, "S3PT"))
|
||||
if (ACPI_COMPARE_NAME (TableHeader.Signature, "RSD "))
|
||||
{
|
||||
*TableLength = FileSize;
|
||||
StandardHeader = FALSE;
|
||||
|
@ -132,12 +132,14 @@ enum AcpiExDebuggerCommands
|
||||
CMD_OPEN,
|
||||
CMD_OSI,
|
||||
CMD_OWNER,
|
||||
CMD_PATHS,
|
||||
CMD_PREDEFINED,
|
||||
CMD_PREFIX,
|
||||
CMD_QUIT,
|
||||
CMD_REFERENCES,
|
||||
CMD_RESOURCES,
|
||||
CMD_RESULTS,
|
||||
CMD_SCI,
|
||||
CMD_SET,
|
||||
CMD_SLEEP,
|
||||
CMD_STATS,
|
||||
@ -203,12 +205,14 @@ static const ACPI_DB_COMMAND_INFO AcpiGbl_DbCommands[] =
|
||||
{"OPEN", 1},
|
||||
{"OSI", 0},
|
||||
{"OWNER", 1},
|
||||
{"PATHS", 0},
|
||||
{"PREDEFINED", 0},
|
||||
{"PREFIX", 0},
|
||||
{"QUIT", 0},
|
||||
{"REFERENCES", 1},
|
||||
{"RESOURCES", 0},
|
||||
{"RESULTS", 0},
|
||||
{"SCI", 0},
|
||||
{"SET", 3},
|
||||
{"SLEEP", 0},
|
||||
{"STATS", 1},
|
||||
@ -259,22 +263,19 @@ static const ACPI_DB_COMMAND_HELP AcpiGbl_DbCommandHelp[] =
|
||||
{0, "\nNamespace Access Commands:", "\n"},
|
||||
{1, " Businfo", "Display system bus info\n"},
|
||||
{1, " Disassemble <Method>", "Disassemble a control method\n"},
|
||||
{1, " Event <F|G> <Value>", "Generate AcpiEvent (Fixed/GPE)\n"},
|
||||
{1, " Find <AcpiName> (? is wildcard)", "Find ACPI name(s) with wildcards\n"},
|
||||
{1, " Gpe <GpeNum> <GpeBlock>", "Simulate a GPE\n"},
|
||||
{1, " Gpes", "Display info on all GPEs\n"},
|
||||
{1, " Integrity", "Validate namespace integrity\n"},
|
||||
{1, " Methods", "Display list of loaded control methods\n"},
|
||||
{1, " Namespace [Object] [Depth]", "Display loaded namespace tree/subtree\n"},
|
||||
{1, " Notify <Object> <Value>", "Send a notification on Object\n"},
|
||||
{1, " Objects <ObjectType>", "Display all objects of the given type\n"},
|
||||
{1, " Owner <OwnerId> [Depth]", "Display loaded namespace by object owner\n"},
|
||||
{1, " Paths", "Display full pathnames of namespace objects\n"},
|
||||
{1, " Predefined", "Check all predefined names\n"},
|
||||
{1, " Prefix [<NamePath>]", "Set or Get current execution prefix\n"},
|
||||
{1, " References <Addr>", "Find all references to object at addr\n"},
|
||||
{1, " Resources [DeviceName]", "Display Device resources (no arg = all devices)\n"},
|
||||
{1, " Set N <NamedObject> <Value>", "Set value for named integer\n"},
|
||||
{1, " Sleep [SleepState]", "Simulate sleep/wake sequence(s) (0-5)\n"},
|
||||
{1, " Template <Object>", "Format/dump a Buffer/ResourceTemplate\n"},
|
||||
{1, " Terminate", "Delete namespace and all internal objects\n"},
|
||||
{1, " Type <Object>", "Display object type\n"},
|
||||
@ -288,7 +289,7 @@ static const ACPI_DB_COMMAND_HELP AcpiGbl_DbCommandHelp[] =
|
||||
{5, " Execute <Namepath> [Arguments]", "Execute control method\n"},
|
||||
{1, " Hex Integer", "Integer method argument\n"},
|
||||
{1, " \"Ascii String\"", "String method argument\n"},
|
||||
{1, " (Byte List)", "Buffer method argument\n"},
|
||||
{1, " (Hex Byte List)", "Buffer method argument\n"},
|
||||
{1, " [Package Element List]", "Package method argument\n"},
|
||||
{1, " Go", "Allow method to run to completion\n"},
|
||||
{1, " Information", "Display info about the current method\n"},
|
||||
@ -303,6 +304,13 @@ static const ACPI_DB_COMMAND_HELP AcpiGbl_DbCommandHelp[] =
|
||||
{1, " Tree", "Display control method calling tree\n"},
|
||||
{1, " <Enter>", "Single step next AML opcode (over calls)\n"},
|
||||
|
||||
{0, "\nHardware Related Commands:", "\n"},
|
||||
{1, " Event <F|G> <Value>", "Generate AcpiEvent (Fixed/GPE)\n"},
|
||||
{1, " Gpe <GpeNum> <GpeBlock>", "Simulate a GPE\n"},
|
||||
{1, " Gpes", "Display info on all GPEs\n"},
|
||||
{1, " Sci", "Generate an SCI\n"},
|
||||
{1, " Sleep [SleepState]", "Simulate sleep/wake sequence(s) (0-5)\n"},
|
||||
|
||||
{0, "\nFile I/O Commands:", "\n"},
|
||||
{1, " Close", "Close debug output file\n"},
|
||||
{1, " Load <Input Filename>", "Load ACPI table from a file\n"},
|
||||
@ -1002,6 +1010,11 @@ AcpiDbCommandDispatch (
|
||||
AcpiDbDumpNamespaceByOwner (AcpiGbl_DbArgs[1], AcpiGbl_DbArgs[2]);
|
||||
break;
|
||||
|
||||
case CMD_PATHS:
|
||||
|
||||
AcpiDbDumpNamespacePaths ();
|
||||
break;
|
||||
|
||||
case CMD_PREDEFINED:
|
||||
|
||||
AcpiDbCheckPredefinedNames ();
|
||||
@ -1027,6 +1040,11 @@ AcpiDbCommandDispatch (
|
||||
AcpiDbDisplayResults ();
|
||||
break;
|
||||
|
||||
case CMD_SCI:
|
||||
|
||||
AcpiDbGenerateSci ();
|
||||
break;
|
||||
|
||||
case CMD_SET:
|
||||
|
||||
AcpiDbSetMethodData (AcpiGbl_DbArgs[1], AcpiGbl_DbArgs[2],
|
||||
|
@ -254,6 +254,37 @@ AcpiDbDumpNamespace (
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: AcpiDbDumpNamespacePaths
|
||||
*
|
||||
* PARAMETERS: None
|
||||
*
|
||||
* RETURN: None
|
||||
*
|
||||
* DESCRIPTION: Dump entire namespace with full object pathnames and object
|
||||
* type information. Alternative to "namespace" command.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
void
|
||||
AcpiDbDumpNamespacePaths (
|
||||
void)
|
||||
{
|
||||
|
||||
AcpiDbSetOutputDestination (ACPI_DB_DUPLICATE_OUTPUT);
|
||||
AcpiOsPrintf ("ACPI Namespace (from root):\n");
|
||||
|
||||
/* Display the entire namespace */
|
||||
|
||||
AcpiDbSetOutputDestination (ACPI_DB_REDIRECTABLE_OUTPUT);
|
||||
AcpiNsDumpObjectPaths (ACPI_TYPE_ANY, ACPI_DISPLAY_SUMMARY,
|
||||
ACPI_UINT32_MAX, ACPI_OWNER_ID_MAX, AcpiGbl_RootNode);
|
||||
|
||||
AcpiDbSetOutputDestination (ACPI_DB_CONSOLE_OUTPUT);
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: AcpiDbDumpNamespaceByOwner
|
||||
|
@ -216,7 +216,7 @@ AcpiEvGetGpeDevice (
|
||||
*
|
||||
* FUNCTION: AcpiEvGetGpeXruptBlock
|
||||
*
|
||||
* PARAMETERS: InterruptNumber - Interrupt for a GPE block
|
||||
* PARAMETERS: InterruptNumber - Interrupt for a GPE block
|
||||
*
|
||||
* RETURN: A GPE interrupt block
|
||||
*
|
||||
|
@ -292,15 +292,6 @@ AcpiEvTerminate (
|
||||
|
||||
Status = AcpiEvWalkGpeList (AcpiHwDisableGpeBlock, NULL);
|
||||
|
||||
/* Remove SCI handler */
|
||||
|
||||
Status = AcpiEvRemoveSciHandler ();
|
||||
if (ACPI_FAILURE(Status))
|
||||
{
|
||||
ACPI_ERROR ((AE_INFO,
|
||||
"Could not remove SCI handler"));
|
||||
}
|
||||
|
||||
Status = AcpiEvRemoveGlobalLockHandler ();
|
||||
if (ACPI_FAILURE(Status))
|
||||
{
|
||||
@ -311,6 +302,15 @@ AcpiEvTerminate (
|
||||
AcpiGbl_EventsInitialized = FALSE;
|
||||
}
|
||||
|
||||
/* Remove SCI handlers */
|
||||
|
||||
Status = AcpiEvRemoveAllSciHandlers ();
|
||||
if (ACPI_FAILURE(Status))
|
||||
{
|
||||
ACPI_ERROR ((AE_INFO,
|
||||
"Could not remove SCI handler"));
|
||||
}
|
||||
|
||||
/* Deallocate all handler objects installed within GPE info structs */
|
||||
|
||||
Status = AcpiEvWalkGpeList (AcpiEvDeleteGpeHandlers, NULL);
|
||||
|
@ -234,18 +234,12 @@ AcpiEvAddressSpaceDispatch (
|
||||
{
|
||||
RegionObj->Region.Flags |= AOPOBJ_SETUP_COMPLETE;
|
||||
|
||||
if (RegionObj2->Extra.RegionContext)
|
||||
/*
|
||||
* Save the returned context for use in all accesses to
|
||||
* the handler for this particular region
|
||||
*/
|
||||
if (!(RegionObj2->Extra.RegionContext))
|
||||
{
|
||||
/* The handler for this region was already installed */
|
||||
|
||||
ACPI_FREE (RegionContext);
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* Save the returned context for use in all accesses to
|
||||
* this particular region
|
||||
*/
|
||||
RegionObj2->Extra.RegionContext = RegionContext;
|
||||
}
|
||||
}
|
||||
@ -261,7 +255,6 @@ AcpiEvAddressSpaceDispatch (
|
||||
ACPI_FORMAT_NATIVE_UINT (RegionObj->Region.Address + RegionOffset),
|
||||
AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
|
||||
|
||||
|
||||
/*
|
||||
* Special handling for GenericSerialBus and GeneralPurposeIo:
|
||||
* There are three extra parameters that must be passed to the
|
||||
@ -424,6 +417,15 @@ AcpiEvDetachRegion(
|
||||
Status = RegionSetup (RegionObj, ACPI_REGION_DEACTIVATE,
|
||||
HandlerObj->AddressSpace.Context, RegionContext);
|
||||
|
||||
/*
|
||||
* RegionContext should have been released by the deactivate
|
||||
* operation. We don't need access to it anymore here.
|
||||
*/
|
||||
if (RegionContext)
|
||||
{
|
||||
*RegionContext = NULL;
|
||||
}
|
||||
|
||||
/* Init routine may fail, Just ignore errors */
|
||||
|
||||
if (ACPI_FAILURE (Status))
|
||||
|
@ -59,6 +59,57 @@ AcpiEvSciXruptHandler (
|
||||
void *Context);
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: AcpiEvSciDispatch
|
||||
*
|
||||
* PARAMETERS: None
|
||||
*
|
||||
* RETURN: Status code indicates whether interrupt was handled.
|
||||
*
|
||||
* DESCRIPTION: Dispatch the SCI to all host-installed SCI handlers.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
UINT32
|
||||
AcpiEvSciDispatch (
|
||||
void)
|
||||
{
|
||||
ACPI_SCI_HANDLER_INFO *SciHandler;
|
||||
ACPI_CPU_FLAGS Flags;
|
||||
UINT32 IntStatus = ACPI_INTERRUPT_NOT_HANDLED;
|
||||
|
||||
|
||||
ACPI_FUNCTION_NAME (EvSciDispatch);
|
||||
|
||||
|
||||
/* Are there any host-installed SCI handlers? */
|
||||
|
||||
if (!AcpiGbl_SciHandlerList)
|
||||
{
|
||||
return (IntStatus);
|
||||
}
|
||||
|
||||
Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
|
||||
|
||||
/* Invoke all host-installed SCI handlers */
|
||||
|
||||
SciHandler = AcpiGbl_SciHandlerList;
|
||||
while (SciHandler)
|
||||
{
|
||||
/* Invoke the installed handler (at interrupt level) */
|
||||
|
||||
IntStatus |= SciHandler->Address (
|
||||
SciHandler->Context);
|
||||
|
||||
SciHandler = SciHandler->Next;
|
||||
}
|
||||
|
||||
AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
|
||||
return (IntStatus);
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: AcpiEvSciXruptHandler
|
||||
@ -100,6 +151,10 @@ AcpiEvSciXruptHandler (
|
||||
*/
|
||||
InterruptHandled |= AcpiEvGpeDetect (GpeXruptList);
|
||||
|
||||
/* Invoke all host-installed SCI handlers */
|
||||
|
||||
InterruptHandled |= AcpiEvSciDispatch ();
|
||||
|
||||
AcpiSciCount++;
|
||||
return_UINT32 (InterruptHandled);
|
||||
}
|
||||
@ -129,14 +184,13 @@ AcpiEvGpeXruptHandler (
|
||||
|
||||
|
||||
/*
|
||||
* We are guaranteed by the ACPI CA initialization/shutdown code that
|
||||
* We are guaranteed by the ACPICA initialization/shutdown code that
|
||||
* if this interrupt handler is installed, ACPI is enabled.
|
||||
*/
|
||||
|
||||
/* GPEs: Check for and dispatch any GPEs that have occurred */
|
||||
|
||||
InterruptHandled |= AcpiEvGpeDetect (GpeXruptList);
|
||||
|
||||
return_UINT32 (InterruptHandled);
|
||||
}
|
||||
|
||||
@ -171,15 +225,15 @@ AcpiEvInstallSciHandler (
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* FUNCTION: AcpiEvRemoveSciHandler
|
||||
* FUNCTION: AcpiEvRemoveAllSciHandlers
|
||||
*
|
||||
* PARAMETERS: none
|
||||
*
|
||||
* RETURN: E_OK if handler uninstalled OK, E_ERROR if handler was not
|
||||
* RETURN: AE_OK if handler uninstalled, AE_ERROR if handler was not
|
||||
* installed to begin with
|
||||
*
|
||||
* DESCRIPTION: Remove the SCI interrupt handler. No further SCIs will be
|
||||
* taken.
|
||||
* taken. Remove all host-installed SCI handlers.
|
||||
*
|
||||
* Note: It doesn't seem important to disable all events or set the event
|
||||
* enable registers to their original values. The OS should disable
|
||||
@ -189,13 +243,15 @@ AcpiEvInstallSciHandler (
|
||||
******************************************************************************/
|
||||
|
||||
ACPI_STATUS
|
||||
AcpiEvRemoveSciHandler (
|
||||
AcpiEvRemoveAllSciHandlers (
|
||||
void)
|
||||
{
|
||||
ACPI_SCI_HANDLER_INFO *SciHandler;
|
||||
ACPI_CPU_FLAGS Flags;
|
||||
ACPI_STATUS Status;
|
||||
|
||||
|
||||
ACPI_FUNCTION_TRACE (EvRemoveSciHandler);
|
||||
ACPI_FUNCTION_TRACE (EvRemoveAllSciHandlers);
|
||||
|
||||
|
||||
/* Just let the OS remove the handler and disable the level */
|
||||
@ -203,6 +259,23 @@ AcpiEvRemoveSciHandler (
|
||||
Status = AcpiOsRemoveInterruptHandler ((UINT32) AcpiGbl_FADT.SciInterrupt,
|
||||
AcpiEvSciXruptHandler);
|
||||
|
||||
if (!AcpiGbl_SciHandlerList)
|
||||
{
|
||||
return (Status);
|
||||
}
|
||||
|
||||
Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
|
||||
|
||||
/* Free all host-installed SCI handlers */
|
||||
|
||||
while (AcpiGbl_SciHandlerList)
|
||||
{
|
||||
SciHandler = AcpiGbl_SciHandlerList;
|
||||
AcpiGbl_SciHandlerList = SciHandler->Next;
|
||||
ACPI_FREE (SciHandler);
|
||||
}
|
||||
|
||||
AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
|
||||
return_ACPI_STATUS (Status);
|
||||
}
|
||||
|
||||
|
@ -433,6 +433,169 @@ ACPI_EXPORT_SYMBOL (AcpiInstallExceptionHandler)
|
||||
|
||||
|
||||
#if (!ACPI_REDUCED_HARDWARE)
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: AcpiInstallSciHandler
|
||||
*
|
||||
* PARAMETERS: Address - Address of the handler
|
||||
* Context - Value passed to the handler on each SCI
|
||||
*
|
||||
* RETURN: Status
|
||||
*
|
||||
* DESCRIPTION: Install a handler for a System Control Interrupt.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
ACPI_STATUS
|
||||
AcpiInstallSciHandler (
|
||||
ACPI_SCI_HANDLER Address,
|
||||
void *Context)
|
||||
{
|
||||
ACPI_SCI_HANDLER_INFO *NewSciHandler;
|
||||
ACPI_SCI_HANDLER_INFO *SciHandler;
|
||||
ACPI_CPU_FLAGS Flags;
|
||||
ACPI_STATUS Status;
|
||||
|
||||
|
||||
ACPI_FUNCTION_TRACE (AcpiInstallSciHandler);
|
||||
|
||||
|
||||
if (!Address)
|
||||
{
|
||||
return_ACPI_STATUS (AE_BAD_PARAMETER);
|
||||
}
|
||||
|
||||
/* Allocate and init a handler object */
|
||||
|
||||
NewSciHandler = ACPI_ALLOCATE (sizeof (ACPI_SCI_HANDLER_INFO));
|
||||
if (!NewSciHandler)
|
||||
{
|
||||
return_ACPI_STATUS (AE_NO_MEMORY);
|
||||
}
|
||||
|
||||
NewSciHandler->Address = Address;
|
||||
NewSciHandler->Context = Context;
|
||||
|
||||
Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
|
||||
if (ACPI_FAILURE (Status))
|
||||
{
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
/* Lock list during installation */
|
||||
|
||||
Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
|
||||
SciHandler = AcpiGbl_SciHandlerList;
|
||||
|
||||
/* Ensure handler does not already exist */
|
||||
|
||||
while (SciHandler)
|
||||
{
|
||||
if (Address == SciHandler->Address)
|
||||
{
|
||||
Status = AE_ALREADY_EXISTS;
|
||||
goto UnlockAndExit;
|
||||
}
|
||||
|
||||
SciHandler = SciHandler->Next;
|
||||
}
|
||||
|
||||
/* Install the new handler into the global list (at head) */
|
||||
|
||||
NewSciHandler->Next = AcpiGbl_SciHandlerList;
|
||||
AcpiGbl_SciHandlerList = NewSciHandler;
|
||||
|
||||
|
||||
UnlockAndExit:
|
||||
|
||||
AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
|
||||
(void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
|
||||
|
||||
Exit:
|
||||
if (ACPI_FAILURE (Status))
|
||||
{
|
||||
ACPI_FREE (NewSciHandler);
|
||||
}
|
||||
return_ACPI_STATUS (Status);
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: AcpiRemoveSciHandler
|
||||
*
|
||||
* PARAMETERS: Address - Address of the handler
|
||||
*
|
||||
* RETURN: Status
|
||||
*
|
||||
* DESCRIPTION: Remove a handler for a System Control Interrupt.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
ACPI_STATUS
|
||||
AcpiRemoveSciHandler (
|
||||
ACPI_SCI_HANDLER Address)
|
||||
{
|
||||
ACPI_SCI_HANDLER_INFO *PrevSciHandler;
|
||||
ACPI_SCI_HANDLER_INFO *NextSciHandler;
|
||||
ACPI_CPU_FLAGS Flags;
|
||||
ACPI_STATUS Status;
|
||||
|
||||
|
||||
ACPI_FUNCTION_TRACE (AcpiRemoveSciHandler);
|
||||
|
||||
|
||||
if (!Address)
|
||||
{
|
||||
return_ACPI_STATUS (AE_BAD_PARAMETER);
|
||||
}
|
||||
|
||||
Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
|
||||
if (ACPI_FAILURE (Status))
|
||||
{
|
||||
return_ACPI_STATUS (Status);
|
||||
}
|
||||
|
||||
/* Remove the SCI handler with lock */
|
||||
|
||||
Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
|
||||
|
||||
PrevSciHandler = NULL;
|
||||
NextSciHandler = AcpiGbl_SciHandlerList;
|
||||
while (NextSciHandler)
|
||||
{
|
||||
if (NextSciHandler->Address == Address)
|
||||
{
|
||||
/* Unlink and free the SCI handler info block */
|
||||
|
||||
if (PrevSciHandler)
|
||||
{
|
||||
PrevSciHandler->Next = NextSciHandler->Next;
|
||||
}
|
||||
else
|
||||
{
|
||||
AcpiGbl_SciHandlerList = NextSciHandler->Next;
|
||||
}
|
||||
|
||||
AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
|
||||
ACPI_FREE (NextSciHandler);
|
||||
goto UnlockAndExit;
|
||||
}
|
||||
|
||||
PrevSciHandler = NextSciHandler;
|
||||
NextSciHandler = NextSciHandler->Next;
|
||||
}
|
||||
|
||||
AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
|
||||
Status = AE_NOT_EXIST;
|
||||
|
||||
|
||||
UnlockAndExit:
|
||||
(void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
|
||||
return_ACPI_STATUS (Status);
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: AcpiInstallGlobalEventHandler
|
||||
|
@ -131,7 +131,8 @@ AcpiRead (
|
||||
UINT64 *ReturnValue,
|
||||
ACPI_GENERIC_ADDRESS *Reg)
|
||||
{
|
||||
UINT32 Value;
|
||||
UINT32 ValueLo;
|
||||
UINT32 ValueHi;
|
||||
UINT32 Width;
|
||||
UINT64 Address;
|
||||
ACPI_STATUS Status;
|
||||
@ -153,13 +154,8 @@ AcpiRead (
|
||||
return (Status);
|
||||
}
|
||||
|
||||
/* Initialize entire 64-bit return value to zero */
|
||||
|
||||
*ReturnValue = 0;
|
||||
Value = 0;
|
||||
|
||||
/*
|
||||
* Two address spaces supported: Memory or IO. PCI_Config is
|
||||
* Two address spaces supported: Memory or I/O. PCI_Config is
|
||||
* not supported here because the GAS structure is insufficient
|
||||
*/
|
||||
if (Reg->SpaceId == ACPI_ADR_SPACE_SYSTEM_MEMORY)
|
||||
@ -173,6 +169,9 @@ AcpiRead (
|
||||
}
|
||||
else /* ACPI_ADR_SPACE_SYSTEM_IO, validated earlier */
|
||||
{
|
||||
ValueLo = 0;
|
||||
ValueHi = 0;
|
||||
|
||||
Width = Reg->BitWidth;
|
||||
if (Width == 64)
|
||||
{
|
||||
@ -180,25 +179,27 @@ AcpiRead (
|
||||
}
|
||||
|
||||
Status = AcpiHwReadPort ((ACPI_IO_ADDRESS)
|
||||
Address, &Value, Width);
|
||||
Address, &ValueLo, Width);
|
||||
if (ACPI_FAILURE (Status))
|
||||
{
|
||||
return (Status);
|
||||
}
|
||||
*ReturnValue = Value;
|
||||
|
||||
if (Reg->BitWidth == 64)
|
||||
{
|
||||
/* Read the top 32 bits */
|
||||
|
||||
Status = AcpiHwReadPort ((ACPI_IO_ADDRESS)
|
||||
(Address + 4), &Value, 32);
|
||||
(Address + 4), &ValueHi, 32);
|
||||
if (ACPI_FAILURE (Status))
|
||||
{
|
||||
return (Status);
|
||||
}
|
||||
*ReturnValue |= ((UINT64) Value << 32);
|
||||
}
|
||||
|
||||
/* Set the return value only if status is AE_OK */
|
||||
|
||||
*ReturnValue = (ValueLo | ((UINT64) ValueHi << 32));
|
||||
}
|
||||
|
||||
ACPI_DEBUG_PRINT ((ACPI_DB_IO,
|
||||
@ -207,7 +208,7 @@ AcpiRead (
|
||||
ACPI_FORMAT_UINT64 (Address),
|
||||
AcpiUtGetRegionName (Reg->SpaceId)));
|
||||
|
||||
return (Status);
|
||||
return (AE_OK);
|
||||
}
|
||||
|
||||
ACPI_EXPORT_SYMBOL (AcpiRead)
|
||||
|
@ -448,8 +448,8 @@ AcpiNsLookup (
|
||||
/* Current scope has no parent scope */
|
||||
|
||||
ACPI_ERROR ((AE_INFO,
|
||||
"ACPI path has too many parent prefixes (^) "
|
||||
"- reached beyond root node"));
|
||||
"%s: Path has too many parent prefixes (^) "
|
||||
"- reached beyond root node", Pathname));
|
||||
return_ACPI_STATUS (AE_NOT_FOUND);
|
||||
}
|
||||
}
|
||||
|
@ -69,6 +69,22 @@ AcpiNsDumpOneDevice (
|
||||
|
||||
|
||||
#if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER)
|
||||
|
||||
static ACPI_STATUS
|
||||
AcpiNsDumpOneObjectPath (
|
||||
ACPI_HANDLE ObjHandle,
|
||||
UINT32 Level,
|
||||
void *Context,
|
||||
void **ReturnValue);
|
||||
|
||||
static ACPI_STATUS
|
||||
AcpiNsGetMaxDepth (
|
||||
ACPI_HANDLE ObjHandle,
|
||||
UINT32 Level,
|
||||
void *Context,
|
||||
void **ReturnValue);
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: AcpiNsPrintPathname
|
||||
@ -695,6 +711,142 @@ AcpiNsDumpObjects (
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: AcpiNsDumpOneObjectPath, AcpiNsGetMaxDepth
|
||||
*
|
||||
* PARAMETERS: ObjHandle - Node to be dumped
|
||||
* Level - Nesting level of the handle
|
||||
* Context - Passed into WalkNamespace
|
||||
* ReturnValue - Not used
|
||||
*
|
||||
* RETURN: Status
|
||||
*
|
||||
* DESCRIPTION: Dump the full pathname to a namespace object. AcpNsGetMaxDepth
|
||||
* computes the maximum nesting depth in the namespace tree, in
|
||||
* order to simplify formatting in AcpiNsDumpOneObjectPath.
|
||||
* These procedures are UserFunctions called by AcpiNsWalkNamespace.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
static ACPI_STATUS
|
||||
AcpiNsDumpOneObjectPath (
|
||||
ACPI_HANDLE ObjHandle,
|
||||
UINT32 Level,
|
||||
void *Context,
|
||||
void **ReturnValue)
|
||||
{
|
||||
UINT32 MaxLevel = *((UINT32 *) Context);
|
||||
char *Pathname;
|
||||
ACPI_NAMESPACE_NODE *Node;
|
||||
int PathIndent;
|
||||
|
||||
|
||||
if (!ObjHandle)
|
||||
{
|
||||
return (AE_OK);
|
||||
}
|
||||
|
||||
Node = AcpiNsValidateHandle (ObjHandle);
|
||||
Pathname = AcpiNsGetExternalPathname (Node);
|
||||
|
||||
PathIndent = 1;
|
||||
if (Level <= MaxLevel)
|
||||
{
|
||||
PathIndent = MaxLevel - Level + 1;
|
||||
}
|
||||
|
||||
AcpiOsPrintf ("%2d%*s%-12s%*s",
|
||||
Level, Level, " ", AcpiUtGetTypeName (Node->Type),
|
||||
PathIndent, " ");
|
||||
|
||||
AcpiOsPrintf ("%s\n", &Pathname[1]);
|
||||
ACPI_FREE (Pathname);
|
||||
return (AE_OK);
|
||||
}
|
||||
|
||||
|
||||
static ACPI_STATUS
|
||||
AcpiNsGetMaxDepth (
|
||||
ACPI_HANDLE ObjHandle,
|
||||
UINT32 Level,
|
||||
void *Context,
|
||||
void **ReturnValue)
|
||||
{
|
||||
UINT32 *MaxLevel = (UINT32 *) Context;
|
||||
|
||||
|
||||
if (Level > *MaxLevel)
|
||||
{
|
||||
*MaxLevel = Level;
|
||||
}
|
||||
return (AE_OK);
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: AcpiNsDumpObjectPaths
|
||||
*
|
||||
* PARAMETERS: Type - Object type to be dumped
|
||||
* DisplayType - 0 or ACPI_DISPLAY_SUMMARY
|
||||
* MaxDepth - Maximum depth of dump. Use ACPI_UINT32_MAX
|
||||
* for an effectively unlimited depth.
|
||||
* OwnerId - Dump only objects owned by this ID. Use
|
||||
* ACPI_UINT32_MAX to match all owners.
|
||||
* StartHandle - Where in namespace to start/end search
|
||||
*
|
||||
* RETURN: None
|
||||
*
|
||||
* DESCRIPTION: Dump full object pathnames within the loaded namespace. Uses
|
||||
* AcpiNsWalkNamespace in conjunction with AcpiNsDumpOneObjectPath.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
void
|
||||
AcpiNsDumpObjectPaths (
|
||||
ACPI_OBJECT_TYPE Type,
|
||||
UINT8 DisplayType,
|
||||
UINT32 MaxDepth,
|
||||
ACPI_OWNER_ID OwnerId,
|
||||
ACPI_HANDLE StartHandle)
|
||||
{
|
||||
ACPI_STATUS Status;
|
||||
UINT32 MaxLevel = 0;
|
||||
|
||||
|
||||
ACPI_FUNCTION_ENTRY ();
|
||||
|
||||
|
||||
/*
|
||||
* Just lock the entire namespace for the duration of the dump.
|
||||
* We don't want any changes to the namespace during this time,
|
||||
* especially the temporary nodes since we are going to display
|
||||
* them also.
|
||||
*/
|
||||
Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
|
||||
if (ACPI_FAILURE (Status))
|
||||
{
|
||||
AcpiOsPrintf ("Could not acquire namespace mutex\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Get the max depth of the namespace tree, for formatting later */
|
||||
|
||||
(void) AcpiNsWalkNamespace (Type, StartHandle, MaxDepth,
|
||||
ACPI_NS_WALK_NO_UNLOCK | ACPI_NS_WALK_TEMP_NODES,
|
||||
AcpiNsGetMaxDepth, NULL, (void *) &MaxLevel, NULL);
|
||||
|
||||
/* Now dump the entire namespace */
|
||||
|
||||
(void) AcpiNsWalkNamespace (Type, StartHandle, MaxDepth,
|
||||
ACPI_NS_WALK_NO_UNLOCK | ACPI_NS_WALK_TEMP_NODES,
|
||||
AcpiNsDumpOneObjectPath, NULL, (void *) &MaxLevel, NULL);
|
||||
|
||||
(void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: AcpiNsDumpEntry
|
||||
|
@ -654,10 +654,19 @@ AcpiWalkNamespace (
|
||||
goto UnlockAndExit;
|
||||
}
|
||||
|
||||
/* Now we can validate the starting node */
|
||||
|
||||
if (!AcpiNsValidateHandle (StartObject))
|
||||
{
|
||||
Status = AE_BAD_PARAMETER;
|
||||
goto UnlockAndExit2;
|
||||
}
|
||||
|
||||
Status = AcpiNsWalkNamespace (Type, StartObject, MaxDepth,
|
||||
ACPI_NS_WALK_UNLOCK, DescendingCallback,
|
||||
AscendingCallback, Context, ReturnValue);
|
||||
|
||||
UnlockAndExit2:
|
||||
(void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
|
||||
|
||||
UnlockAndExit:
|
||||
|
@ -93,14 +93,9 @@ AcpiTbVerifyTable (
|
||||
}
|
||||
}
|
||||
|
||||
/* FACS is the odd table, has no standard ACPI header and no checksum */
|
||||
/* Always calculate checksum, ignore bad checksum if requested */
|
||||
|
||||
if (!ACPI_COMPARE_NAME (&TableDesc->Signature, ACPI_SIG_FACS))
|
||||
{
|
||||
/* Always calculate checksum, ignore bad checksum if requested */
|
||||
|
||||
Status = AcpiTbVerifyChecksum (TableDesc->Pointer, TableDesc->Length);
|
||||
}
|
||||
Status = AcpiTbVerifyChecksum (TableDesc->Pointer, TableDesc->Length);
|
||||
|
||||
return_ACPI_STATUS (Status);
|
||||
}
|
||||
|
@ -158,7 +158,7 @@ AcpiTbPrintTableHeader (
|
||||
Header->Signature, ACPI_CAST_PTR (void, Address),
|
||||
Header->Length));
|
||||
}
|
||||
else if (ACPI_COMPARE_NAME (Header->Signature, ACPI_SIG_RSDP))
|
||||
else if (ACPI_VALIDATE_RSDP_SIG (Header->Signature))
|
||||
{
|
||||
/* RSDP has no common fields */
|
||||
|
||||
@ -211,6 +211,17 @@ AcpiTbVerifyChecksum (
|
||||
UINT8 Checksum;
|
||||
|
||||
|
||||
/*
|
||||
* FACS/S3PT:
|
||||
* They are the odd tables, have no standard ACPI header and no checksum
|
||||
*/
|
||||
|
||||
if (ACPI_COMPARE_NAME (Table->Signature, ACPI_SIG_S3PT) ||
|
||||
ACPI_COMPARE_NAME (Table->Signature, ACPI_SIG_FACS))
|
||||
{
|
||||
return (AE_OK);
|
||||
}
|
||||
|
||||
/* Compute the checksum on the table */
|
||||
|
||||
Checksum = AcpiTbChecksum (ACPI_CAST_PTR (UINT8, Table), Length);
|
||||
|
@ -75,8 +75,7 @@ AcpiTbValidateRsdp (
|
||||
* Note: Sometimes there exists more than one RSDP in memory; the valid
|
||||
* RSDP has a valid checksum, all others have an invalid checksum.
|
||||
*/
|
||||
if (ACPI_STRNCMP ((char *) Rsdp->Signature, ACPI_SIG_RSDP,
|
||||
sizeof (ACPI_SIG_RSDP)-1) != 0)
|
||||
if (!ACPI_VALIDATE_RSDP_SIG (Rsdp->Signature))
|
||||
{
|
||||
/* Nope, BAD Signature */
|
||||
|
||||
|
@ -216,7 +216,7 @@ AcpiDebugPrint (
|
||||
* Display the module name, current line number, thread ID (if requested),
|
||||
* current procedure nesting level, and the current procedure name
|
||||
*/
|
||||
AcpiOsPrintf ("%8s-%04ld ", ModuleName, LineNumber);
|
||||
AcpiOsPrintf ("%9s-%04ld ", ModuleName, LineNumber);
|
||||
|
||||
if (ACPI_LV_THREADS & AcpiDbgLevel)
|
||||
{
|
||||
|
@ -274,7 +274,7 @@ AcpiUtInitGlobals (
|
||||
|
||||
#if (!ACPI_REDUCED_HARDWARE)
|
||||
|
||||
/* GPE support */
|
||||
/* GPE/SCI support */
|
||||
|
||||
AcpiGbl_AllGpesInitialized = FALSE;
|
||||
AcpiGbl_GpeXruptListHead = NULL;
|
||||
@ -283,6 +283,7 @@ AcpiUtInitGlobals (
|
||||
AcpiCurrentGpeCount = 0;
|
||||
|
||||
AcpiGbl_GlobalEventHandler = NULL;
|
||||
AcpiGbl_SciHandlerList = NULL;
|
||||
|
||||
#endif /* !ACPI_REDUCED_HARDWARE */
|
||||
|
||||
|
@ -159,6 +159,10 @@ AcpiDbGenerateGpe (
|
||||
char *GpeArg,
|
||||
char *BlockArg))
|
||||
|
||||
ACPI_HW_DEPENDENT_RETURN_VOID (
|
||||
void
|
||||
AcpiDbGenerateSci (
|
||||
void))
|
||||
|
||||
/*
|
||||
* dbconvert - miscellaneous conversion routines
|
||||
@ -233,6 +237,10 @@ AcpiDbDumpNamespace (
|
||||
char *StartArg,
|
||||
char *DepthArg);
|
||||
|
||||
void
|
||||
AcpiDbDumpNamespacePaths (
|
||||
void);
|
||||
|
||||
void
|
||||
AcpiDbDumpNamespaceByOwner (
|
||||
char *OwnerArg,
|
||||
|
@ -694,6 +694,9 @@ void
|
||||
AcpiDmUnresolvedWarning (
|
||||
UINT8 Type);
|
||||
|
||||
void
|
||||
AcpiDmGetExternalsFromFile (
|
||||
void);
|
||||
|
||||
/*
|
||||
* dmresrc
|
||||
|
@ -338,18 +338,18 @@ UINT32 ACPI_SYSTEM_XFACE
|
||||
AcpiEvGpeXruptHandler (
|
||||
void *Context);
|
||||
|
||||
UINT32
|
||||
AcpiEvSciDispatch (
|
||||
void);
|
||||
|
||||
UINT32
|
||||
AcpiEvInstallSciHandler (
|
||||
void);
|
||||
|
||||
ACPI_STATUS
|
||||
AcpiEvRemoveSciHandler (
|
||||
AcpiEvRemoveAllSciHandlers (
|
||||
void);
|
||||
|
||||
UINT32
|
||||
AcpiEvInitializeSCI (
|
||||
UINT32 ProgramSCI);
|
||||
|
||||
ACPI_HW_DEPENDENT_RETURN_VOID (
|
||||
void
|
||||
AcpiEvTerminate (
|
||||
|
@ -127,8 +127,9 @@ typedef struct acpi_exception_info
|
||||
#define AE_NO_HANDLER EXCEP_ENV (0x001A)
|
||||
#define AE_OWNER_ID_LIMIT EXCEP_ENV (0x001B)
|
||||
#define AE_NOT_CONFIGURED EXCEP_ENV (0x001C)
|
||||
#define AE_ACCESS EXCEP_ENV (0x001D)
|
||||
|
||||
#define AE_CODE_ENV_MAX 0x001C
|
||||
#define AE_CODE_ENV_MAX 0x001D
|
||||
|
||||
|
||||
/*
|
||||
@ -235,7 +236,7 @@ static const ACPI_EXCEPTION_INFO AcpiGbl_ExceptionNames_Env[] =
|
||||
EXCEP_TXT ("AE_NO_ACPI_TABLES", "ACPI tables could not be found"),
|
||||
EXCEP_TXT ("AE_NO_NAMESPACE", "A namespace has not been loaded"),
|
||||
EXCEP_TXT ("AE_NO_MEMORY", "Insufficient dynamic memory"),
|
||||
EXCEP_TXT ("AE_NOT_FOUND", "The name was not found in the namespace"),
|
||||
EXCEP_TXT ("AE_NOT_FOUND", "A requested entity is not found"),
|
||||
EXCEP_TXT ("AE_NOT_EXIST", "A required entity does not exist"),
|
||||
EXCEP_TXT ("AE_ALREADY_EXISTS", "An entity already exists"),
|
||||
EXCEP_TXT ("AE_TYPE", "The object type is incorrect"),
|
||||
@ -258,7 +259,8 @@ static const ACPI_EXCEPTION_INFO AcpiGbl_ExceptionNames_Env[] =
|
||||
EXCEP_TXT ("AE_SAME_HANDLER", "Attempt was made to install the same handler that is already installed"),
|
||||
EXCEP_TXT ("AE_NO_HANDLER", "A handler for the operation is not installed"),
|
||||
EXCEP_TXT ("AE_OWNER_ID_LIMIT", "There are no more Owner IDs available for ACPI tables or control methods"),
|
||||
EXCEP_TXT ("AE_NOT_CONFIGURED", "The interface is not part of the current subsystem configuration")
|
||||
EXCEP_TXT ("AE_NOT_CONFIGURED", "The interface is not part of the current subsystem configuration"),
|
||||
EXCEP_TXT ("AE_ACCESS", "Permission denied for the requested operation")
|
||||
};
|
||||
|
||||
static const ACPI_EXCEPTION_INFO AcpiGbl_ExceptionNames_Pgm[] =
|
||||
|
@ -274,6 +274,7 @@ ACPI_EXTERN ACPI_TABLE_HANDLER AcpiGbl_TableHandler;
|
||||
ACPI_EXTERN void *AcpiGbl_TableHandlerContext;
|
||||
ACPI_EXTERN ACPI_WALK_STATE *AcpiGbl_BreakpointWalk;
|
||||
ACPI_EXTERN ACPI_INTERFACE_HANDLER AcpiGbl_InterfaceHandler;
|
||||
ACPI_EXTERN ACPI_SCI_HANDLER_INFO *AcpiGbl_SciHandlerList;
|
||||
|
||||
/* Owner ID support */
|
||||
|
||||
@ -453,13 +454,6 @@ ACPI_EXTERN BOOLEAN AcpiGbl_DbOpt_tables;
|
||||
ACPI_EXTERN BOOLEAN AcpiGbl_DbOpt_stats;
|
||||
ACPI_EXTERN BOOLEAN AcpiGbl_DbOpt_ini_methods;
|
||||
ACPI_EXTERN BOOLEAN AcpiGbl_DbOpt_NoRegionSupport;
|
||||
|
||||
ACPI_EXTERN char *AcpiGbl_DbArgs[ACPI_DEBUGGER_MAX_ARGS];
|
||||
ACPI_EXTERN ACPI_OBJECT_TYPE AcpiGbl_DbArgTypes[ACPI_DEBUGGER_MAX_ARGS];
|
||||
ACPI_EXTERN char AcpiGbl_DbLineBuf[ACPI_DB_LINE_BUFFER_SIZE];
|
||||
ACPI_EXTERN char AcpiGbl_DbParsedBuf[ACPI_DB_LINE_BUFFER_SIZE];
|
||||
ACPI_EXTERN char AcpiGbl_DbScopeBuf[80];
|
||||
ACPI_EXTERN char AcpiGbl_DbDebugFilename[80];
|
||||
ACPI_EXTERN BOOLEAN AcpiGbl_DbOutputToFile;
|
||||
ACPI_EXTERN char *AcpiGbl_DbBuffer;
|
||||
ACPI_EXTERN char *AcpiGbl_DbFilename;
|
||||
@ -467,6 +461,16 @@ ACPI_EXTERN UINT32 AcpiGbl_DbDebugLevel;
|
||||
ACPI_EXTERN UINT32 AcpiGbl_DbConsoleDebugLevel;
|
||||
ACPI_EXTERN ACPI_NAMESPACE_NODE *AcpiGbl_DbScopeNode;
|
||||
|
||||
ACPI_EXTERN char *AcpiGbl_DbArgs[ACPI_DEBUGGER_MAX_ARGS];
|
||||
ACPI_EXTERN ACPI_OBJECT_TYPE AcpiGbl_DbArgTypes[ACPI_DEBUGGER_MAX_ARGS];
|
||||
|
||||
/* These buffers should all be the same size */
|
||||
|
||||
ACPI_EXTERN char AcpiGbl_DbLineBuf[ACPI_DB_LINE_BUFFER_SIZE];
|
||||
ACPI_EXTERN char AcpiGbl_DbParsedBuf[ACPI_DB_LINE_BUFFER_SIZE];
|
||||
ACPI_EXTERN char AcpiGbl_DbScopeBuf[ACPI_DB_LINE_BUFFER_SIZE];
|
||||
ACPI_EXTERN char AcpiGbl_DbDebugFilename[ACPI_DB_LINE_BUFFER_SIZE];
|
||||
|
||||
/*
|
||||
* Statistic globals
|
||||
*/
|
||||
|
@ -453,6 +453,16 @@ typedef struct acpi_simple_repair_info
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/* Dispatch info for each host-installed SCI handler */
|
||||
|
||||
typedef struct acpi_sci_handler_info
|
||||
{
|
||||
struct acpi_sci_handler_info *Next;
|
||||
ACPI_SCI_HANDLER Address; /* Address of handler */
|
||||
void *Context; /* Context to be passed to handler */
|
||||
|
||||
} ACPI_SCI_HANDLER_INFO;
|
||||
|
||||
/* Dispatch info for each GPE -- either a method or handler, cannot be both */
|
||||
|
||||
typedef struct acpi_gpe_handler_info
|
||||
@ -1217,7 +1227,8 @@ typedef struct acpi_external_list
|
||||
|
||||
/* Values for Flags field above */
|
||||
|
||||
#define ACPI_IPATH_ALLOCATED 0x01
|
||||
#define ACPI_IPATH_ALLOCATED 0x01
|
||||
#define ACPI_FROM_REFERENCE_FILE 0x02
|
||||
|
||||
|
||||
typedef struct acpi_external_file
|
||||
|
@ -272,6 +272,14 @@ AcpiNsDumpObjects (
|
||||
ACPI_OWNER_ID OwnerId,
|
||||
ACPI_HANDLE StartHandle);
|
||||
|
||||
void
|
||||
AcpiNsDumpObjectPaths (
|
||||
ACPI_OBJECT_TYPE Type,
|
||||
UINT8 DisplayType,
|
||||
UINT32 MaxDepth,
|
||||
ACPI_OWNER_ID OwnerId,
|
||||
ACPI_HANDLE StartHandle);
|
||||
|
||||
|
||||
/*
|
||||
* nseval - Namespace evaluation functions
|
||||
|
@ -404,6 +404,7 @@ ACPI_STATUS
|
||||
AcpiOsGetTableByIndex (
|
||||
UINT32 Index,
|
||||
ACPI_TABLE_HEADER **Table,
|
||||
UINT32 *Instance,
|
||||
ACPI_PHYSICAL_ADDRESS *Address);
|
||||
|
||||
ACPI_STATUS
|
||||
|
@ -47,7 +47,7 @@
|
||||
|
||||
/* Current ACPICA subsystem version in YYYYMMDD format */
|
||||
|
||||
#define ACPI_CA_VERSION 0x20130725
|
||||
#define ACPI_CA_VERSION 0x20130823
|
||||
|
||||
#include <contrib/dev/acpica/include/acconfig.h>
|
||||
#include <contrib/dev/acpica/include/actypes.h>
|
||||
@ -375,6 +375,17 @@ AcpiInstallInitializationHandler (
|
||||
ACPI_INIT_HANDLER Handler,
|
||||
UINT32 Function);
|
||||
|
||||
ACPI_HW_DEPENDENT_RETURN_STATUS (
|
||||
ACPI_STATUS
|
||||
AcpiInstallSciHandler (
|
||||
ACPI_SCI_HANDLER Address,
|
||||
void *Context))
|
||||
|
||||
ACPI_HW_DEPENDENT_RETURN_STATUS (
|
||||
ACPI_STATUS
|
||||
AcpiRemoveSciHandler (
|
||||
ACPI_SCI_HANDLER Address))
|
||||
|
||||
ACPI_HW_DEPENDENT_RETURN_STATUS (
|
||||
ACPI_STATUS
|
||||
AcpiInstallGlobalEventHandler (
|
||||
|
@ -488,6 +488,11 @@ typedef UINT64 ACPI_INTEGER;
|
||||
#define ACPI_MOVE_NAME(dest,src) (ACPI_STRNCPY (ACPI_CAST_PTR (char, (dest)), ACPI_CAST_PTR (char, (src)), ACPI_NAME_SIZE))
|
||||
#endif
|
||||
|
||||
/* Support for the special RSDP signature (8 characters) */
|
||||
|
||||
#define ACPI_VALIDATE_RSDP_SIG(a) (!ACPI_STRNCMP (ACPI_CAST_PTR (char, (a)), ACPI_SIG_RSDP, 8))
|
||||
#define ACPI_MAKE_RSDP_SIG(dest) (ACPI_MEMCPY (ACPI_CAST_PTR (char, (dest)), ACPI_SIG_RSDP, 8))
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
@ -1006,6 +1011,10 @@ typedef void
|
||||
* Various handlers and callback procedures
|
||||
*/
|
||||
typedef
|
||||
UINT32 (*ACPI_SCI_HANDLER) (
|
||||
void *Context);
|
||||
|
||||
typedef
|
||||
void (*ACPI_GBL_EVENT_HANDLER) (
|
||||
UINT32 EventType,
|
||||
ACPI_HANDLE Device,
|
||||
|
@ -1023,6 +1023,7 @@ AcpiOsReadPciConfiguration (
|
||||
UINT32 Width)
|
||||
{
|
||||
|
||||
*Value = 0;
|
||||
return (AE_OK);
|
||||
}
|
||||
|
||||
|
@ -119,7 +119,7 @@ static void krping_wait(struct krping_cb *cb, int state)
|
||||
int rc;
|
||||
mtx_lock(&cb->lock);
|
||||
while (cb->state < state) {
|
||||
rc = msleep(cb, &cb->lock, 0, "krping", 0);
|
||||
rc = msleep(cb, &cb->lock, PCATCH, "krping", 0);
|
||||
if (rc && rc != ERESTART) {
|
||||
cb->state = ERROR;
|
||||
break;
|
||||
@ -188,7 +188,12 @@ static int krping_cma_event_handler(struct rdma_cm_id *cma_id,
|
||||
|
||||
case RDMA_CM_EVENT_DEVICE_REMOVAL:
|
||||
DEBUG_LOG(PFX "cma detected device removal!!!!\n");
|
||||
break;
|
||||
cb->state = ERROR;
|
||||
wakeup(cb);
|
||||
mtx_unlock(&cb->lock);
|
||||
krping_wait(cb, CLEANUP);
|
||||
tsleep(cb, 0, "krping", 5000);
|
||||
return 0;
|
||||
|
||||
default:
|
||||
log(LOG_ERR, "oof bad type!\n");
|
||||
@ -603,6 +608,8 @@ static int krping_setup_qp(struct krping_cb *cb, struct rdma_cm_id *cm_id)
|
||||
}
|
||||
DEBUG_LOG(PFX "created pd %p\n", cb->pd);
|
||||
|
||||
strlcpy(cb->name, cb->pd->device->name, sizeof(cb->name));
|
||||
|
||||
cb->cq = ib_create_cq(cm_id->device, krping_cq_event_handler, NULL,
|
||||
cb, cb->txdepth * 2, 0);
|
||||
if (IS_ERR(cb->cq)) {
|
||||
@ -1164,7 +1171,7 @@ static void krping_wlat_test_server(struct krping_cb *cb)
|
||||
}
|
||||
|
||||
wlat_test(cb);
|
||||
|
||||
krping_wait(cb, ERROR);
|
||||
}
|
||||
|
||||
static void krping_bw_test_server(struct krping_cb *cb)
|
||||
@ -1776,6 +1783,12 @@ int krping_doit(char *cmd)
|
||||
else
|
||||
krping_run_client(cb);
|
||||
DEBUG_LOG(PFX "destroy cm_id %p\n", cb->cm_id);
|
||||
|
||||
mtx_lock(&cb->lock);
|
||||
cb->state = CLEANUP;
|
||||
wakeup(cb);
|
||||
mtx_unlock(&cb->lock);
|
||||
|
||||
rdma_destroy_id(cb->cm_id);
|
||||
out:
|
||||
mtx_lock(&krping_mutex);
|
||||
|
@ -37,7 +37,8 @@ enum test_state {
|
||||
RDMA_READ_COMPLETE,
|
||||
RDMA_WRITE_ADV,
|
||||
RDMA_WRITE_COMPLETE,
|
||||
ERROR
|
||||
ERROR,
|
||||
CLEANUP
|
||||
};
|
||||
|
||||
struct krping_rdma_info {
|
||||
@ -100,13 +101,15 @@ struct krping_cb {
|
||||
/* listener on service side. */
|
||||
struct rdma_cm_id *child_cm_id; /* connection on server side */
|
||||
TAILQ_ENTRY(krping_cb) list;
|
||||
|
||||
|
||||
int rlat; /* run read latency test */
|
||||
int wlat; /* run write latency test */
|
||||
int bw; /* run write bw test */
|
||||
int duplex; /* run write bw full duplex test */
|
||||
int poll; /* poll vs block in rlat */
|
||||
int txdepth;
|
||||
|
||||
char name[16];
|
||||
};
|
||||
|
||||
static __inline uint64_t
|
||||
|
@ -112,12 +112,11 @@ krping_read(struct cdev *dev, struct uio *uio, int ioflag)
|
||||
mtx_unlock(&krping_mutex);
|
||||
|
||||
while (!TAILQ_EMPTY(©_cbs)) {
|
||||
|
||||
cb = TAILQ_FIRST(©_cbs);
|
||||
TAILQ_REMOVE(©_cbs, cb, list);
|
||||
if (cb->pd) {
|
||||
uprintf("krping: %4d %10s %10u %10u %10u %10u %10u %10u %10u %10u\n",
|
||||
num++, cb->pd->device->name, cb->stats.send_bytes,
|
||||
num++, cb->name, cb->stats.send_bytes,
|
||||
cb->stats.send_msgs, cb->stats.recv_bytes,
|
||||
cb->stats.recv_msgs, cb->stats.write_bytes,
|
||||
cb->stats.write_msgs,
|
||||
|
@ -308,17 +308,16 @@ mfip_cam_rescan(struct mfi_softc *sc, uint32_t tid)
|
||||
return;
|
||||
}
|
||||
camsc->state = MFIP_STATE_RESCAN;
|
||||
mtx_unlock(&sc->mfi_io_lock);
|
||||
|
||||
ccb = xpt_alloc_ccb_nowait();
|
||||
if (ccb == NULL) {
|
||||
mtx_unlock(&sc->mfi_io_lock);
|
||||
device_printf(sc->mfi_dev,
|
||||
"Cannot allocate ccb for bus rescan.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
sim = camsc->sim;
|
||||
mtx_lock(&sc->mfi_io_lock);
|
||||
if (xpt_create_path(&ccb->ccb_h.path, NULL, cam_sim_path(sim),
|
||||
tid, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
|
||||
xpt_free_ccb(ccb);
|
||||
@ -327,11 +326,8 @@ mfip_cam_rescan(struct mfi_softc *sc, uint32_t tid)
|
||||
"Cannot create path for bus rescan.\n");
|
||||
return;
|
||||
}
|
||||
mtx_unlock(&sc->mfi_io_lock);
|
||||
|
||||
xpt_rescan(ccb);
|
||||
|
||||
mtx_lock(&sc->mfi_io_lock);
|
||||
camsc->state = MFIP_STATE_NONE;
|
||||
mtx_unlock(&sc->mfi_io_lock);
|
||||
}
|
||||
|
3305
sys/dev/vmware/vmxnet3/if_vmx.c
Normal file
3305
sys/dev/vmware/vmxnet3/if_vmx.c
Normal file
File diff suppressed because it is too large
Load Diff
316
sys/dev/vmware/vmxnet3/if_vmxreg.h
Normal file
316
sys/dev/vmware/vmxnet3/if_vmxreg.h
Normal file
@ -0,0 +1,316 @@
|
||||
/*-
|
||||
* Copyright (c) 2013 Tsubai Masanari
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*
|
||||
* $OpenBSD: src/sys/dev/pci/if_vmxreg.h,v 1.2 2013/06/12 01:07:33 uebayasi Exp $
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#ifndef _IF_VMXREG_H
|
||||
#define _IF_VMXREG_H
|
||||
|
||||
struct UPT1_TxStats {
|
||||
uint64_t TSO_packets;
|
||||
uint64_t TSO_bytes;
|
||||
uint64_t ucast_packets;
|
||||
uint64_t ucast_bytes;
|
||||
uint64_t mcast_packets;
|
||||
uint64_t mcast_bytes;
|
||||
uint64_t bcast_packets;
|
||||
uint64_t bcast_bytes;
|
||||
uint64_t error;
|
||||
uint64_t discard;
|
||||
} __packed;
|
||||
|
||||
struct UPT1_RxStats {
|
||||
uint64_t LRO_packets;
|
||||
uint64_t LRO_bytes;
|
||||
uint64_t ucast_packets;
|
||||
uint64_t ucast_bytes;
|
||||
uint64_t mcast_packets;
|
||||
uint64_t mcast_bytes;
|
||||
uint64_t bcast_packets;
|
||||
uint64_t bcast_bytes;
|
||||
uint64_t nobuffer;
|
||||
uint64_t error;
|
||||
} __packed;
|
||||
|
||||
/* Interrupt moderation levels */
|
||||
#define UPT1_IMOD_NONE 0 /* No moderation */
|
||||
#define UPT1_IMOD_HIGHEST 7 /* Least interrupts */
|
||||
#define UPT1_IMOD_ADAPTIVE 8 /* Adaptive interrupt moderation */
|
||||
|
||||
/* Hardware features */
|
||||
#define UPT1_F_CSUM 0x0001 /* Rx checksum verification */
|
||||
#define UPT1_F_RSS 0x0002 /* Receive side scaling */
|
||||
#define UPT1_F_VLAN 0x0004 /* VLAN tag stripping */
|
||||
#define UPT1_F_LRO 0x0008 /* Large receive offloading */
|
||||
|
||||
#define VMXNET3_BAR0_IMASK(irq) (0x000 + (irq) * 8) /* Interrupt mask */
|
||||
#define VMXNET3_BAR0_TXH(q) (0x600 + (q) * 8) /* Tx head */
|
||||
#define VMXNET3_BAR0_RXH1(q) (0x800 + (q) * 8) /* Ring1 Rx head */
|
||||
#define VMXNET3_BAR0_RXH2(q) (0xA00 + (q) * 8) /* Ring2 Rx head */
|
||||
#define VMXNET3_BAR1_VRRS 0x000 /* VMXNET3 revision report selection */
|
||||
#define VMXNET3_BAR1_UVRS 0x008 /* UPT version report selection */
|
||||
#define VMXNET3_BAR1_DSL 0x010 /* Driver shared address low */
|
||||
#define VMXNET3_BAR1_DSH 0x018 /* Driver shared address high */
|
||||
#define VMXNET3_BAR1_CMD 0x020 /* Command */
|
||||
#define VMXNET3_BAR1_MACL 0x028 /* MAC address low */
|
||||
#define VMXNET3_BAR1_MACH 0x030 /* MAC address high */
|
||||
#define VMXNET3_BAR1_INTR 0x038 /* Interrupt status */
|
||||
#define VMXNET3_BAR1_EVENT 0x040 /* Event status */
|
||||
|
||||
#define VMXNET3_CMD_ENABLE 0xCAFE0000 /* Enable VMXNET3 */
|
||||
#define VMXNET3_CMD_DISABLE 0xCAFE0001 /* Disable VMXNET3 */
|
||||
#define VMXNET3_CMD_RESET 0xCAFE0002 /* Reset device */
|
||||
#define VMXNET3_CMD_SET_RXMODE 0xCAFE0003 /* Set interface flags */
|
||||
#define VMXNET3_CMD_SET_FILTER 0xCAFE0004 /* Set address filter */
|
||||
#define VMXNET3_CMD_VLAN_FILTER 0xCAFE0005 /* Set VLAN filter */
|
||||
#define VMXNET3_CMD_GET_STATUS 0xF00D0000 /* Get queue errors */
|
||||
#define VMXNET3_CMD_GET_STATS 0xF00D0001 /* Get queue statistics */
|
||||
#define VMXNET3_CMD_GET_LINK 0xF00D0002 /* Get link status */
|
||||
#define VMXNET3_CMD_GET_MACL 0xF00D0003 /* Get MAC address low */
|
||||
#define VMXNET3_CMD_GET_MACH 0xF00D0004 /* Get MAC address high */
|
||||
#define VMXNET3_CMD_GET_INTRCFG 0xF00D0008 /* Get interrupt config */
|
||||
|
||||
#define VMXNET3_DMADESC_ALIGN 128
|
||||
#define VMXNET3_INIT_GEN 1
|
||||
|
||||
struct vmxnet3_txdesc {
|
||||
uint64_t addr;
|
||||
|
||||
uint32_t len:14;
|
||||
uint32_t gen:1; /* Generation */
|
||||
uint32_t pad1:1;
|
||||
uint32_t dtype:1; /* Descriptor type */
|
||||
uint32_t pad2:1;
|
||||
uint32_t offload_pos:14; /* Offloading position */
|
||||
|
||||
uint32_t hlen:10; /* Header len */
|
||||
uint32_t offload_mode:2; /* Offloading mode */
|
||||
uint32_t eop:1; /* End of packet */
|
||||
uint32_t compreq:1; /* Completion request */
|
||||
uint32_t pad3:1;
|
||||
uint32_t vtag_mode:1; /* VLAN tag insertion mode */
|
||||
uint32_t vtag:16; /* VLAN tag */
|
||||
} __packed;
|
||||
|
||||
/* Offloading modes */
|
||||
#define VMXNET3_OM_NONE 0
|
||||
#define VMXNET3_OM_CSUM 2
|
||||
#define VMXNET3_OM_TSO 3
|
||||
|
||||
struct vmxnet3_txcompdesc {
|
||||
uint32_t eop_idx:12; /* EOP index in Tx ring */
|
||||
uint32_t pad1:20;
|
||||
|
||||
uint32_t pad2:32;
|
||||
uint32_t pad3:32;
|
||||
|
||||
uint32_t rsvd:24;
|
||||
uint32_t type:7;
|
||||
uint32_t gen:1;
|
||||
} __packed;
|
||||
|
||||
struct vmxnet3_rxdesc {
|
||||
uint64_t addr;
|
||||
|
||||
uint32_t len:14;
|
||||
uint32_t btype:1; /* Buffer type */
|
||||
uint32_t dtype:1; /* Descriptor type */
|
||||
uint32_t rsvd:15;
|
||||
uint32_t gen:1;
|
||||
|
||||
uint32_t pad1:32;
|
||||
} __packed;
|
||||
|
||||
/* Buffer types */
|
||||
#define VMXNET3_BTYPE_HEAD 0 /* Head only */
|
||||
#define VMXNET3_BTYPE_BODY 1 /* Body only */
|
||||
|
||||
struct vmxnet3_rxcompdesc {
|
||||
uint32_t rxd_idx:12; /* Rx descriptor index */
|
||||
uint32_t pad1:2;
|
||||
uint32_t eop:1; /* End of packet */
|
||||
uint32_t sop:1; /* Start of packet */
|
||||
uint32_t qid:10;
|
||||
uint32_t rss_type:4;
|
||||
uint32_t no_csum:1; /* No checksum calculated */
|
||||
uint32_t pad2:1;
|
||||
|
||||
uint32_t rss_hash:32; /* RSS hash value */
|
||||
|
||||
uint32_t len:14;
|
||||
uint32_t error:1;
|
||||
uint32_t vlan:1; /* 802.1Q VLAN frame */
|
||||
uint32_t vtag:16; /* VLAN tag */
|
||||
|
||||
uint32_t csum:16;
|
||||
uint32_t csum_ok:1; /* TCP/UDP checksum ok */
|
||||
uint32_t udp:1;
|
||||
uint32_t tcp:1;
|
||||
uint32_t ipcsum_ok:1; /* IP checksum OK */
|
||||
uint32_t ipv6:1;
|
||||
uint32_t ipv4:1;
|
||||
uint32_t fragment:1; /* IP fragment */
|
||||
uint32_t fcs:1; /* Frame CRC correct */
|
||||
uint32_t type:7;
|
||||
uint32_t gen:1;
|
||||
} __packed;
|
||||
|
||||
#define VMXNET3_REV1_MAGIC 0XBABEFEE1
|
||||
|
||||
#define VMXNET3_GOS_UNKNOWN 0x00
|
||||
#define VMXNET3_GOS_LINUX 0x04
|
||||
#define VMXNET3_GOS_WINDOWS 0x08
|
||||
#define VMXNET3_GOS_SOLARIS 0x0C
|
||||
#define VMXNET3_GOS_FREEBSD 0x10
|
||||
#define VMXNET3_GOS_PXE 0x14
|
||||
|
||||
#define VMXNET3_GOS_32BIT 0x01
|
||||
#define VMXNET3_GOS_64BIT 0x02
|
||||
|
||||
#define VMXNET3_MAX_TX_QUEUES 8
|
||||
#define VMXNET3_MAX_RX_QUEUES 16
|
||||
#define VMXNET3_MAX_INTRS \
|
||||
(VMXNET3_MAX_TX_QUEUES + VMXNET3_MAX_RX_QUEUES + 1)
|
||||
|
||||
#define VMXNET3_ICTRL_DISABLE_ALL 0x01
|
||||
|
||||
#define VMXNET3_RXMODE_UCAST 0x01
|
||||
#define VMXNET3_RXMODE_MCAST 0x02
|
||||
#define VMXNET3_RXMODE_BCAST 0x04
|
||||
#define VMXNET3_RXMODE_ALLMULTI 0x08
|
||||
#define VMXNET3_RXMODE_PROMISC 0x10
|
||||
|
||||
#define VMXNET3_EVENT_RQERROR 0x01
|
||||
#define VMXNET3_EVENT_TQERROR 0x02
|
||||
#define VMXNET3_EVENT_LINK 0x04
|
||||
#define VMXNET3_EVENT_DIC 0x08
|
||||
#define VMXNET3_EVENT_DEBUG 0x10
|
||||
|
||||
#define VMXNET3_MIN_MTU 60
|
||||
#define VMXNET3_MAX_MTU 9000
|
||||
|
||||
/* Interrupt mask mode. */
|
||||
#define VMXNET3_IMM_AUTO 0x00
|
||||
#define VMXNET3_IMM_ACTIVE 0x01
|
||||
#define VMXNET3_IMM_LAZY 0x02
|
||||
|
||||
/* Interrupt type. */
|
||||
#define VMXNET3_IT_AUTO 0x00
|
||||
#define VMXNET3_IT_LEGACY 0x01
|
||||
#define VMXNET3_IT_MSI 0x02
|
||||
#define VMXNET3_IT_MSIX 0x03
|
||||
|
||||
struct vmxnet3_driver_shared {
|
||||
uint32_t magic;
|
||||
uint32_t pad1;
|
||||
|
||||
/* Misc. control */
|
||||
uint32_t version; /* Driver version */
|
||||
uint32_t guest; /* Guest OS */
|
||||
uint32_t vmxnet3_revision; /* Supported VMXNET3 revision */
|
||||
uint32_t upt_version; /* Supported UPT version */
|
||||
uint64_t upt_features;
|
||||
uint64_t driver_data;
|
||||
uint64_t queue_shared;
|
||||
uint32_t driver_data_len;
|
||||
uint32_t queue_shared_len;
|
||||
uint32_t mtu;
|
||||
uint16_t nrxsg_max;
|
||||
uint8_t ntxqueue;
|
||||
uint8_t nrxqueue;
|
||||
uint32_t reserved1[4];
|
||||
|
||||
/* Interrupt control */
|
||||
uint8_t automask;
|
||||
uint8_t nintr;
|
||||
uint8_t evintr;
|
||||
uint8_t modlevel[VMXNET3_MAX_INTRS];
|
||||
uint32_t ictrl;
|
||||
uint32_t reserved2[2];
|
||||
|
||||
/* Receive filter parameters */
|
||||
uint32_t rxmode;
|
||||
uint16_t mcast_tablelen;
|
||||
uint16_t pad2;
|
||||
uint64_t mcast_table;
|
||||
uint32_t vlan_filter[4096 / 32];
|
||||
|
||||
struct {
|
||||
uint32_t version;
|
||||
uint32_t len;
|
||||
uint64_t paddr;
|
||||
} rss, pm, plugin;
|
||||
|
||||
uint32_t event;
|
||||
uint32_t reserved3[5];
|
||||
} __packed;
|
||||
|
||||
struct vmxnet3_txq_shared {
|
||||
/* Control */
|
||||
uint32_t npending;
|
||||
uint32_t intr_threshold;
|
||||
uint64_t reserved1;
|
||||
|
||||
/* Config */
|
||||
uint64_t cmd_ring;
|
||||
uint64_t data_ring;
|
||||
uint64_t comp_ring;
|
||||
uint64_t driver_data;
|
||||
uint64_t reserved2;
|
||||
uint32_t cmd_ring_len;
|
||||
uint32_t data_ring_len;
|
||||
uint32_t comp_ring_len;
|
||||
uint32_t driver_data_len;
|
||||
uint8_t intr_idx;
|
||||
uint8_t pad1[7];
|
||||
|
||||
/* Queue status */
|
||||
uint8_t stopped;
|
||||
uint8_t pad2[3];
|
||||
uint32_t error;
|
||||
|
||||
struct UPT1_TxStats stats;
|
||||
|
||||
uint8_t pad3[88];
|
||||
} __packed;
|
||||
|
||||
struct vmxnet3_rxq_shared {
|
||||
uint8_t update_rxhead;
|
||||
uint8_t pad1[7];
|
||||
uint64_t reserved1;
|
||||
|
||||
uint64_t cmd_ring[2];
|
||||
uint64_t comp_ring;
|
||||
uint64_t driver_data;
|
||||
uint64_t reserved2;
|
||||
uint32_t cmd_ring_len[2];
|
||||
uint32_t comp_ring_len;
|
||||
uint32_t driver_data_len;
|
||||
uint8_t intr_idx;
|
||||
uint8_t pad2[7];
|
||||
|
||||
uint8_t stopped;
|
||||
uint8_t pad3[3];
|
||||
uint32_t error;
|
||||
|
||||
struct UPT1_RxStats stats;
|
||||
|
||||
uint8_t pad4[88];
|
||||
} __packed;
|
||||
|
||||
#endif /* _IF_VMXREG_H */
|
319
sys/dev/vmware/vmxnet3/if_vmxvar.h
Normal file
319
sys/dev/vmware/vmxnet3/if_vmxvar.h
Normal file
@ -0,0 +1,319 @@
|
||||
/*-
|
||||
* Copyright (c) 2013 Tsubai Masanari
|
||||
* Copyright (c) 2013 Bryan Venteicher <bryanv@FreeBSD.org>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#ifndef _IF_VMXVAR_H
|
||||
#define _IF_VMXVAR_H
|
||||
|
||||
struct vmxnet3_softc;
|
||||
|
||||
struct vmxnet3_dma_alloc {
|
||||
bus_addr_t dma_paddr;
|
||||
caddr_t dma_vaddr;
|
||||
bus_dma_tag_t dma_tag;
|
||||
bus_dmamap_t dma_map;
|
||||
bus_size_t dma_size;
|
||||
};
|
||||
|
||||
/*
|
||||
* The number of Rx/Tx queues this driver supports.
|
||||
*/
|
||||
#define VMXNET3_RX_QUEUES 1
|
||||
#define VMXNET3_TX_QUEUES 1
|
||||
|
||||
/*
|
||||
* The number of Rx rings in each Rx queue.
|
||||
*/
|
||||
#define VMXNET3_RXRINGS_PERQ 2
|
||||
|
||||
/*
|
||||
* The maximum number of descriptors in each Rx/Tx ring.
|
||||
*/
|
||||
#define VMXNET3_MAX_TX_NDESC 512
|
||||
#define VMXNET3_MAX_RX_NDESC 256
|
||||
#define VMXNET3_MAX_TX_NCOMPDESC VMXNET3_MAX_TX_NDESC
|
||||
#define VMXNET3_MAX_RX_NCOMPDESC \
|
||||
(VMXNET3_MAX_RX_NDESC * VMXNET3_RXRINGS_PERQ)
|
||||
|
||||
/*
|
||||
* The maximum number of Rx segments we accept. When LRO is enabled,
|
||||
* this allows us to receive the maximum sized frame with one MCLBYTES
|
||||
* cluster followed by 16 MJUMPAGESIZE clusters.
|
||||
*/
|
||||
#define VMXNET3_MAX_RX_SEGS 17
|
||||
|
||||
struct vmxnet3_txbuf {
|
||||
bus_dmamap_t vtxb_dmamap;
|
||||
struct mbuf *vtxb_m;
|
||||
};
|
||||
|
||||
struct vmxnet3_txring {
|
||||
struct vmxnet3_txbuf *vxtxr_txbuf;
|
||||
u_int vxtxr_head;
|
||||
u_int vxtxr_next;
|
||||
u_int vxtxr_ndesc;
|
||||
int vxtxr_gen;
|
||||
bus_dma_tag_t vxtxr_txtag;
|
||||
struct vmxnet3_txdesc *vxtxr_txd;
|
||||
struct vmxnet3_dma_alloc vxtxr_dma;
|
||||
};
|
||||
|
||||
static inline int
|
||||
VMXNET3_TXRING_AVAIL(struct vmxnet3_txring *txr)
|
||||
{
|
||||
int avail = txr->vxtxr_next - txr->vxtxr_head - 1;
|
||||
return (avail < 0 ? txr->vxtxr_ndesc + avail : avail);
|
||||
}
|
||||
|
||||
struct vmxnet3_rxbuf {
|
||||
bus_dmamap_t vrxb_dmamap;
|
||||
struct mbuf *vrxb_m;
|
||||
};
|
||||
|
||||
struct vmxnet3_rxring {
|
||||
struct vmxnet3_rxbuf *vxrxr_rxbuf;
|
||||
struct vmxnet3_rxdesc *vxrxr_rxd;
|
||||
u_int vxrxr_fill;
|
||||
u_int vxrxr_ndesc;
|
||||
int vxrxr_gen;
|
||||
int vxrxr_rid;
|
||||
bus_dma_tag_t vxrxr_rxtag;
|
||||
struct vmxnet3_dma_alloc vxrxr_dma;
|
||||
bus_dmamap_t vxrxr_spare_dmap;
|
||||
};
|
||||
|
||||
static inline void
|
||||
vmxnet3_rxr_increment_fill(struct vmxnet3_rxring *rxr)
|
||||
{
|
||||
|
||||
if (++rxr->vxrxr_fill == rxr->vxrxr_ndesc) {
|
||||
rxr->vxrxr_fill = 0;
|
||||
rxr->vxrxr_gen ^= 1;
|
||||
}
|
||||
}
|
||||
|
||||
struct vmxnet3_comp_ring {
|
||||
union {
|
||||
struct vmxnet3_txcompdesc *txcd;
|
||||
struct vmxnet3_rxcompdesc *rxcd;
|
||||
} vxcr_u;
|
||||
u_int vxcr_next;
|
||||
u_int vxcr_ndesc;
|
||||
int vxcr_gen;
|
||||
struct vmxnet3_dma_alloc vxcr_dma;
|
||||
};
|
||||
|
||||
struct vmxnet3_txq_stats {
|
||||
uint64_t vtxrs_full;
|
||||
uint64_t vtxrs_offload_failed;
|
||||
};
|
||||
|
||||
struct vmxnet3_txqueue {
|
||||
struct mtx vxtxq_mtx;
|
||||
struct vmxnet3_softc *vxtxq_sc;
|
||||
int vxtxq_id;
|
||||
int vxtxq_intr_idx;
|
||||
int vxtxq_watchdog;
|
||||
struct vmxnet3_txring vxtxq_cmd_ring;
|
||||
struct vmxnet3_comp_ring vxtxq_comp_ring;
|
||||
struct vmxnet3_txq_stats vxtxq_stats;
|
||||
struct vmxnet3_txq_shared *vxtxq_ts;
|
||||
struct sysctl_oid_list *vxtxq_sysctl;
|
||||
char vxtxq_name[16];
|
||||
};
|
||||
|
||||
#define VMXNET3_TXQ_LOCK(_txq) mtx_lock(&(_txq)->vxtxq_mtx)
|
||||
#define VMXNET3_TXQ_TRYLOCK(_txq) mtx_trylock(&(_txq)->vxtxq_mtx)
|
||||
#define VMXNET3_TXQ_UNLOCK(_txq) mtx_unlock(&(_txq)->vxtxq_mtx)
|
||||
#define VMXNET3_TXQ_LOCK_ASSERT(_txq) \
|
||||
mtx_assert(&(_txq)->vxtxq_mtx, MA_OWNED)
|
||||
#define VMXNET3_TXQ_LOCK_ASSERT_NOTOWNED(_txq) \
|
||||
mtx_assert(&(_txq)->vxtxq_mtx, MA_NOTOWNED)
|
||||
|
||||
struct vmxnet3_rxq_stats {
|
||||
|
||||
};
|
||||
|
||||
struct vmxnet3_rxqueue {
|
||||
struct mtx vxrxq_mtx;
|
||||
struct vmxnet3_softc *vxrxq_sc;
|
||||
int vxrxq_id;
|
||||
int vxrxq_intr_idx;
|
||||
struct vmxnet3_rxring vxrxq_cmd_ring[VMXNET3_RXRINGS_PERQ];
|
||||
struct vmxnet3_comp_ring vxrxq_comp_ring;
|
||||
struct vmxnet3_rxq_stats vxrxq_stats;
|
||||
struct vmxnet3_rxq_shared *vxrxq_rs;
|
||||
struct sysctl_oid_list *vxrxq_sysctl;
|
||||
char vxrxq_name[16];
|
||||
};
|
||||
|
||||
#define VMXNET3_RXQ_LOCK(_rxq) mtx_lock(&(_rxq)->vxrxq_mtx)
|
||||
#define VMXNET3_RXQ_UNLOCK(_rxq) mtx_unlock(&(_rxq)->vxrxq_mtx)
|
||||
#define VMXNET3_RXQ_LOCK_ASSERT(_rxq) \
|
||||
mtx_assert(&(_rxq)->vxrxq_mtx, MA_OWNED)
|
||||
#define VMXNET3_RXQ_LOCK_ASSERT_NOTOWNED(_rxq) \
|
||||
mtx_assert(&(_rxq)->vxrxq_mtx, MA_NOTOWNED)
|
||||
|
||||
struct vmxnet3_statistics {
|
||||
uint32_t vmst_collapsed;
|
||||
uint32_t vmst_mgetcl_failed;
|
||||
uint32_t vmst_mbuf_load_failed;
|
||||
|
||||
};
|
||||
|
||||
struct vmxnet3_interrupt {
|
||||
struct resource *vmxi_irq;
|
||||
int vmxi_rid;
|
||||
void *vmxi_handler;
|
||||
};
|
||||
|
||||
struct vmxnet3_softc {
|
||||
device_t vmx_dev;
|
||||
struct ifnet *vmx_ifp;
|
||||
struct vmxnet3_driver_shared *vmx_ds;
|
||||
uint32_t vmx_flags;
|
||||
#define VMXNET3_FLAG_NO_MSIX 0x0001
|
||||
|
||||
struct vmxnet3_rxqueue *vmx_rxq;
|
||||
struct vmxnet3_txqueue *vmx_txq;
|
||||
|
||||
struct resource *vmx_res0;
|
||||
bus_space_tag_t vmx_iot0;
|
||||
bus_space_handle_t vmx_ioh0;
|
||||
struct resource *vmx_res1;
|
||||
bus_space_tag_t vmx_iot1;
|
||||
bus_space_handle_t vmx_ioh1;
|
||||
struct resource *vmx_msix_res;
|
||||
|
||||
int vmx_link_active;
|
||||
int vmx_link_speed;
|
||||
int vmx_if_flags;
|
||||
int vmx_ntxqueues;
|
||||
int vmx_nrxqueues;
|
||||
int vmx_ntxdescs;
|
||||
int vmx_nrxdescs;
|
||||
int vmx_max_rxsegs;
|
||||
int vmx_rx_max_chain;
|
||||
|
||||
struct vmxnet3_statistics vmx_stats;
|
||||
|
||||
int vmx_intr_type;
|
||||
int vmx_intr_mask_mode;
|
||||
int vmx_event_intr_idx;
|
||||
int vmx_nintrs;
|
||||
struct vmxnet3_interrupt vmx_intrs[VMXNET3_MAX_INTRS];
|
||||
|
||||
struct mtx vmx_mtx;
|
||||
uint8_t *vmx_mcast;
|
||||
void *vmx_qs;
|
||||
struct callout vmx_tick;
|
||||
struct vmxnet3_dma_alloc vmx_ds_dma;
|
||||
struct vmxnet3_dma_alloc vmx_qs_dma;
|
||||
struct vmxnet3_dma_alloc vmx_mcast_dma;
|
||||
struct ifmedia vmx_media;
|
||||
eventhandler_tag vmx_vlan_attach;
|
||||
eventhandler_tag vmx_vlan_detach;
|
||||
uint8_t vmx_vlan_filter[4096/32];
|
||||
uint8_t vmx_lladdr[ETHER_ADDR_LEN];
|
||||
};
|
||||
|
||||
#define VMXNET3_CORE_LOCK_INIT(_sc, _name) \
|
||||
mtx_init(&(_sc)->vmx_mtx, _name, "VMXNET3 Lock", MTX_DEF)
|
||||
#define VMXNET3_CORE_LOCK_DESTROY(_sc) mtx_destroy(&(_sc)->vmx_mtx)
|
||||
#define VMXNET3_CORE_LOCK(_sc) mtx_lock(&(_sc)->vmx_mtx)
|
||||
#define VMXNET3_CORE_UNLOCK(_sc) mtx_unlock(&(_sc)->vmx_mtx)
|
||||
#define VMXNET3_CORE_LOCK_ASSERT(_sc) mtx_assert(&(_sc)->vmx_mtx, MA_OWNED)
|
||||
#define VMXNET3_CORE_LOCK_ASSERT_NOTOWNED(_sc) \
|
||||
mtx_assert(&(_sc)->vmx_mtx, MA_NOTOWNED)
|
||||
|
||||
/*
|
||||
* Our driver version we report to the hypervisor; we just keep
|
||||
* this value constant.
|
||||
*/
|
||||
#define VMXNET3_DRIVER_VERSION 0x00010000
|
||||
|
||||
/*
|
||||
* Convert the FreeBSD version in to something the hypervisor
|
||||
* understands. This is apparently what VMware's driver reports
|
||||
* so mimic it even though it probably is not required.
|
||||
*/
|
||||
#define VMXNET3_GUEST_OS_VERSION \
|
||||
(((__FreeBSD_version / 100000) << 14) | \
|
||||
(((__FreeBSD_version / 1000) % 100) << 6 ) | \
|
||||
(((__FreeBSD_version / 100) % 10) << 30) | \
|
||||
((__FreeBSD_version % 100) << 22))
|
||||
|
||||
/*
|
||||
* Max descriptors per Tx packet. We must limit the size of the
|
||||
* any TSO packets based on the number of segments.
|
||||
*/
|
||||
#define VMXNET3_TX_MAXSEGS 32
|
||||
#define VMXNET3_TSO_MAXSIZE 65550
|
||||
|
||||
/*
|
||||
* Maximum support Tx segments size. The length field in the
|
||||
* Tx descriptor is 14 bits.
|
||||
*/
|
||||
#define VMXNET3_TX_MAXSEGSIZE (1 << 14)
|
||||
|
||||
/*
|
||||
* Predetermined size of the multicast MACs filter table. If the
|
||||
* number of multicast addresses exceeds this size, then the
|
||||
* ALL_MULTI mode is use instead.
|
||||
*/
|
||||
#define VMXNET3_MULTICAST_MAX 32
|
||||
|
||||
/*
|
||||
* Our Tx watchdog timeout.
|
||||
*/
|
||||
#define VMXNET3_WATCHDOG_TIMEOUT 5
|
||||
|
||||
/*
|
||||
* IP protocols that we can perform Tx checksum offloading of.
|
||||
*/
|
||||
#define VMXNET3_CSUM_OFFLOAD (CSUM_TCP | CSUM_UDP)
|
||||
#define VMXNET3_CSUM_OFFLOAD_IPV6 (CSUM_TCP_IPV6 | CSUM_UDP_IPV6)
|
||||
|
||||
#define VMXNET3_CSUM_ALL_OFFLOAD \
|
||||
(VMXNET3_CSUM_OFFLOAD | VMXNET3_CSUM_OFFLOAD_IPV6 | CSUM_TSO)
|
||||
|
||||
/*
|
||||
* Compat macros to keep this driver compiling on old releases.
|
||||
*/
|
||||
|
||||
#if !defined(SYSCTL_ADD_UQUAD)
|
||||
#define SYSCTL_ADD_UQUAD SYSCTL_ADD_QUAD
|
||||
#endif
|
||||
|
||||
#if !defined(IFCAP_TXCSUM_IPV6)
|
||||
#define IFCAP_TXCSUM_IPV6 0
|
||||
#endif
|
||||
|
||||
#if !defined(IFCAP_RXCSUM_IPV6)
|
||||
#define IFCAP_RXCSUM_IPV6 0
|
||||
#endif
|
||||
|
||||
#if !defined(CSUM_TCP_IPV6)
|
||||
#define CSUM_TCP_IPV6 0
|
||||
#endif
|
||||
|
||||
#if !defined(CSUM_UDP_IPV6)
|
||||
#define CSUM_UDP_IPV6 0
|
||||
#endif
|
||||
|
||||
#endif /* _IF_VMXVAR_H */
|
@ -47,6 +47,8 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/limits.h>
|
||||
#include <sys/lock.h>
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/jail.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/systm.h>
|
||||
@ -138,6 +140,7 @@ tmpfs_mount(struct mount *mp)
|
||||
sizeof(struct tmpfs_dirent) + sizeof(struct tmpfs_node));
|
||||
struct tmpfs_mount *tmp;
|
||||
struct tmpfs_node *root;
|
||||
struct thread *td = curthread;
|
||||
int error;
|
||||
/* Size counters. */
|
||||
u_quad_t pages;
|
||||
@ -150,6 +153,9 @@ tmpfs_mount(struct mount *mp)
|
||||
|
||||
struct vattr va;
|
||||
|
||||
if (!prison_allow(td->td_ucred, PR_ALLOW_MOUNT_TMPFS))
|
||||
return (EPERM);
|
||||
|
||||
if (vfs_filteropt(mp->mnt_optnew, tmpfs_opts))
|
||||
return (EINVAL);
|
||||
|
||||
@ -420,4 +426,4 @@ struct vfsops tmpfs_vfsops = {
|
||||
.vfs_statfs = tmpfs_statfs,
|
||||
.vfs_fhtovp = tmpfs_fhtovp,
|
||||
};
|
||||
VFS_SET(tmpfs_vfsops, tmpfs, 0);
|
||||
VFS_SET(tmpfs_vfsops, tmpfs, VFCF_JAIL);
|
||||
|
@ -460,6 +460,12 @@ g_disk_dumpconf(struct sbuf *sb, const char *indent, struct g_geom *gp, struct g
|
||||
if (dp->d_getattr(bp) == 0)
|
||||
sbuf_printf(sb, "%s<lunid>%s</lunid>\n",
|
||||
indent, buf);
|
||||
bp->bio_attribute = "GEOM::lunname";
|
||||
bp->bio_length = DISK_IDENT_SIZE;
|
||||
bp->bio_data = buf;
|
||||
if (dp->d_getattr(bp) == 0)
|
||||
sbuf_printf(sb, "%s<lunname>%s</lunname>\n",
|
||||
indent, buf);
|
||||
g_destroy_bio(bp);
|
||||
g_free(buf);
|
||||
} else
|
||||
|
@ -206,6 +206,7 @@ static char *pr_allow_names[] = {
|
||||
"allow.mount.nullfs",
|
||||
"allow.mount.zfs",
|
||||
"allow.mount.procfs",
|
||||
"allow.mount.tmpfs",
|
||||
};
|
||||
const size_t pr_allow_names_size = sizeof(pr_allow_names);
|
||||
|
||||
@ -221,6 +222,7 @@ static char *pr_allow_nonames[] = {
|
||||
"allow.mount.nonullfs",
|
||||
"allow.mount.nozfs",
|
||||
"allow.mount.noprocfs",
|
||||
"allow.mount.notmpfs",
|
||||
};
|
||||
const size_t pr_allow_nonames_size = sizeof(pr_allow_nonames);
|
||||
|
||||
@ -4228,6 +4230,10 @@ SYSCTL_PROC(_security_jail, OID_AUTO, mount_procfs_allowed,
|
||||
CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE,
|
||||
NULL, PR_ALLOW_MOUNT_PROCFS, sysctl_jail_default_allow, "I",
|
||||
"Processes in jail can mount the procfs file system");
|
||||
SYSCTL_PROC(_security_jail, OID_AUTO, mount_tmpfs_allowed,
|
||||
CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE,
|
||||
NULL, PR_ALLOW_MOUNT_TMPFS, sysctl_jail_default_allow, "I",
|
||||
"Processes in jail can mount the tmpfs file system");
|
||||
SYSCTL_PROC(_security_jail, OID_AUTO, mount_zfs_allowed,
|
||||
CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE,
|
||||
NULL, PR_ALLOW_MOUNT_ZFS, sysctl_jail_default_allow, "I",
|
||||
@ -4380,6 +4386,8 @@ SYSCTL_JAIL_PARAM(_allow_mount, nullfs, CTLTYPE_INT | CTLFLAG_RW,
|
||||
"B", "Jail may mount the nullfs file system");
|
||||
SYSCTL_JAIL_PARAM(_allow_mount, procfs, CTLTYPE_INT | CTLFLAG_RW,
|
||||
"B", "Jail may mount the procfs file system");
|
||||
SYSCTL_JAIL_PARAM(_allow_mount, tmpfs, CTLTYPE_INT | CTLFLAG_RW,
|
||||
"B", "Jail may mount the tmpfs file system");
|
||||
SYSCTL_JAIL_PARAM(_allow_mount, zfs, CTLTYPE_INT | CTLFLAG_RW,
|
||||
"B", "Jail may mount the zfs file system");
|
||||
|
||||
|
@ -410,18 +410,14 @@ mb_ctor_mbuf(void *mem, int size, void *arg, int how)
|
||||
{
|
||||
struct mbuf *m;
|
||||
struct mb_args *args;
|
||||
#ifdef MAC
|
||||
int error;
|
||||
#endif
|
||||
int flags;
|
||||
short type;
|
||||
|
||||
#ifdef INVARIANTS
|
||||
trash_ctor(mem, size, arg, how);
|
||||
#endif
|
||||
m = (struct mbuf *)mem;
|
||||
args = (struct mb_args *)arg;
|
||||
flags = args->flags;
|
||||
type = args->type;
|
||||
|
||||
/*
|
||||
@ -431,32 +427,12 @@ mb_ctor_mbuf(void *mem, int size, void *arg, int how)
|
||||
if (type == MT_NOINIT)
|
||||
return (0);
|
||||
|
||||
m->m_next = NULL;
|
||||
m->m_nextpkt = NULL;
|
||||
m->m_len = 0;
|
||||
m->m_flags = flags;
|
||||
m->m_type = type;
|
||||
if (flags & M_PKTHDR) {
|
||||
m->m_data = m->m_pktdat;
|
||||
m->m_pkthdr.rcvif = NULL;
|
||||
m->m_pkthdr.header = NULL;
|
||||
m->m_pkthdr.len = 0;
|
||||
m->m_pkthdr.csum_flags = 0;
|
||||
m->m_pkthdr.csum_data = 0;
|
||||
m->m_pkthdr.tso_segsz = 0;
|
||||
m->m_pkthdr.ether_vtag = 0;
|
||||
m->m_pkthdr.flowid = 0;
|
||||
m->m_pkthdr.fibnum = 0;
|
||||
SLIST_INIT(&m->m_pkthdr.tags);
|
||||
#ifdef MAC
|
||||
/* If the label init fails, fail the alloc */
|
||||
error = mac_mbuf_init(m, how);
|
||||
if (error)
|
||||
return (error);
|
||||
#endif
|
||||
} else
|
||||
m->m_data = m->m_dat;
|
||||
return (0);
|
||||
m = (struct mbuf *)mem;
|
||||
flags = args->flags;
|
||||
|
||||
error = m_init(m, NULL, size, how, type, flags);
|
||||
|
||||
return (error);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -571,6 +547,7 @@ mb_ctor_clust(void *mem, int size, void *arg, int how)
|
||||
m->m_ext.ext_arg2 = NULL;
|
||||
m->m_ext.ext_size = size;
|
||||
m->m_ext.ext_type = type;
|
||||
m->m_ext.ext_flags = 0;
|
||||
m->m_ext.ref_cnt = refcnt;
|
||||
}
|
||||
|
||||
@ -656,34 +633,14 @@ mb_ctor_pack(void *mem, int size, void *arg, int how)
|
||||
#ifdef INVARIANTS
|
||||
trash_ctor(m->m_ext.ext_buf, MCLBYTES, arg, how);
|
||||
#endif
|
||||
m->m_next = NULL;
|
||||
m->m_nextpkt = NULL;
|
||||
m->m_data = m->m_ext.ext_buf;
|
||||
m->m_len = 0;
|
||||
m->m_flags = (flags | M_EXT);
|
||||
m->m_type = type;
|
||||
|
||||
if (flags & M_PKTHDR) {
|
||||
m->m_pkthdr.rcvif = NULL;
|
||||
m->m_pkthdr.len = 0;
|
||||
m->m_pkthdr.header = NULL;
|
||||
m->m_pkthdr.csum_flags = 0;
|
||||
m->m_pkthdr.csum_data = 0;
|
||||
m->m_pkthdr.tso_segsz = 0;
|
||||
m->m_pkthdr.ether_vtag = 0;
|
||||
m->m_pkthdr.flowid = 0;
|
||||
m->m_pkthdr.fibnum = 0;
|
||||
SLIST_INIT(&m->m_pkthdr.tags);
|
||||
#ifdef MAC
|
||||
/* If the label init fails, fail the alloc */
|
||||
error = mac_mbuf_init(m, how);
|
||||
if (error)
|
||||
return (error);
|
||||
#endif
|
||||
}
|
||||
error = m_init(m, NULL, size, how, type, flags);
|
||||
|
||||
/* m_ext is already initialized. */
|
||||
m->m_data = m->m_ext.ext_buf;
|
||||
m->m_flags = (flags | M_EXT);
|
||||
|
||||
return (0);
|
||||
return (error);
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -54,6 +54,36 @@ physio(struct cdev *dev, struct uio *uio, int ioflag)
|
||||
dev->si_iosize_max = DFLTPHYS;
|
||||
}
|
||||
|
||||
/*
|
||||
* If the driver does not want I/O to be split, that means that we
|
||||
* need to reject any requests that will not fit into one buffer.
|
||||
*/
|
||||
if ((dev->si_flags & SI_NOSPLIT) &&
|
||||
((uio->uio_resid > dev->si_iosize_max) ||
|
||||
(uio->uio_resid > MAXPHYS) ||
|
||||
(uio->uio_iovcnt > 1))) {
|
||||
/*
|
||||
* Tell the user why his I/O was rejected.
|
||||
*/
|
||||
if (uio->uio_resid > dev->si_iosize_max)
|
||||
printf("%s: request size %zd > si_iosize_max=%d, "
|
||||
"cannot split request\n", devtoname(dev),
|
||||
uio->uio_resid, dev->si_iosize_max);
|
||||
|
||||
if (uio->uio_resid > MAXPHYS)
|
||||
printf("%s: request size %zd > MAXPHYS=%d, "
|
||||
"cannot split request\n", devtoname(dev),
|
||||
uio->uio_resid, MAXPHYS);
|
||||
|
||||
if (uio->uio_iovcnt > 1)
|
||||
printf("%s: request vectors=%d > 1, "
|
||||
"cannot split request\n", devtoname(dev),
|
||||
uio->uio_iovcnt);
|
||||
|
||||
error = EFBIG;
|
||||
goto doerror;
|
||||
}
|
||||
|
||||
for (i = 0; i < uio->uio_iovcnt; i++) {
|
||||
while (uio->uio_iov[i].iov_len) {
|
||||
bp->b_flags = 0;
|
||||
@ -83,6 +113,17 @@ physio(struct cdev *dev, struct uio *uio, int ioflag)
|
||||
*/
|
||||
iolen = ((vm_offset_t) bp->b_data) & PAGE_MASK;
|
||||
if ((bp->b_bcount + iolen) > bp->b_kvasize) {
|
||||
/*
|
||||
* This device does not want I/O to be split.
|
||||
*/
|
||||
if (dev->si_flags & SI_NOSPLIT) {
|
||||
printf("%s: request ptr %#jx is not "
|
||||
"on a page boundary, cannot split "
|
||||
"request\n", devtoname(dev),
|
||||
(uintmax_t)bp->b_data);
|
||||
error = EFBIG;
|
||||
goto doerror;
|
||||
}
|
||||
bp->b_bcount = bp->b_kvasize;
|
||||
if (iolen != 0)
|
||||
bp->b_bcount -= PAGE_SIZE;
|
||||
|
@ -267,6 +267,7 @@ m_extadd(struct mbuf *mb, caddr_t buf, u_int size,
|
||||
mb->m_ext.ext_arg1 = arg1;
|
||||
mb->m_ext.ext_arg2 = arg2;
|
||||
mb->m_ext.ext_type = type;
|
||||
mb->m_ext.ext_flags = 0;
|
||||
|
||||
return (0);
|
||||
}
|
||||
@ -342,6 +343,7 @@ mb_free_ext(struct mbuf *m)
|
||||
m->m_ext.ref_cnt = NULL;
|
||||
m->m_ext.ext_size = 0;
|
||||
m->m_ext.ext_type = 0;
|
||||
m->m_ext.ext_flags = 0;
|
||||
m->m_flags &= ~M_EXT;
|
||||
uma_zfree(zone_mbuf, m);
|
||||
}
|
||||
@ -368,6 +370,7 @@ mb_dupcl(struct mbuf *n, struct mbuf *m)
|
||||
n->m_ext.ext_size = m->m_ext.ext_size;
|
||||
n->m_ext.ref_cnt = m->m_ext.ref_cnt;
|
||||
n->m_ext.ext_type = m->m_ext.ext_type;
|
||||
n->m_ext.ext_flags = m->m_ext.ext_flags;
|
||||
n->m_flags |= M_EXT;
|
||||
n->m_flags |= m->m_flags & M_RDONLY;
|
||||
}
|
||||
|
@ -342,6 +342,7 @@ SUBDIR= \
|
||||
${_viawd} \
|
||||
vkbd \
|
||||
${_vmm} \
|
||||
${_vmware} \
|
||||
${_vpo} \
|
||||
vr \
|
||||
vte \
|
||||
@ -368,6 +369,7 @@ SUBDIR= \
|
||||
|
||||
.if ${MACHINE_CPUARCH} == "i386" || ${MACHINE_CPUARCH} == "amd64"
|
||||
_filemon= filemon
|
||||
_vmware= vmware
|
||||
.endif
|
||||
|
||||
.if ${MACHINE_CPUARCH} != "powerpc" && ${MACHINE_CPUARCH} != "arm" && \
|
||||
|
@ -1,9 +1,9 @@
|
||||
# $FreeBSD$
|
||||
|
||||
SUBDIR= addr
|
||||
SUBDIR+= cma
|
||||
SUBDIR+= iwcm
|
||||
SUBDIR+= core
|
||||
#SUBDIR= addr
|
||||
#SUBDIR+= cma
|
||||
#SUBDIR+= iwcm
|
||||
#SUBDIR+= core
|
||||
SUBDIR+= krping
|
||||
|
||||
.include <bsd.subdir.mk>
|
||||
|
28
sys/modules/vmware/Makefile
Normal file
28
sys/modules/vmware/Makefile
Normal file
@ -0,0 +1,28 @@
|
||||
#
|
||||
# $FreeBSD$
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
# SUCH DAMAGE.
|
||||
#
|
||||
|
||||
SUBDIR= vmxnet3
|
||||
|
||||
.include <bsd.subdir.mk>
|
44
sys/modules/vmware/vmxnet3/Makefile
Normal file
44
sys/modules/vmware/vmxnet3/Makefile
Normal file
@ -0,0 +1,44 @@
|
||||
#
|
||||
# $FreeBSD$
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
# SUCH DAMAGE.
|
||||
#
|
||||
|
||||
.PATH: ${.CURDIR}/../../../dev/vmware/vmxnet3
|
||||
|
||||
KMOD= if_vmx
|
||||
SRCS= if_vmx.c
|
||||
SRCS+= bus_if.h device_if.h pci_if.h opt_inet.h opt_inet6.h
|
||||
|
||||
.if !defined(KERNBUILDDIR)
|
||||
.if ${MK_INET_SUPPORT} != "no"
|
||||
opt_inet.h:
|
||||
@echo "#define INET 1" > ${.TARGET}
|
||||
.endif
|
||||
|
||||
.if ${MK_INET6_SUPPORT} != "no"
|
||||
opt_inet6.h:
|
||||
@echo "#define INET6 1" > ${.TARGET}
|
||||
.endif
|
||||
.endif
|
||||
|
||||
.include <bsd.kmod.mk>
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user