Merge ^/head r283596 through r283770.

This commit is contained in:
dim 2015-05-30 15:45:39 +00:00
commit dce6917655
177 changed files with 5334 additions and 1432 deletions

View File

@ -38,7 +38,7 @@
# xargs -n1 | sort | uniq -d;
# done
# 20150529: new clang import which bumps version from 3.6.1 to 3.7.0.
# 2015mmdd: new clang import which bumps version from 3.6.1 to 3.7.0.
OLD_FILES+=usr/lib/clang/3.6.1/include/__stddef_max_align_t.h
OLD_FILES+=usr/lib/clang/3.6.1/include/__wmmintrin_aes.h
OLD_FILES+=usr/lib/clang/3.6.1/include/__wmmintrin_pclmul.h
@ -99,6 +99,10 @@ OLD_FILES+=usr/lib/clang/3.6.1/lib/freebsd/libclang_rt.ubsan_cxx-x86_64.a
OLD_DIRS+=usr/lib/clang/3.6.1/lib/freebsd
OLD_DIRS+=usr/lib/clang/3.6.1/lib
OLD_DIRS+=usr/lib/clang/3.6.1
# 20150528: PCI IOV device driver methods moved to a separate kobj interface.
OLD_FILES+=usr/share/man/man9/PCI_ADD_VF.9
OLD_FILES+=usr/share/man/man9/PCI_INIT_IOV.9
OLD_FILES+=usr/share/man/man9/PCI_UNINIT_IOV.9
# 20150525: new clang import which bumps version from 3.6.0 to 3.6.1.
OLD_FILES+=usr/lib/clang/3.6.0/include/__stddef_max_align_t.h
OLD_FILES+=usr/lib/clang/3.6.0/include/__wmmintrin_aes.h

View File

@ -29,7 +29,7 @@
.\" @(#)ps.1 8.3 (Berkeley) 4/18/94
.\" $FreeBSD$
.\"
.Dd May 22, 2015
.Dd May 27, 2015
.Dt PS 1
.Os
.Sh NAME
@ -350,6 +350,9 @@ the include file
.In sys/proc.h :
.Bl -column P2_INHERIT_PROTECTED 0x00000001
.It Dv "P2_INHERIT_PROTECTED" Ta No "0x00000001" Ta "New children get P_PROTECTED"
.It Dv "P2_NOTRACE" Ta No "0x00000002" Ta "No ptrace(2) attach or coredumps"
.It Dv "P2_NOTRACE_EXEC" Ta No "0x00000004" Ta "Keep P2_NOPTRACE on exec(2)"
.It Dv "P2_AST_SU" Ta No "0x00000008" Ta "Handles SU ast for kthreads"
.El
.It Cm label
The MAC label of the process.

View File

@ -23,7 +23,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: _elftc.h 3175 2015-03-27 17:21:24Z emaste $
* $Id: _elftc.h 3209 2015-05-17 13:40:46Z kaiwang27 $
*/
/**
@ -342,12 +342,13 @@ struct name { \
#if defined(__GLIBC__) || defined(__linux__)
#ifndef _GNU_SOURCE
/*
* GLIBC based systems have a global 'char *' pointer referencing
* the executable's name.
*/
extern const char *program_invocation_short_name;
#endif /* !_GNU_SOURCE */
#define ELFTC_GETPROGNAME() program_invocation_short_name

View File

@ -23,7 +23,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: elfdefinitions.h 3178 2015-03-30 18:29:13Z emaste $
* $Id: elfdefinitions.h 3198 2015-05-14 18:36:19Z emaste $
*/
/*
@ -565,6 +565,7 @@ _ELF_DEFINE_EM(EM_SPARC, 2, "SPARC") \
_ELF_DEFINE_EM(EM_386, 3, "Intel 80386") \
_ELF_DEFINE_EM(EM_68K, 4, "Motorola 68000") \
_ELF_DEFINE_EM(EM_88K, 5, "Motorola 88000") \
_ELF_DEFINE_EM(EM_IAMCU, 6, "Intel MCU") \
_ELF_DEFINE_EM(EM_860, 7, "Intel 80860") \
_ELF_DEFINE_EM(EM_MIPS, 8, "MIPS I Architecture") \
_ELF_DEFINE_EM(EM_S370, 9, "IBM System/370 Processor") \

View File

@ -23,7 +23,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: elfcopy.h 3173 2015-03-27 16:46:13Z emaste $
* $Id: elfcopy.h 3221 2015-05-24 23:42:43Z kaiwang27 $
*/
#include <sys/queue.h>
@ -237,6 +237,7 @@ struct elfcopy {
uint64_t *secndx; /* section index map. */
uint64_t *symndx; /* symbol index map. */
unsigned char *v_rel; /* symbols needed by relocation. */
unsigned char *v_grp; /* symbols refered by section group. */
unsigned char *v_secsym; /* sections with section symbol. */
STAILQ_HEAD(, segment) v_seg; /* list of segments. */
STAILQ_HEAD(, sec_action) v_sac;/* list of section operations. */

View File

@ -39,7 +39,7 @@
#include "elfcopy.h"
ELFTC_VCSID("$Id: main.c 3174 2015-03-27 17:13:41Z emaste $");
ELFTC_VCSID("$Id: main.c 3216 2015-05-23 21:16:36Z kaiwang27 $");
enum options
{
@ -404,8 +404,19 @@ create_elf(struct elfcopy *ecp)
* Insert SHDR table into the internal section list as a "pseudo"
* section, so later it will get sorted and resynced just as "normal"
* sections.
*
* Under FreeBSD, Binutils objcopy always put the section header
* at the end of all the sections. We want to do the same here.
*
* However, note that the behaviour is still different with Binutils:
* elfcopy checks the FreeBSD OSABI tag to tell whether it needs to
* move the section headers, while Binutils is probably configured
* this way when it's compiled on FreeBSD.
*/
shtab = insert_shtab(ecp, 0);
if (oeh.e_ident[EI_OSABI] == ELFOSABI_FREEBSD)
shtab = insert_shtab(ecp, 1);
else
shtab = insert_shtab(ecp, 0);
/*
* Resync section offsets in the output object. This is needed
@ -485,6 +496,11 @@ free_elf(struct elfcopy *ecp)
free(sec);
}
}
if (ecp->secndx != NULL) {
free(ecp->secndx);
ecp->secndx = NULL;
}
}
/* Create a temporary file. */

View File

@ -34,7 +34,7 @@
#include "elfcopy.h"
ELFTC_VCSID("$Id: sections.c 3185 2015-04-11 08:56:34Z kaiwang27 $");
ELFTC_VCSID("$Id: sections.c 3220 2015-05-24 23:42:39Z kaiwang27 $");
static void add_gnu_debuglink(struct elfcopy *ecp);
static uint32_t calc_crc32(const char *p, size_t len, uint32_t crc);
@ -56,6 +56,7 @@ static void print_data(const char *d, size_t sz);
static void print_section(struct section *s);
static void *read_section(struct section *s, size_t *size);
static void update_reloc(struct elfcopy *ecp, struct section *s);
static void update_section_group(struct elfcopy *ecp, struct section *s);
int
is_remove_section(struct elfcopy *ecp, const char *name)
@ -552,6 +553,14 @@ copy_content(struct elfcopy *ecp)
(s->type == SHT_REL || s->type == SHT_RELA))
filter_reloc(ecp, s);
/*
* The section indices in the SHT_GROUP section needs
* to be updated since we might have stripped some
* sections and changed section numbering.
*/
if (s->type == SHT_GROUP)
update_section_group(ecp, s);
if (is_modify_section(ecp, s->name))
modify_section(ecp, s);
@ -571,6 +580,71 @@ copy_content(struct elfcopy *ecp)
}
}
/*
* Update section group section. The section indices in the SHT_GROUP
* section need update after section numbering changed.
*/
static void
update_section_group(struct elfcopy *ecp, struct section *s)
{
GElf_Shdr ish;
Elf_Data *id;
uint32_t *ws, *wd;
uint64_t n;
size_t ishnum;
int i, j;
if (!elf_getshnum(ecp->ein, &ishnum))
errx(EXIT_FAILURE, "elf_getshnum failed: %s",
elf_errmsg(-1));
if (gelf_getshdr(s->is, &ish) == NULL)
errx(EXIT_FAILURE, "gelf_getehdr() failed: %s",
elf_errmsg(-1));
if ((id = elf_getdata(s->is, NULL)) == NULL)
errx(EXIT_FAILURE, "elf_getdata() failed: %s",
elf_errmsg(-1));
if (ish.sh_size == 0)
return;
if (ish.sh_entsize == 0)
ish.sh_entsize = 4;
ws = id->d_buf;
/* We only support COMDAT section. */
#ifndef GRP_COMDAT
#define GRP_COMDAT 0x1
#endif
if ((*ws & GRP_COMDAT) == 0)
return;
if ((s->buf = malloc(ish.sh_size)) == NULL)
err(EXIT_FAILURE, "malloc failed");
s->sz = ish.sh_size;
wd = s->buf;
/* Copy the flag word as-is. */
*wd = *ws;
/* Update the section indices. */
n = ish.sh_size / ish.sh_entsize;
for(i = 1, j = 1; (uint64_t)i < n; i++) {
if (ws[i] != SHN_UNDEF && ws[i] < ishnum &&
ecp->secndx[ws[i]] != 0)
wd[j++] = ecp->secndx[ws[i]];
else
s->sz -= 4;
}
s->nocopy = 1;
}
/*
* Filter relocation entries, only keep those entries whose
* symbol is in the keep list.
@ -1028,8 +1102,11 @@ copy_shdr(struct elfcopy *ecp, struct section *s, const char *name, int copy,
osh.sh_flags |= SHF_WRITE;
if (sec_flags & SF_CODE)
osh.sh_flags |= SHF_EXECINSTR;
} else
} else {
osh.sh_flags = ish.sh_flags;
if (ish.sh_type == SHT_REL || ish.sh_type == SHT_RELA)
osh.sh_flags |= SHF_INFO_LINK;
}
}
if (name == NULL)

View File

@ -33,7 +33,7 @@
#include "elfcopy.h"
ELFTC_VCSID("$Id: symbols.c 3191 2015-05-04 17:07:01Z jkoshy $");
ELFTC_VCSID("$Id: symbols.c 3222 2015-05-24 23:47:23Z kaiwang27 $");
/* Symbol table buffer structure. */
struct symbuf {
@ -77,7 +77,8 @@ static int is_weak_symbol(unsigned char st_info);
static int lookup_exact_string(hash_head *hash, const char *buf,
const char *s);
static int generate_symbols(struct elfcopy *ecp);
static void mark_symbols(struct elfcopy *ecp, size_t sc);
static void mark_reloc_symbols(struct elfcopy *ecp, size_t sc);
static void mark_section_group_symbols(struct elfcopy *ecp, size_t sc);
static int match_wildcard(const char *name, const char *pattern);
uint32_t str_hash(const char *s);
@ -160,6 +161,10 @@ is_needed_symbol(struct elfcopy *ecp, int i, GElf_Sym *s)
if (BIT_ISSET(ecp->v_rel, i))
return (1);
/* Symbols refered by COMDAT sections are needed. */
if (BIT_ISSET(ecp->v_grp, i))
return (1);
/*
* For relocatable files (.o files), global and weak symbols
* are needed.
@ -207,7 +212,10 @@ is_remove_symbol(struct elfcopy *ecp, size_t sc, int i, GElf_Sym *s,
return (1);
if (ecp->v_rel == NULL)
mark_symbols(ecp, sc);
mark_reloc_symbols(ecp, sc);
if (ecp->v_grp == NULL)
mark_section_group_symbols(ecp, sc);
if (is_needed_symbol(ecp, i, s))
return (0);
@ -233,7 +241,7 @@ is_remove_symbol(struct elfcopy *ecp, size_t sc, int i, GElf_Sym *s,
* Mark symbols refered by relocation entries.
*/
static void
mark_symbols(struct elfcopy *ecp, size_t sc)
mark_reloc_symbols(struct elfcopy *ecp, size_t sc)
{
const char *name;
Elf_Data *d;
@ -311,6 +319,49 @@ mark_symbols(struct elfcopy *ecp, size_t sc)
elf_errmsg(elferr));
}
static void
mark_section_group_symbols(struct elfcopy *ecp, size_t sc)
{
const char *name;
Elf_Scn *s;
GElf_Shdr sh;
size_t indx;
int elferr;
ecp->v_grp = calloc((sc + 7) / 8, 1);
if (ecp->v_grp == NULL)
err(EXIT_FAILURE, "calloc failed");
if (elf_getshstrndx(ecp->ein, &indx) == 0)
errx(EXIT_FAILURE, "elf_getshstrndx failed: %s",
elf_errmsg(-1));
s = NULL;
while ((s = elf_nextscn(ecp->ein, s)) != NULL) {
if (gelf_getshdr(s, &sh) != &sh)
errx(EXIT_FAILURE, "elf_getshdr failed: %s",
elf_errmsg(-1));
if (sh.sh_type != SHT_GROUP)
continue;
if ((name = elf_strptr(ecp->ein, indx, sh.sh_name)) == NULL)
errx(EXIT_FAILURE, "elf_strptr failed: %s",
elf_errmsg(-1));
if (is_remove_section(ecp, name))
continue;
if (sh.sh_info > 0 && sh.sh_info < sc)
BIT_SET(ecp->v_grp, sh.sh_info);
else if (sh.sh_info != 0)
warnx("invalid symbox index");
}
elferr = elf_errno();
if (elferr != 0)
errx(EXIT_FAILURE, "elf_nextscn failed: %s",
elf_errmsg(elferr));
}
static int
generate_symbols(struct elfcopy *ecp)
{
@ -351,6 +402,8 @@ generate_symbols(struct elfcopy *ecp)
ecp->symtab->buf = sy_buf;
ecp->strtab->buf = st_buf;
gsym = NULL;
/*
* Create bit vector v_secsym, which is used to mark sections
* that already have corresponding STT_SECTION symbols.
@ -384,7 +437,7 @@ generate_symbols(struct elfcopy *ecp)
/* Symbol table should exist if this function is called. */
if (symndx == 0) {
warnx("can't find .strtab section");
return (0);
goto clean;
}
/* Locate .symtab of input object. */
@ -413,7 +466,6 @@ generate_symbols(struct elfcopy *ecp)
* output object, it is used by update_reloc() later to update
* relocation information.
*/
gsym = NULL;
sc = ish.sh_size / ish.sh_entsize;
if (sc > 0) {
ecp->symndx = calloc(sc, sizeof(*ecp->symndx));
@ -427,7 +479,7 @@ generate_symbols(struct elfcopy *ecp)
if (elferr != 0)
errx(EXIT_FAILURE, "elf_getdata failed: %s",
elf_errmsg(elferr));
return (0);
goto clean;
}
} else
return (0);
@ -523,7 +575,7 @@ generate_symbols(struct elfcopy *ecp)
* check if that only local symbol is the reserved symbol.
*/
if (sy_buf->nls <= 1 && sy_buf->ngs == 0)
return (0);
goto clean;
/*
* Create STT_SECTION symbols for sections that do not already
@ -550,6 +602,7 @@ generate_symbols(struct elfcopy *ecp)
sym.st_value = s->vma;
sym.st_size = 0;
sym.st_info = GELF_ST_INFO(STB_LOCAL, STT_SECTION);
sym.st_other = STV_DEFAULT;
/*
* Don't let add_to_symtab() touch sym.st_shndx.
* In this case, we know the index already.
@ -583,6 +636,12 @@ generate_symbols(struct elfcopy *ecp)
}
return (1);
clean:
free(gsym);
free_symtab(ecp);
return (0);
}
void
@ -624,7 +683,9 @@ create_symtab(struct elfcopy *ecp)
if (((ecp->flags & SYMTAB_INTACT) == 0) && !generate_symbols(ecp)) {
TAILQ_REMOVE(&ecp->v_sec, ecp->symtab, sec_list);
TAILQ_REMOVE(&ecp->v_sec, ecp->strtab, sec_list);
free(ecp->symtab->buf);
free(ecp->symtab);
free(ecp->strtab->buf);
free(ecp->strtab);
ecp->symtab = NULL;
ecp->strtab = NULL;
@ -697,6 +758,23 @@ free_symtab(struct elfcopy *ecp)
}
}
}
if (ecp->symndx != NULL) {
free(ecp->symndx);
ecp->symndx = NULL;
}
if (ecp->v_rel != NULL) {
free(ecp->v_rel);
ecp->v_rel = NULL;
}
if (ecp->v_grp != NULL) {
free(ecp->v_grp);
ecp->v_grp = NULL;
}
if (ecp->v_secsym != NULL) {
free(ecp->v_secsym);
ecp->v_secsym = NULL;
}
}
void

View File

@ -26,7 +26,7 @@
#include "_libdwarf.h"
ELFTC_VCSID("$Id: libdwarf_reloc.c 3149 2015-02-15 19:00:06Z emaste $");
ELFTC_VCSID("$Id: libdwarf_reloc.c 3198 2015-05-14 18:36:19Z emaste $");
Dwarf_Unsigned
_dwarf_get_reloc_type(Dwarf_P_Debug dbg, int is64)
@ -75,6 +75,7 @@ _dwarf_get_reloc_size(Dwarf_Debug dbg, Dwarf_Unsigned rel_type)
return (4);
break;
case EM_386:
case EM_IAMCU:
if (rel_type == R_386_32)
return (4);
break;

View File

@ -36,7 +36,7 @@
#include "_libelftc.h"
ELFTC_VCSID("$Id: libelftc_dem_gnu3.c 3194 2015-05-05 17:55:16Z emaste $");
ELFTC_VCSID("$Id: libelftc_dem_gnu3.c 3212 2015-05-17 13:40:55Z kaiwang27 $");
/**
* @file cpp_demangle.c
@ -50,7 +50,7 @@ ELFTC_VCSID("$Id: libelftc_dem_gnu3.c 3194 2015-05-05 17:55:16Z emaste $");
enum type_qualifier {
TYPE_PTR, TYPE_REF, TYPE_CMX, TYPE_IMG, TYPE_EXT, TYPE_RST, TYPE_VAT,
TYPE_CST
TYPE_CST, TYPE_VEC
};
struct vector_type_qualifier {
@ -84,6 +84,7 @@ struct cpp_demangle_data {
int func_type;
const char *cur; /* current mangled name ptr */
const char *last_sname; /* last source name */
int push_head;
};
#define CPP_DEMANGLE_TRY_LIMIT 128
@ -112,6 +113,8 @@ static int cpp_demangle_read_array(struct cpp_demangle_data *);
static int cpp_demangle_read_encoding(struct cpp_demangle_data *);
static int cpp_demangle_read_expr_primary(struct cpp_demangle_data *);
static int cpp_demangle_read_expression(struct cpp_demangle_data *);
static int cpp_demangle_read_expression_flat(struct cpp_demangle_data *,
char **);
static int cpp_demangle_read_expression_binary(struct cpp_demangle_data *,
const char *, size_t);
static int cpp_demangle_read_expression_unary(struct cpp_demangle_data *,
@ -123,8 +126,12 @@ static int cpp_demangle_read_function(struct cpp_demangle_data *, int *,
static int cpp_demangle_local_source_name(struct cpp_demangle_data *ddata);
static int cpp_demangle_read_local_name(struct cpp_demangle_data *);
static int cpp_demangle_read_name(struct cpp_demangle_data *);
static int cpp_demangle_read_name_flat(struct cpp_demangle_data *,
char**);
static int cpp_demangle_read_nested_name(struct cpp_demangle_data *);
static int cpp_demangle_read_number(struct cpp_demangle_data *, long *);
static int cpp_demangle_read_number_as_string(struct cpp_demangle_data *,
char **);
static int cpp_demangle_read_nv_offset(struct cpp_demangle_data *);
static int cpp_demangle_read_offset(struct cpp_demangle_data *);
static int cpp_demangle_read_offset_number(struct cpp_demangle_data *);
@ -138,6 +145,8 @@ static int cpp_demangle_read_tmpl_arg(struct cpp_demangle_data *);
static int cpp_demangle_read_tmpl_args(struct cpp_demangle_data *);
static int cpp_demangle_read_tmpl_param(struct cpp_demangle_data *);
static int cpp_demangle_read_type(struct cpp_demangle_data *, int);
static int cpp_demangle_read_type_flat(struct cpp_demangle_data *,
char **);
static int cpp_demangle_read_uqname(struct cpp_demangle_data *);
static int cpp_demangle_read_v_offset(struct cpp_demangle_data *);
static char *decode_fp_to_double(const char *, size_t);
@ -156,8 +165,6 @@ static int vector_type_qualifier_init(struct vector_type_qualifier *);
static int vector_type_qualifier_push(struct vector_type_qualifier *,
enum type_qualifier);
static int cpp_demangle_gnu3_push_head;
/**
* @brief Decode the input string by IA-64 C++ ABI style.
*
@ -190,7 +197,6 @@ cpp_demangle_gnu3(const char *org)
if (!cpp_demangle_data_init(&ddata, org + 2))
return (NULL);
cpp_demangle_gnu3_push_head = 0;
rtn = NULL;
if (!cpp_demangle_read_encoding(&ddata))
@ -277,6 +283,7 @@ cpp_demangle_data_init(struct cpp_demangle_data *d, const char *cur)
d->func_type = 0;
d->cur = cur;
d->last_sname = NULL;
d->push_head = 0;
return (1);
@ -309,7 +316,6 @@ cpp_demangle_push_fp(struct cpp_demangle_data *ddata,
fp = ddata->cur;
while (*ddata->cur != 'E')
++ddata->cur;
++ddata->cur;
if ((f = decoder(fp, ddata->cur - fp)) == NULL)
return (0);
@ -320,6 +326,8 @@ cpp_demangle_push_fp(struct cpp_demangle_data *ddata,
free(f);
++ddata->cur;
return (rtn);
}
@ -331,7 +339,7 @@ cpp_demangle_push_str(struct cpp_demangle_data *ddata, const char *str,
if (ddata == NULL || str == NULL || len == 0)
return (0);
if (cpp_demangle_gnu3_push_head > 0)
if (ddata->push_head > 0)
return (vector_str_push(&ddata->output_tmp, str, len));
return (vector_str_push(&ddata->output, str, len));
@ -403,7 +411,8 @@ cpp_demangle_push_type_qualifier(struct cpp_demangle_data *ddata,
if (type_str != NULL) {
if (!vector_str_push(&subst_v, "*", 1))
goto clean;
if (!cpp_demangle_push_subst_v(ddata, &subst_v))
if (!cpp_demangle_push_subst_v(ddata,
&subst_v))
goto clean;
}
break;
@ -414,7 +423,8 @@ cpp_demangle_push_type_qualifier(struct cpp_demangle_data *ddata,
if (type_str != NULL) {
if (!vector_str_push(&subst_v, "&", 1))
goto clean;
if (!cpp_demangle_push_subst_v(ddata, &subst_v))
if (!cpp_demangle_push_subst_v(ddata,
&subst_v))
goto clean;
}
break;
@ -425,7 +435,8 @@ cpp_demangle_push_type_qualifier(struct cpp_demangle_data *ddata,
if (type_str != NULL) {
if (!vector_str_push(&subst_v, " complex", 8))
goto clean;
if (!cpp_demangle_push_subst_v(ddata, &subst_v))
if (!cpp_demangle_push_subst_v(ddata,
&subst_v))
goto clean;
}
break;
@ -434,23 +445,26 @@ cpp_demangle_push_type_qualifier(struct cpp_demangle_data *ddata,
if (!cpp_demangle_push_str(ddata, " imaginary", 10))
goto clean;
if (type_str != NULL) {
if (!vector_str_push(&subst_v, " imaginary", 10))
if (!vector_str_push(&subst_v, " imaginary",
10))
goto clean;
if (!cpp_demangle_push_subst_v(ddata, &subst_v))
if (!cpp_demangle_push_subst_v(ddata,
&subst_v))
goto clean;
}
break;
case TYPE_EXT:
if (e_idx > v->ext_name.size - 1)
if (v->ext_name.size == 0 ||
e_idx > v->ext_name.size - 1)
goto clean;
if ((e_len = strlen(v->ext_name.container[e_idx])) == 0)
if ((e_len = strlen(v->ext_name.container[e_idx])) ==
0)
goto clean;
if ((buf = malloc(sizeof(char) * (e_len + 1))) == NULL)
if ((buf = malloc(e_len + 2)) == NULL)
goto clean;
memcpy(buf, " ", 1);
memcpy(buf + 1, v->ext_name.container[e_idx], e_len);
snprintf(buf, e_len + 2, " %s",
v->ext_name.container[e_idx]);
if (!cpp_demangle_push_str(ddata, buf, e_len + 1)) {
free(buf);
@ -463,7 +477,8 @@ cpp_demangle_push_type_qualifier(struct cpp_demangle_data *ddata,
free(buf);
goto clean;
}
if (!cpp_demangle_push_subst_v(ddata, &subst_v)) {
if (!cpp_demangle_push_subst_v(ddata,
&subst_v)) {
free(buf);
goto clean;
}
@ -478,7 +493,8 @@ cpp_demangle_push_type_qualifier(struct cpp_demangle_data *ddata,
if (type_str != NULL) {
if (!vector_str_push(&subst_v, " restrict", 9))
goto clean;
if (!cpp_demangle_push_subst_v(ddata, &subst_v))
if (!cpp_demangle_push_subst_v(ddata,
&subst_v))
goto clean;
}
break;
@ -489,7 +505,8 @@ cpp_demangle_push_type_qualifier(struct cpp_demangle_data *ddata,
if (type_str != NULL) {
if (!vector_str_push(&subst_v, " volatile", 9))
goto clean;
if (!cpp_demangle_push_subst_v(ddata, &subst_v))
if (!cpp_demangle_push_subst_v(ddata,
&subst_v))
goto clean;
}
break;
@ -500,11 +517,42 @@ cpp_demangle_push_type_qualifier(struct cpp_demangle_data *ddata,
if (type_str != NULL) {
if (!vector_str_push(&subst_v, " const", 6))
goto clean;
if (!cpp_demangle_push_subst_v(ddata, &subst_v))
if (!cpp_demangle_push_subst_v(ddata,
&subst_v))
goto clean;
}
break;
case TYPE_VEC:
if (v->ext_name.size == 0 ||
e_idx > v->ext_name.size - 1)
goto clean;
if ((e_len = strlen(v->ext_name.container[e_idx])) ==
0)
goto clean;
if ((buf = malloc(e_len + 12)) == NULL)
goto clean;
snprintf(buf, e_len + 12, " __vector(%s)",
v->ext_name.container[e_idx]);
if (!cpp_demangle_push_str(ddata, buf, e_len + 11)) {
free(buf);
goto clean;
}
if (type_str != NULL) {
if (!vector_str_push(&subst_v, buf,
e_len + 11)) {
free(buf);
goto clean;
}
if (!cpp_demangle_push_subst_v(ddata,
&subst_v)) {
free(buf);
goto clean;
}
}
free(buf);
++e_idx;
break;
};
--idx;
}
@ -655,10 +703,14 @@ cpp_demangle_read_expr_primary(struct cpp_demangle_data *ddata)
switch (*ddata->cur) {
case 'b':
if (*(ddata->cur + 2) != 'E')
return (0);
switch (*(++ddata->cur)) {
case '0':
ddata->cur += 2;
return (cpp_demangle_push_str(ddata, "false", 5));
case '1':
ddata->cur += 2;
return (cpp_demangle_push_str(ddata, "true", 4));
default:
return (0);
@ -707,7 +759,8 @@ cpp_demangle_read_expr_primary(struct cpp_demangle_data *ddata)
++ddata->cur;
}
++ddata->cur;
return (cpp_demangle_push_str(ddata, num, ddata->cur - num));
return (cpp_demangle_push_str(ddata, num,
ddata->cur - num - 1));
default:
return (0);
@ -998,6 +1051,38 @@ cpp_demangle_read_expression(struct cpp_demangle_data *ddata)
return (0);
}
static int
cpp_demangle_read_expression_flat(struct cpp_demangle_data *ddata, char **str)
{
struct vector_str *output;
size_t i, p_idx, idx, exp_len;
char *exp;
output = ddata->push_head > 0 ? &ddata->output_tmp :
&ddata->output;
p_idx = output->size;
if (!cpp_demangle_read_expression(ddata))
return (0);
if ((exp = vector_str_substr(output, p_idx, output->size - 1,
&exp_len)) == NULL)
return (0);
idx = output->size;
for (i = p_idx; i < idx; ++i) {
if (!vector_str_pop(output)) {
free(exp);
return (0);
}
}
*str = exp;
return (1);
}
static int
cpp_demangle_read_expression_binary(struct cpp_demangle_data *ddata,
const char *name, size_t len)
@ -1127,12 +1212,65 @@ cpp_demangle_read_function(struct cpp_demangle_data *ddata, int *ext_c,
static int
cpp_demangle_read_encoding(struct cpp_demangle_data *ddata)
{
char *name, *type, *num_str;
long offset;
int rtn;
if (ddata == NULL || *ddata->cur == '\0')
return (0);
/* special name */
switch (SIMPLE_HASH(*ddata->cur, *(ddata->cur + 1))) {
case SIMPLE_HASH('G', 'A'):
if (!cpp_demangle_push_str(ddata, "hidden alias for ", 17))
return (0);
ddata->cur += 2;
if (*ddata->cur == '\0')
return (0);
return (cpp_demangle_read_encoding(ddata));
case SIMPLE_HASH('G', 'R'):
if (!cpp_demangle_push_str(ddata, "reference temporary #", 21))
return (0);
ddata->cur += 2;
if (*ddata->cur == '\0')
return (0);
if (!cpp_demangle_read_name_flat(ddata, &name))
return (0);
rtn = 0;
if (!cpp_demangle_read_number_as_string(ddata, &num_str))
goto clean1;
if (!cpp_demangle_push_str(ddata, num_str, strlen(num_str)))
goto clean2;
if (!cpp_demangle_push_str(ddata, " for ", 5))
goto clean2;
if (!cpp_demangle_push_str(ddata, name, strlen(name)))
goto clean2;
rtn = 1;
clean2:
free(num_str);
clean1:
free(name);
return (rtn);
case SIMPLE_HASH('G', 'T'):
ddata->cur += 2;
if (*ddata->cur == '\0')
return (0);
switch (*ddata->cur) {
case 'n':
if (!cpp_demangle_push_str(ddata,
"non-transaction clone for ", 26))
return (0);
case 't':
default:
if (!cpp_demangle_push_str(ddata,
"transaction clone for ", 22))
return (0);
}
++ddata->cur;
return (cpp_demangle_read_encoding(ddata));
case SIMPLE_HASH('G', 'V'):
/* sentry object for 1 time init */
if (!cpp_demangle_push_str(ddata, "guard variable for ", 20))
@ -1154,14 +1292,49 @@ cpp_demangle_read_encoding(struct cpp_demangle_data *ddata)
return (0);
return (cpp_demangle_read_encoding(ddata));
case SIMPLE_HASH('T', 'C'):
/* construction vtable */
if (!cpp_demangle_push_str(ddata, "construction vtable for ",
24))
return (0);
ddata->cur += 2;
if (*ddata->cur == '\0')
return (0);
if (!cpp_demangle_read_type_flat(ddata, &type))
return (0);
rtn = 0;
if (!cpp_demangle_read_number(ddata, &offset))
goto clean3;
if (*ddata->cur++ != '_')
goto clean3;
if (!cpp_demangle_read_type(ddata, 0))
goto clean3;
if (!cpp_demangle_push_str(ddata, "-in-", 4))
goto clean3;
if (!cpp_demangle_push_str(ddata, type, strlen(type)))
goto clean3;
rtn = 1;
clean3:
free(type);
return (rtn);
case SIMPLE_HASH('T', 'D'):
/* typeinfo common proxy */
break;
case SIMPLE_HASH('T', 'F'):
/* typeinfo fn */
if (!cpp_demangle_push_str(ddata, "typeinfo fn for ", 16))
return (0);
ddata->cur += 2;
if (*ddata->cur == '\0')
return (0);
return (cpp_demangle_read_type(ddata, 0));
case SIMPLE_HASH('T', 'h'):
/* virtual function non-virtual override thunk */
if (cpp_demangle_push_str(ddata,
"virtual function non-virtual override ", 38) == 0)
if (!cpp_demangle_push_str(ddata,
"virtual function non-virtual override ", 38))
return (0);
ddata->cur += 2;
if (*ddata->cur == '\0')
@ -1170,24 +1343,51 @@ cpp_demangle_read_encoding(struct cpp_demangle_data *ddata)
return (0);
return (cpp_demangle_read_encoding(ddata));
case SIMPLE_HASH('T', 'I'):
/* typeinfo structure */
/* FALLTHROUGH */
case SIMPLE_HASH('T', 'S'):
/* RTTI name (NTBS) */
if (!cpp_demangle_push_str(ddata, "typeinfo for ", 14))
case SIMPLE_HASH('T', 'H'):
/* TLS init function */
if (!cpp_demangle_push_str(ddata, "TLS init function for ",
22))
return (0);
ddata->cur += 2;
if (*ddata->cur == '\0')
return (0);
return (cpp_demangle_read_type(ddata, 1));
break;
case SIMPLE_HASH('T', 'I'):
/* typeinfo structure */
if (!cpp_demangle_push_str(ddata, "typeinfo for ", 13))
return (0);
ddata->cur += 2;
if (*ddata->cur == '\0')
return (0);
return (cpp_demangle_read_type(ddata, 0));
case SIMPLE_HASH('T', 'J'):
/* java class */
if (!cpp_demangle_push_str(ddata, "java Class for ", 15))
return (0);
ddata->cur += 2;
if (*ddata->cur == '\0')
return (0);
return (cpp_demangle_read_type(ddata, 0));
case SIMPLE_HASH('T', 'S'):
/* RTTI name (NTBS) */
if (!cpp_demangle_push_str(ddata, "typeinfo name for ", 18))
return (0);
ddata->cur += 2;
if (*ddata->cur == '\0')
return (0);
return (cpp_demangle_read_type(ddata, 0));
case SIMPLE_HASH('T', 'T'):
/* VTT table */
if (!cpp_demangle_push_str(ddata, "VTT for ", 8))
return (0);
ddata->cur += 2;
return (cpp_demangle_read_type(ddata, 1));
if (*ddata->cur == '\0')
return (0);
return (cpp_demangle_read_type(ddata, 0));
case SIMPLE_HASH('T', 'v'):
/* virtual function virtual override thunk */
@ -1208,7 +1408,17 @@ cpp_demangle_read_encoding(struct cpp_demangle_data *ddata)
ddata->cur += 2;
if (*ddata->cur == '\0')
return (0);
return (cpp_demangle_read_type(ddata, 1));
return (cpp_demangle_read_type(ddata, 0));
case SIMPLE_HASH('T', 'W'):
/* TLS wrapper function */
if (!cpp_demangle_push_str(ddata, "TLS wrapper function for ",
25))
return (0);
ddata->cur += 2;
if (*ddata->cur == '\0')
return (0);
break;
};
return (cpp_demangle_read_name(ddata));
@ -1270,8 +1480,7 @@ cpp_demangle_read_name(struct cpp_demangle_data *ddata)
if (ddata == NULL || *ddata->cur == '\0')
return (0);
output = cpp_demangle_gnu3_push_head > 0 ?
&ddata->output_tmp : &ddata->output;
output = ddata->push_head > 0 ? &ddata->output_tmp : &ddata->output;
subst_str = NULL;
@ -1326,6 +1535,38 @@ clean:
return (rtn);
}
static int
cpp_demangle_read_name_flat(struct cpp_demangle_data *ddata, char **str)
{
struct vector_str *output;
size_t i, p_idx, idx, name_len;
char *name;
output = ddata->push_head > 0 ? &ddata->output_tmp :
&ddata->output;
p_idx = output->size;
if (!cpp_demangle_read_name(ddata))
return (0);
if ((name = vector_str_substr(output, p_idx, output->size - 1,
&name_len)) == NULL)
return (0);
idx = output->size;
for (i = p_idx; i < idx; ++i) {
if (!vector_str_pop(output)) {
free(name);
return (0);
}
}
*str = name;
return (1);
}
static int
cpp_demangle_read_nested_name(struct cpp_demangle_data *ddata)
{
@ -1355,8 +1596,7 @@ cpp_demangle_read_nested_name(struct cpp_demangle_data *ddata)
++ddata->cur;
}
output = cpp_demangle_gnu3_push_head > 0 ?
&ddata->output_tmp : &ddata->output;
output = ddata->push_head > 0 ? &ddata->output_tmp : &ddata->output;
if (!vector_str_init(&v))
return (0);
@ -1452,6 +1692,24 @@ cpp_demangle_read_number(struct cpp_demangle_data *ddata, long *rtn)
return (1);
}
static int
cpp_demangle_read_number_as_string(struct cpp_demangle_data *ddata, char **str)
{
long n;
if (!cpp_demangle_read_number(ddata, &n)) {
*str = NULL;
return (0);
}
if (asprintf(str, "%ld", n) < 0) {
*str = NULL;
return (0);
}
return (1);
}
static int
cpp_demangle_read_nv_offset(struct cpp_demangle_data *ddata)
{
@ -1581,9 +1839,18 @@ static int
cpp_demangle_read_sname(struct cpp_demangle_data *ddata)
{
long len;
int err;
if (ddata == NULL || cpp_demangle_read_number(ddata, &len) == 0 ||
len <= 0 || cpp_demangle_push_str(ddata, ddata->cur, len) == 0)
len <= 0)
return (0);
if (len == 12 && (memcmp("_GLOBAL__N_1", ddata->cur, 12) == 0))
err = cpp_demangle_push_str(ddata, "(anonymous namespace)", 21);
else
err = cpp_demangle_push_str(ddata, ddata->cur, len);
if (err == 0)
return (0);
assert(ddata->output.size > 0);
@ -1732,8 +1999,7 @@ cpp_demangle_read_subst_std(struct cpp_demangle_data *ddata)
ddata->cur += 2;
output = cpp_demangle_gnu3_push_head > 0 ?
&ddata->output_tmp : &ddata->output;
output = ddata->push_head > 0 ? &ddata->output_tmp : &ddata->output;
p_idx = output->size;
if (!cpp_demangle_read_uqname(ddata))
@ -1783,8 +2049,7 @@ cpp_demangle_read_subst_stdtmpl(struct cpp_demangle_data *ddata,
if (ddata == NULL || str == NULL || len == 0)
return (0);
output = cpp_demangle_gnu3_push_head > 0 ? &ddata->output_tmp :
&ddata->output;
output = ddata->push_head > 0 ? &ddata->output_tmp : &ddata->output;
p_idx = output->size;
substr = NULL;
@ -1852,8 +2117,7 @@ cpp_demangle_read_tmpl_args(struct cpp_demangle_data *ddata)
return (0);
limit = 0;
v = cpp_demangle_gnu3_push_head > 0 ?
&ddata->output_tmp : &ddata->output;
v = ddata->push_head > 0 ? &ddata->output_tmp : &ddata->output;
for (;;) {
idx = v->size;
if (!cpp_demangle_read_tmpl_arg(ddata))
@ -1936,14 +2200,14 @@ cpp_demangle_read_type(struct cpp_demangle_data *ddata, int delimit)
size_t p_idx, type_str_len;
int extern_c, is_builtin;
long len;
char *type_str;
char *type_str, *exp_str, *num_str;
if (ddata == NULL)
return (0);
output = &ddata->output;
if (!strncmp(ddata->output.container[ddata->output.size - 1], ">", 1)) {
cpp_demangle_gnu3_push_head++;
ddata->push_head++;
output = &ddata->output_tmp;
} else if (delimit == 1) {
if (ddata->paren == false) {
@ -1978,7 +2242,7 @@ cpp_demangle_read_type(struct cpp_demangle_data *ddata, int delimit)
extern_c = 0;
is_builtin = 1;
p_idx = output->size;
type_str = NULL;
type_str = exp_str = num_str = NULL;
again:
/* builtin type */
switch (*ddata->cur) {
@ -2024,6 +2288,82 @@ again:
++ddata->cur;
goto rtn;
case 'D':
++ddata->cur;
switch (*ddata->cur) {
case 'd':
/* IEEE 754r decimal floating point (64 bits) */
if (!cpp_demangle_push_str(ddata, "decimal64", 9))
goto clean;
++ddata->cur;
break;
case 'e':
/* IEEE 754r decimal floating point (128 bits) */
if (!cpp_demangle_push_str(ddata, "decimal128", 10))
goto clean;
++ddata->cur;
break;
case 'f':
/* IEEE 754r decimal floating point (32 bits) */
if (!cpp_demangle_push_str(ddata, "decimal32", 9))
goto clean;
++ddata->cur;
break;
case 'h':
/* IEEE 754r half-precision floating point (16 bits) */
if (!cpp_demangle_push_str(ddata, "half", 4))
goto clean;
++ddata->cur;
break;
case 'i':
/* char32_t */
if (!cpp_demangle_push_str(ddata, "char32_t", 8))
goto clean;
++ddata->cur;
break;
case 'n':
/* std::nullptr_t (i.e., decltype(nullptr)) */
if (!cpp_demangle_push_str(ddata, "decltype(nullptr)",
17))
goto clean;
++ddata->cur;
break;
case 's':
/* char16_t */
if (!cpp_demangle_push_str(ddata, "char16_t", 8))
goto clean;
++ddata->cur;
break;
case 'v':
/* gcc vector_size extension. */
++ddata->cur;
if (*ddata->cur == '_') {
++ddata->cur;
if (!cpp_demangle_read_expression_flat(ddata,
&exp_str))
goto clean;
if (!vector_str_push(&v.ext_name, exp_str,
strlen(exp_str)))
goto clean;
} else {
if (!cpp_demangle_read_number_as_string(ddata,
&num_str))
goto clean;
if (!vector_str_push(&v.ext_name, num_str,
strlen(num_str)))
goto clean;
}
if (*ddata->cur != '_')
goto clean;
++ddata->cur;
if (!vector_type_qualifier_push(&v, TYPE_VEC))
goto clean;
goto again;
default:
goto clean;
}
goto rtn;
case 'e':
/* long double */
if (!cpp_demangle_push_str(ddata, "long double", 11))
@ -2118,7 +2458,7 @@ again:
case 'o':
/* unsigned __int128 */
if (!cpp_demangle_push_str(ddata, "unsigned _;int128", 17))
if (!cpp_demangle_push_str(ddata, "unsigned __int128", 17))
goto clean;
++ddata->cur;
goto rtn;
@ -2189,6 +2529,8 @@ again:
if (!vector_str_push(&v.ext_name, ddata->cur, len))
return (0);
ddata->cur += len;
if (!vector_type_qualifier_push(&v, TYPE_EXT))
goto clean;
goto again;
case 'v':
@ -2253,14 +2595,16 @@ rtn:
goto clean;
free(type_str);
free(exp_str);
free(num_str);
vector_type_qualifier_dest(&v);
if (cpp_demangle_gnu3_push_head > 0) {
if (ddata->push_head > 0) {
if (*ddata->cur == 'I' && cpp_demangle_read_tmpl_args(ddata)
== 0)
return (0);
if (--cpp_demangle_gnu3_push_head > 0)
if (--ddata->push_head > 0)
return (1);
if (!vector_str_push(&ddata->output_tmp, " ", 1))
@ -2284,11 +2628,45 @@ rtn:
return (1);
clean:
free(type_str);
free(exp_str);
free(num_str);
vector_type_qualifier_dest(&v);
return (0);
}
static int
cpp_demangle_read_type_flat(struct cpp_demangle_data *ddata, char **str)
{
struct vector_str *output;
size_t i, p_idx, idx, type_len;
char *type;
output = ddata->push_head > 0 ? &ddata->output_tmp :
&ddata->output;
p_idx = output->size;
if (!cpp_demangle_read_type(ddata, 0))
return (0);
if ((type = vector_str_substr(output, p_idx, output->size - 1,
&type_len)) == NULL)
return (0);
idx = output->size;
for (i = p_idx; i < idx; ++i) {
if (!vector_str_pop(output)) {
free(type);
return (0);
}
}
*str = type;
return (1);
}
/*
* read unqualified-name, unqualified name are operator-name, ctor-dtor-name,
* source-name

View File

@ -1,3 +1,3 @@
# $Id: os.Linux.mk 994 2010-06-13 10:39:19Z jkoshy $
# $Id: os.Linux.mk 3210 2015-05-17 13:40:49Z kaiwang27 $
CFLAGS+= -Wall
CFLAGS+= -Wall -D_GNU_SOURCE

View File

@ -22,7 +22,7 @@
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
.\" $Id: readelf.1 3195 2015-05-12 17:22:19Z emaste $
.\" $Id: readelf.1 3219 2015-05-24 23:42:34Z kaiwang27 $
.\"
.Dd September 13, 2012
.Os
@ -90,7 +90,7 @@ sections in the ELF object.
.It Fl e | Fl -headers
Print all program, file and section headers in the ELF object.
.It Fl g | Fl -section-groups
This option is recognized, but is ignored.
Print the contents of the section groups in the ELF object.
.It Fl h | Fl -file-header
Print the file header of the ELF object.
.It Fl l | Fl -program-headers

View File

@ -1,5 +1,5 @@
/*-
* Copyright (c) 2009-2014 Kai Wang
* Copyright (c) 2009-2015 Kai Wang
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -46,7 +46,7 @@
#include "_elftc.h"
ELFTC_VCSID("$Id: readelf.c 3189 2015-04-20 17:02:01Z emaste $");
ELFTC_VCSID("$Id: readelf.c 3223 2015-05-25 20:37:57Z emaste $");
/*
* readelf(1) options.
@ -302,6 +302,7 @@ static void dump_gnu_hash(struct readelf *re, struct section *s);
static void dump_hash(struct readelf *re);
static void dump_phdr(struct readelf *re);
static void dump_ppc_attributes(uint8_t *p, uint8_t *pe);
static void dump_section_groups(struct readelf *re);
static void dump_symtab(struct readelf *re, int i);
static void dump_symtabs(struct readelf *re);
static uint8_t *dump_unknown_tag(uint64_t tag, uint8_t *p);
@ -445,6 +446,7 @@ elf_machine(unsigned int mach)
case EM_SPARC: return "Sun SPARC";
case EM_386: return "Intel i386";
case EM_68K: return "Motorola 68000";
case EM_IAMCU: return "Intel MCU";
case EM_88K: return "Motorola 88000";
case EM_860: return "Intel i860";
case EM_MIPS: return "MIPS R3000 Big-Endian only";
@ -1050,6 +1052,7 @@ r_type(unsigned int mach, unsigned int type)
switch(mach) {
case EM_NONE: return "";
case EM_386:
case EM_IAMCU:
switch(type) {
case 0: return "R_386_NONE";
case 1: return "R_386_32";
@ -2381,6 +2384,7 @@ dwarf_reg(unsigned int mach, unsigned int reg)
switch (mach) {
case EM_386:
case EM_IAMCU:
switch (reg) {
case 0: return "eax";
case 1: return "ecx";
@ -4047,6 +4051,61 @@ dump_liblist(struct readelf *re)
#undef Elf_Lib
static void
dump_section_groups(struct readelf *re)
{
struct section *s;
const char *symname;
Elf_Data *d;
uint32_t *w;
int i, j, elferr;
size_t n;
for (i = 0; (size_t) i < re->shnum; i++) {
s = &re->sl[i];
if (s->type != SHT_GROUP)
continue;
(void) elf_errno();
if ((d = elf_getdata(s->scn, NULL)) == NULL) {
elferr = elf_errno();
if (elferr != 0)
warnx("elf_getdata failed: %s",
elf_errmsg(elferr));
continue;
}
if (d->d_size <= 0)
continue;
w = d->d_buf;
/* We only support COMDAT section. */
#ifndef GRP_COMDAT
#define GRP_COMDAT 0x1
#endif
if ((*w++ & GRP_COMDAT) == 0)
return;
if (s->entsize == 0)
s->entsize = 4;
symname = get_symbol_name(re, s->link, s->info);
n = s->sz / s->entsize;
if (n-- < 1)
return;
printf("\nCOMDAT group section [%5d] `%s' [%s] contains %ju"
" sections:\n", i, s->name, symname, (uintmax_t)n);
printf(" %-10.10s %s\n", "[Index]", "Name");
for (j = 0; (size_t) j < n; j++, w++) {
if (*w >= re->shnum) {
warnx("invalid section index: %u", *w);
continue;
}
printf(" [%5u] %s\n", *w, re->sl[*w].name);
}
}
}
static uint8_t *
dump_unknown_tag(uint64_t tag, uint8_t *p)
{
@ -6838,6 +6897,8 @@ dump_elf(struct readelf *re)
dump_phdr(re);
if (re->options & RE_SS)
dump_shdr(re);
if (re->options & RE_G)
dump_section_groups(re);
if (re->options & RE_D)
dump_dynamic(re);
if (re->options & RE_R)
@ -7311,7 +7372,7 @@ Usage: %s [options] file...\n\
-c | --archive-index Print the archive symbol table for archives.\n\
-d | --dynamic Print the contents of SHT_DYNAMIC sections.\n\
-e | --headers Print all headers in the object.\n\
-g | --section-groups (accepted, but ignored)\n\
-g | --section-groups Print the contents of the section groups.\n\
-h | --file-header Print the file header for the object.\n\
-l | --program-headers Print the PHDR table for the object.\n\
-n | --notes Print the contents of SHT_NOTE sections.\n\
@ -7365,8 +7426,8 @@ main(int argc, char **argv)
re->options |= RE_AA;
break;
case 'a':
re->options |= RE_AA | RE_D | RE_H | RE_II | RE_L |
RE_R | RE_SS | RE_S | RE_VV;
re->options |= RE_AA | RE_D | RE_G | RE_H | RE_II |
RE_L | RE_R | RE_SS | RE_S | RE_VV;
break;
case 'c':
re->options |= RE_C;

View File

@ -29,6 +29,8 @@
#include <sys/endian.h>
#include <machine/float.h>
#include <math.h>
#include <stdint.h>
@ -84,10 +86,18 @@ __fpclassifyl(long double e)
return (FP_SUBNORMAL);
}
mask_nbit_l(u); /* Mask normalization bit if applicable. */
#if LDBL_MANT_DIG == 53
if (u.bits.exp == 2047) {
if ((u.bits.manl | u.bits.manh) == 0)
return (FP_INFINITE);
return (FP_NAN);
}
#else
if (u.bits.exp == 32767) {
if ((u.bits.manl | u.bits.manh) == 0)
return (FP_INFINITE);
return (FP_NAN);
}
#endif
return (FP_NORMAL);
}

View File

@ -26,6 +26,8 @@
* $FreeBSD$
*/
#include <machine/float.h>
#include <math.h>
#include "fpmath.h"
@ -62,9 +64,9 @@ __isinfl(long double e)
u.e = e;
mask_nbit_l(u);
#ifndef __alpha__
return (u.bits.exp == 32767 && u.bits.manl == 0 && u.bits.manh == 0);
#else
#if LDBL_MANT_DIG == 53
return (u.bits.exp == 2047 && u.bits.manl == 0 && u.bits.manh == 0);
#else
return (u.bits.exp == 32767 && u.bits.manl == 0 && u.bits.manh == 0);
#endif
}

View File

@ -3,7 +3,7 @@
SRCS+= trivial-vdso_tc.c
MDASM= Ovfork.S brk.S cerror.S exect.S \
fork.S pipe.S ptrace.S sbrk.S syscall.S
pipe.S ptrace.S sbrk.S syscall.S
# Don't generate default code for these syscalls:
NOASM= break.o exit.o getlogin.o openbsd_poll.o sstk.o vfork.o yield.o

View File

@ -1,57 +0,0 @@
/* $NetBSD: fork.S,v 1.11 2003/08/07 16:42:17 agc Exp $ */
/*-
* Copyright (c) 1991, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Ralph Campbell.
*
* 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.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
*/
#include <machine/asm.h>
__FBSDID("$FreeBSD$");
#include "SYS.h"
#if defined(LIBC_SCCS) && !defined(lint)
ASMSTR("from: @(#)fork.s 8.1 (Berkeley) 6/4/93")
ASMSTR("$NetBSD: fork.S,v 1.11 2003/08/07 16:42:17 agc Exp $")
#endif /* LIBC_SCCS and not lint */
LEAF(__sys_fork)
WEAK_ALIAS(fork, __sys_fork)
WEAK_ALIAS(_fork, __sys_fork)
PIC_PROLOGUE(__sys_fork)
li v0, SYS_fork # pid = fork()
syscall
bne a3, zero, 2f
beq v1, zero, 1f # v1 == 0 in parent, 1 in child
move v0, zero
1:
PIC_RETURN()
2:
PIC_TAILCALL(__cerror)
END(__sys_fork)

View File

@ -6,5 +6,5 @@
const char *
elftc_version(void)
{
return "elftoolchain r3197M";
return "elftoolchain r3223M";
}

View File

@ -10,7 +10,8 @@ SHLIB_MAJOR= 9
SRCS= _secure_path.c auth.c expand_number.c flopen.c fparseln.c gr_util.c \
hexdump.c humanize_number.c kinfo_getfile.c kinfo_getfile.c \
kinfo_getallproc.c kinfo_getproc.c kinfo_getvmmap.c kld.c \
kinfo_getallproc.c kinfo_getproc.c kinfo_getvmmap.c \
kinfo_getvmobject.c kld.c \
login_auth.c login_cap.c \
login_class.c login_crypt.c login_ok.c login_times.c login_tty.c \
pidfile.c property.c pty.c pw_util.c quotafile.c realhostname.c \
@ -27,7 +28,8 @@ CFLAGS+= -I${.CURDIR} -I${.CURDIR}/../libc/gen/
MAN+= expand_number.3 flopen.3 fparseln.3 hexdump.3 \
humanize_number.3 kinfo_getallproc.3 kinfo_getfile.3 \
kinfo_getproc.3 kinfo_getvmmap.3 kld.3 login_auth.3 login_cap.3 \
kinfo_getproc.3 kinfo_getvmmap.3 kinfo_getvmobject.3 kld.3 \
login_auth.3 login_cap.3 \
login_class.3 login_ok.3 login_times.3 login_tty.3 pidfile.3 \
property.3 pty.3 quotafile.3 realhostname.3 realhostname_sa.3 \
_secure_path.3 trimdomain.3 uucplock.3 pw_util.3

View File

@ -25,7 +25,7 @@
.\"
.\" $FreeBSD$
.\"
.Dd July 9, 2009
.Dd May 27, 2015
.Dt KINFO_GETALLPROC 3
.Os
.Sh NAME
@ -35,6 +35,7 @@
.Lb libutil
.Sh SYNOPSIS
.In sys/types.h
.In sys/user.h
.In libutil.h
.Ft struct kinfo_proc *
.Fn kinfo_getallproc "int *cntp"

View File

@ -25,7 +25,7 @@
.\"
.\" $FreeBSD$
.\"
.Dd December 6, 2008
.Dd May 27, 2015
.Dt KINFO_GETFILE 3
.Os
.Sh NAME
@ -35,6 +35,7 @@
.Lb libutil
.Sh SYNOPSIS
.In sys/types.h
.In sys/user.h
.In libutil.h
.Ft struct kinfo_file *
.Fn kinfo_getfile "pid_t pid" "int *cntp"

View File

@ -25,7 +25,7 @@
.\"
.\" $FreeBSD$
.\"
.Dd March 1, 2013
.Dd May 27, 2015
.Dt KINFO_GETPROC 3
.Os
.Sh NAME
@ -35,6 +35,7 @@
.Lb libutil
.Sh SYNOPSIS
.In sys/types.h
.In sys/user.h
.In libutil.h
.Ft struct kinfo_proc *
.Fn kinfo_getproc "pid_t pid"

View File

@ -25,7 +25,7 @@
.\"
.\" $FreeBSD$
.\"
.Dd December 6, 2008
.Dd May 27, 2015
.Dt KINFO_GETVMMAP 3
.Os
.Sh NAME
@ -35,6 +35,7 @@
.Lb libutil
.Sh SYNOPSIS
.In sys/types.h
.In sys/user.h
.In libutil.h
.Ft struct kinfo_vmentry *
.Fn kinfo_getvmmap "pid_t pid" "int *cntp"

View File

@ -0,0 +1,74 @@
.\"
.\" Copyright (c) 2015 John Baldwin <jhb@FreeBSD.org>
.\" All rights reserved.
.\"
.\" 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.
.\"
.\" $FreeBSD$
.\"
.Dd May 27, 2015
.Dt KINFO_GETVMOBJECT 3
.Os
.Sh NAME
.Nm kinfo_getvmobject
.Nd function for getting system-wide memory information
.Sh LIBRARY
.Lb libutil
.Sh SYNOPSIS
.In sys/types.h
.In sys/user.h
.In libutil.h
.Ft struct kinfo_vmobject *
.Fn kinfo_getvmobject "int *cntp"
.Sh DESCRIPTION
This function is used to obtain information about the objects using memory
in the system.
.Pp
The
.Ar cntp
argument allows the caller to know how many records are returned.
.Pp
This function is a wrapper around the
.Dq vm.objects
.Xr sysctl 3
MIB.
While the kernel returns a packed structure, this function expands the
data into a fixed record format.
.Sh RETURN VALUES
On success the
.Fn kinfo_getvmobject
function returns a pointer to an array of
.Vt struct kinfo_vmobject
structures as defined by
.In sys/user.h .
The array is allocated by an internal call to
.Xr malloc 3
and must be freed by the caller with a call to
.Xr free 3 .
On failure the
.Fn kinfo_getvmobject
function returns
.Dv NULL .
.Sh SEE ALSO
.Xr free 3 ,
.Xr kinfo_getvmmap 3 ,
.Xr malloc 3

View File

@ -0,0 +1,94 @@
/*
* Copyright (c) 2013 Hudson River Trading LLC
* Written by: John H. Baldwin <jhb@FreeBSD.org>
* All rights reserved.
*
* 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.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/types.h>
#include <sys/sysctl.h>
#include <sys/user.h>
#include <stdlib.h>
#include <string.h>
#include "libutil.h"
struct kinfo_vmobject *
kinfo_getvmobject(int *cntp)
{
char *buf, *bp, *ep;
struct kinfo_vmobject *kvo, *list, *kp;
size_t len;
int cnt, i;
buf = NULL;
for (i = 0; i < 3; i++) {
if (sysctlbyname("vm.objects", NULL, &len, NULL, 0) < 0)
return (NULL);
buf = reallocf(buf, len);
if (buf == NULL)
return (NULL);
if (sysctlbyname("vm.objects", buf, &len, NULL, 0) == 0)
goto unpack;
if (errno != ENOMEM) {
free(buf);
return (NULL);
}
}
free(buf);
return (NULL);
unpack:
/* Count items */
cnt = 0;
bp = buf;
ep = buf + len;
while (bp < ep) {
kvo = (struct kinfo_vmobject *)(uintptr_t)bp;
bp += kvo->kvo_structsize;
cnt++;
}
list = calloc(cnt, sizeof(*list));
if (list == NULL) {
free(buf);
return (NULL);
}
/* Unpack */
bp = buf;
kp = list;
while (bp < ep) {
kvo = (struct kinfo_vmobject *)(uintptr_t)bp;
memcpy(kp, kvo, kvo->kvo_structsize);
bp += kvo->kvo_structsize;
kp->kvo_structsize = sizeof(*kp);
kp++;
}
free(buf);
*cntp = cnt;
return (list);
}

View File

@ -102,6 +102,8 @@ struct kinfo_file *
kinfo_getfile(pid_t _pid, int *_cntp);
struct kinfo_vmentry *
kinfo_getvmmap(pid_t _pid, int *_cntp);
struct kinfo_vmobject *
kinfo_getvmobject(int *_cntp);
struct kinfo_proc *
kinfo_getallproc(int *_cntp);
struct kinfo_proc *

View File

@ -49,7 +49,7 @@ BUILDDATE!= cd ${.CURDIR} && date -j -f '%s' $$(stat -f "%c" ${.OBJDIR}/dist/ba
BUILDDATE!= date +%Y%m%d
. endif
. endif
_SNAP_SUFFIX:= -r${SVNREVISION}-${BUILDDATE}
_SNAP_SUFFIX:= ${BUILDDATE}-r${SVNREVISION}
.else
# release
SNAPSHOT=

View File

@ -8,13 +8,13 @@ EMBEDDED_TARGET="arm"
EMBEDDED_TARGET_ARCH="armv6"
EMBEDDEDPORTS="sysutils/u-boot-pandaboard"
KERNEL="PANDABOARD"
NODOC=1
WORLD_FLAGS="${WORLD_FLAGS} UBLDR_LOADADDR=0x88000000"
IMAGE_SIZE="1G"
PART_SCHEME="MBR"
FAT_SIZE="2m"
FAT_TYPE="12"
MD_ARGS="-x 63 -y 255"
NODOC=1
arm_install_uboot() {
UBOOT_DIR="/usr/local/share/u-boot/u-boot-pandaboard"

View File

@ -8,13 +8,13 @@ EMBEDDED_TARGET="arm"
EMBEDDED_TARGET_ARCH="armv6"
EMBEDDEDPORTS="sysutils/u-boot-rpi2"
KERNEL="RPI2"
NODOC=1
WORLD_FLAGS="${WORLD_FLAGS} UBLDR_LOADADDR=0x2000000"
IMAGE_SIZE="1G"
PART_SCHEME="MBR"
FAT_SIZE="50m"
FAT_TYPE="16"
MD_ARGS="-x 63 -y 255"
NODOC=1
arm_install_uboot() {
UBOOT_DIR="/usr/local/share/u-boot/u-boot-rpi2"

View File

@ -15,6 +15,7 @@ FAT_SIZE="50m -b 16384"
FAT_TYPE="16"
MD_ARGS="-x 63 -y 255"
NODOC=1
export BOARDNAME="WANDBOARD"
arm_install_uboot() {
UBOOT_DIR="/usr/local/share/u-boot/u-boot-wandboard"

View File

@ -1845,12 +1845,16 @@ rewrite_client_leases(void)
leaseFile = fopen(path_dhclient_db, "w");
if (!leaseFile)
error("can't create %s: %m", path_dhclient_db);
cap_rights_init(&rights, CAP_FSTAT, CAP_FSYNC, CAP_FTRUNCATE,
CAP_SEEK, CAP_WRITE);
cap_rights_init(&rights, CAP_FCNTL, CAP_FSTAT, CAP_FSYNC,
CAP_FTRUNCATE, CAP_SEEK, CAP_WRITE);
if (cap_rights_limit(fileno(leaseFile), &rights) < 0 &&
errno != ENOSYS) {
error("can't limit lease descriptor: %m");
}
if (cap_fcntls_limit(fileno(leaseFile), CAP_FCNTL_GETFL) < 0 &&
errno != ENOSYS) {
error("can't limit lease descriptor fcntls: %m");
}
} else {
fflush(leaseFile);
rewind(leaseFile);

View File

@ -67,7 +67,10 @@ is undefined.
The
.Fn pthread_setspecific
function may be called from a thread-specific data destructor function,
however this may result in lost storage or infinite loops.
however this may result in lost storage or infinite loops if doing so
causes non-NULL key values to remain after
.Bq PTHREAD_DESTRUCTOR_ITERATIONS
iterations of destructor calls have been made.
.Sh RETURN VALUES
If successful, the
.Fn pthread_setspecific

View File

@ -192,6 +192,7 @@ MAN= aac.4 \
icmp6.4 \
ida.4 \
ifmib.4 \
ig4.4 \
igb.4 \
igmp.4 \
iic.4 \

79
share/man/man4/ig4.4 Normal file
View File

@ -0,0 +1,79 @@
.\" Copyright (c) 2015 Michael Gmelin <freebsd@grem.de>
.\" All rights reserved.
.\"
.\" 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.
.\"
.\" $FreeBSD$
.\"
.Dd May 30, 2015
.Dt IG4 4
.Os
.Sh NAME
.Nm ig4
.Nd Intel(R) fourth generation mobile CPU integrated I2C SMBus driver
.Sh SYNOPSIS
To compile this driver into the kernel, place the following lines into
the kernel configuration file:
.Bd -ragged -offset indent
.Cd "device ig4"
.Cd "device smbus"
.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
ig4_load="YES"
.Ed
.Sh DESCRIPTION
The
.Nm
driver provides access to peripherals attached to an I2C SMB controller.
.Nm
supports the SMBus controller found in fourth generation Intel(R) Core(TM)
processors based on the mobile U-processor line for intelligent systems.
This includes the i7-4650U, i5-4300U, i3-4010U, and 2980U.
.Sh SYSCTL VARIABLES
These
.Xr sysctl 8
variables are available:
.Bl -tag -width "debug.ig4_dump"
.It Va debug.ig4_dump
Setting this to a non-zero value dumps controller registers to console and
syslog once.
The sysctl resets to zero immediately.
.El
.Sh SEE ALSO
.Xr smb 4 ,
.Xr smbus 4
.Sh AUTHORS
.An -nosplit
The
.Nm
driver was written for DragonFly BSD by
.An Matthew Dillon
and subsequently ported to
.Fx
by
.An Michael Gmelin Aq Mt freebsd@grem.de .
.Pp
This manual page was written by
.An Michael Gmelin Aq Mt freebsd@grem.de .

View File

@ -195,10 +195,10 @@ MAN= accept_filter.9 \
p_candebug.9 \
p_cansee.9 \
pci.9 \
PCI_ADD_VF.9 \
PCI_INIT_IOV.9 \
PCI_IOV_ADD_VF.9 \
PCI_IOV_INIT.9 \
pci_iov_schema.9 \
PCI_UNINIT_IOV.9 \
PCI_IOV_UNINIT.9 \
pfil.9 \
pfind.9 \
pget.9 \

View File

@ -25,38 +25,37 @@
.\"
.\" $FreeBSD$
.\"
.Dd May 24, 2014
.Dt PCI_ADD_VF 9
.Dd May 28, 2015
.Dt PCI_IOV_ADD_VF 9
.Os
.Sh NAME
.Nm PCI_ADD_VF
.Nm PCI_IOV_ADD_VF
.Nd inform a PF driver that a VF is being created
.Sh SYNOPSIS
.In sys/bus.h
.In machine/stdarg.h
.In sys/nv.h
.In dev/pci/pcireg.h
.In dev/pci/pcivar.h
.In dev/pci/pci_iov.h
.Ft int
.Fn PCI_ADD_VF "device_t dev" "uint16_t vfnum" "const nvlist_t *vf_config"
.Fn PCI_IOV_ADD_VF "device_t dev" "uint16_t vfnum" "const nvlist_t *vf_config"
.Sh DESCRIPTION
The
.Fn PCI_ADD_VF
.Fn PCI_IOV_ADD_VF
method is called by the PCI Single-Root I/O Virtualization
.Pq SR-IOV
infrastructure when it is initializating a new Virtual Function (VF) as a child
of the given Physical Function (PF) device.
This method will not be called until a successful call to
.Xr PCI_INIT_IOV 9
.Xr PCI_IOV_INIT 9
has been made.
It is not guaranteed that this method will be called following a successful call
to
.Xr PCI_INIT_IOV 9 .
.Xr PCI_IOV_INIT 9 .
If the infrastructure encounters a failure to allocate resources following the
call to
.Xr PCI_INIT_IOV 9 ,
.Xr PCI_IOV_INIT 9 ,
the VF creation will be aborted and
.Xr PCI_UNINIT_IOV 9
.Xr PCI_IOV_UNINIT 9
will be called immediately without any preceding calls to
.Nm .
.Pp
@ -87,15 +86,15 @@ Note that it is possible for the user to set different configuration values on
different VF devices that are children of the same PF.
The PF driver must not cache configuration parameters passed in previous calls
to
.Fn PCI_ADD_VF
.Fn PCI_IOV_ADD_VF
for other VFs and apply those parameters to the current VF.
.Pp
This function will not be called twice for the same
.Fa vf_num
on the same PF device without
.Xr PCI_UNINIT_IOV 9
.Xr PCI_IOV_UNINIT 9
and
.Xr PCI_INIT_IOV 9
.Xr PCI_IOV_INIT 9
first being called, in that order.
.Sh RETURN VALUES
This method returns 0 on success, otherwise an appropriate error is returned.
@ -106,8 +105,8 @@ the PF.
.Xr nv 9 ,
.Xr pci 9 ,
.Xr pci_iov_schema 9 ,
.Xr PCI_INIT_IOV 9 ,
.Xr PCI_UNINIT_IOV 9
.Xr PCI_IOV_INIT 9 ,
.Xr PCI_IOV_UNINIT 9
.Sh AUTHORS
This manual page was written by
.An Ryan Stone Aq Mt rstone@FreeBSD.org .

View File

@ -25,23 +25,22 @@
.\"
.\" $FreeBSD$
.\"
.Dd May 24, 2014
.Dt PCI_INIT_IOV 9
.Dd May 28, 2015
.Dt PCI_IOV_INIT 9
.Os
.Sh NAME
.Nm PCI_INIT_IOV
.Nm PCI_IOV_INIT
.Nd enable SR-IOV on a PF device
.Sh SYNOPSIS
.In sys/bus.h
.In machine/stdarg.h
.In sys/nv.h
.In dev/pci/pcireg.h
.In dev/pci/pcivar.h
.In dev/pci/pci_iov.h
.Ft int
.Fn PCI_INIT_IOV "device_t dev" "uint16_t num_vfs" "const nvlist_t *pf_config"
.Fn PCI_IOV_INIT "device_t dev" "uint16_t num_vfs" "const nvlist_t *pf_config"
.Sh DESCRIPTION
The
.Fn PCI_INIT_IOV
.Fn PCI_IOV_INIT
method is called by the PCI Single-Root I/O Virtualization (SR-IOV)
infrastucture when the user requests that SR-IOV be enabled on a Physical
Function (PF).
@ -70,7 +69,7 @@ valid values specified in the schema.
.Pp
If this method returns successfully, then this method will not be called again
on the same device until after a call to
.Xr PCI_UNINIT_IOV .
.Xr PCI_IOV_UNINIT .
.Sh RETURN VALUES
Returns 0 on success, otherwise an appropriate error is returned.
If this method returns an error then the SR-IOV configuration will be aborted
@ -79,8 +78,8 @@ and no VFs will be created.
.Xr nv 9 ,
.Xr pci 9 ,
.Xr pci_iov_schema 9 ,
.Xr PCI_ADD_VF 9 ,
.Xr PCI_UNINIT_IOV 9
.Xr PCI_IOV_ADD_VF 9 ,
.Xr PCI_IOV_UNINIT 9
.Sh AUTHORS
This manual page was written by
.An Ryan Stone Aq Mt rstone@FreeBSD.org .

View File

@ -25,21 +25,20 @@
.\"
.\" $FreeBSD$
.\"
.Dd May 24, 2014
.Dt PCI_UNINIT_IOV 9
.Dd May 28, 2015
.Dt PCI_IOV_UNINIT 9
.Os
.Sh NAME
.Nm PCI_UNINIT_IOV
.Nm PCI_IOV_UNINIT
.Nd disable SR-IOV on a PF device
.Sh SYNOPSIS
.In sys/bus.h
.In dev/pci/pcireg.h
.In dev/pci/pcivar.h
.In dev/pci/pci_iov.h
.Ft void
.Fn PCI_UNINIT_IOV "device_t dev"
.Fn PCI_IOV_UNINIT "device_t dev"
.Sh DESCRIPTION
The
.Fn PCI_UNINIT_IOV
.Fn PCI_IOV_UNINIT
method is called by the PCI Single-Root I/O Virtualization (SR-IOV)
infrastructure when the user requests that SR-IOV be disabled on a Physical
Function (PF).
@ -48,17 +47,17 @@ resources that it has allocated and disable any device-specific SR-IOV
configuration in the device.
.Pp
This method will only be called following a successful call to
.Xr PCI_INIT_IOV .
.Xr PCI_IOV_INIT .
It is not guaranteed that
.Xr PCI_ADD_VF
.Xr PCI_IOV_ADD_VF
will have been called for any Virtual Function (VF) after the call to
.Xr PCI_INIT_IOV
.Xr PCI_IOV_INIT
and before the call to
.Nm .
.Sh SEE ALSO
.Xr pci 9 ,
.Xr PCI_ADD_VF 9 ,
.Xr PCI_INIT_IOV 9
.Xr PCI_IOV_ADD_VF 9 ,
.Xr PCI_IOV_INIT 9
.Sh AUTHORS
This manual page was written by
.An Ryan Stone Aq Mt rstone@FreeBSD.org .

View File

@ -25,7 +25,7 @@
.\"
.\" $FreeBSD$
.\"
.Dd May 24, 2014
.Dd May 28, 2015
.Dt PCI 9
.Os
.Sh NAME
@ -97,10 +97,6 @@
.Ft int
.Fn pci_get_vpd_readonly "device_t dev" "const char *kw" "const char **vptr"
.Ft int
.Fn pci_iov_attach "device_t dev" "nvlist_t *pf_schema" "nvlist_t *vf_schema"
.Ft int
.Fn pci_iov_detach "device_t dev"
.Ft int
.Fn pci_msi_count "device_t dev"
.Ft int
.Fn pci_msix_count "device_t dev"
@ -122,6 +118,11 @@
.Fn pci_set_powerstate "device_t dev" "int state"
.Ft void
.Fn pci_write_config "device_t dev" "int reg" "uint32_t val" "int width"
.In dev/pci/pci_iov.h
.Ft int
.Fn pci_iov_attach "device_t dev" "nvlist_t *pf_schema" "nvlist_t *vf_schema"
.Ft int
.Fn pci_iov_detach "device_t dev"
.Sh DESCRIPTION
The
.Nm
@ -446,10 +447,10 @@ function is used to advertise that the given device
supports PCI Single-Root I/O Virtualization
.Po SR-IOV Pc .
A driver that supports SR-IOV must implement the
.Xr PCI_INIT_IOV 9 ,
.Xr PCI_ADD_VF 9
.Xr PCI_IOV_INIT 9 ,
.Xr PCI_IOV_ADD_VF 9
and
.Xr PCI_UNIT_IOV 9
.Xr PCI_IOV_UNINIT 9
methods.
This function should be called during the
.Xr DEVICE_ATTACH 9

View File

@ -25,7 +25,7 @@
.\"
.\" $FreeBSD$
.\"
.Dd May 25, 2014
.Dd May 28, 2015
.Dt pci_iov_schema 9
.Os
.Sh NAME
@ -258,8 +258,8 @@ The
function returns a pointer to the allocated schema, or NULL if a failure occurs.
.Sh SEE ALSO
.Xr pci 9 ,
.Xr PCI_ADD_VF 9 ,
.Xr PCI_INIT_IOV 9
.Xr PCI_IOV_ADD_VF 9 ,
.Xr PCI_IOV_INIT 9
.Sh AUTHORS
This manual page was written by
.An Ryan Stone Aq rstone@FreeBSD.org .

View File

@ -9,8 +9,12 @@
.include <src.opts.mk>
ROOTSRCDIR= ${.MAKE.MAKEFILES:M*/src.libnames.mk:H:H:H}
ROOTOBJDIR= ${.OBJDIR:S/${.CURDIR}//}${ROOTSRCDIR}
.if ${.OBJDIR:S,${.CURDIR},,} != ${.OBJDIR}
ROOTOBJDIR= ${.OBJDIR:S,${.CURDIR},,}${SRCTOP}
.elif defined(OBJTOP) && ${.OBJDIR:M${OBJTOP}*} != ""
ROOTOBJDIR= ${OBJTOP}
.endif
_PRIVATELIBS= \
atf_c \
atf_cxx \

View File

@ -5,13 +5,16 @@
# to preserve historical (and useful) behavior. Changes here need to
# be reflected there so SRCCONF isn't included multiple times.
# make sure this is defined in a consistent manner
SRCTOP:= ${.PARSEDIR:tA:H:H}
# Allow user to configure things that only effect src tree builds.
SRCCONF?= /etc/src.conf
.if (exists(${SRCCONF}) || ${SRCCONF} != "/etc/src.conf") && !target(_srcconf_included_)
.include "${SRCCONF}"
.sinclude "${SRCCONF}"
_srcconf_included_: .NOTMAIN
.endif
# If we were found via .../share/mk we need to replace that in
# If we were found via .../share/mk we need to replace that
# with ${.PARSEDIR:tA} so that we can be found by
# sub-makes launched from objdir.
.if ${.MAKEFLAGS:M.../share/mk} != ""

View File

@ -8,9 +8,9 @@ CSCOPEDIRS= boot bsm cam cddl compat conf contrib crypto ddb dev fs gdb \
rpc security sys ufs vm xdr xen ${CSCOPE_ARCHDIR}
.if !defined(CSCOPE_ARCHDIR)
.if defined(ALL_ARCH)
CSCOPE_ARCHDIR = amd64 arm i386 mips pc98 powerpc sparc64 x86
CSCOPE_ARCHDIR = amd64 arm arm64 i386 mips pc98 powerpc sparc64 x86
.else
CSCOPE_ARCHDIR = ${MACHINE}
CSCOPE_ARCHDIR = ${MACHINE}
.if ${MACHINE} != ${MACHINE_CPUARCH}
CSCOPE_ARCHDIR += ${MACHINE_CPUARCH}
.endif

View File

@ -381,7 +381,7 @@ caddr_t CADDR1 = 0;
static int pmap_flags = PMAP_PDE_SUPERPAGE; /* flags for x86 pmaps */
int pmap_pcid_enabled = 0;
int pmap_pcid_enabled = 1;
SYSCTL_INT(_vm_pmap, OID_AUTO, pcid_enabled, CTLFLAG_RDTUN | CTLFLAG_NOFETCH,
&pmap_pcid_enabled, 0, "Is TLB Context ID enabled ?");
int invpcid_works = 0;
@ -3935,7 +3935,6 @@ pmap_promote_pde(pmap_t pmap, pd_entry_t *pde, vm_offset_t va,
pd_entry_t newpde;
pt_entry_t *firstpte, oldpte, pa, *pte;
pt_entry_t PG_G, PG_A, PG_M, PG_RW, PG_V;
vm_offset_t oldpteva;
vm_page_t mpte;
int PG_PTE_CACHE;
@ -3995,10 +3994,9 @@ setpte:
if (!atomic_cmpset_long(pte, oldpte, oldpte & ~PG_RW))
goto setpte;
oldpte &= ~PG_RW;
oldpteva = (oldpte & PG_FRAME & PDRMASK) |
(va & ~PDRMASK);
CTR2(KTR_PMAP, "pmap_promote_pde: protect for va %#lx"
" in pmap %p", oldpteva, pmap);
" in pmap %p", (oldpte & PG_FRAME & PDRMASK) |
(va & ~PDRMASK), pmap);
}
if ((oldpte & PG_PTE_PROMOTE) != (newpde & PG_PTE_PROMOTE)) {
atomic_add_long(&pmap_pde_p_failures, 1);

View File

@ -155,7 +155,6 @@ cpu_fork(td1, p2, td2, flags)
struct pcb *pcb2;
struct mdproc *mdp1, *mdp2;
struct proc_ldt *pldt;
pmap_t pmap2;
p1 = td1->td_proc;
if ((flags & RFPROC) == 0) {
@ -218,7 +217,6 @@ cpu_fork(td1, p2, td2, flags)
* Set registers for trampoline to user mode. Leave space for the
* return address on stack. These are the kernel mode register values.
*/
pmap2 = vmspace_pmap(p2->p_vmspace);
pcb2->pcb_r12 = (register_t)fork_return; /* fork_trampoline argument */
pcb2->pcb_rbp = 0;
pcb2->pcb_rsp = (register_t)td2->td_frame - sizeof(void *);

View File

@ -79,11 +79,9 @@ __FBSDID("$FreeBSD$");
int
fill_regs32(struct thread *td, struct reg32 *regs)
{
struct pcb *pcb;
struct trapframe *tp;
tp = td->td_frame;
pcb = td->td_pcb;
if (tp->tf_flags & TF_HASSEGS) {
regs->r_gs = tp->tf_gs;
regs->r_fs = tp->tf_fs;
@ -113,18 +111,16 @@ fill_regs32(struct thread *td, struct reg32 *regs)
int
set_regs32(struct thread *td, struct reg32 *regs)
{
struct pcb *pcb;
struct trapframe *tp;
tp = td->td_frame;
if (!EFL_SECURE(regs->r_eflags, tp->tf_rflags) || !CS_SECURE(regs->r_cs))
return (EINVAL);
pcb = td->td_pcb;
tp->tf_gs = regs->r_gs;
tp->tf_fs = regs->r_fs;
tp->tf_es = regs->r_es;
tp->tf_ds = regs->r_ds;
set_pcb_flags(pcb, PCB_FULL_IRET);
set_pcb_flags(td->td_pcb, PCB_FULL_IRET);
tp->tf_flags = TF_HASSEGS;
tp->tf_rdi = regs->r_edi;
tp->tf_rsi = regs->r_esi;

View File

@ -120,13 +120,18 @@ struct vm_object;
struct vm_guest_paging;
struct pmap;
struct vm_eventinfo {
void *rptr; /* rendezvous cookie */
int *sptr; /* suspend cookie */
int *iptr; /* reqidle cookie */
};
typedef int (*vmm_init_func_t)(int ipinum);
typedef int (*vmm_cleanup_func_t)(void);
typedef void (*vmm_resume_func_t)(void);
typedef void * (*vmi_init_func_t)(struct vm *vm, struct pmap *pmap);
typedef int (*vmi_run_func_t)(void *vmi, int vcpu, register_t rip,
struct pmap *pmap, void *rendezvous_cookie,
void *suspend_cookie);
struct pmap *pmap, struct vm_eventinfo *info);
typedef void (*vmi_cleanup_func_t)(void *vmi);
typedef int (*vmi_get_register_t)(void *vmi, int vcpu, int num,
uint64_t *retval);
@ -208,6 +213,7 @@ struct vm_exit *vm_exitinfo(struct vm *vm, int vcpuid);
void vm_exit_suspended(struct vm *vm, int vcpuid, uint64_t rip);
void vm_exit_rendezvous(struct vm *vm, int vcpuid, uint64_t rip);
void vm_exit_astpending(struct vm *vm, int vcpuid, uint64_t rip);
void vm_exit_reqidle(struct vm *vm, int vcpuid, uint64_t rip);
#ifdef _SYS__CPUSET_H_
/*
@ -232,17 +238,24 @@ cpuset_t vm_suspended_cpus(struct vm *vm);
#endif /* _SYS__CPUSET_H_ */
static __inline int
vcpu_rendezvous_pending(void *rendezvous_cookie)
vcpu_rendezvous_pending(struct vm_eventinfo *info)
{
return (*(uintptr_t *)rendezvous_cookie != 0);
return (*((uintptr_t *)(info->rptr)) != 0);
}
static __inline int
vcpu_suspended(void *suspend_cookie)
vcpu_suspended(struct vm_eventinfo *info)
{
return (*(int *)suspend_cookie);
return (*info->sptr);
}
static __inline int
vcpu_reqidle(struct vm_eventinfo *info)
{
return (*info->iptr);
}
/*
@ -506,6 +519,7 @@ enum vm_exitcode {
VM_EXITCODE_MONITOR,
VM_EXITCODE_MWAIT,
VM_EXITCODE_SVM,
VM_EXITCODE_REQIDLE,
VM_EXITCODE_MAX
};

View File

@ -1900,7 +1900,7 @@ enable_gintr(void)
*/
static int
svm_vmrun(void *arg, int vcpu, register_t rip, pmap_t pmap,
void *rend_cookie, void *suspended_cookie)
struct vm_eventinfo *evinfo)
{
struct svm_regctx *gctx;
struct svm_softc *svm_sc;
@ -1975,18 +1975,24 @@ svm_vmrun(void *arg, int vcpu, register_t rip, pmap_t pmap,
*/
disable_gintr();
if (vcpu_suspended(suspended_cookie)) {
if (vcpu_suspended(evinfo)) {
enable_gintr();
vm_exit_suspended(vm, vcpu, state->rip);
break;
}
if (vcpu_rendezvous_pending(rend_cookie)) {
if (vcpu_rendezvous_pending(evinfo)) {
enable_gintr();
vm_exit_rendezvous(vm, vcpu, state->rip);
break;
}
if (vcpu_reqidle(evinfo)) {
enable_gintr();
vm_exit_reqidle(vm, vcpu, state->rip);
break;
}
/* We are asked to give the cpu by scheduler. */
if (vcpu_should_yield(vm, vcpu)) {
enable_gintr();

View File

@ -2554,7 +2554,7 @@ vmx_exit_handle_nmi(struct vmx *vmx, int vcpuid, struct vm_exit *vmexit)
static int
vmx_run(void *arg, int vcpu, register_t rip, pmap_t pmap,
void *rendezvous_cookie, void *suspend_cookie)
struct vm_eventinfo *evinfo)
{
int rc, handled, launched;
struct vmx *vmx;
@ -2623,18 +2623,24 @@ vmx_run(void *arg, int vcpu, register_t rip, pmap_t pmap,
* vmx_inject_interrupts() can suspend the vcpu due to a
* triple fault.
*/
if (vcpu_suspended(suspend_cookie)) {
if (vcpu_suspended(evinfo)) {
enable_intr();
vm_exit_suspended(vmx->vm, vcpu, rip);
break;
}
if (vcpu_rendezvous_pending(rendezvous_cookie)) {
if (vcpu_rendezvous_pending(evinfo)) {
enable_intr();
vm_exit_rendezvous(vmx->vm, vcpu, rip);
break;
}
if (vcpu_reqidle(evinfo)) {
enable_intr();
vm_exit_reqidle(vmx->vm, vcpu, rip);
break;
}
if (vcpu_should_yield(vm, vcpu)) {
enable_intr();
vm_exit_astpending(vmx->vm, vcpu, rip);

View File

@ -95,6 +95,7 @@ struct vcpu {
struct mtx mtx; /* (o) protects 'state' and 'hostcpu' */
enum vcpu_state state; /* (o) vcpu state */
int hostcpu; /* (o) vcpu's host cpu */
int reqidle; /* (i) request vcpu to idle */
struct vlapic *vlapic; /* (i) APIC device model */
enum x2apic_state x2apic_state; /* (i) APIC mode */
uint64_t exitintinfo; /* (i) events pending at VM exit */
@ -164,8 +165,8 @@ static struct vmm_ops *ops;
#define VMM_RESUME() (ops != NULL ? (*ops->resume)() : 0)
#define VMINIT(vm, pmap) (ops != NULL ? (*ops->vminit)(vm, pmap): NULL)
#define VMRUN(vmi, vcpu, rip, pmap, rptr, sptr) \
(ops != NULL ? (*ops->vmrun)(vmi, vcpu, rip, pmap, rptr, sptr) : ENXIO)
#define VMRUN(vmi, vcpu, rip, pmap, evinfo) \
(ops != NULL ? (*ops->vmrun)(vmi, vcpu, rip, pmap, evinfo) : ENXIO)
#define VMCLEANUP(vmi) (ops != NULL ? (*ops->vmcleanup)(vmi) : NULL)
#define VMSPACE_ALLOC(min, max) \
(ops != NULL ? (*ops->vmspace_alloc)(min, max) : NULL)
@ -221,6 +222,28 @@ TUNABLE_INT("hw.vmm.force_iommu", &vmm_force_iommu);
SYSCTL_INT(_hw_vmm, OID_AUTO, force_iommu, CTLFLAG_RDTUN, &vmm_force_iommu, 0,
"Force use of I/O MMU even if no passthrough devices were found.");
static void vcpu_notify_event_locked(struct vcpu *vcpu, bool lapic_intr);
#ifdef KTR
static const char *
vcpu_state2str(enum vcpu_state state)
{
switch (state) {
case VCPU_IDLE:
return ("idle");
case VCPU_FROZEN:
return ("frozen");
case VCPU_RUNNING:
return ("running");
case VCPU_SLEEPING:
return ("sleeping");
default:
return ("unknown");
}
}
#endif
static void
vcpu_cleanup(struct vm *vm, int i, bool destroy)
{
@ -255,6 +278,7 @@ vcpu_init(struct vm *vm, int vcpu_id, bool create)
vcpu->vlapic = VLAPIC_INIT(vm->cookie, vcpu_id);
vm_set_x2apic_state(vm, vcpu_id, X2APIC_DISABLED);
vcpu->reqidle = 0;
vcpu->exitintinfo = 0;
vcpu->nmi_pending = 0;
vcpu->extint_pending = 0;
@ -980,11 +1004,13 @@ save_guest_fpustate(struct vcpu *vcpu)
static VMM_STAT(VCPU_IDLE_TICKS, "number of ticks vcpu was idle");
static int
vcpu_set_state_locked(struct vcpu *vcpu, enum vcpu_state newstate,
vcpu_set_state_locked(struct vm *vm, int vcpuid, enum vcpu_state newstate,
bool from_idle)
{
struct vcpu *vcpu;
int error;
vcpu = &vm->vcpu[vcpuid];
vcpu_assert_locked(vcpu);
/*
@ -993,8 +1019,13 @@ vcpu_set_state_locked(struct vcpu *vcpu, enum vcpu_state newstate,
* ioctl() operating on a vcpu at any point.
*/
if (from_idle) {
while (vcpu->state != VCPU_IDLE)
while (vcpu->state != VCPU_IDLE) {
vcpu->reqidle = 1;
vcpu_notify_event_locked(vcpu, false);
VCPU_CTR1(vm, vcpuid, "vcpu state change from %s to "
"idle requested", vcpu_state2str(vcpu->state));
msleep_spin(&vcpu->state, &vcpu->mtx, "vmstat", hz);
}
} else {
KASSERT(vcpu->state != VCPU_IDLE, ("invalid transition from "
"vcpu idle state"));
@ -1031,6 +1062,9 @@ vcpu_set_state_locked(struct vcpu *vcpu, enum vcpu_state newstate,
if (error)
return (EBUSY);
VCPU_CTR2(vm, vcpuid, "vcpu state changed from %s to %s",
vcpu_state2str(vcpu->state), vcpu_state2str(newstate));
vcpu->state = newstate;
if (newstate == VCPU_RUNNING)
vcpu->hostcpu = curcpu;
@ -1053,11 +1087,11 @@ vcpu_require_state(struct vm *vm, int vcpuid, enum vcpu_state newstate)
}
static void
vcpu_require_state_locked(struct vcpu *vcpu, enum vcpu_state newstate)
vcpu_require_state_locked(struct vm *vm, int vcpuid, enum vcpu_state newstate)
{
int error;
if ((error = vcpu_set_state_locked(vcpu, newstate, false)) != 0)
if ((error = vcpu_set_state_locked(vm, vcpuid, newstate, false)) != 0)
panic("Error %d setting state to %d", error, newstate);
}
@ -1145,7 +1179,7 @@ vm_handle_hlt(struct vm *vm, int vcpuid, bool intr_disabled, bool *retu)
* vcpu returned from VMRUN() and before it acquired the
* vcpu lock above.
*/
if (vm->rendezvous_func != NULL || vm->suspend)
if (vm->rendezvous_func != NULL || vm->suspend || vcpu->reqidle)
break;
if (vm_nmi_pending(vm, vcpuid))
break;
@ -1182,13 +1216,13 @@ vm_handle_hlt(struct vm *vm, int vcpuid, bool intr_disabled, bool *retu)
}
t = ticks;
vcpu_require_state_locked(vcpu, VCPU_SLEEPING);
vcpu_require_state_locked(vm, vcpuid, VCPU_SLEEPING);
/*
* XXX msleep_spin() cannot be interrupted by signals so
* wake up periodically to check pending signals.
*/
msleep_spin(vcpu, &vcpu->mtx, wmesg, hz);
vcpu_require_state_locked(vcpu, VCPU_FROZEN);
vcpu_require_state_locked(vm, vcpuid, VCPU_FROZEN);
vmm_stat_incr(vm, vcpuid, VCPU_IDLE_TICKS, ticks - t);
}
@ -1350,9 +1384,9 @@ vm_handle_suspend(struct vm *vm, int vcpuid, bool *retu)
if (vm->rendezvous_func == NULL) {
VCPU_CTR0(vm, vcpuid, "Sleeping during suspend");
vcpu_require_state_locked(vcpu, VCPU_SLEEPING);
vcpu_require_state_locked(vm, vcpuid, VCPU_SLEEPING);
msleep_spin(vcpu, &vcpu->mtx, "vmsusp", hz);
vcpu_require_state_locked(vcpu, VCPU_FROZEN);
vcpu_require_state_locked(vm, vcpuid, VCPU_FROZEN);
} else {
VCPU_CTR0(vm, vcpuid, "Rendezvous during suspend");
vcpu_unlock(vcpu);
@ -1375,6 +1409,19 @@ vm_handle_suspend(struct vm *vm, int vcpuid, bool *retu)
return (0);
}
static int
vm_handle_reqidle(struct vm *vm, int vcpuid, bool *retu)
{
struct vcpu *vcpu = &vm->vcpu[vcpuid];
vcpu_lock(vcpu);
KASSERT(vcpu->reqidle, ("invalid vcpu reqidle %d", vcpu->reqidle));
vcpu->reqidle = 0;
vcpu_unlock(vcpu);
*retu = true;
return (0);
}
int
vm_suspend(struct vm *vm, enum vm_suspend_how how)
{
@ -1431,6 +1478,18 @@ vm_exit_rendezvous(struct vm *vm, int vcpuid, uint64_t rip)
vmm_stat_incr(vm, vcpuid, VMEXIT_RENDEZVOUS, 1);
}
void
vm_exit_reqidle(struct vm *vm, int vcpuid, uint64_t rip)
{
struct vm_exit *vmexit;
vmexit = vm_exitinfo(vm, vcpuid);
vmexit->rip = rip;
vmexit->inst_length = 0;
vmexit->exitcode = VM_EXITCODE_REQIDLE;
vmm_stat_incr(vm, vcpuid, VMEXIT_REQIDLE, 1);
}
void
vm_exit_astpending(struct vm *vm, int vcpuid, uint64_t rip)
{
@ -1446,6 +1505,7 @@ vm_exit_astpending(struct vm *vm, int vcpuid, uint64_t rip)
int
vm_run(struct vm *vm, struct vm_run *vmrun)
{
struct vm_eventinfo evinfo;
int error, vcpuid;
struct vcpu *vcpu;
struct pcb *pcb;
@ -1453,7 +1513,6 @@ vm_run(struct vm *vm, struct vm_run *vmrun)
struct vm_exit *vme;
bool retu, intr_disabled;
pmap_t pmap;
void *rptr, *sptr;
vcpuid = vmrun->cpuid;
@ -1466,11 +1525,12 @@ vm_run(struct vm *vm, struct vm_run *vmrun)
if (CPU_ISSET(vcpuid, &vm->suspended_cpus))
return (EINVAL);
rptr = &vm->rendezvous_func;
sptr = &vm->suspend;
pmap = vmspace_pmap(vm->vmspace);
vcpu = &vm->vcpu[vcpuid];
vme = &vcpu->exitinfo;
evinfo.rptr = &vm->rendezvous_func;
evinfo.sptr = &vm->suspend;
evinfo.iptr = &vcpu->reqidle;
restart:
critical_enter();
@ -1485,7 +1545,7 @@ restart:
restore_guest_fpustate(vcpu);
vcpu_require_state(vm, vcpuid, VCPU_RUNNING);
error = VMRUN(vm->cookie, vcpuid, vcpu->nextrip, pmap, rptr, sptr);
error = VMRUN(vm->cookie, vcpuid, vcpu->nextrip, pmap, &evinfo);
vcpu_require_state(vm, vcpuid, VCPU_FROZEN);
save_guest_fpustate(vcpu);
@ -1498,6 +1558,9 @@ restart:
retu = false;
vcpu->nextrip = vme->rip + vme->inst_length;
switch (vme->exitcode) {
case VM_EXITCODE_REQIDLE:
error = vm_handle_reqidle(vm, vcpuid, &retu);
break;
case VM_EXITCODE_SUSPENDED:
error = vm_handle_suspend(vm, vcpuid, &retu);
break;
@ -1536,6 +1599,8 @@ restart:
if (error == 0 && retu == false)
goto restart;
VCPU_CTR2(vm, vcpuid, "retu %d/%d", error, vme->exitcode);
/* copy the exit information */
bcopy(vme, &vmrun->vm_exit, sizeof(struct vm_exit));
return (error);
@ -2072,7 +2137,7 @@ vcpu_set_state(struct vm *vm, int vcpuid, enum vcpu_state newstate,
vcpu = &vm->vcpu[vcpuid];
vcpu_lock(vcpu);
error = vcpu_set_state_locked(vcpu, newstate, from_idle);
error = vcpu_set_state_locked(vm, vcpuid, newstate, from_idle);
vcpu_unlock(vcpu);
return (error);
@ -2168,15 +2233,11 @@ vm_set_x2apic_state(struct vm *vm, int vcpuid, enum x2apic_state state)
* - If the vcpu is running on a different host_cpu then an IPI will be directed
* to the host_cpu to cause the vcpu to trap into the hypervisor.
*/
void
vcpu_notify_event(struct vm *vm, int vcpuid, bool lapic_intr)
static void
vcpu_notify_event_locked(struct vcpu *vcpu, bool lapic_intr)
{
int hostcpu;
struct vcpu *vcpu;
vcpu = &vm->vcpu[vcpuid];
vcpu_lock(vcpu);
hostcpu = vcpu->hostcpu;
if (vcpu->state == VCPU_RUNNING) {
KASSERT(hostcpu != NOCPU, ("vcpu running on invalid hostcpu"));
@ -2201,6 +2262,15 @@ vcpu_notify_event(struct vm *vm, int vcpuid, bool lapic_intr)
if (vcpu->state == VCPU_SLEEPING)
wakeup_one(vcpu);
}
}
void
vcpu_notify_event(struct vm *vm, int vcpuid, bool lapic_intr)
{
struct vcpu *vcpu = &vm->vcpu[vcpuid];
vcpu_lock(vcpu);
vcpu_notify_event_locked(vcpu, lapic_intr);
vcpu_unlock(vcpu);
}

View File

@ -164,6 +164,7 @@ VMM_STAT(VMEXIT_NESTED_FAULT, "vm exits due to nested page fault");
VMM_STAT(VMEXIT_INST_EMUL, "vm exits for instruction emulation");
VMM_STAT(VMEXIT_UNKNOWN, "number of vm exits for unknown reason");
VMM_STAT(VMEXIT_ASTPENDING, "number of times astpending at exit");
VMM_STAT(VMEXIT_REQIDLE, "number of times idle requested at exit");
VMM_STAT(VMEXIT_USERSPACE, "number of vm exits handled in userspace");
VMM_STAT(VMEXIT_RENDEZVOUS, "number of times rendezvous pending at exit");
VMM_STAT(VMEXIT_EXCEPTION, "number of vm exits due to exceptions");

View File

@ -157,4 +157,5 @@ VMM_STAT_DECLARE(VMEXIT_ASTPENDING);
VMM_STAT_DECLARE(VMEXIT_USERSPACE);
VMM_STAT_DECLARE(VMEXIT_RENDEZVOUS);
VMM_STAT_DECLARE(VMEXIT_EXCEPTION);
VMM_STAT_DECLARE(VMEXIT_REQIDLE);
#endif

View File

@ -697,6 +697,7 @@ zfsctl_unmount_snap(zfs_snapentry_t *sep, int fflags, cred_t *cr)
return (0);
#else
vfs_ref(vn_mountedvfs(svp));
return (dounmount(vn_mountedvfs(svp), fflags, curthread));
#endif
}

View File

@ -3481,6 +3481,7 @@ zfs_unmount_snap(const char *snapname)
#ifdef illumos
(void) dounmount(vfsp, MS_FORCE, kcred);
#else
vfs_ref(vfsp);
(void) dounmount(vfsp, MS_FORCE, curthread);
#endif
return (0);

View File

@ -2314,8 +2314,10 @@ bail:
* Since we couldn't setup the sa framework, try to force
* unmount this file system.
*/
if (vn_vfswlock(zfsvfs->z_vfs->vfs_vnodecovered) == 0)
if (vn_vfswlock(zfsvfs->z_vfs->vfs_vnodecovered) == 0) {
vfs_ref(zfsvfs->z_vfs);
(void) dounmount(zfsvfs->z_vfs, MS_FORCE, curthread);
}
}
return (err);
}

View File

@ -1427,6 +1427,8 @@ dev/hptiop/hptiop.c optional hptiop scbus
dev/hwpmc/hwpmc_logging.c optional hwpmc
dev/hwpmc/hwpmc_mod.c optional hwpmc
dev/hwpmc/hwpmc_soft.c optional hwpmc
dev/ichiic/ig4_iic.c optional ichiic
dev/ichiic/ig4_pci.c optional ichiic pci
dev/ichsmb/ichsmb.c optional ichsmb
dev/ichsmb/ichsmb_pci.c optional ichsmb pci
dev/ida/ida.c optional ida
@ -2024,6 +2026,7 @@ dev/pci/isa_pci.c optional pci isa
dev/pci/pci.c optional pci
dev/pci/pci_if.m standard
dev/pci/pci_iov.c optional pci pci_iov
dev/pci/pci_iov_if.m standard
dev/pci/pci_iov_schema.c optional pci pci_iov
dev/pci/pci_pci.c optional pci
dev/pci/pci_subr.c optional pci

View File

@ -349,7 +349,7 @@ MFILES?= dev/acpica/acpi_if.m dev/acpi_support/acpi_wmi_if.m \
dev/mbox/mbox_if.m dev/mmc/mmcbr_if.m dev/mmc/mmcbus_if.m \
dev/mii/miibus_if.m dev/mvs/mvs_if.m dev/ofw/ofw_bus_if.m \
dev/pccard/card_if.m dev/pccard/power_if.m dev/pci/pci_if.m \
dev/pci/pcib_if.m dev/ppbus/ppbus_if.m \
dev/pci/pci_iov_if.m dev/pci/pcib_if.m dev/ppbus/ppbus_if.m \
dev/sdhci/sdhci_if.m dev/smbus/smbus_if.m dev/spibus/spibus_if.m \
dev/sound/pci/hda/hdac_if.m \
dev/sound/pcm/ac97_if.m dev/sound/pcm/channel_if.m \

View File

@ -39,6 +39,7 @@ __FBSDID("$FreeBSD$");
#include "opt_acpi.h"
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/bus.h>
#include <machine/cpufunc.h>
@ -261,6 +262,37 @@ static struct {
{ NULL, 0, NULL, 0 }
};
/*
* Per-model default list of event mask.
*/
#define ACPI_IBM_HKEY_RFKILL_MASK (1 << 4)
#define ACPI_IBM_HKEY_DSWITCH_MASK (1 << 6)
#define ACPI_IBM_HKEY_BRIGHTNESS_UP_MASK (1 << 15)
#define ACPI_IBM_HKEY_BRIGHTNESS_DOWN_MASK (1 << 16)
#define ACPI_IBM_HKEY_SEARCH_MASK (1 << 18)
#define ACPI_IBM_HKEY_MICMUTE_MASK (1 << 26)
#define ACPI_IBM_HKEY_SETTINGS_MASK (1 << 28)
#define ACPI_IBM_HKEY_VIEWOPEN_MASK (1 << 30)
#define ACPI_IBM_HKEY_VIEWALL_MASK (1 << 31)
struct acpi_ibm_models {
const char *maker;
const char *product;
uint32_t eventmask;
} acpi_ibm_models[] = {
{ "LENOVO", "20BSCTO1WW",
ACPI_IBM_HKEY_RFKILL_MASK |
ACPI_IBM_HKEY_DSWITCH_MASK |
ACPI_IBM_HKEY_BRIGHTNESS_UP_MASK |
ACPI_IBM_HKEY_BRIGHTNESS_DOWN_MASK |
ACPI_IBM_HKEY_SEARCH_MASK |
ACPI_IBM_HKEY_MICMUTE_MASK |
ACPI_IBM_HKEY_SETTINGS_MASK |
ACPI_IBM_HKEY_VIEWOPEN_MASK |
ACPI_IBM_HKEY_VIEWALL_MASK
}
};
ACPI_SERIAL_DECL(ibm, "ACPI IBM extras");
static int acpi_ibm_probe(device_t dev);
@ -354,7 +386,9 @@ acpi_ibm_probe(device_t dev)
static int
acpi_ibm_attach(device_t dev)
{
int i;
struct acpi_ibm_softc *sc;
char *maker, *product;
devclass_t ec_devclass;
ACPI_FUNCTION_TRACE((char *)(uintptr_t) __func__);
@ -448,6 +482,27 @@ acpi_ibm_attach(device_t dev)
sc->led_dev = led_create_state(ibm_led, sc, "thinklight",
(sc->light_val ? 1 : 0));
/* Enable per-model events. */
maker = kern_getenv("smbios.system.maker");
product = kern_getenv("smbios.system.product");
for (i = 0; i < nitems(acpi_ibm_models); i++) {
if (strcmp(maker, acpi_ibm_models[i].maker) == 0 &&
strcmp(product, acpi_ibm_models[i].product) == 0) {
ACPI_SERIAL_BEGIN(ibm);
acpi_ibm_sysctl_set(sc, ACPI_IBM_METHOD_EVENTMASK,
acpi_ibm_models[i].eventmask);
ACPI_SERIAL_END(ibm);
}
}
freeenv(maker);
freeenv(product);
/* Enable events by default. */
ACPI_SERIAL_BEGIN(ibm);
acpi_ibm_sysctl_set(sc, ACPI_IBM_METHOD_EVENTS, 1);
ACPI_SERIAL_END(ibm);
return (0);
}
@ -770,7 +825,6 @@ acpi_ibm_sysctl_init(struct acpi_ibm_softc *sc, int method)
switch (method) {
case ACPI_IBM_METHOD_EVENTS:
/* Events are disabled by default */
return (TRUE);
case ACPI_IBM_METHOD_EVENTMASK:
@ -1229,7 +1283,6 @@ acpi_ibm_notify(ACPI_HANDLE h, UINT32 notify, void *context)
for (;;) {
acpi_GetInteger(acpi_get_handle(dev), IBM_NAME_EVENTS_GET, &event);
if (event == 0)
break;

View File

@ -843,9 +843,11 @@ update_stats(struct ath_softc *sc, struct ath_node *an,
}
static void
badrate(struct ifnet *ifp, int series, int hwrate, int tries, int status)
badrate(struct ath_softc *sc, int series, int hwrate, int tries, int status)
{
if_printf(ifp, "bad series%d hwrate 0x%x, tries %u ts_status 0x%x\n",
device_printf(sc->sc_dev,
"bad series%d hwrate 0x%x, tries %u ts_status 0x%x\n",
series, hwrate, tries, status);
}
@ -891,9 +893,10 @@ ath_rate_tx_complete(struct ath_softc *sc, struct ath_node *an,
if (!mrr || ts->ts_finaltsi == 0) {
if (!IS_RATE_DEFINED(sn, final_rix)) {
device_printf(sc->sc_dev, "%s: ts_rate=%d ts_finaltsi=%d, final_rix=%d\n",
device_printf(sc->sc_dev,
"%s: ts_rate=%d ts_finaltsi=%d, final_rix=%d\n",
__func__, ts->ts_rate, ts->ts_finaltsi, final_rix);
badrate(ifp, 0, ts->ts_rate, long_tries, status);
badrate(sc, 0, ts->ts_rate, long_tries, status);
return;
}
/*
@ -945,7 +948,7 @@ ath_rate_tx_complete(struct ath_softc *sc, struct ath_node *an,
for (i = 0; i < 4; i++) {
if (rc[i].tries && !IS_RATE_DEFINED(sn, rc[i].rix))
badrate(ifp, 0, rc[i].ratecode, rc[i].tries,
badrate(sc, 0, rc[i].ratecode, rc[i].tries,
status);
}

View File

@ -595,7 +595,6 @@ ath_attach(u_int16_t devid, struct ath_softc *sc)
ic->ic_softc = sc;
ic->ic_name = device_get_nameunit(sc->sc_dev);
/* set these up early for if_printf use */
if_initname(ifp, device_get_name(sc->sc_dev),
device_get_unit(sc->sc_dev));
CURVNET_RESTORE();
@ -612,8 +611,8 @@ ath_attach(u_int16_t devid, struct ath_softc *sc)
ah = ath_hal_attach(devid, sc, sc->sc_st, sc->sc_sh,
sc->sc_eepromdata, &ah_config, &status);
if (ah == NULL) {
if_printf(ifp, "unable to attach hardware; HAL status %u\n",
status);
device_printf(sc->sc_dev,
"unable to attach hardware; HAL status %u\n", status);
error = ENXIO;
goto bad;
}
@ -664,8 +663,9 @@ ath_attach(u_int16_t devid, struct ath_softc *sc)
*/
sc->sc_keymax = ath_hal_keycachesize(ah);
if (sc->sc_keymax > ATH_KEYMAX) {
if_printf(ifp, "Warning, using only %u of %u key cache slots\n",
ATH_KEYMAX, sc->sc_keymax);
device_printf(sc->sc_dev,
"Warning, using only %u of %u key cache slots\n",
ATH_KEYMAX, sc->sc_keymax);
sc->sc_keymax = ATH_KEYMAX;
}
/*
@ -704,14 +704,14 @@ ath_attach(u_int16_t devid, struct ath_softc *sc)
*/
error = ath_desc_alloc(sc);
if (error != 0) {
if_printf(ifp, "failed to allocate TX descriptors: %d\n",
error);
device_printf(sc->sc_dev,
"failed to allocate TX descriptors: %d\n", error);
goto bad;
}
error = ath_txdma_setup(sc);
if (error != 0) {
if_printf(ifp, "failed to allocate TX descriptors: %d\n",
error);
device_printf(sc->sc_dev,
"failed to allocate TX descriptors: %d\n", error);
goto bad;
}
@ -720,8 +720,8 @@ ath_attach(u_int16_t devid, struct ath_softc *sc)
*/
error = ath_rxdma_setup(sc);
if (error != 0) {
if_printf(ifp, "failed to allocate RX descriptors: %d\n",
error);
device_printf(sc->sc_dev,
"failed to allocate RX descriptors: %d\n", error);
goto bad;
}
@ -752,20 +752,22 @@ ath_attach(u_int16_t devid, struct ath_softc *sc)
*/
sc->sc_bhalq = ath_beaconq_setup(sc);
if (sc->sc_bhalq == (u_int) -1) {
if_printf(ifp, "unable to setup a beacon xmit queue!\n");
device_printf(sc->sc_dev,
"unable to setup a beacon xmit queue!\n");
error = EIO;
goto bad2;
}
sc->sc_cabq = ath_txq_setup(sc, HAL_TX_QUEUE_CAB, 0);
if (sc->sc_cabq == NULL) {
if_printf(ifp, "unable to setup CAB xmit queue!\n");
device_printf(sc->sc_dev, "unable to setup CAB xmit queue!\n");
error = EIO;
goto bad2;
}
/* NB: insure BK queue is the lowest priority h/w queue */
if (!ath_tx_setup(sc, WME_AC_BK, HAL_WME_AC_BK)) {
if_printf(ifp, "unable to setup xmit queue for %s traffic!\n",
ieee80211_wme_acnames[WME_AC_BK]);
device_printf(sc->sc_dev,
"unable to setup xmit queue for %s traffic!\n",
ieee80211_wme_acnames[WME_AC_BK]);
error = EIO;
goto bad2;
}
@ -1828,8 +1830,8 @@ ath_vap_delete(struct ieee80211vap *vap)
* be reset if we just destroyed the last vap).
*/
if (ath_startrecv(sc) != 0)
if_printf(ifp, "%s: unable to restart recv logic\n",
__func__);
device_printf(sc->sc_dev,
"%s: unable to restart recv logic\n", __func__);
if (sc->sc_beacons) { /* restart beacons */
#ifdef IEEE80211_SUPPORT_TDMA
if (sc->sc_tdma)
@ -2316,7 +2318,7 @@ ath_fatal_proc(void *arg, int pending)
u_int32_t len;
void *sp;
if_printf(ifp, "hardware error; resetting\n");
device_printf(sc->sc_dev, "hardware error; resetting\n");
/*
* Fatal errors are unrecoverable. Typically these
* are caused by DMA errors. Collect h/w state from
@ -2325,9 +2327,9 @@ ath_fatal_proc(void *arg, int pending)
if (ath_hal_getfatalstate(sc->sc_ah, &sp, &len)) {
KASSERT(len >= 6*sizeof(u_int32_t), ("len %u bytes", len));
state = sp;
if_printf(ifp, "0x%08x 0x%08x 0x%08x, 0x%08x 0x%08x 0x%08x\n",
state[0], state[1] , state[2], state[3],
state[4], state[5]);
device_printf(sc->sc_dev,
"0x%08x 0x%08x 0x%08x, 0x%08x 0x%08x 0x%08x\n", state[0],
state[1] , state[2], state[3], state[4], state[5]);
}
ath_reset(ifp, ATH_RESET_NOLOSS);
}
@ -2434,7 +2436,8 @@ ath_bmiss_proc(void *arg, int pending)
*/
if (ath_hal_gethangstate(sc->sc_ah, 0xff, &hangs) && hangs != 0) {
ath_reset(ifp, ATH_RESET_NOLOSS);
if_printf(ifp, "bb hang detected (0x%x), resetting\n", hangs);
device_printf(sc->sc_dev,
"bb hang detected (0x%x), resetting\n", hangs);
} else {
ath_reset(ifp, ATH_RESET_NOLOSS);
ieee80211_beacon_miss(ifp->if_l2com);
@ -2509,9 +2512,10 @@ ath_init(void *arg)
ath_hal_setchainmasks(sc->sc_ah, sc->sc_cur_txchainmask,
sc->sc_cur_rxchainmask);
if (!ath_hal_reset(ah, sc->sc_opmode, ic->ic_curchan, AH_FALSE, &status)) {
if_printf(ifp, "unable to reset hardware; hal status %u\n",
status);
if (!ath_hal_reset(ah, sc->sc_opmode, ic->ic_curchan, AH_FALSE,
&status)) {
device_printf(sc->sc_dev,
"unable to reset hardware; hal status %u\n", status);
ATH_UNLOCK(sc);
return;
}
@ -2569,7 +2573,7 @@ ath_init(void *arg)
* here except setup the interrupt mask.
*/
if (ath_startrecv(sc) != 0) {
if_printf(ifp, "unable to start recv logic\n");
device_printf(sc->sc_dev, "unable to start recv logic\n");
ath_power_restore_power_state(sc);
ATH_UNLOCK(sc);
return;
@ -2911,8 +2915,9 @@ ath_reset(struct ifnet *ifp, ATH_RESET_TYPE reset_type)
ath_hal_setchainmasks(sc->sc_ah, sc->sc_cur_txchainmask,
sc->sc_cur_rxchainmask);
if (!ath_hal_reset(ah, sc->sc_opmode, ic->ic_curchan, AH_TRUE, &status))
if_printf(ifp, "%s: unable to reset hardware; hal status %u\n",
__func__, status);
device_printf(sc->sc_dev,
"%s: unable to reset hardware; hal status %u\n",
__func__, status);
sc->sc_diversity = ath_hal_getdiversity(ah);
ATH_RX_LOCK(sc);
@ -2941,7 +2946,8 @@ ath_reset(struct ifnet *ifp, ATH_RESET_TYPE reset_type)
ath_hal_setenforcetxop(sc->sc_ah, 0);
if (ath_startrecv(sc) != 0) /* restart recv */
if_printf(ifp, "%s: unable to start recv logic\n", __func__);
device_printf(sc->sc_dev,
"%s: unable to start recv logic\n", __func__);
/*
* We may be doing a reset in response to an ioctl
* that changes the channel so update any state that
@ -3747,7 +3753,7 @@ ath_reset_proc(void *arg, int pending)
struct ifnet *ifp = sc->sc_ifp;
#if 0
if_printf(ifp, "%s: resetting\n", __func__);
device_printf(sc->sc_dev, "%s: resetting\n", __func__);
#endif
ath_reset(ifp, ATH_RESET_NOLOSS);
}
@ -3763,15 +3769,15 @@ ath_bstuck_proc(void *arg, int pending)
uint32_t hangs = 0;
if (ath_hal_gethangstate(sc->sc_ah, 0xff, &hangs) && hangs != 0)
if_printf(ifp, "bb hang detected (0x%x)\n", hangs);
device_printf(sc->sc_dev, "bb hang detected (0x%x)\n", hangs);
#ifdef ATH_DEBUG_ALQ
if (if_ath_alq_checkdebug(&sc->sc_alq, ATH_ALQ_STUCK_BEACON))
if_ath_alq_post(&sc->sc_alq, ATH_ALQ_STUCK_BEACON, 0, NULL);
#endif
if_printf(ifp, "stuck beacon; resetting (bmiss count %u)\n",
sc->sc_bmisscount);
device_printf(sc->sc_dev, "stuck beacon; resetting (bmiss count %u)\n",
sc->sc_bmisscount);
sc->sc_stats.ast_bstuck++;
/*
* This assumes that there's no simultaneous channel mode change
@ -3803,7 +3809,6 @@ ath_descdma_alloc_desc(struct ath_softc *sc,
((_dd)->dd_desc_paddr + ((caddr_t)(_ds) - (caddr_t)(_dd)->dd_desc))
#define ATH_DESC_4KB_BOUND_CHECK(_daddr, _len) \
((((u_int32_t)(_daddr) & 0xFFF) > (0x1000 - (_len))) ? 1 : 0)
struct ifnet *ifp = sc->sc_ifp;
int error;
dd->dd_descsize = ds_size;
@ -3844,7 +3849,8 @@ ath_descdma_alloc_desc(struct ath_softc *sc,
NULL, /* lockarg */
&dd->dd_dmat);
if (error != 0) {
if_printf(ifp, "cannot allocate %s DMA tag\n", dd->dd_name);
device_printf(sc->sc_dev,
"cannot allocate %s DMA tag\n", dd->dd_name);
return error;
}
@ -3853,8 +3859,9 @@ ath_descdma_alloc_desc(struct ath_softc *sc,
BUS_DMA_NOWAIT | BUS_DMA_COHERENT,
&dd->dd_dmamap);
if (error != 0) {
if_printf(ifp, "unable to alloc memory for %u %s descriptors, "
"error %u\n", ndesc, dd->dd_name, error);
device_printf(sc->sc_dev,
"unable to alloc memory for %u %s descriptors, error %u\n",
ndesc, dd->dd_name, error);
goto fail1;
}
@ -3863,8 +3870,9 @@ ath_descdma_alloc_desc(struct ath_softc *sc,
ath_load_cb, &dd->dd_desc_paddr,
BUS_DMA_NOWAIT);
if (error != 0) {
if_printf(ifp, "unable to map %s descriptors, error %u\n",
dd->dd_name, error);
device_printf(sc->sc_dev,
"unable to map %s descriptors, error %u\n",
dd->dd_name, error);
goto fail2;
}
@ -3894,7 +3902,6 @@ ath_descdma_setup(struct ath_softc *sc,
((_dd)->dd_desc_paddr + ((caddr_t)(_ds) - (caddr_t)(_dd)->dd_desc))
#define ATH_DESC_4KB_BOUND_CHECK(_daddr, _len) \
((((u_int32_t)(_daddr) & 0xFFF) > (0x1000 - (_len))) ? 1 : 0)
struct ifnet *ifp = sc->sc_ifp;
uint8_t *ds;
struct ath_buf *bf;
int i, bsize, error;
@ -3914,8 +3921,9 @@ ath_descdma_setup(struct ath_softc *sc,
bsize = sizeof(struct ath_buf) * nbuf;
bf = malloc(bsize, M_ATHDEV, M_NOWAIT | M_ZERO);
if (bf == NULL) {
if_printf(ifp, "malloc of %s buffers failed, size %u\n",
dd->dd_name, bsize);
device_printf(sc->sc_dev,
"malloc of %s buffers failed, size %u\n",
dd->dd_name, bsize);
goto fail3;
}
dd->dd_bufptr = bf;
@ -3941,8 +3949,9 @@ ath_descdma_setup(struct ath_softc *sc,
error = bus_dmamap_create(sc->sc_dmat, BUS_DMA_NOWAIT,
&bf->bf_dmamap);
if (error != 0) {
if_printf(ifp, "unable to create dmamap for %s "
"buffer %u, error %u\n", dd->dd_name, i, error);
device_printf(sc->sc_dev, "unable to create dmamap "
"for %s buffer %u, error %u\n",
dd->dd_name, i, error);
ath_descdma_cleanup(sc, dd, head);
return error;
}
@ -3978,7 +3987,6 @@ ath_descdma_setup_rx_edma(struct ath_softc *sc,
struct ath_descdma *dd, ath_bufhead *head,
const char *name, int nbuf, int rx_status_len)
{
struct ifnet *ifp = sc->sc_ifp;
struct ath_buf *bf;
int i, bsize, error;
@ -4001,8 +4009,9 @@ ath_descdma_setup_rx_edma(struct ath_softc *sc,
bsize = sizeof(struct ath_buf) * nbuf;
bf = malloc(bsize, M_ATHDEV, M_NOWAIT | M_ZERO);
if (bf == NULL) {
if_printf(ifp, "malloc of %s buffers failed, size %u\n",
dd->dd_name, bsize);
device_printf(sc->sc_dev,
"malloc of %s buffers failed, size %u\n",
dd->dd_name, bsize);
error = ENOMEM;
goto fail3;
}
@ -4017,8 +4026,9 @@ ath_descdma_setup_rx_edma(struct ath_softc *sc,
error = bus_dmamap_create(sc->sc_dmat, BUS_DMA_NOWAIT,
&bf->bf_dmamap);
if (error != 0) {
if_printf(ifp, "unable to create dmamap for %s "
"buffer %u, error %u\n", dd->dd_name, i, error);
device_printf(sc->sc_dev, "unable to create dmamap "
"for %s buffer %u, error %u\n",
dd->dd_name, i, error);
ath_descdma_cleanup(sc, dd, head);
return error;
}
@ -4392,9 +4402,8 @@ ath_txq_update(struct ath_softc *sc, int ac)
qi.tqi_aifs, qi.tqi_cwmin, qi.tqi_cwmax, qi.tqi_burstTime);
if (!ath_hal_settxqueueprops(ah, txq->axq_qnum, &qi)) {
if_printf(ifp, "unable to update hardware queue "
"parameters for %s traffic!\n",
ieee80211_wme_acnames[ac]);
device_printf(sc->sc_dev, "unable to update hardware queue "
"parameters for %s traffic!\n", ieee80211_wme_acnames[ac]);
return 0;
} else {
ath_hal_resettxqueue(ah, txq->axq_qnum); /* push to h/w */
@ -5560,7 +5569,7 @@ ath_chan_set(struct ath_softc *sc, struct ieee80211_channel *chan)
ath_hal_setchainmasks(sc->sc_ah, sc->sc_cur_txchainmask,
sc->sc_cur_rxchainmask);
if (!ath_hal_reset(ah, sc->sc_opmode, chan, AH_TRUE, &status)) {
if_printf(ifp, "%s: unable to reset "
device_printf(sc->sc_dev, "%s: unable to reset "
"channel %u (%u MHz, flags 0x%x), hal status %u\n",
__func__, ieee80211_chan2ieee(ic, chan),
chan->ic_freq, chan->ic_flags, status);
@ -5599,8 +5608,8 @@ ath_chan_set(struct ath_softc *sc, struct ieee80211_channel *chan)
* Re-enable rx framework.
*/
if (ath_startrecv(sc) != 0) {
if_printf(ifp, "%s: unable to restart recv logic\n",
__func__);
device_printf(sc->sc_dev,
"%s: unable to restart recv logic\n", __func__);
ret = EIO;
goto finish;
}
@ -6375,8 +6384,9 @@ ath_getchannels(struct ath_softc *sc)
status = ath_hal_init_channels(ah, ic->ic_channels, IEEE80211_CHAN_MAX,
&ic->ic_nchans, HAL_MODE_ALL, CTRY_DEFAULT, SKU_NONE, AH_TRUE);
if (status != HAL_OK) {
if_printf(ifp, "%s: unable to collect channel list from hal, "
"status %d\n", __func__, status);
device_printf(sc->sc_dev,
"%s: unable to collect channel list from hal, status %d\n",
__func__, status);
return EINVAL;
}
(void) ath_hal_getregdomain(ah, &sc->sc_eerd);
@ -6538,10 +6548,10 @@ ath_watchdog(void *arg)
if (ath_hal_gethangstate(sc->sc_ah, 0xffff, &hangs) &&
hangs != 0) {
if_printf(ifp, "%s hang detected (0x%x)\n",
device_printf(sc->sc_dev, "%s hang detected (0x%x)\n",
hangs & 0xff ? "bb" : "mac", hangs);
} else
if_printf(ifp, "device timeout\n");
device_printf(sc->sc_dev, "device timeout\n");
do_reset = 1;
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
sc->sc_stats.ast_watchdog++;
@ -6786,31 +6796,32 @@ ath_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
static void
ath_announce(struct ath_softc *sc)
{
struct ifnet *ifp = sc->sc_ifp;
struct ath_hal *ah = sc->sc_ah;
if_printf(ifp, "AR%s mac %d.%d RF%s phy %d.%d\n",
device_printf(sc->sc_dev, "AR%s mac %d.%d RF%s phy %d.%d\n",
ath_hal_mac_name(ah), ah->ah_macVersion, ah->ah_macRev,
ath_hal_rf_name(ah), ah->ah_phyRev >> 4, ah->ah_phyRev & 0xf);
if_printf(ifp, "2GHz radio: 0x%.4x; 5GHz radio: 0x%.4x\n",
device_printf(sc->sc_dev, "2GHz radio: 0x%.4x; 5GHz radio: 0x%.4x\n",
ah->ah_analog2GhzRev, ah->ah_analog5GhzRev);
if (bootverbose) {
int i;
for (i = 0; i <= WME_AC_VO; i++) {
struct ath_txq *txq = sc->sc_ac2q[i];
if_printf(ifp, "Use hw queue %u for %s traffic\n",
txq->axq_qnum, ieee80211_wme_acnames[i]);
device_printf(sc->sc_dev,
"Use hw queue %u for %s traffic\n",
txq->axq_qnum, ieee80211_wme_acnames[i]);
}
if_printf(ifp, "Use hw queue %u for CAB traffic\n",
sc->sc_cabq->axq_qnum);
if_printf(ifp, "Use hw queue %u for beacons\n", sc->sc_bhalq);
device_printf(sc->sc_dev, "Use hw queue %u for CAB traffic\n",
sc->sc_cabq->axq_qnum);
device_printf(sc->sc_dev, "Use hw queue %u for beacons\n",
sc->sc_bhalq);
}
if (ath_rxbuf != ATH_RXBUF)
if_printf(ifp, "using %u rx buffers\n", ath_rxbuf);
device_printf(sc->sc_dev, "using %u rx buffers\n", ath_rxbuf);
if (ath_txbuf != ATH_TXBUF)
if_printf(ifp, "using %u tx buffers\n", ath_txbuf);
device_printf(sc->sc_dev, "using %u tx buffers\n", ath_txbuf);
if (sc->sc_mcastkey && bootverbose)
if_printf(ifp, "using multicast key search\n");
device_printf(sc->sc_dev, "using multicast key search\n");
}
static void

View File

@ -1037,7 +1037,7 @@ ath_rx_proc(struct ath_softc *sc, int resched)
bf = TAILQ_FIRST(&sc->sc_rxbuf);
if (sc->sc_rxslink && bf == NULL) { /* NB: shouldn't happen */
if_printf(ifp, "%s: no buffer!\n", __func__);
device_printf(sc->sc_dev, "%s: no buffer!\n", __func__);
break;
} else if (bf == NULL) {
/*
@ -1054,7 +1054,7 @@ ath_rx_proc(struct ath_softc *sc, int resched)
* will be no mbuf; try again to re-populate it.
*/
/* XXX make debug msg */
if_printf(ifp, "%s: no mbuf!\n", __func__);
device_printf(sc->sc_dev, "%s: no mbuf!\n", __func__);
TAILQ_REMOVE(&sc->sc_rxbuf, bf, bf_list);
goto rx_proc_next;
}

View File

@ -259,7 +259,7 @@ ath_tdma_config(struct ath_softc *sc, struct ieee80211vap *vap)
if (vap == NULL) {
vap = TAILQ_FIRST(&ic->ic_vaps); /* XXX */
if (vap == NULL) {
if_printf(ifp, "%s: no vaps?\n", __func__);
device_printf(sc->sc_dev, "%s: no vaps?\n", __func__);
return;
}
}

View File

@ -1691,8 +1691,8 @@ ath_tx_normal_setup(struct ath_softc *sc, struct ieee80211_node *ni,
flags |= HAL_TXDESC_NOACK;
break;
default:
if_printf(ifp, "bogus frame type 0x%x (%s)\n",
wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK, __func__);
device_printf(sc->sc_dev, "bogus frame type 0x%x (%s)\n",
wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK, __func__);
/* XXX statistic */
/* XXX free tx dmamap */
ath_freetx(m0);

View File

@ -101,7 +101,6 @@ static void bwi_mac_opmode_init(struct bwi_mac *);
static void bwi_mac_hostflags_init(struct bwi_mac *);
static void bwi_mac_bss_param_init(struct bwi_mac *);
static int bwi_mac_fw_alloc(struct bwi_mac *);
static void bwi_mac_fw_free(struct bwi_mac *);
static int bwi_mac_fw_load(struct bwi_mac *);
static int bwi_mac_fw_init(struct bwi_mac *);
@ -325,10 +324,6 @@ bwi_mac_init(struct bwi_mac *mac)
/*
* Load and initialize firmwares
*/
error = bwi_mac_fw_alloc(mac);
if (error)
return error;
error = bwi_mac_fw_load(mac);
if (error)
return error;
@ -879,11 +874,10 @@ bwi_fwimage_is_valid(struct bwi_softc *sc, const struct firmware *fw,
/*
* XXX Error cleanup
*/
static int
int
bwi_mac_fw_alloc(struct bwi_mac *mac)
{
struct bwi_softc *sc = mac->mac_sc;
struct ifnet *ifp = sc->sc_ifp;
char fwname[64];
int idx;
@ -895,10 +889,8 @@ bwi_mac_fw_alloc(struct bwi_mac *mac)
snprintf(fwname, sizeof(fwname), BWI_FW_STUB_PATH,
sc->sc_fw_version);
mac->mac_stub = firmware_get(fwname);
if (mac->mac_stub == NULL) {
if_printf(ifp, "request firmware %s failed\n", fwname);
return ENOMEM;
}
if (mac->mac_stub == NULL)
goto no_firmware;
}
if (mac->mac_ucode == NULL) {
@ -907,11 +899,8 @@ bwi_mac_fw_alloc(struct bwi_mac *mac)
mac->mac_rev >= 5 ? 5 : mac->mac_rev);
mac->mac_ucode = firmware_get(fwname);
if (mac->mac_ucode == NULL) {
if_printf(ifp, "request firmware %s failed\n", fwname);
return ENOMEM;
}
if (mac->mac_ucode == NULL)
goto no_firmware;
if (!bwi_fwimage_is_valid(sc, mac->mac_ucode, BWI_FW_T_UCODE))
return EINVAL;
}
@ -922,11 +911,8 @@ bwi_mac_fw_alloc(struct bwi_mac *mac)
mac->mac_rev < 5 ? 4 : 5);
mac->mac_pcm = firmware_get(fwname);
if (mac->mac_pcm == NULL) {
if_printf(ifp, "request firmware %s failed\n", fwname);
return ENOMEM;
}
if (mac->mac_pcm == NULL)
goto no_firmware;
if (!bwi_fwimage_is_valid(sc, mac->mac_pcm, BWI_FW_T_PCM))
return EINVAL;
}
@ -938,8 +924,8 @@ bwi_mac_fw_alloc(struct bwi_mac *mac)
} else if (mac->mac_rev >= 5 && mac->mac_rev <= 10) {
idx = 5;
} else {
if_printf(ifp, "no suitible IV for MAC rev %d\n",
mac->mac_rev);
device_printf(sc->sc_dev,
"no suitible IV for MAC rev %d\n", mac->mac_rev);
return ENODEV;
}
@ -947,10 +933,8 @@ bwi_mac_fw_alloc(struct bwi_mac *mac)
sc->sc_fw_version, idx);
mac->mac_iv = firmware_get(fwname);
if (mac->mac_iv == NULL) {
if_printf(ifp, "request firmware %s failed\n", fwname);
return ENOMEM;
}
if (mac->mac_iv == NULL)
goto no_firmware;
if (!bwi_fwimage_is_valid(sc, mac->mac_iv, BWI_FW_T_IV))
return EINVAL;
}
@ -960,12 +944,12 @@ bwi_mac_fw_alloc(struct bwi_mac *mac)
if (mac->mac_rev == 2 || mac->mac_rev == 4 ||
mac->mac_rev >= 11) {
/* No extended IV */
goto back;
return (0);
} else if (mac->mac_rev >= 5 && mac->mac_rev <= 10) {
idx = 5;
} else {
if_printf(ifp, "no suitible ExtIV for MAC rev %d\n",
mac->mac_rev);
device_printf(sc->sc_dev,
"no suitible ExtIV for MAC rev %d\n", mac->mac_rev);
return ENODEV;
}
@ -973,15 +957,16 @@ bwi_mac_fw_alloc(struct bwi_mac *mac)
sc->sc_fw_version, idx);
mac->mac_iv_ext = firmware_get(fwname);
if (mac->mac_iv_ext == NULL) {
if_printf(ifp, "request firmware %s failed\n", fwname);
return ENOMEM;
}
if (mac->mac_iv_ext == NULL)
goto no_firmware;
if (!bwi_fwimage_is_valid(sc, mac->mac_iv_ext, BWI_FW_T_IV))
return EINVAL;
}
back:
return 0;
return (0);
no_firmware:
device_printf(sc->sc_dev, "request firmware %s failed\n", fwname);
return (ENOENT);
}
static void

View File

@ -57,6 +57,7 @@ void bwi_mac_init_tpctl_11bg(struct bwi_mac *);
void bwi_mac_dummy_xmit(struct bwi_mac *);
void bwi_mac_reset_hwkeys(struct bwi_mac *);
int bwi_mac_config_ps(struct bwi_mac *);
int bwi_mac_fw_alloc(struct bwi_mac *);
uint16_t bwi_memobj_read_2(struct bwi_mac *, uint16_t, uint16_t);
uint32_t bwi_memobj_read_4(struct bwi_mac *, uint16_t, uint16_t);

View File

@ -446,6 +446,10 @@ bwi_attach(struct bwi_softc *sc)
if (error)
goto fail;
error = bwi_mac_fw_alloc(mac);
if (error)
goto fail;
ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211);
if (ifp == NULL) {
device_printf(dev, "can not if_alloc()\n");
@ -1921,7 +1925,7 @@ bwi_dma_alloc(struct bwi_softc *sc)
BUS_SPACE_MAXSIZE, /* maxsize */
BUS_SPACE_UNRESTRICTED, /* nsegments */
BUS_SPACE_MAXSIZE_32BIT, /* maxsegsize */
BUS_DMA_ALLOCNOW, /* flags */
0, /* flags */
NULL, NULL, /* lockfunc, lockarg */
&sc->sc_parent_dtag);
if (error) {
@ -1941,8 +1945,8 @@ bwi_dma_alloc(struct bwi_softc *sc)
NULL, NULL,
tx_ring_sz,
1,
BUS_SPACE_MAXSIZE_32BIT,
BUS_DMA_ALLOCNOW,
tx_ring_sz,
0,
NULL, NULL,
&sc->sc_txring_dtag);
if (error) {
@ -1971,8 +1975,8 @@ bwi_dma_alloc(struct bwi_softc *sc)
NULL, NULL,
rx_ring_sz,
1,
BUS_SPACE_MAXSIZE_32BIT,
BUS_DMA_ALLOCNOW,
rx_ring_sz,
0,
NULL, NULL,
&sc->sc_rxring_dtag);
if (error) {
@ -2096,8 +2100,8 @@ bwi_dma_txstats_alloc(struct bwi_softc *sc, uint32_t ctrl_base,
NULL, NULL,
dma_size,
1,
BUS_SPACE_MAXSIZE_32BIT,
BUS_DMA_ALLOCNOW,
dma_size,
0,
NULL, NULL,
&st->stats_ring_dtag);
if (error) {
@ -2144,8 +2148,8 @@ bwi_dma_txstats_alloc(struct bwi_softc *sc, uint32_t ctrl_base,
NULL, NULL,
dma_size,
1,
BUS_SPACE_MAXSIZE_32BIT,
BUS_DMA_ALLOCNOW,
dma_size,
0,
NULL, NULL,
&st->stats_dtag);
if (error) {
@ -2227,7 +2231,7 @@ bwi_dma_mbuf_create(struct bwi_softc *sc)
NULL, NULL,
MCLBYTES,
1,
BUS_SPACE_MAXSIZE_32BIT,
MCLBYTES,
BUS_DMA_ALLOCNOW,
NULL, NULL,
&sc->sc_buf_dtag);

View File

@ -161,12 +161,6 @@ bwi_pci_attach(device_t dev)
device_printf(dev, "could not map interrupt\n");
goto bad1;
}
if (bus_setup_intr(dev, sc->sc_irq_res,
INTR_TYPE_NET | INTR_MPSAFE,
NULL, bwi_intr, sc, &sc->sc_irq_handle)) {
device_printf(dev, "could not establish interrupt\n");
goto bad2;
}
/* Get more PCI information */
sc->sc_pci_did = pci_get_device(dev);
@ -174,11 +168,17 @@ bwi_pci_attach(device_t dev)
sc->sc_pci_subvid = pci_get_subvendor(dev);
sc->sc_pci_subdid = pci_get_subdevice(dev);
error = bwi_attach(sc);
if (error == 0) /* success */
return 0;
if ((error = bwi_attach(sc)) != 0)
goto bad2;
if (bus_setup_intr(dev, sc->sc_irq_res,
INTR_TYPE_NET | INTR_MPSAFE,
NULL, bwi_intr, sc, &sc->sc_irq_handle)) {
device_printf(dev, "could not establish interrupt\n");
goto bad2;
}
return (0);
bus_teardown_intr(dev, sc->sc_irq_res, sc->sc_irq_handle);
bad2:
bus_release_resource(dev, SYS_RES_IRQ, 0, sc->sc_irq_res);
bad1:

966
sys/dev/ichiic/ig4_iic.c Normal file
View File

@ -0,0 +1,966 @@
/*
* Copyright (c) 2014 The DragonFly Project. All rights reserved.
*
* This code is derived from software contributed to The DragonFly Project
* by Matthew Dillon <dillon@backplane.com> and was subsequently ported
* to FreeBSD by Michael Gmelin <freebsd@grem.de>
*
* 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.
* 3. Neither the name of The DragonFly Project nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific, prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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
* COPYRIGHT HOLDERS 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.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
/*
* Intel fourth generation mobile cpus integrated I2C device, smbus driver.
*
* See ig4_reg.h for datasheet reference and notes.
*/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/module.h>
#include <sys/errno.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/syslog.h>
#include <sys/bus.h>
#include <sys/sysctl.h>
#include <machine/bus.h>
#include <sys/rman.h>
#include <dev/pci/pcivar.h>
#include <dev/pci/pcireg.h>
#include <dev/smbus/smbconf.h>
#include <dev/ichiic/ig4_reg.h>
#include <dev/ichiic/ig4_var.h>
#define TRANS_NORMAL 1
#define TRANS_PCALL 2
#define TRANS_BLOCK 3
static void ig4iic_start(void *xdev);
static void ig4iic_intr(void *cookie);
static void ig4iic_dump(ig4iic_softc_t *sc);
static int ig4_dump;
SYSCTL_INT(_debug, OID_AUTO, ig4_dump, CTLTYPE_INT | CTLFLAG_RW,
&ig4_dump, 0, "");
/*
* Low-level inline support functions
*/
static __inline void
reg_write(ig4iic_softc_t *sc, uint32_t reg, uint32_t value)
{
bus_write_4(sc->regs_res, reg, value);
bus_barrier(sc->regs_res, reg, 4, BUS_SPACE_BARRIER_WRITE);
}
static __inline uint32_t
reg_read(ig4iic_softc_t *sc, uint32_t reg)
{
uint32_t value;
bus_barrier(sc->regs_res, reg, 4, BUS_SPACE_BARRIER_READ);
value = bus_read_4(sc->regs_res, reg);
return (value);
}
/*
* Enable or disable the controller and wait for the controller to acknowledge
* the state change.
*/
static int
set_controller(ig4iic_softc_t *sc, uint32_t ctl)
{
int retry;
int error;
uint32_t v;
reg_write(sc, IG4_REG_I2C_EN, ctl);
error = SMB_ETIMEOUT;
for (retry = 100; retry > 0; --retry) {
v = reg_read(sc, IG4_REG_ENABLE_STATUS);
if (((v ^ ctl) & IG4_I2C_ENABLE) == 0) {
error = 0;
break;
}
mtx_sleep(sc, &sc->mutex, 0, "i2cslv", 1);
}
return (error);
}
/*
* Wait up to 25ms for the requested status using a 25uS polling loop.
*/
static int
wait_status(ig4iic_softc_t *sc, uint32_t status)
{
uint32_t v;
int error;
int txlvl = -1;
u_int count_us = 0;
u_int limit_us = 25000; /* 25ms */
error = SMB_ETIMEOUT;
for (;;) {
/*
* Check requested status
*/
v = reg_read(sc, IG4_REG_I2C_STA);
if (v & status) {
error = 0;
break;
}
/*
* When waiting for receive data break-out if the interrupt
* loaded data into the FIFO.
*/
if (status & IG4_STATUS_RX_NOTEMPTY) {
if (sc->rpos != sc->rnext) {
error = 0;
break;
}
}
/*
* When waiting for the transmit FIFO to become empty,
* reset the timeout if we see a change in the transmit
* FIFO level as progress is being made.
*/
if (status & IG4_STATUS_TX_EMPTY) {
v = reg_read(sc, IG4_REG_TXFLR) & IG4_FIFOLVL_MASK;
if (txlvl != v) {
txlvl = v;
count_us = 0;
}
}
/*
* Stop if we've run out of time.
*/
if (count_us >= limit_us)
break;
/*
* When waiting for receive data let the interrupt do its
* work, otherwise poll with the lock held.
*/
if (status & IG4_STATUS_RX_NOTEMPTY) {
mtx_sleep(sc, &sc->mutex, PZERO, "i2cwait",
(hz + 99) / 100); /* sleep up to 10ms */
count_us += 10000;
} else {
DELAY(25);
count_us += 25;
}
}
return (error);
}
/*
* Read I2C data. The data might have already been read by
* the interrupt code, otherwise it is sitting in the data
* register.
*/
static uint8_t
data_read(ig4iic_softc_t *sc)
{
uint8_t c;
if (sc->rpos == sc->rnext) {
c = (uint8_t)reg_read(sc, IG4_REG_DATA_CMD);
} else {
c = sc->rbuf[sc->rpos & IG4_RBUFMASK];
++sc->rpos;
}
return (c);
}
/*
* Set the slave address. The controller must be disabled when
* changing the address.
*
* This operation does not issue anything to the I2C bus but sets
* the target address for when the controller later issues a START.
*/
static void
set_slave_addr(ig4iic_softc_t *sc, uint8_t slave, int trans_op)
{
uint32_t tar;
uint32_t ctl;
int use_10bit;
use_10bit = sc->use_10bit;
if (trans_op & SMB_TRANS_7BIT)
use_10bit = 0;
if (trans_op & SMB_TRANS_10BIT)
use_10bit = 1;
if (sc->slave_valid && sc->last_slave == slave &&
sc->use_10bit == use_10bit) {
return;
}
sc->use_10bit = use_10bit;
/*
* Wait for TXFIFO to drain before disabling the controller.
*
* If a write message has not been completed it's really a
* programming error, but for now in that case issue an extra
* byte + STOP.
*
* If a read message has not been completed it's also a programming
* error, for now just ignore it.
*/
wait_status(sc, IG4_STATUS_TX_NOTFULL);
if (sc->write_started) {
reg_write(sc, IG4_REG_DATA_CMD, IG4_DATA_STOP);
sc->write_started = 0;
}
if (sc->read_started)
sc->read_started = 0;
wait_status(sc, IG4_STATUS_TX_EMPTY);
set_controller(sc, 0);
ctl = reg_read(sc, IG4_REG_CTL);
ctl &= ~IG4_CTL_10BIT;
ctl |= IG4_CTL_RESTARTEN;
tar = slave;
if (sc->use_10bit) {
tar |= IG4_TAR_10BIT;
ctl |= IG4_CTL_10BIT;
}
reg_write(sc, IG4_REG_CTL, ctl);
reg_write(sc, IG4_REG_TAR_ADD, tar);
set_controller(sc, IG4_I2C_ENABLE);
sc->slave_valid = 1;
sc->last_slave = slave;
}
/*
* Issue START with byte command, possible count, and a variable length
* read or write buffer, then possible turn-around read. The read also
* has a possible count received.
*
* For SMBUS -
*
* Quick: START+ADDR+RD/WR STOP
*
* Normal: START+ADDR+WR CMD DATA..DATA STOP
*
* START+ADDR+RD CMD
* RESTART+ADDR RDATA..RDATA STOP
* (can also be used for I2C transactions)
*
* Process Call: START+ADDR+WR CMD DATAL DATAH
* RESTART+ADDR+RD RDATAL RDATAH STOP
*
* Block: START+ADDR+RD CMD
* RESTART+ADDR+RD RCOUNT DATA... STOP
*
* START+ADDR+WR CMD
* RESTART+ADDR+WR WCOUNT DATA... STOP
*
* For I2C - basically, no *COUNT fields, possibly no *CMD field. If the
* sender needs to issue a 2-byte command it will incorporate it
* into the write buffer and also set NOCMD.
*
* Generally speaking, the START+ADDR / RESTART+ADDR is handled automatically
* by the controller at the beginning of a command sequence or on a data
* direction turn-around, and we only need to tell it when to issue the STOP.
*/
static int
smb_transaction(ig4iic_softc_t *sc, char cmd, int op,
char *wbuf, int wcount, char *rbuf, int rcount, int *actualp)
{
int error;
int unit;
uint32_t last;
/*
* Debugging - dump registers
*/
if (ig4_dump) {
unit = device_get_unit(sc->dev);
if (ig4_dump & (1 << unit)) {
ig4_dump &= ~(1 << unit);
ig4iic_dump(sc);
}
}
/*
* Issue START or RESTART with next data byte, clear any previous
* abort condition that may have been holding the txfifo in reset.
*/
last = IG4_DATA_RESTART;
reg_read(sc, IG4_REG_CLR_TX_ABORT);
if (actualp)
*actualp = 0;
/*
* Issue command if not told otherwise (smbus).
*/
if ((op & SMB_TRANS_NOCMD) == 0) {
error = wait_status(sc, IG4_STATUS_TX_NOTFULL);
if (error)
goto done;
last |= (u_char)cmd;
if (wcount == 0 && rcount == 0 && (op & SMB_TRANS_NOSTOP) == 0)
last |= IG4_DATA_STOP;
reg_write(sc, IG4_REG_DATA_CMD, last);
last = 0;
}
/*
* Clean out any previously received data.
*/
if (sc->rpos != sc->rnext &&
(op & SMB_TRANS_NOREPORT) == 0) {
device_printf(sc->dev,
"discarding %d bytes of spurious data\n",
sc->rnext - sc->rpos);
}
sc->rpos = 0;
sc->rnext = 0;
/*
* If writing and not told otherwise, issue the write count (smbus).
*/
if (wcount && (op & SMB_TRANS_NOCNT) == 0) {
error = wait_status(sc, IG4_STATUS_TX_NOTFULL);
if (error)
goto done;
last |= (u_char)cmd;
reg_write(sc, IG4_REG_DATA_CMD, last);
last = 0;
}
/*
* Bulk write (i2c)
*/
while (wcount) {
error = wait_status(sc, IG4_STATUS_TX_NOTFULL);
if (error)
goto done;
last |= (u_char)*wbuf;
if (wcount == 1 && rcount == 0 && (op & SMB_TRANS_NOSTOP) == 0)
last |= IG4_DATA_STOP;
reg_write(sc, IG4_REG_DATA_CMD, last);
--wcount;
++wbuf;
last = 0;
}
/*
* Issue reads to xmit FIFO (strange, I know) to tell the controller
* to clock in data. At the moment just issue one read ahead to
* pipeline the incoming data.
*
* NOTE: In the case of NOCMD and wcount == 0 we still issue a
* RESTART here, even if the data direction has not changed
* from the previous CHAINing call. This we force the RESTART.
* (A new START is issued automatically by the controller in
* the other nominal cases such as a data direction change or
* a previous STOP was issued).
*
* If this will be the last byte read we must also issue the STOP
* at the end of the read.
*/
if (rcount) {
last = IG4_DATA_RESTART | IG4_DATA_COMMAND_RD;
if (rcount == 1 &&
(op & (SMB_TRANS_NOSTOP | SMB_TRANS_NOCNT)) ==
SMB_TRANS_NOCNT) {
last |= IG4_DATA_STOP;
}
reg_write(sc, IG4_REG_DATA_CMD, last);
last = IG4_DATA_COMMAND_RD;
}
/*
* Bulk read (i2c) and count field handling (smbus)
*/
while (rcount) {
/*
* Maintain a pipeline by queueing the allowance for the next
* read before waiting for the current read.
*/
if (rcount > 1) {
if (op & SMB_TRANS_NOCNT)
last = (rcount == 2) ? IG4_DATA_STOP : 0;
else
last = 0;
reg_write(sc, IG4_REG_DATA_CMD, IG4_DATA_COMMAND_RD |
last);
}
error = wait_status(sc, IG4_STATUS_RX_NOTEMPTY);
if (error) {
if ((op & SMB_TRANS_NOREPORT) == 0) {
device_printf(sc->dev,
"rx timeout addr 0x%02x\n",
sc->last_slave);
}
goto done;
}
last = data_read(sc);
if (op & SMB_TRANS_NOCNT) {
*rbuf = (u_char)last;
++rbuf;
--rcount;
if (actualp)
++*actualp;
} else {
/*
* Handle count field (smbus), which is not part of
* the rcount'ed buffer. The first read data in a
* bulk transfer is the count.
*
* XXX if rcount is loaded as 0 how do I generate a
* STOP now without issuing another RD or WR?
*/
if (rcount > (u_char)last)
rcount = (u_char)last;
op |= SMB_TRANS_NOCNT;
}
}
error = 0;
done:
/* XXX wait for xmit buffer to become empty */
last = reg_read(sc, IG4_REG_TX_ABRT_SOURCE);
return (error);
}
/*
* SMBUS API FUNCTIONS
*
* Called from ig4iic_pci_attach/detach()
*/
int
ig4iic_attach(ig4iic_softc_t *sc)
{
int error;
uint32_t v;
v = reg_read(sc, IG4_REG_COMP_TYPE);
v = reg_read(sc, IG4_REG_COMP_PARAM1);
v = reg_read(sc, IG4_REG_GENERAL);
if ((v & IG4_GENERAL_SWMODE) == 0) {
v |= IG4_GENERAL_SWMODE;
reg_write(sc, IG4_REG_GENERAL, v);
v = reg_read(sc, IG4_REG_GENERAL);
}
v = reg_read(sc, IG4_REG_SW_LTR_VALUE);
v = reg_read(sc, IG4_REG_AUTO_LTR_VALUE);
v = reg_read(sc, IG4_REG_COMP_VER);
if (v != IG4_COMP_VER) {
error = ENXIO;
goto done;
}
v = reg_read(sc, IG4_REG_SS_SCL_HCNT);
v = reg_read(sc, IG4_REG_SS_SCL_LCNT);
v = reg_read(sc, IG4_REG_FS_SCL_HCNT);
v = reg_read(sc, IG4_REG_FS_SCL_LCNT);
v = reg_read(sc, IG4_REG_SDA_HOLD);
v = reg_read(sc, IG4_REG_SS_SCL_HCNT);
reg_write(sc, IG4_REG_FS_SCL_HCNT, v);
v = reg_read(sc, IG4_REG_SS_SCL_LCNT);
reg_write(sc, IG4_REG_FS_SCL_LCNT, v);
/*
* Program based on a 25000 Hz clock. This is a bit of a
* hack (obviously). The defaults are 400 and 470 for standard
* and 60 and 130 for fast. The defaults for standard fail
* utterly (presumably cause an abort) because the clock time
* is ~18.8ms by default. This brings it down to ~4ms (for now).
*/
reg_write(sc, IG4_REG_SS_SCL_HCNT, 100);
reg_write(sc, IG4_REG_SS_SCL_LCNT, 125);
reg_write(sc, IG4_REG_FS_SCL_HCNT, 100);
reg_write(sc, IG4_REG_FS_SCL_LCNT, 125);
/*
* Use a threshold of 1 so we get interrupted on each character,
* allowing us to use mtx_sleep() in our poll code. Not perfect
* but this is better than using DELAY() for receiving data.
*/
reg_write(sc, IG4_REG_RX_TL, 1);
reg_write(sc, IG4_REG_CTL,
IG4_CTL_MASTER |
IG4_CTL_SLAVE_DISABLE |
IG4_CTL_RESTARTEN |
IG4_CTL_SPEED_STD);
sc->smb = device_add_child(sc->dev, "smbus", -1);
if (sc->smb == NULL) {
device_printf(sc->dev, "smbus driver not found\n");
error = ENXIO;
goto done;
}
#if 0
/*
* Don't do this, it blows up the PCI config
*/
reg_write(sc, IG4_REG_RESETS, IG4_RESETS_ASSERT);
reg_write(sc, IG4_REG_RESETS, IG4_RESETS_DEASSERT);
#endif
/*
* Interrupt on STOP detect or receive character ready
*/
reg_write(sc, IG4_REG_INTR_MASK, IG4_INTR_STOP_DET |
IG4_INTR_RX_FULL);
mtx_lock(&sc->mutex);
if (set_controller(sc, 0))
device_printf(sc->dev, "controller error during attach-1\n");
if (set_controller(sc, IG4_I2C_ENABLE))
device_printf(sc->dev, "controller error during attach-2\n");
mtx_unlock(&sc->mutex);
error = bus_setup_intr(sc->dev, sc->intr_res, INTR_TYPE_MISC | INTR_MPSAFE,
NULL, ig4iic_intr, sc, &sc->intr_handle);
if (error) {
device_printf(sc->dev,
"Unable to setup irq: error %d\n", error);
}
sc->enum_hook.ich_func = ig4iic_start;
sc->enum_hook.ich_arg = sc->dev;
/* We have to wait until interrupts are enabled. I2C read and write
* only works if the interrupts are available.
*/
if (config_intrhook_establish(&sc->enum_hook) != 0)
error = ENOMEM;
else
error = 0;
done:
return (error);
}
void
ig4iic_start(void *xdev)
{
int error;
ig4iic_softc_t *sc;
device_t dev = (device_t)xdev;
sc = device_get_softc(dev);
config_intrhook_disestablish(&sc->enum_hook);
/* Attach us to the smbus */
error = bus_generic_attach(sc->dev);
if (error) {
device_printf(sc->dev,
"failed to attach child: error %d\n", error);
}
}
int
ig4iic_detach(ig4iic_softc_t *sc)
{
int error;
if (device_is_attached(sc->dev)) {
error = bus_generic_detach(sc->dev);
if (error)
return (error);
}
if (sc->smb)
device_delete_child(sc->dev, sc->smb);
if (sc->intr_handle)
bus_teardown_intr(sc->dev, sc->intr_res, sc->intr_handle);
mtx_lock(&sc->mutex);
sc->smb = NULL;
sc->intr_handle = NULL;
reg_write(sc, IG4_REG_INTR_MASK, 0);
reg_read(sc, IG4_REG_CLR_INTR);
set_controller(sc, 0);
mtx_unlock(&sc->mutex);
return (0);
}
int
ig4iic_smb_callback(device_t dev, int index, void *data)
{
ig4iic_softc_t *sc = device_get_softc(dev);
int error;
mtx_lock(&sc->mutex);
switch (index) {
case SMB_REQUEST_BUS:
error = 0;
break;
case SMB_RELEASE_BUS:
error = 0;
break;
default:
error = SMB_EABORT;
break;
}
mtx_unlock(&sc->mutex);
return (error);
}
/*
* Quick command. i.e. START + cmd + R/W + STOP and no data. It is
* unclear to me how I could implement this with the intel i2c controller
* because the controler sends STARTs and STOPs automatically with data.
*/
int
ig4iic_smb_quick(device_t dev, u_char slave, int how)
{
ig4iic_softc_t *sc = device_get_softc(dev);
int error;
mtx_lock(&sc->mutex);
switch (how) {
case SMB_QREAD:
error = SMB_ENOTSUPP;
break;
case SMB_QWRITE:
error = SMB_ENOTSUPP;
break;
default:
error = SMB_ENOTSUPP;
break;
}
mtx_unlock(&sc->mutex);
return (error);
}
/*
* Incremental send byte without stop (?). It is unclear why the slave
* address is specified if this presumably is used in combination with
* ig4iic_smb_quick().
*
* (Also, how would this work anyway? Issue the last byte with writeb()?)
*/
int
ig4iic_smb_sendb(device_t dev, u_char slave, char byte)
{
ig4iic_softc_t *sc = device_get_softc(dev);
uint32_t cmd;
int error;
mtx_lock(&sc->mutex);
set_slave_addr(sc, slave, 0);
cmd = byte;
if (wait_status(sc, IG4_STATUS_TX_NOTFULL) == 0) {
reg_write(sc, IG4_REG_DATA_CMD, cmd);
error = 0;
} else {
error = SMB_ETIMEOUT;
}
mtx_unlock(&sc->mutex);
return (error);
}
/*
* Incremental receive byte without stop (?). It is unclear why the slave
* address is specified if this presumably is used in combination with
* ig4iic_smb_quick().
*/
int
ig4iic_smb_recvb(device_t dev, u_char slave, char *byte)
{
ig4iic_softc_t *sc = device_get_softc(dev);
int error;
mtx_lock(&sc->mutex);
set_slave_addr(sc, slave, 0);
reg_write(sc, IG4_REG_DATA_CMD, IG4_DATA_COMMAND_RD);
if (wait_status(sc, IG4_STATUS_RX_NOTEMPTY) == 0) {
*byte = data_read(sc);
error = 0;
} else {
*byte = 0;
error = SMB_ETIMEOUT;
}
mtx_unlock(&sc->mutex);
return (error);
}
/*
* Write command and single byte in transaction.
*/
int
ig4iic_smb_writeb(device_t dev, u_char slave, char cmd, char byte)
{
ig4iic_softc_t *sc = device_get_softc(dev);
int error;
mtx_lock(&sc->mutex);
set_slave_addr(sc, slave, 0);
error = smb_transaction(sc, cmd, SMB_TRANS_NOCNT,
&byte, 1, NULL, 0, NULL);
mtx_unlock(&sc->mutex);
return (error);
}
/*
* Write command and single word in transaction.
*/
int
ig4iic_smb_writew(device_t dev, u_char slave, char cmd, short word)
{
ig4iic_softc_t *sc = device_get_softc(dev);
char buf[2];
int error;
mtx_lock(&sc->mutex);
set_slave_addr(sc, slave, 0);
buf[0] = word & 0xFF;
buf[1] = word >> 8;
error = smb_transaction(sc, cmd, SMB_TRANS_NOCNT,
buf, 2, NULL, 0, NULL);
mtx_unlock(&sc->mutex);
return (error);
}
/*
* write command and read single byte in transaction.
*/
int
ig4iic_smb_readb(device_t dev, u_char slave, char cmd, char *byte)
{
ig4iic_softc_t *sc = device_get_softc(dev);
int error;
mtx_lock(&sc->mutex);
set_slave_addr(sc, slave, 0);
error = smb_transaction(sc, cmd, SMB_TRANS_NOCNT,
NULL, 0, byte, 1, NULL);
mtx_unlock(&sc->mutex);
return (error);
}
/*
* write command and read word in transaction.
*/
int
ig4iic_smb_readw(device_t dev, u_char slave, char cmd, short *word)
{
ig4iic_softc_t *sc = device_get_softc(dev);
char buf[2];
int error;
mtx_lock(&sc->mutex);
set_slave_addr(sc, slave, 0);
if ((error = smb_transaction(sc, cmd, SMB_TRANS_NOCNT,
NULL, 0, buf, 2, NULL)) == 0) {
*word = (u_char)buf[0] | ((u_char)buf[1] << 8);
}
mtx_unlock(&sc->mutex);
return (error);
}
/*
* write command and word and read word in transaction
*/
int
ig4iic_smb_pcall(device_t dev, u_char slave, char cmd,
short sdata, short *rdata)
{
ig4iic_softc_t *sc = device_get_softc(dev);
char rbuf[2];
char wbuf[2];
int error;
mtx_lock(&sc->mutex);
set_slave_addr(sc, slave, 0);
wbuf[0] = sdata & 0xFF;
wbuf[1] = sdata >> 8;
if ((error = smb_transaction(sc, cmd, SMB_TRANS_NOCNT,
wbuf, 2, rbuf, 2, NULL)) == 0) {
*rdata = (u_char)rbuf[0] | ((u_char)rbuf[1] << 8);
}
mtx_unlock(&sc->mutex);
return (error);
}
int
ig4iic_smb_bwrite(device_t dev, u_char slave, char cmd,
u_char wcount, char *buf)
{
ig4iic_softc_t *sc = device_get_softc(dev);
int error;
mtx_lock(&sc->mutex);
set_slave_addr(sc, slave, 0);
error = smb_transaction(sc, cmd, 0,
buf, wcount, NULL, 0, NULL);
mtx_unlock(&sc->mutex);
return (error);
}
int
ig4iic_smb_bread(device_t dev, u_char slave, char cmd,
u_char *countp_char, char *buf)
{
ig4iic_softc_t *sc = device_get_softc(dev);
int rcount = *countp_char;
int error;
mtx_lock(&sc->mutex);
set_slave_addr(sc, slave, 0);
error = smb_transaction(sc, cmd, 0,
NULL, 0, buf, rcount, &rcount);
*countp_char = rcount;
mtx_unlock(&sc->mutex);
return (error);
}
int
ig4iic_smb_trans(device_t dev, int slave, char cmd, int op,
char *wbuf, int wcount, char *rbuf, int rcount,
int *actualp)
{
ig4iic_softc_t *sc = device_get_softc(dev);
int error;
mtx_lock(&sc->mutex);
set_slave_addr(sc, slave, op);
error = smb_transaction(sc, cmd, op,
wbuf, wcount, rbuf, rcount, actualp);
mtx_unlock(&sc->mutex);
return (error);
}
/*
* Interrupt Operation
*/
static void
ig4iic_intr(void *cookie)
{
ig4iic_softc_t *sc = cookie;
uint32_t status;
mtx_lock(&sc->mutex);
/* reg_write(sc, IG4_REG_INTR_MASK, IG4_INTR_STOP_DET);*/
status = reg_read(sc, IG4_REG_I2C_STA);
while (status & IG4_STATUS_RX_NOTEMPTY) {
sc->rbuf[sc->rnext & IG4_RBUFMASK] =
(uint8_t)reg_read(sc, IG4_REG_DATA_CMD);
++sc->rnext;
status = reg_read(sc, IG4_REG_I2C_STA);
}
reg_read(sc, IG4_REG_CLR_INTR);
wakeup(sc);
mtx_unlock(&sc->mutex);
}
#define REGDUMP(sc, reg) \
device_printf(sc->dev, " %-23s %08x\n", #reg, reg_read(sc, reg))
static void
ig4iic_dump(ig4iic_softc_t *sc)
{
device_printf(sc->dev, "ig4iic register dump:\n");
REGDUMP(sc, IG4_REG_CTL);
REGDUMP(sc, IG4_REG_TAR_ADD);
REGDUMP(sc, IG4_REG_SS_SCL_HCNT);
REGDUMP(sc, IG4_REG_SS_SCL_LCNT);
REGDUMP(sc, IG4_REG_FS_SCL_HCNT);
REGDUMP(sc, IG4_REG_FS_SCL_LCNT);
REGDUMP(sc, IG4_REG_INTR_STAT);
REGDUMP(sc, IG4_REG_INTR_MASK);
REGDUMP(sc, IG4_REG_RAW_INTR_STAT);
REGDUMP(sc, IG4_REG_RX_TL);
REGDUMP(sc, IG4_REG_TX_TL);
REGDUMP(sc, IG4_REG_I2C_EN);
REGDUMP(sc, IG4_REG_I2C_STA);
REGDUMP(sc, IG4_REG_TXFLR);
REGDUMP(sc, IG4_REG_RXFLR);
REGDUMP(sc, IG4_REG_SDA_HOLD);
REGDUMP(sc, IG4_REG_TX_ABRT_SOURCE);
REGDUMP(sc, IG4_REG_SLV_DATA_NACK);
REGDUMP(sc, IG4_REG_DMA_CTRL);
REGDUMP(sc, IG4_REG_DMA_TDLR);
REGDUMP(sc, IG4_REG_DMA_RDLR);
REGDUMP(sc, IG4_REG_SDA_SETUP);
REGDUMP(sc, IG4_REG_ENABLE_STATUS);
REGDUMP(sc, IG4_REG_COMP_PARAM1);
REGDUMP(sc, IG4_REG_COMP_VER);
REGDUMP(sc, IG4_REG_COMP_TYPE);
REGDUMP(sc, IG4_REG_CLK_PARMS);
REGDUMP(sc, IG4_REG_RESETS);
REGDUMP(sc, IG4_REG_GENERAL);
REGDUMP(sc, IG4_REG_SW_LTR_VALUE);
REGDUMP(sc, IG4_REG_AUTO_LTR_VALUE);
}
#undef REGDUMP
DRIVER_MODULE(smbus, ig4iic, smbus_driver, smbus_devclass, NULL, NULL);

192
sys/dev/ichiic/ig4_pci.c Normal file
View File

@ -0,0 +1,192 @@
/*
* Copyright (c) 2014 The DragonFly Project. All rights reserved.
*
* This code is derived from software contributed to The DragonFly Project
* by Matthew Dillon <dillon@backplane.com> and was subsequently ported
* to FreeBSD by Michael Gmelin <freebsd@grem.de>
*
* 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.
* 3. Neither the name of The DragonFly Project nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific, prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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
* COPYRIGHT HOLDERS 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.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
/*
* Intel fourth generation mobile cpus integrated I2C device, smbus driver.
*
* See ig4_reg.h for datasheet reference and notes.
*/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/module.h>
#include <sys/errno.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/syslog.h>
#include <sys/bus.h>
#include <machine/bus.h>
#include <sys/rman.h>
#include <machine/resource.h>
#include <dev/pci/pcivar.h>
#include <dev/pci/pcireg.h>
#include <dev/smbus/smbconf.h>
#include "smbus_if.h"
#include <dev/ichiic/ig4_reg.h>
#include <dev/ichiic/ig4_var.h>
static int ig4iic_pci_detach(device_t dev);
#define PCI_CHIP_LYNXPT_LP_I2C_1 0x9c618086
#define PCI_CHIP_LYNXPT_LP_I2C_2 0x9c628086
static int
ig4iic_pci_probe(device_t dev)
{
switch(pci_get_devid(dev)) {
case PCI_CHIP_LYNXPT_LP_I2C_1:
device_set_desc(dev, "Intel Lynx Point-LP I2C Controller-1");
break;
case PCI_CHIP_LYNXPT_LP_I2C_2:
device_set_desc(dev, "Intel Lynx Point-LP I2C Controller-2");
break;
default:
return (ENXIO);
}
return (BUS_PROBE_DEFAULT);
}
static int
ig4iic_pci_attach(device_t dev)
{
ig4iic_softc_t *sc = device_get_softc(dev);
int error;
bzero(sc, sizeof(*sc));
mtx_init(&sc->mutex, device_get_nameunit(dev), "ig4iic", MTX_DEF);
sc->dev = dev;
sc->regs_rid = PCIR_BAR(0);
sc->regs_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
&sc->regs_rid, RF_ACTIVE);
if (sc->regs_res == NULL) {
device_printf(dev, "unable to map registers\n");
ig4iic_pci_detach(dev);
return (ENXIO);
}
sc->intr_rid = 0;
if (pci_alloc_msi(dev, &sc->intr_rid)) {
device_printf(dev, "Using MSI\n");
}
sc->intr_res = bus_alloc_resource_any(dev, SYS_RES_IRQ,
&sc->intr_rid, RF_SHAREABLE | RF_ACTIVE);
if (sc->intr_res == NULL) {
device_printf(dev, "unable to map interrupt\n");
ig4iic_pci_detach(dev);
return (ENXIO);
}
sc->pci_attached = 1;
error = ig4iic_attach(sc);
if (error)
ig4iic_pci_detach(dev);
return (error);
}
static int
ig4iic_pci_detach(device_t dev)
{
ig4iic_softc_t *sc = device_get_softc(dev);
int error;
if (sc->pci_attached) {
error = ig4iic_detach(sc);
if (error)
return (error);
sc->pci_attached = 0;
}
if (sc->intr_res) {
bus_release_resource(dev, SYS_RES_IRQ,
sc->intr_rid, sc->intr_res);
sc->intr_res = NULL;
}
if (sc->intr_rid != 0)
pci_release_msi(dev);
if (sc->regs_res) {
bus_release_resource(dev, SYS_RES_MEMORY,
sc->regs_rid, sc->regs_res);
sc->regs_res = NULL;
}
mtx_destroy(&sc->mutex);
return (0);
}
static device_method_t ig4iic_pci_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, ig4iic_pci_probe),
DEVMETHOD(device_attach, ig4iic_pci_attach),
DEVMETHOD(device_detach, ig4iic_pci_detach),
/* SMBus methods from ig4_smb.c */
DEVMETHOD(smbus_callback, ig4iic_smb_callback),
DEVMETHOD(smbus_quick, ig4iic_smb_quick),
DEVMETHOD(smbus_sendb, ig4iic_smb_sendb),
DEVMETHOD(smbus_recvb, ig4iic_smb_recvb),
DEVMETHOD(smbus_writeb, ig4iic_smb_writeb),
DEVMETHOD(smbus_writew, ig4iic_smb_writew),
DEVMETHOD(smbus_readb, ig4iic_smb_readb),
DEVMETHOD(smbus_readw, ig4iic_smb_readw),
DEVMETHOD(smbus_pcall, ig4iic_smb_pcall),
DEVMETHOD(smbus_bwrite, ig4iic_smb_bwrite),
DEVMETHOD(smbus_bread, ig4iic_smb_bread),
DEVMETHOD(smbus_trans, ig4iic_smb_trans),
DEVMETHOD_END
};
static driver_t ig4iic_pci_driver = {
"ig4iic",
ig4iic_pci_methods,
sizeof(struct ig4iic_softc)
};
static devclass_t ig4iic_pci_devclass;
DRIVER_MODULE(ig4iic, pci, ig4iic_pci_driver, ig4iic_pci_devclass, 0, 0);
MODULE_DEPEND(ig4iic, pci, 1, 1, 1);
MODULE_DEPEND(ig4iic, smbus, SMBUS_MINVER, SMBUS_PREFVER, SMBUS_MAXVER);
MODULE_VERSION(ig4iic, 1);

622
sys/dev/ichiic/ig4_reg.h Normal file
View File

@ -0,0 +1,622 @@
/*
* Copyright (c) 2014 The DragonFly Project. All rights reserved.
*
* This code is derived from software contributed to The DragonFly Project
* by Matthew Dillon <dillon@backplane.com> and was subsequently ported
* to FreeBSD by Michael Gmelin <freebsd@grem.de>
*
* 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.
* 3. Neither the name of The DragonFly Project nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific, prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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
* COPYRIGHT HOLDERS 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.
*
* $FreeBSD$
*/
/*
* Intel fourth generation mobile cpus integrated I2C device.
*
* Datasheet reference: Section 22.
*
* http://www.intel.com/content/www/us/en/processors/core/4th-gen-core-family-mobile-i-o-datasheet.html?wapkw=datasheets+4th+generation
*
* This is a from-scratch driver under the BSD license using the Intel data
* sheet and the linux driver for reference. All code is freshly written
* without referencing the linux driver code. However, during testing
* I am also using the linux driver code as a reference to help resolve any
* issues that come. These will be specifically documented in the code.
*
* Please see protocol notes in section 5.21. This controller is an I2C
* master only and cannot act as a slave. The IO voltage should be set by
* the BIOS. Standard (100Kb/s) and Fast (400Kb/s) and fast mode plus
* (1MB/s) is supported. High speed mode (3.4 MB/s) is NOT supported.
*/
#ifndef _BUS_SMBUS_INTELGEN4_IG4_REG_H_
#define _BUS_SMBUS_INTELGEN4_IG4_REG_H_
/*
* 22.2 MMIO registers can be accessed through BAR0 in PCI mode or through
* BAR1 when in ACPI mode.
*
* Register width is 32-bits
*
* 22.2 Default Values on device reset are 0 except as specified here:
* TAR_ADD 0x00000055
* SS_SCL_HCNT 0x00000264
* SS_SCL_LCNT 0x000002C2
* FS_SCL_HCNT 0x0000006E
* FS_SCL_LCNT 0x000000CF
* INTR_MASK 0x000008FF
* I2C_STA 0x00000006
* SDA_HOLD 0x00000001
* SDA_SETUP 0x00000064
* COMP_PARAM1 0x00FFFF6E
* COMP_VER 0x3131352A
*/
#define IG4_REG_CTL 0x0000 /* RW Control Register */
#define IG4_REG_TAR_ADD 0x0004 /* RW Target Address */
#define IG4_REG_DATA_CMD 0x0010 /* RW Data Buffer and Command */
#define IG4_REG_SS_SCL_HCNT 0x0014 /* RW Std Speed clock High Count */
#define IG4_REG_SS_SCL_LCNT 0x0018 /* RW Std Speed clock Low Count */
#define IG4_REG_FS_SCL_HCNT 0x001C /* RW Fast Speed clock High Count */
#define IG4_REG_FS_SCL_LCNT 0x0020 /* RW Fast Speed clock Low Count */
#define IG4_REG_INTR_STAT 0x002C /* RO Interrupt Status */
#define IG4_REG_INTR_MASK 0x0030 /* RW Interrupt Mask */
#define IG4_REG_RAW_INTR_STAT 0x0034 /* RO Raw Interrupt Status */
#define IG4_REG_RX_TL 0x0038 /* RW Receive FIFO Threshold */
#define IG4_REG_TX_TL 0x003C /* RW Transmit FIFO Threshold */
#define IG4_REG_CLR_INTR 0x0040 /* RO Clear Interrupt */
#define IG4_REG_CLR_RX_UNDER 0x0044 /* RO Clear RX_Under Interrupt */
#define IG4_REG_CLR_RX_OVER 0x0048 /* RO Clear RX_Over Interrupt */
#define IG4_REG_CLR_TX_OVER 0x004C /* RO Clear TX_Over Interrupt */
#define IG4_REG_CLR_TX_ABORT 0x0054 /* RO Clear TX_Abort Interrupt */
#define IG4_REG_CLR_ACTIVITY 0x005C /* RO Clear Activity Interrupt */
#define IG4_REG_CLR_STOP_DET 0x0060 /* RO Clear STOP Detection Int */
#define IG4_REG_CLR_START_DET 0x0064 /* RO Clear START Detection Int */
#define IG4_REG_CLR_GEN_CALL 0x0068 /* RO Clear General Call Interrupt */
#define IG4_REG_I2C_EN 0x006C /* RW I2C Enable */
#define IG4_REG_I2C_STA 0x0070 /* RO I2C Status */
#define IG4_REG_TXFLR 0x0074 /* RO Transmit FIFO Level */
#define IG4_REG_RXFLR 0x0078 /* RO Receive FIFO Level */
#define IG4_REG_SDA_HOLD 0x007C /* RW SDA Hold Time Length */
#define IG4_REG_TX_ABRT_SOURCE 0x0080 /* RO Transmit Abort Source */
#define IG4_REG_SLV_DATA_NACK 0x0084 /* RW General Slave Data NACK */
#define IG4_REG_DMA_CTRL 0x0088 /* RW DMA Control */
#define IG4_REG_DMA_TDLR 0x008C /* RW DMA Transmit Data Level */
#define IG4_REG_DMA_RDLR 0x0090 /* RW DMA Receive Data Level */
#define IG4_REG_SDA_SETUP 0x0094 /* RW SDA Setup */
#define IG4_REG_ENABLE_STATUS 0x009C /* RO Enable Status */
#define IG4_REG_COMP_PARAM1 0x00F4 /* RO Component Parameter */
#define IG4_REG_COMP_VER 0x00F8 /* RO Component Version */
#define IG4_REG_COMP_TYPE 0x00FC /* RO Probe width/endian? (linux) */
#define IG4_REG_CLK_PARMS 0x0800 /* RW Clock Parameters */
#define IG4_REG_RESETS 0x0804 /* RW Reset Register */
#define IG4_REG_GENERAL 0x0808 /* RW General Register */
#define IG4_REG_SW_LTR_VALUE 0x0810 /* RW SW LTR Value */
#define IG4_REG_AUTO_LTR_VALUE 0x0814 /* RW Auto LTR Value */
/*
* CTL - Control Register 22.2.1
* Default Value: 0x0000007F.
*
* RESTARTEN - RW Restart Enable
* 10BIT - RW Controller operates in 10-bit mode, else 7-bit
*
* NOTE: When restart is disabled the controller is incapable of
* performing the following functions:
*
* Sending a START Byte
* Performing any high-speed mode op
* Performing direction changes in combined format mode
* Performing a read operation with a 10-bit address
*
* Attempting to perform the above operations will result in the
* TX_ABORT bit being set in RAW_INTR_STAT.
*/
#define IG4_CTL_SLAVE_DISABLE 0x0040 /* snarfed from linux */
#define IG4_CTL_RESTARTEN 0x0020 /* Allow Restart when master */
#define IG4_CTL_10BIT 0x0010 /* ctlr accepts 10-bit addresses */
#define IG4_CTL_SPEED_FAST 0x0004 /* snarfed from linux */
#define IG4_CTL_SPEED_STD 0x0002 /* snarfed from linux */
#define IG4_CTL_MASTER 0x0001 /* snarfed from linux */
/*
* TAR_ADD - Target Address Register 22.2.2
* Default Value: 0x00000055F
*
* 10BIT - RW controller starts its transfers in 10-bit
* address mode, else 7-bit.
*
* SPECIAL - RW Indicates whether software performs a General Call
* or START BYTE command.
*
* 0 Ignore GC_OR_START and use TAR address.
*
* 1 Perform special I2C Command based on GC_OR_START.
*
* GC_OR_START - RW (only if SPECIAL is set)
*
* 0 General Call Address. After issuing a General Call,
* only writes may be performed. Attempting to issue
* a read command results in IX_ABRT in RAW_INTR_STAT.
* The controller remains in General Call mode until
* bit 11 (SPECIAL) is cleared.
*
* 1 START BYTE.
*
*
* IC_TAR - RW when transmitting a general call, these bits are
* ignored. To generate a START BYTE, the address
* needs to be written into these bits once.
*
* This register should only be updated when the IIC is disabled (I2C_ENABLE=0)
*/
#define IG4_TAR_10BIT 0x1000 /* start xfer in 10-bit mode */
#define IG4_TAR_SPECIAL 0x0800 /* Perform special command */
#define IG4_TAR_GC_OR_START 0x0400 /* General Call or Start */
#define IG4_TAR_ADDR_MASK 0x03FF /* Target address */
/*
* TAR_DATA_CMD - Data Buffer and Command Register 22.2.3
*
* RESTART - RW This bit controls whether a forced RESTART is
* issued before the byte is sent or received.
*
* 0 If not set a RESTART is only issued if the tranfer
* direction is changing from the previous command.
*
* 1 A RESTART is issued before the byte is sent or
* received, regardless of whether or not the transfer
* direction is changing from the previous command.
*
* STOP - RW This bit controls whether a STOP is issued after
* the byte is sent or received.
*
* 0 STOP is not issued after this byte, regardless
* of whether or not the Tx FIFO is empty.
*
* 1 STOP is issued after this byte, regardless of
* whether or not the Tx FIFO is empty. If the
* Tx FIFO is not empty the master immediately tries
* to start a new transfer by issuing a START and
* arbitrating for the bus.
*
* i.e. the STOP is issued along with this byte,
* within the write stream.
*
* COMMAND - RW Control whether a read or write is performed.
*
* 0 WRITE
*
* 1 READ
*
* DATA (7:0) - RW Contains the data to be transmitted or received
* on the I2C bus.
*
* NOTE: Writing to this register causes a START + slave + RW to be
* issued if the direction has changed or the last data byte was
* sent with a STOP.
*
* NOTE: We control termination? so this register must be written
* for each byte we wish to receive. We can then drain the
* receive FIFO.
*/
#define IG4_DATA_RESTART 0x0400 /* Force RESTART */
#define IG4_DATA_STOP 0x0200 /* Force STOP[+START] */
#define IG4_DATA_COMMAND_RD 0x0100 /* bus direction 0=write 1=read */
#define IG4_DATA_MASK 0x00FF
/*
* SS_SCL_HCNT - Standard Speed Clock High Count Register 22.2.4
* SS_SCL_LCNT - Standard Speed Clock Low Count Register 22.2.5
* FS_SCL_HCNT - Fast Speed Clock High Count Register 22.2.6
* FS_SCL_LCNT - Fast Speed Clock Low Count Register 22.2.7
*
* COUNT (15:0) - Set the period count to a value between 6 and
* 65525.
*/
#define IG4_SCL_CLOCK_MASK 0xFFFFU /* count bits in register */
/*
* INTR_STAT - (RO) Interrupt Status Register 22.2.8
* INTR_MASK - (RW) Interrupt Mask Register 22.2.9
* RAW_INTR_STAT- (RO) Raw Interrupt Status Register 22.2.10
*
* GEN_CALL Set only when a general call (broadcast) address
* is received and acknowleged, stays set until
* cleared by reading CLR_GEN_CALL.
*
* START_DET Set when a START or RESTART condition has occurred
* on the interface.
*
* STOP_DET Set when a STOP condition has occurred on the
* interface.
*
* ACTIVITY Set by any activity on the interface. Cleared
* by reading CLR_ACTIVITY or CLR_INTR.
*
* TX_ABRT Indicates the controller as a transmitter is
* unable to complete the intended action. When set,
* the controller will hold the TX FIFO in a reset
* state (flushed) until CLR_TX_ABORT is read to
* clear the condition. Once cleared, the TX FIFO
* will be available again.
*
* TX_EMPTY Indicates that the transmitter is at or below
* the specified TX_TL threshold. Automatically
* cleared by HW when the buffer level goes above
* the threshold.
*
* TX_OVER Indicates that the processer attempted to write
* to the TX FIFO while the TX FIFO was full. Cleared
* by reading CLR_TX_OVER.
*
* RX_FULL Indicates that the receive FIFO has reached or
* exceeded the specified RX_TL threshold. Cleared
* by HW when the cpu drains the FIFO to below the
* threshold.
*
* RX_OVER Indicates that the receive FIFO was unable to
* accept new data and data was lost. Cleared by
* reading CLR_RX_OVER.
*
* RX_UNDER Indicates that the cpu attempted to read data
* from the receive buffer while the RX FIFO was
* empty. Cleared by reading CLR_RX_UNDER.
*
* NOTES ON RAW_INTR_STAT:
*
* This register can be used to monitor the GEN_CALL, START_DET,
* STOP_DET, ACTIVITY, TX_ABRT, TX_EMPTY, TX_OVER, RX_FULL, RX_OVER,
* and RX_UNDER bits. The documentation is a bit unclear but presumably
* this is the unlatched version.
*
* Code should test FIFO conditions using the I2C_STA (status) register,
* not the interrupt status registers.
*/
#define IG4_INTR_GEN_CALL 0x0800
#define IG4_INTR_START_DET 0x0400
#define IG4_INTR_STOP_DET 0x0200
#define IG4_INTR_ACTIVITY 0x0100
#define IG4_INTR_TX_ABRT 0x0040
#define IG4_INTR_TX_EMPTY 0x0010
#define IG4_INTR_TX_OVER 0x0008
#define IG4_INTR_RX_FULL 0x0004
#define IG4_INTR_RX_OVER 0x0002
#define IG4_INTR_RX_UNDER 0x0001
/*
* RX_TL - (RW) Receive FIFO Threshold Register 22.2.11
* TX_TL - (RW) Transmit FIFO Threshold Register 22.2.12
*
* Specify the receive and transmit FIFO threshold register. The
* FIFOs have 16 elements. The valid range is 0-15. Setting a
* value greater than 15 causes the actual value to be the maximum
* depth of the FIFO.
*
* Generally speaking since everything is messaged, we can use a
* mid-level setting for both parameters and (e.g.) fully drain the
* receive FIFO on the STOP_DET condition to handle loose ends.
*/
#define IG4_FIFO_MASK 0x00FF
#define IG4_FIFO_LIMIT 16
/*
* CLR_INTR - (RO) Clear Interrupt Register 22.2.13
* CLR_RX_UNDER - (RO) Clear Interrupt Register (specific) 22.2.14
* CLR_RX_OVER - (RO) Clear Interrupt Register (specific) 22.2.15
* CLR_TX_OVER - (RO) Clear Interrupt Register (specific) 22.2.16
* CLR_TX_ABORT - (RO) Clear Interrupt Register (specific) 22.2.17
* CLR_ACTIVITY - (RO) Clear Interrupt Register (specific) 22.2.18
* CLR_STOP_DET - (RO) Clear Interrupt Register (specific) 22.2.19
* CLR_START_DET- (RO) Clear Interrupt Register (specific) 22.2.20
* CLR_GEN_CALL - (RO) Clear Interrupt Register (specific) 22.2.21
*
* CLR_* specific operations clear the appropriate bit in the
* RAW_INTR_STAT register. Intel does not really document whether
* these operations clear the normal interrupt status register.
*
* CLR_INTR clears bits in the normal interrupt status register and
* presumably also the raw(?) register? Intel is again unclear.
*
* NOTE: CLR_INTR only clears software-clearable interrupts. Hardware
* clearable interrupts are controlled entirely by the hardware.
* CLR_INTR also clears the TX_ABRT_SOURCE register.
*
* NOTE: CLR_TX_ABORT also clears the TX_ABRT_SOURCE register and releases
* the TX FIFO from its flushed/reset state, allowing more writes
* to the TX FIFO.
*
* NOTE: CLR_ACTIVITY has no effect if the I2C bus is still active.
* Intel documents that the bit is automatically cleared when
* there is no further activity on the bus.
*/
#define IG4_CLR_BIT 0x0001 /* Reflects source */
/*
* I2C_EN - (RW) I2C Enable Register 22.2.22
*
* ABORT Software can abort an I2C transfer by setting this
* bit. Hardware will clear the bit once the STOP has
* been detected. This bit can only be set while the
* I2C interface is enabled.
*
* I2C_ENABLE Enable the controller, else disable it.
* (Use I2C_ENABLE_STATUS to poll enable status
* & wait for changes)
*/
#define IG4_I2C_ABORT 0x0002
#define IG4_I2C_ENABLE 0x0001
/*
* I2C_STA - (RO) I2C Status Register 22.2.23
*/
#define IG4_STATUS_ACTIVITY 0x0020 /* Controller is active */
#define IG4_STATUS_RX_FULL 0x0010 /* RX FIFO completely full */
#define IG4_STATUS_RX_NOTEMPTY 0x0008 /* RX FIFO not empty */
#define IG4_STATUS_TX_EMPTY 0x0004 /* TX FIFO completely empty */
#define IG4_STATUS_TX_NOTFULL 0x0002 /* TX FIFO not full */
#define IG4_STATUS_I2C_ACTIVE 0x0001 /* I2C bus is active */
/*
* TXFLR - (RO) Transmit FIFO Level Register 22.2.24
* RXFLR - (RO) Receive FIFO Level Register 22.2.25
*
* Read the number of entries currently in the Transmit or Receive
* FIFOs. Note that for some reason the mask is 9 bits instead of
* the 8 bits the fill level controls.
*/
#define IG4_FIFOLVL_MASK 0x001F
/*
* SDA_HOLD - (RW) SDA Hold Time Length Register 22.2.26
*
* Set the SDA hold time length register in I2C clocks.
*/
#define IG4_SDA_HOLD_MASK 0x00FF
/*
* TX_ABRT_SOURCE- (RO) Transmit Abort Source Register 22.2.27
*
* Indicates the cause of a transmit abort. This can indicate a
* software programming error or a device expected address width
* mismatch or other issues. The NORESTART conditions and GENCALL_NOACK
* can only occur if a programming error was made in the driver software.
*
* In particular, it should be possible to detect whether any devices
* are on the bus by observing the GENCALL_READ status, and it might
* be possible to detect ADDR7 vs ADDR10 mismatches.
*/
#define IG4_ABRTSRC_TRANSFER 0x00010000 /* Abort initiated by user */
#define IG4_ABRTSRC_ARBLOST 0x00001000 /* Arbitration lost */
#define IG4_ABRTSRC_NORESTART_10 0x00000400 /* RESTART disabled */
#define IG4_ABRTSRC_NORESTART_START 0x00000200 /* RESTART disabled */
#define IG4_ABRTSRC_ACKED_START 0x00000080 /* Improper acked START */
#define IG4_ABRTSRC_GENCALL_NOACK 0x00000020 /* Improper GENCALL */
#define IG4_ABRTSRC_GENCALL_READ 0x00000010 /* Nobody acked GENCALL */
#define IG4_ABRTSRC_TXNOACK_DATA 0x00000008 /* data phase no ACK */
#define IG4_ABRTSRC_TXNOACK_ADDR10_2 0x00000004 /* addr10/1 phase no ACK */
#define IG4_ABRTSRC_TXNOACK_ADDR10_1 0x00000002 /* addr10/2 phase no ACK */
#define IG4_ABRTSRC_TXNOACK_ADDR7 0x00000001 /* addr7 phase no ACK */
/*
* SLV_DATA_NACK - (RW) Generate Slave DATA NACK Register 22.2.28
*
* When the controller is a receiver a NACK can be generated on
* receipt of data.
*
* NACK_GENERATE Set to 0 for normal NACK/ACK generation.
* Set to 1 to generate a NACK after next data
* byte received.
*
*/
#define IG4_NACK_GENERATE 0x0001
/*
* DMA_CTRL - (RW) DMA Control Register 22.2.29
*
* Enables DMA on the transmit and/or receive DMA channel.
*/
#define IG4_TX_DMA_ENABLE 0x0002
#define IG4_RX_DMA_ENABLE 0x0001
/*
* DMA_TDLR - (RW) DMA Transmit Data Level Register 22.2.30
* DMA_RDLR - (RW) DMA Receive Data Level Register 22.2.31
*
* Similar to RX_TL and TX_TL but controls when a DMA burst occurs
* to empty or fill the FIFOs. Use the same IG4_FIFO_MASK and
* IG4_FIFO_LIMIT defines for RX_RL and TX_TL.
*/
/* empty */
/*
* SDA_SETUP - (RW) SDA Setup Time Length Register 22.2.32
*
* Set the SDA setup time length register in I2C clocks.
* The register must be programmed with a value >=2.
* (Defaults to 0x64).
*/
#define IG4_SDA_SETUP_MASK 0x00FF
/*
* ACK_GEN_CALL - (RW) ACK General Call Register 22.2.33
*
* Control whether the controller responds with a ACK or NACK when
* it receives an I2C General Call address.
*
* If set to 0 a NACK is generated and a General Call interrupt is
* NOT generated. Otherwise an ACK + interrupt is generated.
*/
#define IG4_ACKGC_ACK 0x0001
/*
* ENABLE_STATUS - (RO) Enable Status Registger 22.2.34
*
* DATA_LOST - Indicates that a slave receiver operation has
* been aborted with at least one data byte received
* from a transfer due to the I2C controller being
* disabled (IG4_I2C_ENABLE -> 0)
*
* ENABLED - Intel documentation is lacking but I assume this
* is a reflection of the IG4_I2C_ENABLE bit in the
* I2C_EN register.
*
*/
#define IG4_ENASTAT_DATA_LOST 0x0004
#define IG4_ENASTAT_ENABLED 0x0001
/*
* COMP_PARAM1 - (RO) Component Parameter Register 22.2.35
* Default Value 0x00FFFF6E
*
* VALID - Intel documentation is unclear but I believe this
* must be read as a 1 to indicate that the rest of
* the bits in the register are valid.
*
* HASDMA - Indicates that the chip is DMA-capable. Presumably
* in certain virtualization cases the chip might be
* set to not be DMA-capable.
*
* INTR_IO - Indicates that all interrupts are combined to
* generate one interrupt. If not set, interrupts
* are individual (more virtualization stuff?)
*
* HCCNT_RO - Indicates that the clock timing registers are
* RW. If not set, the registers are RO.
* (more virtualization stuff).
*
* MAXSPEED - Indicates the maximum speed supported.
*
* DATAW - Indicates the internal bus width in bits.
*/
#define IG4_PARAM1_TXFIFO_DEPTH(v) (((v) >> 16) & 0xFF)
#define IG4_PARAM1_RXFIFO_DEPTH(v) (((v) >> 8) & 0xFF)
#define IG4_PARAM1_CONFIG_VALID 0x00000080
#define IG4_PARAM1_CONFIG_HASDMA 0x00000040
#define IG4_PARAM1_CONFIG_INTR_IO 0x00000020
#define IG4_PARAM1_CONFIG_HCCNT_RO 0x00000010
#define IG4_PARAM1_CONFIG_MAXSPEED_MASK 0x0000000C
#define IG4_PARAM1_CONFIG_DATAW_MASK 0x00000003
#define IG4_CONFIG_MAXSPEED_RESERVED00 0x00000000
#define IG4_CONFIG_MAXSPEED_STANDARD 0x00000004
#define IG4_CONFIG_MAXSPEED_FAST 0x00000008
#define IG4_CONFIG_MAXSPEED_HIGH 0x0000000C
#define IG4_CONFIG_DATAW_8 0x00000000
#define IG4_CONFIG_DATAW_16 0x00000001
#define IG4_CONFIG_DATAW_32 0x00000002
#define IG4_CONFIG_DATAW_RESERVED11 0x00000003
/*
* COMP_VER - (RO) Component Version Register 22.2.36
* Default Value 0x3131352A
*
* Contains the chip version number. All 32 bits.
*/
#define IG4_COMP_VER 0x3131352A
/*
* COMP_TYPE - (RO) (linux) Endian and bus width probe
*
* Read32 from this register and test against IG4_COMP_TYPE
* to determine the bus width. e.g. 01404457 = endian-reversed,
* and 00000140 or 00004457 means internal 16-bit bus (?).
*
* This register is not in the intel documentation, I pulled it
* from the linux driver i2c-designware-core.c.
*/
#define IG4_COMP_TYPE 0x44570140
/*
* RESETS - (RW) Resets Register 22.2.37
*
* Used to reset the I2C host controller by SW. There is no timing
* requirement, software can assert and de-assert in back-to-back
* transactions.
*
* 00 I2C host controller is NOT in reset.
* 01 (reserved)
* 10 (reserved)
* 11 I2C host controller is in reset.
*/
#define IG4_RESETS_ASSERT 0x0003
#define IG4_RESETS_DEASSERT 0x0000
/*
* GENERAL - (RW) General Reigster 22.2.38
*
* IOVOLT 0=1.8V 1=3.3V
*
* LTR 0=Auto 1=SW
*
* In Auto mode the BIOS will write to the host controller's
* AUTO LTR Value register (offset 0x0814) with the active
* state LTR value, and will write to the SW LTR Value register
* (offset 0x0810) with the idle state LTR value.
*
* In SW mode the SW will write to the host controller SW LTR
* value (offset 0x0810). It is the SW responsibility to update
* the LTR with the appropriate value.
*/
#define IG4_GENERAL_IOVOLT3_3 0x0008
#define IG4_GENERAL_SWMODE 0x0004
/*
* SW_LTR_VALUE - (RW) SW LTR Value Register 22.2.39
* AUTO_LTR_VALUE - (RW) SW LTR Value Register 22.2.40
*
* Default value is 0x00000800 which means the best possible
* service/response time.
*
* It isn't quite clear how the snooping works. There are two scale
* bits for both sets but two of the four codes are reserved. The
* *SNOOP_VALUE() is specified as a 10-bit latency value. If 0, it
* indicates that the device cannot tolerate any delay and needs the
* best possible service/response time.
*
* I think this is for snooping (testing) the I2C bus. The lowest
* delay (0) probably runs the controller polling at a high, power hungry
* rate. But I dunno.
*/
#define IG4_SWLTR_NSNOOP_REQ 0x80000000 /* (ro) */
#define IG4_SWLTR_NSNOOP_SCALE_MASK 0x1C000000 /* (ro) */
#define IG4_SWLTR_NSNOOP_SCALE_1US 0x08000000 /* (ro) */
#define IG4_SWLTR_NSNOOP_SCALE_32US 0x0C000000 /* (ro) */
#define IG4_SWLTR_NSNOOP_VALUE_DECODE(v) (((v) >> 16) & 0x3F)
#define IG4_SWLTR_NSNOOP_VALUE_ENCODE(v) (((v) & 0x3F) << 16)
#define IG4_SWLTR_SNOOP_REQ 0x00008000 /* (rw) */
#define IG4_SWLTR_SNOOP_SCALE_MASK 0x00001C00 /* (rw) */
#define IG4_SWLTR_SNOOP_SCALE_1US 0x00000800 /* (rw) */
#define IG4_SWLTR_SNOOP_SCALE_32US 0x00000C00 /* (rw) */
#define IG4_SWLTR_SNOOP_VALUE_DECODE(v) ((v) & 0x3F)
#define IG4_SWLTR_SNOOP_VALUE_ENCODE(v) ((v) & 0x3F)
#endif

96
sys/dev/ichiic/ig4_var.h Normal file
View File

@ -0,0 +1,96 @@
/*
* Copyright (c) 2014 The DragonFly Project. All rights reserved.
*
* This code is derived from software contributed to The DragonFly Project
* by Matthew Dillon <dillon@backplane.com> and was subsequently ported
* to FreeBSD by Michael Gmelin <freebsd@grem.de>
*
* 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.
* 3. Neither the name of The DragonFly Project nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific, prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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
* COPYRIGHT HOLDERS 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.
*
* $FreeBSD$
*/
#ifndef _BUS_SMBUS_INTELGEN4_IG4_VAR_H_
#define _BUS_SMBUS_INTELGEN4_IG4_VAR_H_
#include "bus_if.h"
#include "device_if.h"
#include "pci_if.h"
#include "smbus_if.h"
#define IG4_RBUFSIZE 128
#define IG4_RBUFMASK (IG4_RBUFSIZE - 1)
enum ig4_op { IG4_IDLE, IG4_READ, IG4_WRITE };
struct ig4iic_softc {
device_t dev;
struct intr_config_hook enum_hook;
device_t smb;
struct resource *regs_res;
int regs_rid;
struct resource *intr_res;
int intr_rid;
void *intr_handle;
int intr_type;
enum ig4_op op;
int cmd;
int rnext;
int rpos;
char rbuf[IG4_RBUFSIZE];
int error;
uint8_t last_slave;
int pci_attached : 1;
int use_10bit : 1;
int slave_valid : 1;
int read_started : 1;
int write_started : 1;
struct mtx mutex;
};
typedef struct ig4iic_softc ig4iic_softc_t;
/* Attach/Detach called from ig4iic_pci_*() */
int ig4iic_attach(ig4iic_softc_t *sc);
int ig4iic_detach(ig4iic_softc_t *sc);
/* SMBus methods */
extern smbus_callback_t ig4iic_smb_callback;
extern smbus_quick_t ig4iic_smb_quick;
extern smbus_sendb_t ig4iic_smb_sendb;
extern smbus_recvb_t ig4iic_smb_recvb;
extern smbus_writeb_t ig4iic_smb_writeb;
extern smbus_writew_t ig4iic_smb_writew;
extern smbus_readb_t ig4iic_smb_readb;
extern smbus_readw_t ig4iic_smb_readw;
extern smbus_pcall_t ig4iic_smb_pcall;
extern smbus_bwrite_t ig4iic_smb_bwrite;
extern smbus_bread_t ig4iic_smb_bread;
extern smbus_trans_t ig4iic_smb_trans;
#endif

View File

@ -199,8 +199,8 @@ static int ixl_sysctl_switch_config(SYSCTL_HANDLER_ARGS);
#ifdef PCI_IOV
static int ixl_adminq_err_to_errno(enum i40e_admin_queue_err err);
static int ixl_init_iov(device_t dev, uint16_t num_vfs, const nvlist_t*);
static void ixl_uninit_iov(device_t dev);
static int ixl_iov_init(device_t dev, uint16_t num_vfs, const nvlist_t*);
static void ixl_iov_uninit(device_t dev);
static int ixl_add_vf(device_t dev, uint16_t vfnum, const nvlist_t*);
static void ixl_handle_vf_msg(struct ixl_pf *,
@ -222,9 +222,9 @@ static device_method_t ixl_methods[] = {
DEVMETHOD(device_detach, ixl_detach),
DEVMETHOD(device_shutdown, ixl_shutdown),
#ifdef PCI_IOV
DEVMETHOD(pci_init_iov, ixl_init_iov),
DEVMETHOD(pci_uninit_iov, ixl_uninit_iov),
DEVMETHOD(pci_add_vf, ixl_add_vf),
DEVMETHOD(pci_iov_init, ixl_iov_init),
DEVMETHOD(pci_iov_uninit, ixl_iov_uninit),
DEVMETHOD(pci_iov_add_vf, ixl_add_vf),
#endif
{0, 0}
};
@ -6456,7 +6456,7 @@ ixl_adminq_err_to_errno(enum i40e_admin_queue_err err)
}
static int
ixl_init_iov(device_t dev, uint16_t num_vfs, const nvlist_t *params)
ixl_iov_init(device_t dev, uint16_t num_vfs, const nvlist_t *params)
{
struct ixl_pf *pf;
struct i40e_hw *hw;
@ -6504,7 +6504,7 @@ fail:
}
static void
ixl_uninit_iov(device_t dev)
ixl_iov_uninit(device_t dev)
{
struct ixl_pf *pf;
struct i40e_hw *hw;

View File

@ -93,6 +93,7 @@
#ifdef PCI_IOV
#include <sys/nv.h>
#include <sys/iov_schema.h>
#include <dev/pci/pci_iov.h>
#endif
#include "i40e_type.h"

View File

@ -163,33 +163,10 @@ mmcsd_attach(device_t dev)
d->d_sectorsize = mmc_get_sector_size(dev);
d->d_maxsize = mmc_get_max_data(dev) * d->d_sectorsize;
d->d_mediasize = (off_t)mmc_get_media_size(dev) * d->d_sectorsize;
d->d_stripeoffset = 0;
d->d_stripesize = mmc_get_erase_sector(dev) * d->d_sectorsize;
d->d_unit = device_get_unit(dev);
d->d_flags = DISKFLAG_CANDELETE;
d->d_delmaxsize = mmc_get_erase_sector(dev) * d->d_sectorsize * 1; /* conservative */
/*
* The d_fw* values are fake. However, layout is aided by making the
* number of fwsectors equal to the erase sectors from the drive since
* we set the stripe size equal to that. We set fwheads such that there
* are ~20 cylinder groups since all values are somewhat arbitrary here
* and this gives good behavior with ffs without wasting too much
* space. Sadly, geom_part wants to round partitions to these
* values. While not bad, in and of itself, the values we present here
* will almost certainly be different then the values that USB SD
* adapters use and there's too much variation between brands to just
* use those values here. Also SD to ATA adapters favor traditional
* ata sizes, which are different again from the USB adapters (which
* favor SCSI values). This rounding leads to a loss of up to 5% of the
* usable space (usually much less, but that's why 20 was selected: to
* limit this effect at a few percent). gpart needs a way to override
* this behavior for situations like this, but doesn't provide
* one. Perhaps this behavior should be tunable as well, but maybe that
* belongs in the disk layer. These values will be much better than
* the default ones.
*/
d->d_fwsectors = mmc_get_erase_sector(dev);
d->d_fwheads = mmc_get_media_size(dev) / (d->d_fwsectors * 20);
d->d_delmaxsize = mmc_get_erase_sector(dev) * d->d_sectorsize;
strlcpy(d->d_ident, mmc_get_card_sn_string(dev), sizeof(d->d_ident));
strlcpy(d->d_descr, mmc_get_card_id_string(dev), sizeof(d->d_descr));

View File

@ -1,5 +1,6 @@
/*-
* Copyright (c) 2013 LSI Corp.
* Copyright (c) 2012-2015 LSI Corp.
* Copyright (c) 2013-2015 Avago Technologies
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -26,13 +27,14 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* LSI MPT-Fusion Host Adapter FreeBSD
* Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD
*
* $FreeBSD$
*/
/*
* Copyright (c) 2000-2013 LSI Corporation.
* Copyright (c) 2000-2015 LSI Corporation.
* Copyright (c) 2013-2015 Avago Technologies
*
*
* Name: mpi2.h

View File

@ -1,5 +1,6 @@
/*-
* Copyright (c) 2013 LSI Corp.
* Copyright (c) 2012-2015 LSI Corp.
* Copyright (c) 2013-2015 Avago Technologies
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -26,13 +27,14 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* LSI MPT-Fusion Host Adapter FreeBSD
* Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD
*
* $FreeBSD$
*/
/*
* Copyright (c) 2000-2013 LSI Corporation.
* Copyright (c) 2000-2015 LSI Corporation.
* Copyright (c) 2013-2015 Avago Technologies
*
*
* Name: mpi2_cnfg.h

View File

@ -1,5 +1,6 @@
/*-
* Copyright (c) 2013 LSI Corp.
* Copyright (c) 2012-2015 LSI Corp.
* Copyright (c) 2013-2015 Avago Technologies
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -26,13 +27,14 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* LSI MPT-Fusion Host Adapter FreeBSD
* Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD
*
* $FreeBSD$
*/
/*
* Copyright (c) 2009-2011 LSI Corporation.
* Copyright (c) 2009-2015 LSI Corporation.
* Copyright (c) 2013-2015 Avago Technologies
*
*
* Name: mpi2_hbd.h

View File

@ -1,5 +1,6 @@
/*-
* Copyright (c) 2013 LSI Corp.
* Copyright (c) 2012-2015 LSI Corp.
* Copyright (c) 2013-2015 Avago Technologies
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -26,7 +27,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* LSI MPT-Fusion Host Adapter FreeBSD
* Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD
*
* $FreeBSD$
*/
@ -35,7 +36,8 @@
Fusion-MPT MPI 2.0 / 2.5 Header File Change History
==============================
Copyright (c) 2000-2013 LSI Corporation.
Copyright (c) 2000-2015 LSI Corporation.
Copyright (c) 2013-2015 Avago Technologies
---------------------------------------
Header Set Release Version: 02.00.33

View File

@ -1,5 +1,6 @@
/*-
* Copyright (c) 2013 LSI Corp.
* Copyright (c) 2012-2015 LSI Corp.
* Copyright (c) 2013-2015 Avago Technologies
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -26,13 +27,14 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* LSI MPT-Fusion Host Adapter FreeBSD
* Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD
*
* $FreeBSD$
*/
/*
* Copyright (c) 2000-2013 LSI Corporation.
* Copyright (c) 2000-2015 LSI Corporation.
* Copyright (c) 2013-2015 Avago Technologies
*
*
* Name: mpi2_init.h

View File

@ -1,5 +1,6 @@
/*-
* Copyright (c) 2013 LSI Corp.
* Copyright (c) 2012-2015 LSI Corp.
* Copyright (c) 2013-2015 Avago Technologies
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -26,13 +27,14 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* LSI MPT-Fusion Host Adapter FreeBSD
* Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD
*
* $FreeBSD$
*/
/*
* Copyright (c) 2000-2013 LSI Corporation.
* Copyright (c) 2000-2015 LSI Corporation.
* Copyright (c) 2013-2015 Avago Technologies
*
*
* Name: mpi2_ioc.h

View File

@ -1,5 +1,6 @@
/*-
* Copyright (c) 2013 LSI Corp.
* Copyright (c) 2012-2015 LSI Corp.
* Copyright (c) 2013-2015 Avago Technologies
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -26,13 +27,14 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* LSI MPT-Fusion Host Adapter FreeBSD
* Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD
*
* $FreeBSD$
*/
/*
* Copyright (c) 2009 LSI Corporation.
* Copyright (c) 2012-2015 LSI Corporation.
* Copyright (c) 2013-2015 Avago Technologies
*
*
* Name: mpi2_ra.h

View File

@ -1,5 +1,6 @@
/*-
* Copyright (c) 2013 LSI Corp.
* Copyright (c) 2012-2015 LSI Corp.
* Copyright (c) 2013-2015 Avago Technologies
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -26,13 +27,14 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* LSI MPT-Fusion Host Adapter FreeBSD
* Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD
*
* $FreeBSD$
*/
/*
* Copyright (c) 2000-2013 LSI Corporation.
* Copyright (c) 2000-2015 LSI Corporation.
* Copyright (c) 2013-2015 Avago Technologies
*
*
* Name: mpi2_raid.h

View File

@ -1,5 +1,6 @@
/*-
* Copyright (c) 2013 LSI Corp.
* Copyright (c) 2012-2015 LSI Corp.
* Copyright (c) 2013-2015 Avago Technologies
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -26,13 +27,14 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* LSI MPT-Fusion Host Adapter FreeBSD
* Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD
*
* $FreeBSD$
*/
/*
* Copyright (c) 2000-2013 LSI Corporation.
* Copyright (c) 2000-2015 LSI Corporation.
* Copyright (c) 2013-2015 Avago Technologies
*
*
* Name: mpi2_sas.h

View File

@ -1,5 +1,6 @@
/*-
* Copyright (c) 2013 LSI Corp.
* Copyright (c) 2012-2015 LSI Corp.
* Copyright (c) 2013-2015 Avago Technologies
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -26,13 +27,14 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* LSI MPT-Fusion Host Adapter FreeBSD
* Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD
*
* $FreeBSD$
*/
/*
* Copyright (c) 2000-2012 LSI Corporation.
* Copyright (c) 2000-2015 LSI Corporation.
* Copyright (c) 2013-2015 Avago Technologies
*
*
* Name: mpi2_targ.h

View File

@ -1,5 +1,6 @@
/*-
* Copyright (c) 2013 LSI Corp.
* Copyright (c) 2012-2015 LSI Corp.
* Copyright (c) 2013-2015 Avago Technologies
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -26,13 +27,14 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* LSI MPT-Fusion Host Adapter FreeBSD
* Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD
*
* $FreeBSD$
*/
/*
* Copyright (c) 2000-2013 LSI Corporation.
* Copyright (c) 2000-2015 LSI Corporation.
* Copyright (c) 2013-2015 Avago Technologies
*
*
* Name: mpi2_tool.h

View File

@ -1,5 +1,6 @@
/*-
* Copyright (c) 2013 LSI Corp.
* Copyright (c) 2012-2015 LSI Corp.
* Copyright (c) 2013-2015 Avago Technologies
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -26,13 +27,14 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* LSI MPT-Fusion Host Adapter FreeBSD
* Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD
*
* $FreeBSD$
*/
/*
* Copyright (c) 2000-2007 LSI Corporation.
* Copyright (c) 2000-2015 LSI Corporation.
* Copyright (c) 2013-2015 Avago Technologies
*
*
* Name: mpi2_type.h

View File

@ -1,6 +1,7 @@
/*-
* Copyright (c) 2009 Yahoo! Inc.
* Copyright (c) 2012-2014 LSI Corp.
* Copyright (c) 2011-2015 LSI Corp.
* Copyright (c) 2013-2015 Avago Technologies
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -24,12 +25,14 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD
*
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
/* Communications core for LSI MPT2 */
/* Communications core for Avago Technologies (LSI) MPT3 */
/* TODO Move headers to mprvar */
#include <sys/types.h>
@ -72,7 +75,6 @@ __FBSDID("$FreeBSD$");
#include <dev/mpr/mpr_ioctl.h>
#include <dev/mpr/mprvar.h>
#include <dev/mpr/mpr_table.h>
#include <dev/mpr/mpr_sas.h>
static int mpr_diag_reset(struct mpr_softc *sc, int sleep_flag);
static int mpr_init_queues(struct mpr_softc *sc);
@ -352,11 +354,9 @@ mpr_transition_operational(struct mpr_softc *sc)
static int
mpr_iocfacts_allocate(struct mpr_softc *sc, uint8_t attaching)
{
int error, i;
int error;
Mpi2IOCFactsReply_t saved_facts;
uint8_t saved_mode, reallocating;
struct mprsas_lun *lun, *lun_tmp;
struct mprsas_target *targ;
mpr_dprint(sc, MPR_TRACE, "%s\n", __func__);
@ -513,27 +513,7 @@ mpr_iocfacts_allocate(struct mpr_softc *sc, uint8_t attaching)
*/
if (reallocating) {
mpr_iocfacts_free(sc);
/*
* The number of targets is based on IOC Facts, so free all of
* the allocated LUNs for each target and then the target buffer
* itself.
*/
for (i=0; i< saved_facts.MaxTargets; i++) {
targ = &sc->sassc->targets[i];
SLIST_FOREACH_SAFE(lun, &targ->luns, lun_link,
lun_tmp) {
free(lun, M_MPR);
}
}
free(sc->sassc->targets, M_MPR);
sc->sassc->targets = malloc(sizeof(struct mprsas_target) *
sc->facts->MaxTargets, M_MPR, M_WAITOK|M_ZERO);
if (!sc->sassc->targets) {
panic("%s failed to alloc targets with error %d\n",
__func__, ENOMEM);
}
mprsas_realloc_targets(sc, saved_facts.MaxTargets);
}
/*
@ -775,7 +755,7 @@ mpr_reinit(struct mpr_softc *sc)
/* the end of discovery will release the simq, so we're done. */
mpr_dprint(sc, MPR_INFO, "%s finished sc %p post %u free %u\n",
__func__, sc, sc->replypostindex, sc->replyfreeindex);
mprsas_release_simq_reinit(sassc);
mprsas_release_simq_reinit(sassc);
return 0;
}
@ -816,7 +796,8 @@ mpr_wait_db_ack(struct mpr_softc *sc, int timeout, int sleep_flag)
* 0.5 milisecond
*/
if (mtx_owned(&sc->mpr_mtx) && sleep_flag == CAN_SLEEP)
msleep(&sc->msleep_fake_chan, &sc->mpr_mtx, 0, "mprdba", hz/1000);
msleep(&sc->msleep_fake_chan, &sc->mpr_mtx, 0, "mprdba",
hz/1000);
else if (sleep_flag == CAN_SLEEP)
pause("mprdba", hz/1000);
else
@ -982,7 +963,7 @@ mpr_enqueue_request(struct mpr_softc *sc, struct mpr_command *cm)
reply_descriptor rd;
MPR_FUNCTRACE(sc);
mpr_dprint(sc, MPR_TRACE, "%s SMID %u cm %p ccb %p\n", __func__,
mpr_dprint(sc, MPR_TRACE, "SMID %u cm %p ccb %p\n",
cm->cm_desc.Default.SMID, cm, cm->cm_ccb);
if (sc->mpr_flags & MPR_FLAGS_ATTACH_DONE && !(sc->mpr_flags &
@ -1372,6 +1353,8 @@ mpr_get_tunables(struct mpr_softc *sc)
sc->disable_msix = 0;
sc->disable_msi = 0;
sc->max_chains = MPR_CHAIN_FRAMES;
sc->enable_ssu = MPR_SSU_ENABLE_SSD_DISABLE_HDD;
sc->spinup_wait_time = DEFAULT_SPINUP_WAIT;
/*
* Grab the global variables.
@ -1380,6 +1363,8 @@ mpr_get_tunables(struct mpr_softc *sc)
TUNABLE_INT_FETCH("hw.mpr.disable_msix", &sc->disable_msix);
TUNABLE_INT_FETCH("hw.mpr.disable_msi", &sc->disable_msi);
TUNABLE_INT_FETCH("hw.mpr.max_chains", &sc->max_chains);
TUNABLE_INT_FETCH("hw.mpr.enable_ssu", &sc->enable_ssu);
TUNABLE_INT_FETCH("hw.mpr.spinup_wait_time", &sc->spinup_wait_time);
/* Grab the unit-instance variables */
snprintf(tmpstr, sizeof(tmpstr), "dev.mpr.%d.debug_level",
@ -1402,6 +1387,14 @@ mpr_get_tunables(struct mpr_softc *sc)
snprintf(tmpstr, sizeof(tmpstr), "dev.mpr.%d.exclude_ids",
device_get_unit(sc->mpr_dev));
TUNABLE_STR_FETCH(tmpstr, sc->exclude_ids, sizeof(sc->exclude_ids));
snprintf(tmpstr, sizeof(tmpstr), "dev.mpr.%d.enable_ssu",
device_get_unit(sc->mpr_dev));
TUNABLE_INT_FETCH(tmpstr, &sc->enable_ssu);
snprintf(tmpstr, sizeof(tmpstr), "dev.mpr.%d.spinup_wait_time",
device_get_unit(sc->mpr_dev));
TUNABLE_INT_FETCH(tmpstr, &sc->spinup_wait_time);
}
static void
@ -1474,11 +1467,20 @@ mpr_setup_sysctl(struct mpr_softc *sc)
OID_AUTO, "max_chains", CTLFLAG_RD,
&sc->max_chains, 0,"maximum chain frames that will be allocated");
SYSCTL_ADD_INT(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree),
OID_AUTO, "enable_ssu", CTLFLAG_RW, &sc->enable_ssu, 0,
"enable SSU to SATA SSD/HDD at shutdown");
#if __FreeBSD_version >= 900030
SYSCTL_ADD_UQUAD(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree),
OID_AUTO, "chain_alloc_fail", CTLFLAG_RD,
&sc->chain_alloc_fail, "chain allocation failures");
#endif //FreeBSD_version >= 900030
SYSCTL_ADD_INT(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree),
OID_AUTO, "spinup_wait_time", CTLFLAG_RD,
&sc->spinup_wait_time, DEFAULT_SPINUP_WAIT, "seconds to wait for "
"spinup after SATA ID error");
}
int
@ -2096,7 +2098,7 @@ mpr_update_events(struct mpr_softc *sc, struct mpr_event_handle *handle,
(reply->IOCStatus & MPI2_IOCSTATUS_MASK) != MPI2_IOCSTATUS_SUCCESS)
error = ENXIO;
if(reply)
if (reply)
mpr_print_event(sc, reply);
mpr_dprint(sc, MPR_TRACE, "%s finished error %d\n", __func__, error);
@ -2163,8 +2165,8 @@ mpr_deregister_events(struct mpr_softc *sc, struct mpr_event_handle *handle)
* Add a chain element as the next SGE for the specified command.
* Reset cm_sge and cm_sgesize to indicate all the available space. Chains are
* only required for IEEE commands. Therefore there is no code for commands
* that have the MPR_CM_FLAGS_SGE_SIMPLE flag set (and those commands shouldn't
* be requesting chains).
* that have the MPR_CM_FLAGS_SGE_SIMPLE flag set (and those commands
* shouldn't be requesting chains).
*/
static int
mpr_add_chain(struct mpr_command *cm, int segsleft)
@ -2246,9 +2248,9 @@ mpr_add_chain(struct mpr_command *cm, int segsleft)
/*
* Add one scatter-gather element to the scatter-gather list for a command.
* Maintain cm_sglsize and cm_sge as the remaining size and pointer to the next
* SGE to fill in, respectively. In Gen3, the MPI SGL does not have a chain,
* so don't consider any chain additions.
* Maintain cm_sglsize and cm_sge as the remaining size and pointer to the
* next SGE to fill in, respectively. In Gen3, the MPI SGL does not have a
* chain, so don't consider any chain additions.
*/
int
mpr_push_sge(struct mpr_command *cm, MPI2_SGE_SIMPLE64 *sge, size_t len,
@ -2660,7 +2662,7 @@ mpr_request_polled(struct mpr_softc *sc, struct mpr_command *cm)
}
}
if(error) {
if (error) {
mpr_dprint(sc, MPR_FAULT, "Calling Reinit from %s\n", __func__);
rc = mpr_reinit(sc);
mpr_dprint(sc, MPR_FAULT, "Reinit %s\n", (rc == 0) ?
@ -2717,9 +2719,12 @@ mpr_read_config_page(struct mpr_softc *sc, struct mpr_config_params *params)
cm->cm_data = params->buffer;
cm->cm_length = params->length;
cm->cm_sge = &req->PageBufferSGE;
cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAIN;
if (cm->cm_data != NULL) {
cm->cm_sge = &req->PageBufferSGE;
cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION);
cm->cm_flags = MPR_CM_FLAGS_SGE_SIMPLE | MPR_CM_FLAGS_DATAIN;
} else
cm->cm_sge = NULL;
cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
cm->cm_complete_data = params;
@ -2776,9 +2781,12 @@ mpr_config_complete(struct mpr_softc *sc, struct mpr_command *cm)
goto done;
}
params->status = reply->IOCStatus;
if (params->hdr.Ext.ExtPageType != 0) {
if (params->hdr.Struct.PageType == MPI2_CONFIG_PAGETYPE_EXTENDED) {
params->hdr.Ext.ExtPageType = reply->ExtPageType;
params->hdr.Ext.ExtPageLength = reply->ExtPageLength;
params->hdr.Ext.PageType = reply->Header.PageType;
params->hdr.Ext.PageNumber = reply->Header.PageNumber;
params->hdr.Ext.PageVersion = reply->Header.PageVersion;
} else {
params->hdr.Struct.PageType = reply->Header.PageType;
params->hdr.Struct.PageNumber = reply->Header.PageNumber;

View File

@ -1,5 +1,6 @@
/*-
* Copyright (c) 2011-2014 LSI Corp.
* Copyright (c) 2011-2015 LSI Corp.
* Copyright (c) 2013-2015 Avago Technologies
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -23,7 +24,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* LSI MPT-Fusion Host Adapter FreeBSD
* Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD
*/
#include <sys/cdefs.h>

View File

@ -27,12 +27,13 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* LSI MPT-Fusion Host Adapter FreeBSD userland interface
* Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD userland interface
*
* $FreeBSD$
*/
/*-
* Copyright (c) 2011-2014 LSI Corp.
* Copyright (c) 2011-2015 LSI Corp.
* Copyright (c) 2013-2015 Avago Technologies
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -56,7 +57,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* LSI MPT-Fusion Host Adapter FreeBSD
* Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD
*
* $FreeBSD$
*/

View File

@ -1,5 +1,6 @@
/*-
* Copyright (c) 2011-2014 LSI Corp.
* Copyright (c) 2011-2015 LSI Corp.
* Copyright (c) 2013-2015 Avago Technologies
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -23,7 +24,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* LSI MPT-Fusion Host Adapter FreeBSD
* Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD
*/
#include <sys/cdefs.h>
@ -326,11 +327,13 @@ _mapping_get_high_missing_mt_idx(struct mpr_softc *sc)
{
u32 map_idx, high_idx = MPR_ENCTABLE_BAD_IDX;
u8 high_missing_count = 0;
u32 start_idx, end_idx, start_idx_ir = 0, end_idx_ir;
u32 start_idx, end_idx, start_idx_ir, end_idx_ir;
struct dev_mapping_table *mt_entry;
u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags);
start_idx = 0;
start_idx_ir = 0;
end_idx_ir = 0;
end_idx = sc->max_devices;
if (ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_RESERVED_TARGETID_0)
start_idx = 1;
@ -887,14 +890,14 @@ _mapping_get_dev_info(struct mpr_softc *sc,
u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags);
Mpi2ConfigReply_t mpi_reply;
Mpi2SasDevicePage0_t sas_device_pg0;
u8 entry, enc_idx, phy_idx;
u8 entry, enc_idx, phy_idx, sata_end_device;
u32 map_idx, index, device_info;
struct _map_phy_change *phy_change, *tmp_phy_change;
uint64_t sas_address;
struct enc_mapping_table *et_entry;
struct dev_mapping_table *mt_entry;
u8 add_code = MPI2_EVENT_SAS_TOPO_RC_TARG_ADDED;
int rc;
int rc = 1;
for (entry = 0; entry < topo_change->num_entries; entry++) {
phy_change = &topo_change->phy_details[entry];
@ -908,41 +911,36 @@ _mapping_get_dev_info(struct mpr_softc *sc,
continue;
}
/*
* Always get SATA Identify information because this is used
* to determine if Start/Stop Unit should be sent to the drive
* when the system is shutdown.
*/
device_info = le32toh(sas_device_pg0.DeviceInfo);
if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) ==
MPI2_IOCPAGE8_FLAGS_DEVICE_PERSISTENCE_MAPPING) {
if ((device_info & MPI2_SAS_DEVICE_INFO_END_DEVICE) &&
(device_info & MPI2_SAS_DEVICE_INFO_SATA_DEVICE)) {
rc = mprsas_get_sas_address_for_sata_disk(sc,
&sas_address, phy_change->dev_handle,
device_info);
if (rc) {
printf("%s: failed to compute the "
"hashed SAS Address for SATA "
"device with handle 0x%04x\n",
__func__, phy_change->dev_handle);
sas_address =
sas_device_pg0.SASAddress.High;
sas_address = (sas_address << 32) |
sas_device_pg0.SASAddress.Low;
}
sas_address = sas_device_pg0.SASAddress.High;
sas_address = (sas_address << 32) |
sas_device_pg0.SASAddress.Low;
sata_end_device = 0;
if ((device_info & MPI2_SAS_DEVICE_INFO_END_DEVICE) &&
(device_info & MPI2_SAS_DEVICE_INFO_SATA_DEVICE)) {
sata_end_device = 1;
rc = mprsas_get_sas_address_for_sata_disk(sc,
&sas_address, phy_change->dev_handle, device_info,
&phy_change->is_SATA_SSD);
if (rc) {
mpr_dprint(sc, MPR_ERROR, "%s: failed to get "
"disk type (SSD or HDD) and SAS Address "
"for SATA device with handle 0x%04x\n",
__func__, phy_change->dev_handle);
} else {
mpr_dprint(sc, MPR_INFO, "SAS Address for SATA "
"device = %jx\n", sas_address);
} else {
sas_address =
sas_device_pg0.SASAddress.High;
sas_address = (sas_address << 32) |
sas_device_pg0.SASAddress.Low;
}
} else {
sas_address = sas_device_pg0.SASAddress.High;
sas_address = (sas_address << 32) |
sas_device_pg0.SASAddress.Low;
}
phy_change->physical_id = sas_address;
phy_change->slot = le16toh(sas_device_pg0.Slot);
phy_change->device_info =
le32toh(sas_device_pg0.DeviceInfo);
phy_change->device_info = le32toh(sas_device_pg0.DeviceInfo);
if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) ==
MPI2_IOCPAGE8_FLAGS_ENCLOSURE_SLOT_MAPPING) {
@ -950,10 +948,10 @@ _mapping_get_dev_info(struct mpr_softc *sc,
topo_change->enc_handle);
if (enc_idx == MPR_ENCTABLE_BAD_IDX) {
phy_change->is_processed = 1;
printf("%s: failed to add the device with "
"handle 0x%04x because the enclosure is "
"not in the mapping table\n", __func__,
phy_change->dev_handle);
mpr_dprint(sc, MPR_MAPPING, "%s: failed to add "
"the device with handle 0x%04x because the "
"enclosure is not in the mapping table\n",
__func__, phy_change->dev_handle);
continue;
}
if (!((phy_change->device_info &

View File

@ -1,5 +1,6 @@
/*-
* Copyright (c) 2011-2014 LSI Corp.
* Copyright (c) 2011-2015 LSI Corp.
* Copyright (c) 2013-2015 Avago Technologies
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -23,7 +24,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* LSI MPT-Fusion Host Adapter FreeBSD
* Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD
*
* $FreeBSD$
*/
@ -38,6 +39,7 @@
* @dev_handle: device handle for the device pointed by this entry
* @slot: slot ID
* @is_processed: Flag to indicate whether this entry is processed or not
* @is_SATA_SSD: 1 if this is a SATA device AND an SSD, 0 otherwise
*/
struct _map_phy_change {
uint64_t physical_id;
@ -46,6 +48,8 @@ struct _map_phy_change {
uint16_t slot;
uint8_t reason;
uint8_t is_processed;
uint8_t is_SATA_SSD;
uint8_t reserved;
};
/**
@ -66,6 +70,6 @@ struct _map_topology_change {
extern int
mprsas_get_sas_address_for_sata_disk(struct mpr_softc *ioc,
u64 *sas_address, u16 handle, u32 device_info);
u64 *sas_address, u16 handle, u32 device_info, u8 *is_SATA_SSD);
#endif

View File

@ -27,7 +27,7 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
/* PCI/PCI-X/PCIe bus interface for the LSI MPT2 controllers */
/* PCI/PCI-X/PCIe bus interface for the Avago Tech (LSI) MPT3 controllers */
/* TODO Move headers to mprvar */
#include <sys/types.h>
@ -99,17 +99,17 @@ struct mpr_ident {
const char *desc;
} mpr_identifiers[] = {
{ MPI2_MFGPAGE_VENDORID_LSI, MPI25_MFGPAGE_DEVID_SAS3004,
0xffff, 0xffff, 0, "LSI SAS3004" },
0xffff, 0xffff, 0, "Avago Technologies (LSI) SAS3004" },
{ MPI2_MFGPAGE_VENDORID_LSI, MPI25_MFGPAGE_DEVID_SAS3008,
0xffff, 0xffff, 0, "LSI SAS3008" },
0xffff, 0xffff, 0, "Avago Technologies (LSI) SAS3008" },
{ MPI2_MFGPAGE_VENDORID_LSI, MPI25_MFGPAGE_DEVID_SAS3108_1,
0xffff, 0xffff, 0, "LSI SAS3108_1" },
0xffff, 0xffff, 0, "Avago Technologies (LSI) SAS3108_1" },
{ MPI2_MFGPAGE_VENDORID_LSI, MPI25_MFGPAGE_DEVID_SAS3108_2,
0xffff, 0xffff, 0, "LSI SAS3108_2" },
0xffff, 0xffff, 0, "Avago Technologies (LSI) SAS3108_2" },
{ MPI2_MFGPAGE_VENDORID_LSI, MPI25_MFGPAGE_DEVID_SAS3108_5,
0xffff, 0xffff, 0, "LSI SAS3108_5" },
0xffff, 0xffff, 0, "Avago Technologies (LSI) SAS3108_5" },
{ MPI2_MFGPAGE_VENDORID_LSI, MPI25_MFGPAGE_DEVID_SAS3108_6,
0xffff, 0xffff, 0, "LSI SAS3108_6" },
0xffff, 0xffff, 0, "Avago Technologies (LSI) SAS3108_6" },
{ 0, 0, 0, 0, 0, NULL }
};

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,6 @@
/*-
* Copyright (c) 2011-2014 LSI Corp.
* Copyright (c) 2011-2015 LSI Corp.
* Copyright (c) 2013-2015 Avago Technologies
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -23,7 +24,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* LSI MPT-Fusion Host Adapter FreeBSD
* Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD
*
* $FreeBSD$
*/
@ -35,7 +36,6 @@ struct mprsas_lun {
lun_id_t lun_id;
uint8_t eedp_formatted;
uint32_t eedp_block_size;
uint8_t stop_at_shutdown;
};
struct mprsas_target {
@ -55,11 +55,10 @@ struct mprsas_target {
#define MPRSAS_TARGET_INREMOVAL (1 << 3)
#define MPR_TARGET_FLAGS_RAID_COMPONENT (1 << 4)
#define MPR_TARGET_FLAGS_VOLUME (1 << 5)
#define MPR_TARGET_IS_SATA_SSD (1 << 6)
#define MPRSAS_TARGET_INRECOVERY (MPRSAS_TARGET_INABORT | \
MPRSAS_TARGET_INRESET | MPRSAS_TARGET_INCHIPRESET)
#define MPRSAS_TARGET_ADD (1 << 29)
#define MPRSAS_TARGET_REMOVE (1 << 30)
uint16_t tid;
SLIST_HEAD(, mprsas_lun) luns;
TAILQ_HEAD(, mpr_command) commands;
@ -82,6 +81,8 @@ struct mprsas_target {
unsigned int logical_unit_resets;
unsigned int target_resets;
uint8_t scsi_req_desc_type;
uint8_t stop_at_shutdown;
uint8_t supports_SSU;
};
struct mprsas_softc {
@ -92,7 +93,6 @@ struct mprsas_softc {
#define MPRSAS_DISCOVERY_TIMEOUT_PENDING (1 << 2)
#define MPRSAS_QUEUE_FROZEN (1 << 3)
#define MPRSAS_SHUTDOWN (1 << 4)
#define MPRSAS_SCANTHREAD (1 << 5)
u_int maxtargets;
struct mprsas_target *targets;
struct cam_devq *devq;
@ -103,7 +103,6 @@ struct mprsas_softc {
struct mpr_event_handle *mprsas_eh;
u_int startup_refcount;
u_int tm_count;
struct proc *sysctl_proc;
struct taskqueue *ev_tq;
@ -150,6 +149,19 @@ mprsas_set_lun(uint8_t *lun, u_int ccblun)
return (0);
}
static __inline void
mprsas_set_ccbstatus(union ccb *ccb, int status)
{
ccb->ccb_h.status &= ~CAM_STATUS_MASK;
ccb->ccb_h.status |= status;
}
static __inline int
mprsas_get_ccbstatus(union ccb *ccb)
{
return (ccb->ccb_h.status & CAM_STATUS_MASK);
}
#define MPR_SET_SINGLE_LUN(req, lun) \
do { \
bzero((req)->LUN, 8); \
@ -158,11 +170,10 @@ do { \
void mprsas_rescan_target(struct mpr_softc *sc, struct mprsas_target *targ);
void mprsas_discovery_end(struct mprsas_softc *sassc);
void mprsas_prepare_for_tm(struct mpr_softc *sc, struct mpr_command *tm,
struct mprsas_target *target, lun_id_t lun_id);
void mprsas_startup_increment(struct mprsas_softc *sassc);
void mprsas_startup_decrement(struct mprsas_softc *sassc);
void mprsas_release_simq_reinit(struct mprsas_softc *sassc);
struct mpr_command * mprsas_alloc_tm(struct mpr_softc *sc);
void mprsas_free_tm(struct mpr_softc *sc, struct mpr_command *tm);
void mprsas_firmware_event_work(void *arg, int pending);
int mprsas_check_id(struct mprsas_softc *sassc, int id);

View File

@ -1,5 +1,6 @@
/*-
* Copyright (c) 2011-2014 LSI Corp.
* Copyright (c) 2011-2015 LSI Corp.
* Copyright (c) 2013-2015 Avago Technologies
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -23,13 +24,13 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* LSI MPT-Fusion Host Adapter FreeBSD
* Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
/* Communications core for LSI MPT2 */
/* Communications core for LSI MPT3 */
/* TODO Move headers to mprvar */
#include <sys/types.h>
@ -105,7 +106,9 @@ struct _ata_identify_device_data {
u16 serial_number[10]; /* 10-19 */
u16 reserved2[7]; /* 20-26 */
u16 model_number[20]; /* 27-46*/
u16 reserved3[209]; /* 47-255*/
u16 reserved3[170]; /* 47-216 */
u16 rotational_speed; /* 217 */
u16 reserved4[38]; /* 218-255 */
};
static u32 event_count;
static void mprsas_fw_work(struct mpr_softc *sc,
@ -116,8 +119,9 @@ static int mprsas_add_device(struct mpr_softc *sc, u16 handle, u8 linkrate);
static int mprsas_get_sata_identify(struct mpr_softc *sc, u16 handle,
Mpi2SataPassthroughReply_t *mpi_reply, char *id_buffer, int sz,
u32 devinfo);
static void mprsas_ata_id_timeout(void *data);
int mprsas_get_sas_address_for_sata_disk(struct mpr_softc *sc,
u64 *sas_address, u16 handle, u32 device_info);
u64 *sas_address, u16 handle, u32 device_info, u8 *is_SATA_SSD);
static int mprsas_volume_add(struct mpr_softc *sc,
u16 handle);
static void mprsas_SSU_to_SATA_devices(struct mpr_softc *sc);
@ -325,7 +329,7 @@ mprsas_fw_work(struct mpr_softc *sc, struct mpr_fw_event_work *fw_event)
return;
}
mpr_dprint(sc, MPR_INFO, "Sending FP action "
mpr_dprint(sc, MPR_EVENT, "Sending FP action "
"from "
"MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST "
":\n");
@ -350,9 +354,9 @@ mprsas_fw_work(struct mpr_softc *sc, struct mpr_fw_event_work *fw_event)
if (reply && (le16toh(reply->IOCStatus) &
MPI2_IOCSTATUS_MASK) !=
MPI2_IOCSTATUS_SUCCESS) {
mpr_dprint(sc, MPR_INFO, "%s: error "
"sending RaidActionPage; iocstatus "
"= 0x%x\n", __func__,
mpr_dprint(sc, MPR_ERROR, "%s: error "
"sending RaidActionPage; "
"iocstatus = 0x%x\n", __func__,
le16toh(reply->IOCStatus));
}
@ -360,7 +364,7 @@ mprsas_fw_work(struct mpr_softc *sc, struct mpr_fw_event_work *fw_event)
mpr_free_command(sc, cm);
}
skip_fp_send:
mpr_dprint(sc, MPR_INFO, "Received "
mpr_dprint(sc, MPR_EVENT, "Received "
"MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST Reason "
"code %x:\n", element->ReasonCode);
switch (element->ReasonCode) {
@ -421,7 +425,6 @@ skip_fp_send:
break;
targ->flags |= MPR_TARGET_FLAGS_RAID_COMPONENT;
mprsas_rescan_target(sc, targ);
break;
case MPI2_EVENT_IR_CHANGE_RC_PD_DELETED:
/*
@ -678,14 +681,13 @@ mprsas_add_device(struct mpr_softc *sc, u16 handle, u8 linkrate){
struct mprsas_target *targ;
Mpi2ConfigReply_t mpi_reply;
Mpi2SasDevicePage0_t config_page;
uint64_t sas_address, sata_sas_address;
uint64_t parent_sas_address = 0;
u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags);
uint64_t sas_address, parent_sas_address = 0;
u32 device_info, parent_devinfo = 0;
unsigned int id;
int ret;
int error = 0;
int ret = 1, error = 0, i;
struct mprsas_lun *lun;
u8 is_SATA_SSD = 0;
struct mpr_command *cm;
sassc = sc->sassc;
mprsas_startup_increment(sassc);
@ -717,26 +719,29 @@ mprsas_add_device(struct mpr_softc *sc, u16 handle, u8 linkrate){
}
/* TODO Check proper endianess */
sas_address = config_page.SASAddress.High;
sas_address = (sas_address << 32) |
config_page.SASAddress.Low;
sas_address = (sas_address << 32) | config_page.SASAddress.Low;
mpr_dprint(sc, MPR_INFO, "SAS Address from SAS device page0 = %jx\n",
sas_address);
if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE)
== MPI2_IOCPAGE8_FLAGS_DEVICE_PERSISTENCE_MAPPING) {
if (device_info & MPI2_SAS_DEVICE_INFO_SATA_DEVICE) {
ret = mprsas_get_sas_address_for_sata_disk(sc,
&sata_sas_address, handle, device_info);
if (!ret)
id = mpr_mapping_get_sas_id(sc,
sata_sas_address, handle);
else
id = mpr_mapping_get_sas_id(sc,
sas_address, handle);
} else
id = mpr_mapping_get_sas_id(sc, sas_address,
handle);
} else
id = mpr_mapping_get_sas_id(sc, sas_address, handle);
/*
* Always get SATA Identify information because this is used to
* determine if Start/Stop Unit should be sent to the drive when the
* system is shutdown.
*/
if (device_info & MPI2_SAS_DEVICE_INFO_SATA_DEVICE) {
ret = mprsas_get_sas_address_for_sata_disk(sc, &sas_address,
handle, device_info, &is_SATA_SSD);
if (ret) {
mpr_dprint(sc, MPR_ERROR, "%s: failed to get disk type "
"(SSD or HDD) for SATA device with handle 0x%04x\n",
__func__, handle);
} else {
mpr_dprint(sc, MPR_INFO, "SAS Address from SATA "
"device = %jx\n", sas_address);
}
}
id = mpr_mapping_get_sas_id(sc, sas_address, handle);
if (id == MPR_MAP_BAD_ID) {
printf("failure at %s:%d/%s()! Could not get ID for device "
"with handle 0x%04x\n", __FILE__, __LINE__, __func__,
@ -750,7 +755,7 @@ mprsas_add_device(struct mpr_softc *sc, u16 handle, u8 linkrate){
error = ENXIO;
goto out;
}
mpr_dprint(sc, MPR_MAPPING, "SAS Address from SAS device page0 = %jx\n",
sas_address);
targ = &sassc->targets[id];
@ -773,6 +778,9 @@ mprsas_add_device(struct mpr_softc *sc, u16 handle, u8 linkrate){
targ->tid = id;
targ->linkrate = (linkrate>>4);
targ->flags = 0;
if (is_SATA_SSD) {
targ->flags = MPR_TARGET_IS_SATA_SSD;
}
if (le16toh(config_page.Flags) &
MPI25_SAS_DEVICE0_FLAGS_FAST_PATH_CAPABLE) {
targ->scsi_req_desc_type =
@ -792,12 +800,12 @@ mprsas_add_device(struct mpr_softc *sc, u16 handle, u8 linkrate){
SLIST_INIT(&targ->luns);
mpr_describe_devinfo(targ->devinfo, devstring, 80);
mpr_dprint(sc, (MPR_XINFO|MPR_MAPPING), "Found device <%s> <%s> "
mpr_dprint(sc, (MPR_INFO|MPR_MAPPING), "Found device <%s> <%s> "
"handle<0x%04x> enclosureHandle<0x%04x> slot %d\n", devstring,
mpr_describe_table(mpr_linkrate_names, targ->linkrate),
targ->handle, targ->encl_handle, targ->encl_slot);
if (targ->encl_level_valid) {
mpr_dprint(sc, (MPR_XINFO|MPR_MAPPING), "At enclosure level %d "
mpr_dprint(sc, (MPR_INFO|MPR_MAPPING), "At enclosure level %d "
"and connector name (%4s)\n", targ->encl_level,
targ->connector_name);
}
@ -807,15 +815,57 @@ mprsas_add_device(struct mpr_softc *sc, u16 handle, u8 linkrate){
#endif
mprsas_rescan_target(sc, targ);
mpr_dprint(sc, MPR_MAPPING, "Target id 0x%x added\n", targ->tid);
/*
* Check all commands to see if the SATA_ID_TIMEOUT flag has been set.
* If so, send a Target Reset TM to the target that was just created.
* An Abort Task TM should be used instead of a Target Reset, but that
* would be much more difficult because targets have not been fully
* discovered yet, and LUN's haven't been setup. So, just reset the
* target instead of the LUN.
*/
for (i = 1; i < sc->num_reqs; i++) {
cm = &sc->commands[i];
if (cm->cm_flags & MPR_CM_FLAGS_SATA_ID_TIMEOUT) {
targ->timeouts++;
cm->cm_state = MPR_CM_STATE_TIMEDOUT;
if ((targ->tm = mprsas_alloc_tm(sc)) != NULL) {
mpr_dprint(sc, MPR_INFO, "%s: sending Target "
"Reset for stuck SATA identify command "
"(cm = %p)\n", __func__, cm);
targ->tm->cm_targ = targ;
mprsas_send_reset(sc, targ->tm,
MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET);
} else {
mpr_dprint(sc, MPR_ERROR, "Failed to allocate "
"tm for Target Reset after SATA ID "
"command timed out (cm %p)\n", cm);
}
/*
* No need to check for more since the target is
* already being reset.
*/
break;
}
}
out:
/*
* Free the commands that may not have been freed from the SATA ID call
*/
for (i = 1; i < sc->num_reqs; i++) {
cm = &sc->commands[i];
if (cm->cm_flags & MPR_CM_FLAGS_SATA_ID_TIMEOUT) {
mpr_free_command(sc, cm);
}
}
mprsas_startup_decrement(sassc);
return (error);
}
int
mprsas_get_sas_address_for_sata_disk(struct mpr_softc *sc,
u64 *sas_address, u16 handle, u32 device_info)
u64 *sas_address, u16 handle, u32 device_info, u8 *is_SATA_SSD)
{
Mpi2SataPassthroughReply_t mpi_reply;
int i, rc, try_count;
@ -835,7 +885,16 @@ mprsas_get_sas_address_for_sata_disk(struct mpr_softc *sc,
ioc_status = le16toh(mpi_reply.IOCStatus)
& MPI2_IOCSTATUS_MASK;
sas_status = mpi_reply.SASStatus;
} while ((rc == -EAGAIN || ioc_status || sas_status) &&
if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
if (sc->spinup_wait_time > 0) {
mpr_dprint(sc, MPR_INFO, "Sleeping %d seconds "
"after SATA ID error to wait for spinup\n",
sc->spinup_wait_time);
msleep(&sc->msleep_fake_chan, &sc->mpr_mtx, 0,
"mprid", sc->spinup_wait_time * hz);
}
}
} while (((rc && (rc != EWOULDBLOCK)) || ioc_status || sas_status) &&
(try_count < 5));
if (rc == 0 && !ioc_status && !sas_status) {
@ -884,6 +943,10 @@ mprsas_get_sas_address_for_sata_disk(struct mpr_softc *sc,
(u64)hash_address.wwid[3] << 32 | (u64)hash_address.wwid[4] << 24 |
(u64)hash_address.wwid[5] << 16 | (u64)hash_address.wwid[6] << 8 |
(u64)hash_address.wwid[7];
if (ata_identify.rotational_speed == 1) {
*is_SATA_SSD = 1;
}
return 0;
}
@ -923,14 +986,29 @@ mprsas_get_sata_identify(struct mpr_softc *sc, u16 handle,
cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
cm->cm_data = buffer;
cm->cm_length = htole32(sz);
/*
* Start a timeout counter specifically for the SATA ID command. This
* is used to fix a problem where the FW does not send a reply sometimes
* when a bad disk is in the topology. So, this is used to timeout the
* command so that processing can continue normally.
*/
mpr_dprint(sc, MPR_XINFO, "%s start timeout counter for SATA ID "
"command\n", __func__);
callout_reset(&cm->cm_callout, MPR_ATA_ID_TIMEOUT * hz,
mprsas_ata_id_timeout, cm);
error = mpr_wait_command(sc, cm, 60, CAN_SLEEP);
mpr_dprint(sc, MPR_XINFO, "%s stop timeout counter for SATA ID "
"command\n", __func__);
callout_stop(&cm->cm_callout);
reply = (Mpi2SataPassthroughReply_t *)cm->cm_reply;
if (error || (reply == NULL)) {
/* FIXME */
/*
* If the request returns an error then we need to do a diag
* reset
*/
*/
printf("%s: request for page completed with error %d",
__func__, error);
error = ENXIO;
@ -946,11 +1024,66 @@ mprsas_get_sata_identify(struct mpr_softc *sc, u16 handle,
goto out;
}
out:
mpr_free_command(sc, cm);
free(buffer, M_MPR);
/*
* If the SATA_ID_TIMEOUT flag has been set for this command, don't free
* it. The command will be freed after sending a target reset TM. If
* the command did timeout, use EWOULDBLOCK.
*/
if ((cm->cm_flags & MPR_CM_FLAGS_SATA_ID_TIMEOUT) == 0)
mpr_free_command(sc, cm);
else if (error == 0)
error = EWOULDBLOCK;
free(buffer, M_MPR);
return (error);
}
static void
mprsas_ata_id_timeout(void *data)
{
struct mpr_softc *sc;
struct mpr_command *cm;
cm = (struct mpr_command *)data;
sc = cm->cm_sc;
mtx_assert(&sc->mpr_mtx, MA_OWNED);
mpr_dprint(sc, MPR_INFO, "%s checking ATA ID command %p sc %p\n",
__func__, cm, sc);
if ((callout_pending(&cm->cm_callout)) ||
(!callout_active(&cm->cm_callout))) {
mpr_dprint(sc, MPR_INFO, "%s ATA ID command almost timed "
"out\n", __func__);
return;
}
callout_deactivate(&cm->cm_callout);
/*
* Run the interrupt handler to make sure it's not pending. This
* isn't perfect because the command could have already completed
* and been re-used, though this is unlikely.
*/
mpr_intr_locked(sc);
if (cm->cm_state == MPR_CM_STATE_FREE) {
mpr_dprint(sc, MPR_INFO, "%s ATA ID command almost timed "
"out\n", __func__);
return;
}
mpr_dprint(sc, MPR_INFO, "ATA ID command timeout cm %p\n", cm);
/*
* Send wakeup() to the sleeping thread that issued this ATA ID
* command. wakeup() will cause msleep to return a 0 (not EWOULDBLOCK),
* and this will keep reinit() from being called. This way, an Abort
* Task TM can be issued so that the timed out command can be cleared.
* The Abort Task cannot be sent from here because the driver has not
* completed setting up targets. Instead, the command is flagged so
* that special handling will be used to send the abort.
*/
cm->cm_flags |= MPR_CM_FLAGS_SATA_ID_TIMEOUT;
wakeup(cm);
}
static int
mprsas_volume_add(struct mpr_softc *sc, u16 handle)
{
@ -1024,15 +1157,13 @@ mprsas_SSU_to_SATA_devices(struct mpr_softc *sc)
path_id_t pathid = cam_sim_path(sassc->sim);
target_id_t targetid;
struct mprsas_target *target;
struct mprsas_lun *lun;
char path_str[64];
struct timeval cur_time, start_time;
mpr_lock(sc);
/*
* For each LUN of each target, issue a StartStopUnit command to stop
* the device.
* For each target, issue a StartStopUnit command to stop the device.
*/
sc->SSU_started = TRUE;
sc->SSU_refcount = 0;
@ -1042,59 +1173,52 @@ mprsas_SSU_to_SATA_devices(struct mpr_softc *sc)
continue;
}
SLIST_FOREACH(lun, &target->luns, lun_link) {
ccb = xpt_alloc_ccb_nowait();
if (ccb == NULL) {
mpr_unlock(sc);
mpr_dprint(sc, MPR_FAULT, "Unable to alloc "
"CCB to stop unit.\n");
ccb = xpt_alloc_ccb_nowait();
if (ccb == NULL) {
mpr_dprint(sc, MPR_FAULT, "Unable to alloc CCB to stop "
"unit.\n");
return;
}
/*
* The stop_at_shutdown flag will be set if this device is
* a SATA direct-access end device.
*/
if (target->stop_at_shutdown) {
if (xpt_create_path(&ccb->ccb_h.path, xpt_periph,
pathid, targetid, CAM_LUN_WILDCARD) !=
CAM_REQ_CMP) {
mpr_dprint(sc, MPR_ERROR, "Unable to create "
"path to stop unit.\n");
xpt_free_ccb(ccb);
return;
}
xpt_path_string(ccb->ccb_h.path, path_str,
sizeof(path_str));
mpr_dprint(sc, MPR_INFO, "Sending StopUnit: path %s "
"handle %d\n", path_str, target->handle);
/*
* The stop_at_shutdown flag will be set if this LUN is
* a SATA direct-access end device.
* Issue a START STOP UNIT command for the target.
* Increment the SSU counter to be used to count the
* number of required replies.
*/
if (lun->stop_at_shutdown) {
if (xpt_create_path(&ccb->ccb_h.path,
xpt_periph, pathid, targetid,
lun->lun_id) != CAM_REQ_CMP) {
mpr_dprint(sc, MPR_FAULT, "Unable to "
"create LUN path to stop unit.\n");
xpt_free_ccb(ccb);
mpr_unlock(sc);
return;
}
xpt_path_string(ccb->ccb_h.path, path_str,
sizeof(path_str));
mpr_dprint(sc, MPR_INFO, "Sending StopUnit: "
"path %s handle %d\n", path_str,
target->handle);
/*
* Issue a START STOP UNIT command for the LUN.
* Increment the SSU counter to be used to
* count the number of required replies.
*/
mpr_dprint(sc, MPR_INFO, "Incrementing SSU "
"count\n");
sc->SSU_refcount++;
ccb->ccb_h.target_id =
xpt_path_target_id(ccb->ccb_h.path);
ccb->ccb_h.target_lun = lun->lun_id;
ccb->ccb_h.ppriv_ptr1 = sassc;
scsi_start_stop(&ccb->csio,
/*retries*/0,
mprsas_stop_unit_done,
MSG_SIMPLE_Q_TAG,
/*start*/FALSE,
/*load/eject*/0,
/*immediate*/FALSE,
MPR_SENSE_LEN,
/*timeout*/10000);
xpt_action(ccb);
}
mpr_dprint(sc, MPR_INFO, "Incrementing SSU count\n");
sc->SSU_refcount++;
ccb->ccb_h.target_id =
xpt_path_target_id(ccb->ccb_h.path);
ccb->ccb_h.ppriv_ptr1 = sassc;
scsi_start_stop(&ccb->csio,
/*retries*/0,
mprsas_stop_unit_done,
MSG_SIMPLE_Q_TAG,
/*start*/FALSE,
/*load/eject*/0,
/*immediate*/FALSE,
MPR_SENSE_LEN,
/*timeout*/10000);
xpt_action(ccb);
}
}
@ -1102,7 +1226,7 @@ mprsas_SSU_to_SATA_devices(struct mpr_softc *sc)
/*
* Wait until all of the SSU commands have completed or time has
* expired (60 seconds). pause for 100ms each time through. If any
* expired (60 seconds). Pause for 100ms each time through. If any
* command times out, the target will be reset in the SCSI command
* timeout routine.
*/
@ -1112,7 +1236,7 @@ mprsas_SSU_to_SATA_devices(struct mpr_softc *sc)
getmicrotime(&cur_time);
if ((cur_time.tv_sec - start_time.tv_sec) > 60) {
mpr_dprint(sc, MPR_FAULT, "Time has expired waiting "
mpr_dprint(sc, MPR_ERROR, "Time has expired waiting "
"for SSU commands to complete.\n");
break;
}
@ -1162,6 +1286,8 @@ mprsas_ir_shutdown(struct mpr_softc *sc)
unsigned int id, found_volume = 0;
struct mpr_command *cm;
Mpi2RaidActionRequest_t *action;
target_id_t targetid;
struct mprsas_target *target;
mpr_dprint(sc, MPR_TRACE, "%s\n", __func__);
@ -1214,5 +1340,47 @@ mprsas_ir_shutdown(struct mpr_softc *sc)
mpr_free_command(sc, cm);
out:
/*
* All of the targets must have the correct value set for
* 'stop_at_shutdown' for the current 'enable_ssu' sysctl variable.
*
* The possible values for the 'enable_ssu' variable are:
* 0: disable to SSD and HDD
* 1: disable only to HDD (default)
* 2: disable only to SSD
* 3: enable to SSD and HDD
* anything else will default to 1.
*/
for (targetid = 0; targetid < sc->facts->MaxTargets; targetid++) {
target = &sc->sassc->targets[targetid];
if (target->handle == 0x0) {
continue;
}
if (target->supports_SSU) {
switch (sc->enable_ssu) {
case MPR_SSU_DISABLE_SSD_DISABLE_HDD:
target->stop_at_shutdown = FALSE;
break;
case MPR_SSU_DISABLE_SSD_ENABLE_HDD:
target->stop_at_shutdown = TRUE;
if (target->flags & MPR_TARGET_IS_SATA_SSD) {
target->stop_at_shutdown = FALSE;
}
break;
case MPR_SSU_ENABLE_SSD_ENABLE_HDD:
target->stop_at_shutdown = TRUE;
break;
case MPR_SSU_ENABLE_SSD_DISABLE_HDD:
default:
target->stop_at_shutdown = TRUE;
if ((target->flags &
MPR_TARGET_IS_SATA_SSD) == 0) {
target->stop_at_shutdown = FALSE;
}
break;
}
}
}
mprsas_SSU_to_SATA_devices(sc);
}

View File

@ -27,10 +27,11 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* LSI MPT-Fusion Host Adapter FreeBSD userland interface
* Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD userland interface
*/
/*-
* Copyright (c) 2011-2014 LSI Corp.
* Copyright (c) 2011-2015 LSI Corp.
* Copyright (c) 2013-2015 Avago Technologies
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -54,7 +55,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* LSI MPT-Fusion Host Adapter FreeBSD
* Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD
*
* $FreeBSD$
*/
@ -90,7 +91,7 @@ __FBSDID("$FreeBSD$");
#include <sys/rman.h>
#include <cam/cam.h>
#include <cam/scsi/scsi_all.h>
#include <cam/cam_ccb.h>
#include <dev/mpr/mpi/mpi2_type.h>
#include <dev/mpr/mpi/mpi2.h>
@ -284,8 +285,7 @@ mpr_user_read_cfg_header(struct mpr_softc *sc,
static int
mpr_user_read_cfg_page(struct mpr_softc *sc,
struct mpr_cfg_page_req *page_req,
void *buf)
struct mpr_cfg_page_req *page_req, void *buf)
{
MPI2_CONFIG_PAGE_HEADER *reqhdr, *hdr;
struct mpr_config_params params;
@ -328,6 +328,10 @@ mpr_user_read_extcfg_header(struct mpr_softc *sc,
hdr->PageNumber = ext_page_req->header.PageNumber;
hdr->ExtPageType = ext_page_req->header.ExtPageType;
params.page_address = le32toh(ext_page_req->page_address);
params.buffer = NULL;
params.length = 0;
params.callback = NULL;
if ((error = mpr_read_config_page(sc, &params)) != 0) {
/*
* Leave the request. Without resetting the chip, it's
@ -365,8 +369,8 @@ mpr_user_read_extcfg_page(struct mpr_softc *sc,
params.action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
params.page_address = le32toh(ext_page_req->page_address);
hdr->PageVersion = reqhdr->PageVersion;
hdr->PageNumber = reqhdr->PageNumber;
hdr->PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
hdr->PageNumber = reqhdr->PageNumber;
hdr->ExtPageType = reqhdr->ExtPageType;
hdr->ExtPageLength = reqhdr->ExtPageLength;
params.buffer = buf;
@ -541,6 +545,8 @@ mpi_pre_fw_upload(struct mpr_command *cm, struct mpr_usr_command *cmd)
req->ImageOffset = 0;
req->ImageSize = cmd->len;
cm->cm_flags |= MPR_CM_FLAGS_DATAIN;
return (mpr_push_ieee_sge(cm, &req->SGL, 0));
}
@ -834,11 +840,22 @@ mpr_user_pass_thru(struct mpr_softc *sc, mpr_pass_thru_t *data)
task->TaskMID = cm->cm_desc.Default.SMID;
cm->cm_data = NULL;
cm->cm_desc.HighPriority.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY;
cm->cm_desc.HighPriority.RequestFlags =
MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY;
cm->cm_complete = NULL;
cm->cm_complete_data = NULL;
err = mpr_wait_command(sc, cm, 30, CAN_SLEEP);
targ = mprsas_find_target_by_handle(sc->sassc, 0,
task->DevHandle);
if (targ == NULL) {
mpr_dprint(sc, MPR_INFO,
"%s %d : invalid handle for requested TM 0x%x \n",
__func__, __LINE__, task->DevHandle);
err = 1;
} else {
mprsas_prepare_for_tm(sc, cm, targ, CAM_LUN_WILDCARD);
err = mpr_wait_command(sc, cm, 30, CAN_SLEEP);
}
if (err != 0) {
err = EIO;
@ -1029,7 +1046,7 @@ mpr_user_pass_thru(struct mpr_softc *sc, mpr_pass_thru_t *data)
if (cm->cm_flags & MPR_CM_FLAGS_DATAIN)
dir = BUS_DMASYNC_POSTREAD;
else if (cm->cm_flags & MPR_CM_FLAGS_DATAOUT)
dir = BUS_DMASYNC_POSTWRITE;;
dir = BUS_DMASYNC_POSTWRITE;
bus_dmamap_sync(sc->buffer_dmat, cm->cm_dmamap, dir);
bus_dmamap_unload(sc->buffer_dmat, cm->cm_dmamap);
@ -1351,8 +1368,8 @@ done:
}
static int
mpr_diag_register(struct mpr_softc *sc,
mpr_fw_diag_register_t *diag_register, uint32_t *return_code)
mpr_diag_register(struct mpr_softc *sc, mpr_fw_diag_register_t *diag_register,
uint32_t *return_code)
{
mpr_fw_diagnostic_buffer_t *pBuffer;
uint8_t extended_type, buffer_type, i;

View File

@ -1,6 +1,7 @@
/*-
* Copyright (c) 2009 Yahoo! Inc.
* Copyright (c) 2011-2014 LSI Corp.
* Copyright (c) 2011-2015 LSI Corp.
* Copyright (c) 2013-2015 Avago Technologies
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -24,13 +25,15 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD
*
* $FreeBSD$
*/
#ifndef _MPRVAR_H
#define _MPRVAR_H
#define MPR_DRIVER_VERSION "05.255.05.00-fbsd"
#define MPR_DRIVER_VERSION "09.255.01.00-fbsd"
#define MPR_DB_MAX_WAIT 2500
@ -47,16 +50,19 @@
#define MPR_FUNCTRACE(sc) \
mpr_dprint((sc), MPR_TRACE, "%s\n", __func__)
#define CAN_SLEEP 1
#define NO_SLEEP 0
#define CAN_SLEEP 1
#define NO_SLEEP 0
#define MPR_PERIODIC_DELAY 1 /* 1 second heartbeat/watchdog check */
#define MPR_ATA_ID_TIMEOUT 5 /* 5 second timeout for SATA ID cmd */
#define IFAULT_IOP_OVER_TEMP_THRESHOLD_EXCEEDED 0x2810
#define MPR_SCSI_RI_INVALID_FRAME (0x00000002)
#define MPR_STRING_LENGTH 64
#define DEFAULT_SPINUP_WAIT 3 /* seconds to wait for spinup */
#include <sys/endian.h>
/*
@ -213,13 +219,14 @@ struct mpr_command {
#define MPR_CM_FLAGS_CHAIN_FAILED (1 << 8)
#define MPR_CM_FLAGS_ERROR_MASK MPR_CM_FLAGS_CHAIN_FAILED
#define MPR_CM_FLAGS_USE_CCB (1 << 9)
#define MPR_CM_FLAGS_SATA_ID_TIMEOUT (1 << 10)
u_int cm_state;
#define MPR_CM_STATE_FREE 0
#define MPR_CM_STATE_BUSY 1
#define MPR_CM_STATE_TIMEDOUT 2
bus_dmamap_t cm_dmamap;
struct scsi_sense_data *cm_sense;
TAILQ_HEAD(, mpr_chain) cm_chain_list;
TAILQ_HEAD(, mpr_chain) cm_chain_list;
uint32_t cm_req_busaddr;
uint32_t cm_sense_busaddr;
struct callout cm_callout;
@ -256,6 +263,8 @@ struct mpr_softc {
int chain_free;
int max_chains;
int chain_free_lowwater;
u_int enable_ssu;
int spinup_wait_time;
#if __FreeBSD_version >= 900030
uint64_t chain_alloc_fail;
#endif
@ -270,7 +279,7 @@ struct mpr_softc {
char tmp_string[MPR_STRING_LENGTH];
TAILQ_HEAD(, mpr_command) req_list;
TAILQ_HEAD(, mpr_command) high_priority_req_list;
TAILQ_HEAD(, mpr_chain) chain_list;
TAILQ_HEAD(, mpr_chain) chain_list;
TAILQ_HEAD(, mpr_command) tm_list;
int replypostindex;
int replyfreeindex;
@ -291,7 +300,7 @@ struct mpr_softc {
uint8_t event_mask[16];
TAILQ_HEAD(, mpr_event_handle) event_list;
struct mpr_event_handle *mpr_log_eh;
struct mpr_event_handle *mpr_log_eh;
struct mtx mpr_mtx;
struct intr_config_hook mpr_ich;
@ -565,6 +574,11 @@ mpr_unlock(struct mpr_softc *sc)
#define MPR_MAPPING (1 << 9) /* Trace device mappings */
#define MPR_TRACE (1 << 10) /* Function-by-function trace */
#define MPR_SSU_DISABLE_SSD_DISABLE_HDD 0
#define MPR_SSU_ENABLE_SSD_DISABLE_HDD 1
#define MPR_SSU_DISABLE_SSD_ENABLE_HDD 2
#define MPR_SSU_ENABLE_SSD_ENABLE_HDD 3
#define mpr_printf(sc, args...) \
device_printf((sc)->mpr_dev, ##args)
@ -600,9 +614,6 @@ do { \
#define MPR_EVENTFIELD(sc, facts, attr, fmt) \
mpr_dprint_field((sc), MPR_EVENT, #attr ": " #fmt "\n", (facts)->attr)
#define CAN_SLEEP 1
#define NO_SLEEP 0
static __inline void
mpr_from_u64(uint64_t data, U64 *mpr)
{
@ -613,7 +624,6 @@ mpr_from_u64(uint64_t data, U64 *mpr)
static __inline uint64_t
mpr_to_u64(U64 *data)
{
return (((uint64_t)le32toh(data->High) << 32) | le32toh(data->Low));
}
@ -727,6 +737,12 @@ void mprsas_prepare_volume_remove(struct mprsas_softc *sassc,
int mprsas_startup(struct mpr_softc *sc);
struct mprsas_target * mprsas_find_target_by_handle(struct mprsas_softc *,
int, uint16_t);
void mprsas_realloc_targets(struct mpr_softc *sc, int maxtargets);
struct mpr_command * mprsas_alloc_tm(struct mpr_softc *sc);
void mprsas_free_tm(struct mpr_softc *sc, struct mpr_command *tm);
void mprsas_release_simq_reinit(struct mprsas_softc *sassc);
int mprsas_send_reset(struct mpr_softc *sc, struct mpr_command *tm,
uint8_t type);
SYSCTL_DECL(_hw_mpr);

View File

@ -2389,7 +2389,7 @@ pci_set_powerstate_method(device_t dev, device_t child, int state)
struct pci_devinfo *dinfo = device_get_ivars(child);
pcicfgregs *cfg = &dinfo->cfg;
uint16_t status;
int result, oldstate, highest, delay;
int oldstate, highest, delay;
if (cfg->pp.pp_cap == 0)
return (EOPNOTSUPP);
@ -2424,7 +2424,6 @@ pci_set_powerstate_method(device_t dev, device_t child, int state)
delay = 0;
status = PCI_READ_CONFIG(dev, child, cfg->pp.pp_status, 2)
& ~PCIM_PSTAT_DMASK;
result = 0;
switch (state) {
case PCI_POWERSTATE_D0:
status |= PCIM_PSTAT_D0;
@ -2989,7 +2988,6 @@ static void
pci_ata_maps(device_t bus, device_t dev, struct resource_list *rl, int force,
uint32_t prefetchmask)
{
struct resource *r;
int rid, type, progif;
#if 0
/* if this device supports PCI native addressing use it */
@ -3012,11 +3010,11 @@ pci_ata_maps(device_t bus, device_t dev, struct resource_list *rl, int force,
} else {
rid = PCIR_BAR(0);
resource_list_add(rl, type, rid, 0x1f0, 0x1f7, 8);
r = resource_list_reserve(rl, bus, dev, type, &rid, 0x1f0,
(void)resource_list_reserve(rl, bus, dev, type, &rid, 0x1f0,
0x1f7, 8, 0);
rid = PCIR_BAR(1);
resource_list_add(rl, type, rid, 0x3f6, 0x3f6, 1);
r = resource_list_reserve(rl, bus, dev, type, &rid, 0x3f6,
(void)resource_list_reserve(rl, bus, dev, type, &rid, 0x3f6,
0x3f6, 1, 0);
}
if (progif & PCIP_STORAGE_IDE_MODESEC) {
@ -3027,11 +3025,11 @@ pci_ata_maps(device_t bus, device_t dev, struct resource_list *rl, int force,
} else {
rid = PCIR_BAR(2);
resource_list_add(rl, type, rid, 0x170, 0x177, 8);
r = resource_list_reserve(rl, bus, dev, type, &rid, 0x170,
(void)resource_list_reserve(rl, bus, dev, type, &rid, 0x170,
0x177, 8, 0);
rid = PCIR_BAR(3);
resource_list_add(rl, type, rid, 0x376, 0x376, 1);
r = resource_list_reserve(rl, bus, dev, type, &rid, 0x376,
(void)resource_list_reserve(rl, bus, dev, type, &rid, 0x376,
0x376, 1, 0);
}
pci_add_map(bus, dev, PCIR_BAR(4), rl, force,
@ -3727,7 +3725,6 @@ pci_detach(device_t dev)
static void
pci_set_power_child(device_t dev, device_t child, int state)
{
struct pci_devinfo *dinfo;
device_t pcib;
int dstate;
@ -3739,7 +3736,6 @@ pci_set_power_child(device_t dev, device_t child, int state)
* are handled separately.
*/
pcib = device_get_parent(dev);
dinfo = device_get_ivars(child);
dstate = state;
if (device_is_attached(child) &&
PCIB_POWER_FOR_SLEEP(pcib, child, &dstate) == 0)

View File

@ -214,22 +214,6 @@ METHOD int iov_detach {
device_t child;
};
METHOD int init_iov {
device_t dev;
uint16_t num_vfs;
const struct nvlist *config;
};
METHOD void uninit_iov {
device_t dev;
};
METHOD int add_vf {
device_t dev;
uint16_t vfnum;
const struct nvlist *config;
};
METHOD device_t create_iov_child {
device_t bus;
device_t pf;
@ -237,4 +221,3 @@ METHOD device_t create_iov_child {
uint16_t vid;
uint16_t did;
} DEFAULT null_create_iov_child;

View File

@ -53,11 +53,11 @@ __FBSDID("$FreeBSD$");
#include <dev/pci/pcireg.h>
#include <dev/pci/pcivar.h>
#include <dev/pci/pci_iov.h>
#include <dev/pci/pci_private.h>
#include <dev/pci/pci_iov_private.h>
#include <dev/pci/schema_private.h>
#include "pci_if.h"
#include "pcib_if.h"
static MALLOC_DEFINE(M_SRIOV, "sr_iov", "PCI SR-IOV allocations");
@ -483,13 +483,13 @@ pci_iov_config_page_size(struct pci_devinfo *dinfo)
}
static int
pci_init_iov(device_t dev, uint16_t num_vfs, const nvlist_t *config)
pci_iov_init(device_t dev, uint16_t num_vfs, const nvlist_t *config)
{
const nvlist_t *device, *driver_config;
device = nvlist_get_nvlist(config, PF_CONFIG_NAME);
driver_config = nvlist_get_nvlist(device, DRIVER_CONFIG_NAME);
return (PCI_INIT_IOV(dev, num_vfs, driver_config));
return (PCI_IOV_INIT(dev, num_vfs, driver_config));
}
static int
@ -595,7 +595,7 @@ pci_iov_enumerate_vfs(struct pci_devinfo *dinfo, const nvlist_t *config,
pci_iov_add_bars(iov, vfinfo);
error = PCI_ADD_VF(dev, i, driver_config);
error = PCI_IOV_ADD_VF(dev, i, driver_config);
if (error != 0) {
device_printf(dev, "Failed to add VF %d\n", i);
pci_delete_child(bus, vf);
@ -652,7 +652,7 @@ pci_iov_config(struct cdev *cdev, struct pci_iov_arg *arg)
if (error != 0)
goto out;
error = pci_init_iov(dev, num_vfs, config);
error = pci_iov_init(dev, num_vfs, config);
if (error != 0)
goto out;
iov_inited = 1;
@ -700,7 +700,7 @@ pci_iov_config(struct cdev *cdev, struct pci_iov_arg *arg)
return (0);
out:
if (iov_inited)
PCI_UNINIT_IOV(dev);
PCI_IOV_UNINIT(dev);
for (i = 0; i <= PCIR_MAX_BAR_0; i++) {
if (iov->iov_bar[i].res != NULL) {
@ -793,7 +793,7 @@ pci_iov_delete(struct cdev *cdev)
if (pci_iov_is_child_vf(iov, vf))
pci_delete_child(bus, vf);
}
PCI_UNINIT_IOV(dev);
PCI_IOV_UNINIT(dev);
iov_ctl = IOV_READ(dinfo, PCIR_SRIOV_CTL, 2);
iov_ctl &= ~(PCIM_SRIOV_VF_EN | PCIM_SRIOV_VF_MSE);

Some files were not shown because too many files have changed in this diff Show More