diff options
57 files changed, 597 insertions, 667 deletions
diff --git a/bin/sh/eval.c b/bin/sh/eval.c index 51206d9..dfbbc04 100644 --- a/bin/sh/eval.c +++ b/bin/sh/eval.c @@ -82,7 +82,7 @@ static int builtin_flags; /* evalcommand flags for builtins */ char *commandname; -struct strlist *cmdenviron; +struct arglist *cmdenviron; int exitstatus; /* exit status of last command */ int oexitstatus; /* saved exit status */ @@ -352,20 +352,19 @@ evalfor(union node *n, int flags) { struct arglist arglist; union node *argp; - struct strlist *sp; + int i; int status; - arglist.lastp = &arglist.list; + emptyarglist(&arglist); for (argp = n->nfor.args ; argp ; argp = argp->narg.next) { oexitstatus = exitstatus; expandarg(argp, &arglist, EXP_FULL | EXP_TILDE); } - *arglist.lastp = NULL; loopnest++; status = 0; - for (sp = arglist.list ; sp ; sp = sp->next) { - setvar(n->nfor.var, sp->text, 0); + for (i = 0; i < arglist.count; i++) { + setvar(n->nfor.var, arglist.args[i], 0); evaltree(n->nfor.body, flags); status = exitstatus; if (evalskip) { @@ -396,12 +395,12 @@ evalcase(union node *n) union node *patp; struct arglist arglist; - arglist.lastp = &arglist.list; + emptyarglist(&arglist); oexitstatus = exitstatus; expandarg(n->ncase.expr, &arglist, EXP_TILDE); for (cp = n->ncase.cases ; cp ; cp = cp->nclist.next) { for (patp = cp->nclist.pattern ; patp ; patp = patp->narg.next) { - if (casematch(patp, arglist.list->text)) { + if (casematch(patp, arglist.args[0])) { while (cp->nclist.next && cp->type == NCLISTFALLTHRU && cp->nclist.body == NULL) @@ -508,7 +507,7 @@ exphere(union node *redir, struct arglist *fn) else { handler = &jmploc; expandarg(redir->nhere.doc, fn, 0); - redir->nhere.expdoc = fn->list->text; + redir->nhere.expdoc = fn->args[0]; INTOFF; } handler = savehandler; @@ -532,7 +531,7 @@ expredir(union node *n) for (redir = n ; redir ; redir = redir->nfile.next) { struct arglist fn; - fn.lastp = &fn.list; + emptyarglist(&fn); switch (redir->type) { case NFROM: case NTO: @@ -540,13 +539,13 @@ expredir(union node *n) case NAPPEND: case NCLOBBER: expandarg(redir->nfile.fname, &fn, EXP_TILDE); - redir->nfile.expfname = fn.list->text; + redir->nfile.expfname = fn.args[0]; break; case NFROMFD: case NTOFD: if (redir->ndup.vname) { expandarg(redir->ndup.vname, &fn, EXP_TILDE); - fixredir(redir, fn.list->text, 1); + fixredir(redir, fn.args[0], 1); } break; case NXHERE: @@ -753,28 +752,30 @@ isdeclarationcmd(struct narg *arg) static void xtracecommand(struct arglist *varlist, struct arglist *arglist) { - struct strlist *sp; char sep = 0; - const char *p, *ps4; + const char *text, *p, *ps4; + int i; ps4 = expandstr(ps4val()); out2str(ps4 != NULL ? ps4 : ps4val()); - for (sp = varlist->list ; sp ; sp = sp->next) { + for (i = 0; i < varlist->count; i++) { + text = varlist->args[i]; if (sep != 0) out2c(' '); - p = strchr(sp->text, '='); + p = strchr(text, '='); if (p != NULL) { p++; - outbin(sp->text, p - sp->text, out2); + outbin(text, p - text, out2); out2qstr(p); } else - out2qstr(sp->text); + out2qstr(text); sep = ' '; } - for (sp = arglist->list ; sp ; sp = sp->next) { + for (i = 0; i < arglist->count; i++) { + text = arglist->args[i]; if (sep != 0) out2c(' '); - out2qstr(sp->text); + out2qstr(text); sep = ' '; } out2c('\n'); @@ -822,7 +823,6 @@ evalcommand(union node *cmd, int flags, struct backcmd *backcmd) int argc; char **envp; int varflag; - struct strlist *sp; int mode; int pip[2]; struct cmdentry cmdentry; @@ -838,11 +838,12 @@ evalcommand(union node *cmd, int flags, struct backcmd *backcmd) int realstatus; int do_clearcmdentry; const char *path = pathval(); + int i; /* First expand the arguments. */ TRACE(("evalcommand(%p, %d) called\n", (void *)cmd, flags)); - arglist.lastp = &arglist.list; - varlist.lastp = &varlist.list; + emptyarglist(&arglist); + emptyarglist(&varlist); varflag = 1; jp = NULL; do_clearcmdentry = 0; @@ -857,25 +858,17 @@ evalcommand(union node *cmd, int flags, struct backcmd *backcmd) varflag = isdeclarationcmd(&argp->narg) ? 2 : 0; expandarg(argp, &arglist, EXP_FULL | EXP_TILDE); } - *arglist.lastp = NULL; - *varlist.lastp = NULL; expredir(cmd->ncmd.redirect); - argc = 0; - for (sp = arglist.list ; sp ; sp = sp->next) - argc++; + argc = arglist.count; /* Add one slot at the beginning for tryexec(). */ argv = stalloc(sizeof (char *) * (argc + 2)); argv++; - for (sp = arglist.list ; sp ; sp = sp->next) { - TRACE(("evalcommand arg: %s\n", sp->text)); - *argv++ = sp->text; - } - *argv = NULL; + memcpy(argv, arglist.args, sizeof(*argv) * argc); + argv[argc] = NULL; lastarg = NULL; if (iflag && funcnest == 0 && argc > 0) - lastarg = argv[-1]; - argv -= argc; + lastarg = argv[argc - 1]; /* Print the command if xflag is set. */ if (xflag) @@ -895,9 +888,9 @@ evalcommand(union node *cmd, int flags, struct backcmd *backcmd) * Modify the command lookup path, if a PATH= assignment * is present */ - for (sp = varlist.list ; sp ; sp = sp->next) - if (strncmp(sp->text, PATH, sizeof(PATH) - 1) == 0) { - path = sp->text + sizeof(PATH) - 1; + for (i = 0; i < varlist.count; i++) + if (strncmp(varlist.args[i], PATH, sizeof(PATH) - 1) == 0) { + path = varlist.args[i] + sizeof(PATH) - 1; /* * On `PATH=... command`, we need to make * sure that the command isn't using the @@ -999,7 +992,7 @@ evalcommand(union node *cmd, int flags, struct backcmd *backcmd) } if (cmdentry.cmdtype == CMDNORMAL && cmd->ncmd.redirect == NULL && - varlist.list == NULL && + varlist.count == 0 && (mode == FORK_FG || mode == FORK_NOJOB) && !disvforkset() && !iflag && !mflag) { vforkexecshell(jp, argv, environment(), path, @@ -1053,8 +1046,8 @@ evalcommand(union node *cmd, int flags, struct backcmd *backcmd) funcnest++; redirect(cmd->ncmd.redirect, REDIR_PUSH); INTON; - for (sp = varlist.list ; sp ; sp = sp->next) - mklocal(sp->text); + for (i = 0; i < varlist.count; i++) + mklocal(varlist.args[i]); exitstatus = oexitstatus; evaltree(getfuncnode(cmdentry.u.func), flags & (EV_TESTED | EV_EXIT)); @@ -1087,7 +1080,7 @@ evalcommand(union node *cmd, int flags, struct backcmd *backcmd) } savecmdname = commandname; savetopfile = getcurrentfile(); - cmdenviron = varlist.list; + cmdenviron = &varlist; e = -1; savehandler = handler; if (setjmp(jmploc.loc)) { @@ -1152,8 +1145,8 @@ cmddone: trputs("normal command: "); trargs(argv); #endif redirect(cmd->ncmd.redirect, 0); - for (sp = varlist.list ; sp ; sp = sp->next) - setvareq(sp->text, VEXPORT|VSTACK); + for (i = 0; i < varlist.count; i++) + setvareq(varlist.args[i], VEXPORT|VSTACK); envp = environment(); shellexec(argv, envp, path, cmdentry.u.index); /*NOTREACHED*/ @@ -1336,6 +1329,8 @@ truecmd(int argc __unused, char **argv __unused) int execcmd(int argc, char **argv) { + int i; + /* * Because we have historically not supported any options, * only treat "--" specially. @@ -1343,13 +1338,11 @@ execcmd(int argc, char **argv) if (argc > 1 && strcmp(argv[1], "--") == 0) argc--, argv++; if (argc > 1) { - struct strlist *sp; - iflag = 0; /* exit on error */ mflag = 0; optschanged(); - for (sp = cmdenviron; sp ; sp = sp->next) - setvareq(sp->text, VEXPORT|VSTACK); + for (i = 0; i < cmdenviron->count; i++) + setvareq(cmdenviron->args[i], VEXPORT|VSTACK); shellexec(argv + 1, environment(), pathval(), 0); } diff --git a/bin/sh/eval.h b/bin/sh/eval.h index d4092be..e781336 100644 --- a/bin/sh/eval.h +++ b/bin/sh/eval.h @@ -36,7 +36,7 @@ extern char *commandname; /* currently executing command */ extern int exitstatus; /* exit status of last command */ extern int oexitstatus; /* saved exit status */ -extern struct strlist *cmdenviron; /* environment for builtin command */ +extern struct arglist *cmdenviron; /* environment for builtin command */ struct backcmd { /* result of evalbackcmd */ diff --git a/bin/sh/expand.c b/bin/sh/expand.c index 88d80ea..567b8a4 100644 --- a/bin/sh/expand.c +++ b/bin/sh/expand.c @@ -96,7 +96,6 @@ static char *expdest; /* output of current string */ static struct nodelist *argbackq; /* list of back quote expressions */ static struct ifsregion ifsfirst; /* first struct in list of ifs regions */ static struct ifsregion *ifslastp; /* last struct in list */ -static struct arglist exparg; /* holds expanded arg list */ static char *argstr(char *, int); static char *exptilde(char *, int); @@ -110,15 +109,43 @@ static void varvalue(const char *, int, int, int); static void recordregion(int, int, int); static void removerecordregions(int); static void ifsbreakup(char *, struct arglist *); -static void expandmeta(struct strlist *); -static void expmeta(char *, char *); -static void addfname(char *); -static struct strlist *expsort(struct strlist *); -static struct strlist *msort(struct strlist *, int); +static void expandmeta(struct arglist *, struct arglist *); +static void expmeta(char *, char *, struct arglist *); +static int expsortcmp(const void *, const void *); static int patmatch(const char *, const char *, int); static char *cvtnum(int, char *); +static void appendarglist(struct arglist *, char *); static int collate_range_cmp(wchar_t, wchar_t); +void +emptyarglist(struct arglist *list) +{ + + list->args = list->smallarg; + list->count = 0; + list->capacity = sizeof(list->smallarg) / sizeof(list->smallarg[0]); +} + +static void +appendarglist(struct arglist *list, char *str) +{ + char **newargs; + int newcapacity; + + if (list->count >= list->capacity) { + newcapacity = list->capacity * 2; + if (newcapacity < 16) + newcapacity = 16; + if (newcapacity > INT_MAX / (int)sizeof(newargs[0])) + error("Too many entries in arglist"); + newargs = stalloc(newcapacity * sizeof(newargs[0])); + memcpy(newargs, list->args, list->count * sizeof(newargs[0])); + list->args = newargs; + list->capacity = newcapacity; + } + list->args[list->count++] = str; +} + static int collate_range_cmp(wchar_t c1, wchar_t c2) { @@ -157,7 +184,7 @@ stputs_quotes(const char *data, const char *syntax, char *p) void expandarg(union node *arg, struct arglist *arglist, int flag) { - struct strlist *sp; + struct arglist exparg; char *p; argbackq = arg->narg.backquote; @@ -171,18 +198,12 @@ expandarg(union node *arg, struct arglist *arglist, int flag) } STPUTC('\0', expdest); p = grabstackstr(expdest); - exparg.lastp = &exparg.list; + emptyarglist(&exparg); if (flag & EXP_FULL) { ifsbreakup(p, &exparg); - *exparg.lastp = NULL; - exparg.lastp = &exparg.list; - expandmeta(exparg.list); - } else { - sp = (struct strlist *)stalloc(sizeof (struct strlist)); - sp->text = p; - *exparg.lastp = sp; - exparg.lastp = &sp->next; - } + expandmeta(&exparg, arglist); + } else + appendarglist(arglist, p); while (ifsfirst.next != NULL) { struct ifsregion *ifsp; INTOFF; @@ -191,11 +212,6 @@ expandarg(union node *arg, struct arglist *arglist, int flag) ifsfirst.next = ifsp; INTON; } - *exparg.lastp = NULL; - if (exparg.list) { - *arglist->lastp = exparg.list; - arglist->lastp = exparg.lastp; - } } @@ -984,7 +1000,6 @@ static void ifsbreakup(char *string, struct arglist *arglist) { struct ifsregion *ifsp; - struct strlist *sp; char *start; char *p; char *q; @@ -996,10 +1011,7 @@ ifsbreakup(char *string, struct arglist *arglist) if (ifslastp == NULL) { /* Return entire argument, IFS doesn't apply to any of it */ - sp = (struct strlist *)stalloc(sizeof *sp); - sp->text = start; - *arglist->lastp = sp; - arglist->lastp = &sp->next; + appendarglist(arglist, start); return; } @@ -1038,10 +1050,7 @@ ifsbreakup(char *string, struct arglist *arglist) /* Save this argument... */ *q = '\0'; - sp = (struct strlist *)stalloc(sizeof *sp); - sp->text = start; - *arglist->lastp = sp; - arglist->lastp = &sp->next; + appendarglist(arglist, start); p++; if (ifsspc != NULL) { @@ -1071,12 +1080,8 @@ ifsbreakup(char *string, struct arglist *arglist) * Some recent clarification of the Posix spec say that it * should only generate one.... */ - if (had_param_ch || *start != 0) { - sp = (struct strlist *)stalloc(sizeof *sp); - sp->text = start; - *arglist->lastp = sp; - arglist->lastp = &sp->next; - } + if (had_param_ch || *start != 0) + appendarglist(arglist, start); } @@ -1086,45 +1091,42 @@ static char expdir[PATH_MAX]; /* * Perform pathname generation and remove control characters. * At this point, the only control characters should be CTLESC and CTLQUOTEMARK. - * The results are stored in the list exparg. + * The results are stored in the list dstlist. */ static void -expandmeta(struct strlist *str) +expandmeta(struct arglist *srclist, struct arglist *dstlist) { char *p; - struct strlist **savelastp; - struct strlist *sp; + int firstmatch; + int i; char c; - while (str) { - savelastp = exparg.lastp; + for (i = 0; i < srclist->count; i++) { + firstmatch = dstlist->count; if (!fflag) { - p = str->text; + p = srclist->args[i]; for (; (c = *p) != '\0'; p++) { /* fast check for meta chars */ if (c == '*' || c == '?' || c == '[') { INTOFF; - expmeta(expdir, str->text); + expmeta(expdir, srclist->args[i], + dstlist); INTON; break; } } } - if (exparg.lastp == savelastp) { + if (dstlist->count == firstmatch) { /* * no matches */ - *exparg.lastp = str; - rmescapes(str->text); - exparg.lastp = &str->next; + rmescapes(srclist->args[i]); + appendarglist(dstlist, srclist->args[i]); } else { - *exparg.lastp = NULL; - *savelastp = sp = expsort(*savelastp); - while (sp->next != NULL) - sp = sp->next; - exparg.lastp = &sp->next; + qsort(&dstlist->args[firstmatch], + dstlist->count - firstmatch, + sizeof(dstlist->args[0]), expsortcmp); } - str = str->next; } } @@ -1134,7 +1136,7 @@ expandmeta(struct strlist *str) */ static void -expmeta(char *enddir, char *name) +expmeta(char *enddir, char *name, struct arglist *arglist) { const char *p; const char *q; @@ -1199,7 +1201,7 @@ expmeta(char *enddir, char *name) return; } if (metaflag == 0 || lstat(expdir, &statb) >= 0) - addfname(expdir); + appendarglist(arglist, stsavestr(expdir)); return; } endname = name + (p - name); @@ -1251,7 +1253,7 @@ expmeta(char *enddir, char *name) continue; memcpy(enddir, dp->d_name, namlen + 1); if (atend) - addfname(expdir); + appendarglist(arglist, stsavestr(expdir)); else { if (dp->d_type != DT_UNKNOWN && dp->d_type != DT_DIR && @@ -1261,7 +1263,7 @@ expmeta(char *enddir, char *name) continue; enddir[namlen] = '/'; enddir[namlen + 1] = '\0'; - expmeta(enddir + namlen + 1, endname); + expmeta(enddir + namlen + 1, endname, arglist); } } } @@ -1271,81 +1273,13 @@ expmeta(char *enddir, char *name) } -/* - * Add a file name to the list. - */ - -static void -addfname(char *name) -{ - char *p; - struct strlist *sp; - - p = stsavestr(name); - sp = (struct strlist *)stalloc(sizeof *sp); - sp->text = p; - *exparg.lastp = sp; - exparg.lastp = &sp->next; -} - - -/* - * Sort the results of file name expansion. It calculates the number of - * strings to sort and then calls msort (short for merge sort) to do the - * work. - */ - -static struct strlist * -expsort(struct strlist *str) +static int +expsortcmp(const void *p1, const void *p2) { - int len; - struct strlist *sp; - - len = 0; - for (sp = str ; sp ; sp = sp->next) - len++; - return msort(str, len); -} + const char *s1 = *(const char * const *)p1; + const char *s2 = *(const char * const *)p2; - -static struct strlist * -msort(struct strlist *list, int len) -{ - struct strlist *p, *q = NULL; - struct strlist **lpp; - int half; - int n; - - if (len <= 1) - return list; - half = len >> 1; - p = list; - for (n = half ; --n >= 0 ; ) { - q = p; - p = p->next; - } - q->next = NULL; /* terminate first half of list */ - q = msort(list, half); /* sort first half of list */ - p = msort(p, len - half); /* sort second half */ - lpp = &list; - for (;;) { - if (strcmp(p->text, q->text) < 0) { - *lpp = p; - lpp = &p->next; - if ((p = *lpp) == NULL) { - *lpp = q; - break; - } - } else { - *lpp = q; - lpp = &q->next; - if ((q = *lpp) == NULL) { - *lpp = p; - break; - } - } - } - return list; + return (strcmp(s1, s2)); } @@ -1666,11 +1600,11 @@ freebsd_wordexpcmd(int argc __unused, char **argv __unused) { struct arglist arglist; union node *args, *n; - struct strlist *sp; - size_t count, len; + size_t len; int ch; int protected = 0; int fd = -1; + int i; while ((ch = nextopt("f:p")) != '\0') { switch (ch) { @@ -1699,14 +1633,13 @@ freebsd_wordexpcmd(int argc __unused, char **argv __unused) } } outcslow(' ', out1); - arglist.lastp = &arglist.list; + emptyarglist(&arglist); for (n = args; n != NULL; n = n->narg.next) expandarg(n, &arglist, EXP_FULL | EXP_TILDE); - *arglist.lastp = NULL; - for (sp = arglist.list, count = len = 0; sp; sp = sp->next) - count++, len += strlen(sp->text); - out1fmt("%016zx %016zx", count, len); - for (sp = arglist.list; sp; sp = sp->next) - outbin(sp->text, strlen(sp->text) + 1, out1); + for (i = 0, len = 0; i < arglist.count; i++) + len += strlen(arglist.args[i]); + out1fmt("%016x %016zx", arglist.count, len); + for (i = 0; i < arglist.count; i++) + outbin(arglist.args[i], strlen(arglist.args[i]) + 1, out1); return (0); } diff --git a/bin/sh/expand.h b/bin/sh/expand.h index 93c80f3..c377156 100644 --- a/bin/sh/expand.h +++ b/bin/sh/expand.h @@ -33,15 +33,11 @@ * $FreeBSD$ */ -struct strlist { - struct strlist *next; - char *text; -}; - - struct arglist { - struct strlist *list; - struct strlist **lastp; + char **args; + int count; + int capacity; + char *smallarg[1]; }; /* @@ -55,6 +51,7 @@ struct arglist { #define EXP_LIT_QUOTED 0x40 /* for EXP_SPLIT_LIT, start off quoted */ +void emptyarglist(struct arglist *); union node; void expandarg(union node *, struct arglist *, int); void rmescapes(char *); diff --git a/bin/sh/var.c b/bin/sh/var.c index f60dea1..cfba0ba 100644 --- a/bin/sh/var.c +++ b/bin/sh/var.c @@ -403,14 +403,13 @@ setvareq_const(const char *s, int flags) */ void -listsetvar(struct strlist *list, int flags) +listsetvar(struct arglist *list, int flags) { - struct strlist *lp; + int i; INTOFF; - for (lp = list ; lp ; lp = lp->next) { - setvareq(savestr(lp->text), flags); - } + for (i = 0; i < list->count; i++) + setvareq(savestr(list->args[i]), flags); INTON; } @@ -442,14 +441,14 @@ lookupvar(const char *name) char * bltinlookup(const char *name, int doall) { - struct strlist *sp; struct var *v; char *result; + int i; result = NULL; - for (sp = cmdenviron ; sp ; sp = sp->next) { - if (varequal(sp->text, name)) - result = strchr(sp->text, '=') + 1; + if (cmdenviron) for (i = 0; i < cmdenviron->count; i++) { + if (varequal(cmdenviron->args[i], name)) + result = strchr(cmdenviron->args[i], '=') + 1; } if (result != NULL) return result; @@ -468,13 +467,12 @@ bltinlookup(const char *name, int doall) void bltinsetlocale(void) { - struct strlist *lp; int act = 0; char *loc, *locdef; int i; - for (lp = cmdenviron ; lp ; lp = lp->next) { - if (localevar(lp->text)) { + if (cmdenviron) for (i = 0; i < cmdenviron->count; i++) { + if (localevar(cmdenviron->args[i])) { act = 1; break; } @@ -507,11 +505,11 @@ bltinsetlocale(void) void bltinunsetlocale(void) { - struct strlist *lp; + int i; INTOFF; - for (lp = cmdenviron ; lp ; lp = lp->next) { - if (localevar(lp->text)) { + if (cmdenviron) for (i = 0; i < cmdenviron->count; i++) { + if (localevar(cmdenviron->args[i])) { setlocale(LC_ALL, ""); updatecharset(); return; diff --git a/bin/sh/var.h b/bin/sh/var.h index 6e831ae..ede13cf 100644 --- a/bin/sh/var.h +++ b/bin/sh/var.h @@ -114,8 +114,8 @@ extern int initial_localeisutf8; void initvar(void); void setvar(const char *, const char *, int); void setvareq(char *, int); -struct strlist; -void listsetvar(struct strlist *, int); +struct arglist; +void listsetvar(struct arglist *, int); char *lookupvar(const char *); char *bltinlookup(const char *, int); void bltinsetlocale(void); diff --git a/share/mk/netbsd-tests.test.mk b/share/mk/netbsd-tests.test.mk index 2186594..7061db6 100644 --- a/share/mk/netbsd-tests.test.mk +++ b/share/mk/netbsd-tests.test.mk @@ -3,7 +3,7 @@ .if !target(__netbsd_tests.test.mk__) __netbsd_tests.test.mk__: -OBJROOT?= ${.OBJDIR:S/${RELDIR}//} +OBJTOP?= ${.OBJDIR:S/${RELDIR}//} TESTSRC?= ${SRCTOP}/contrib/netbsd-tests/${RELDIR:H} diff --git a/sys/dev/ath/if_ath.c b/sys/dev/ath/if_ath.c index 8ba0958..4166bb7 100644 --- a/sys/dev/ath/if_ath.c +++ b/sys/dev/ath/if_ath.c @@ -3262,7 +3262,7 @@ ath_transmit(struct ieee80211com *ic, struct mbuf *m) * XXXGL: is mbuf valid after ath_txfrag_setup? If yes, * we shouldn't free it but return back. */ - ath_freetx(m); + ieee80211_free_mbuf(m); m = NULL; goto bad; } @@ -3356,7 +3356,7 @@ reclaim: __func__, ieee80211_state_name[ni->ni_vap->iv_state]); /* XXX dmamap */ - ath_freetx(next); + ieee80211_free_mbuf(next); goto reclaim; } m = next; diff --git a/sys/dev/ath/if_ath_tx.c b/sys/dev/ath/if_ath_tx.c index bee6320..7350bb0 100644 --- a/sys/dev/ath/if_ath_tx.c +++ b/sys/dev/ath/if_ath_tx.c @@ -283,22 +283,6 @@ ath_txfrag_setup(struct ath_softc *sc, ath_bufhead *frags, return !TAILQ_EMPTY(frags); } -/* - * Reclaim mbuf resources. For fragmented frames we - * need to claim each frag chained with m_nextpkt. - */ -void -ath_freetx(struct mbuf *m) -{ - struct mbuf *next; - - do { - next = m->m_nextpkt; - m->m_nextpkt = NULL; - m_freem(m); - } while ((m = next) != NULL); -} - static int ath_tx_dmasetup(struct ath_softc *sc, struct ath_buf *bf, struct mbuf *m0) { @@ -317,7 +301,7 @@ ath_tx_dmasetup(struct ath_softc *sc, struct ath_buf *bf, struct mbuf *m0) bf->bf_nseg = ATH_MAX_SCATTER + 1; } else if (error != 0) { sc->sc_stats.ast_tx_busdma++; - ath_freetx(m0); + ieee80211_free_mbuf(m0); return error; } /* @@ -329,7 +313,7 @@ ath_tx_dmasetup(struct ath_softc *sc, struct ath_buf *bf, struct mbuf *m0) sc->sc_stats.ast_tx_linear++; m = m_collapse(m0, M_NOWAIT, ATH_MAX_SCATTER); if (m == NULL) { - ath_freetx(m0); + ieee80211_free_mbuf(m0); sc->sc_stats.ast_tx_nombuf++; return ENOMEM; } @@ -339,14 +323,14 @@ ath_tx_dmasetup(struct ath_softc *sc, struct ath_buf *bf, struct mbuf *m0) BUS_DMA_NOWAIT); if (error != 0) { sc->sc_stats.ast_tx_busdma++; - ath_freetx(m0); + ieee80211_free_mbuf(m0); return error; } KASSERT(bf->bf_nseg <= ATH_MAX_SCATTER, ("too many segments after defrag; nseg %u", bf->bf_nseg)); } else if (bf->bf_nseg == 0) { /* null packet, discard */ sc->sc_stats.ast_tx_nodata++; - ath_freetx(m0); + ieee80211_free_mbuf(m0); return EIO; } DPRINTF(sc, ATH_DEBUG_XMIT, "%s: m %p len %u\n", @@ -1581,7 +1565,7 @@ ath_tx_normal_setup(struct ath_softc *sc, struct ieee80211_node *ni, /* Handle encryption twiddling if needed */ if (! ath_tx_tag_crypto(sc, ni, m0, iswep, isfrag, &hdrlen, &pktlen, &keyix)) { - ath_freetx(m0); + ieee80211_free_mbuf(m0); return EIO; } @@ -1693,7 +1677,7 @@ ath_tx_normal_setup(struct ath_softc *sc, struct ieee80211_node *ni, wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK, __func__); /* XXX statistic */ /* XXX free tx dmamap */ - ath_freetx(m0); + ieee80211_free_mbuf(m0); return EIO; } @@ -1749,7 +1733,7 @@ ath_tx_normal_setup(struct ath_softc *sc, struct ieee80211_node *ni, "%s: discard frame, ACK required w/ TDMA\n", __func__); sc->sc_stats.ast_tdma_ack++; /* XXX free tx dmamap */ - ath_freetx(m0); + ieee80211_free_mbuf(m0); return EIO; } #endif @@ -2133,7 +2117,7 @@ ath_tx_raw_start(struct ath_softc *sc, struct ieee80211_node *ni, if (! ath_tx_tag_crypto(sc, ni, m0, params->ibp_flags & IEEE80211_BPF_CRYPTO, 0, &hdrlen, &pktlen, &keyix)) { - ath_freetx(m0); + ieee80211_free_mbuf(m0); return EIO; } /* packet header may have moved, reset our local pointer */ @@ -2468,7 +2452,6 @@ badbad: ATH_KTR(sc, ATH_KTR_TX, 2, "ath_raw_xmit: bad0: m=%p, params=%p", m, params); sc->sc_stats.ast_tx_raw_fail++; - ieee80211_free_node(ni); return error; } diff --git a/sys/dev/ath/if_ath_tx.h b/sys/dev/ath/if_ath_tx.h index 281dbcb..19f7707 100644 --- a/sys/dev/ath/if_ath_tx.h +++ b/sys/dev/ath/if_ath_tx.h @@ -85,7 +85,6 @@ */ #define ATH_AGGR_MAXSIZE 65530 -extern void ath_freetx(struct mbuf *m); extern void ath_tx_node_flush(struct ath_softc *sc, struct ath_node *an); extern void ath_tx_txq_drain(struct ath_softc *sc, struct ath_txq *txq); extern void ath_txfrag_cleanup(struct ath_softc *sc, ath_bufhead *frags, diff --git a/sys/dev/bwi/if_bwi.c b/sys/dev/bwi/if_bwi.c index 0a220a1..ebed09c 100644 --- a/sys/dev/bwi/if_bwi.c +++ b/sys/dev/bwi/if_bwi.c @@ -1399,7 +1399,6 @@ bwi_raw_xmit(struct ieee80211_node *ni, struct mbuf *m, int idx, error; if ((sc->sc_flags & BWI_F_RUNNING) == 0) { - ieee80211_free_node(ni); m_freem(m); return ENETDOWN; } @@ -1424,9 +1423,7 @@ bwi_raw_xmit(struct ieee80211_node *ni, struct mbuf *m, tbd->tbd_used++; tbd->tbd_idx = (idx + 1) % BWI_TX_NDESC; sc->sc_tx_timer = 5; - } else - /* NB: m is reclaimed on encap failure */ - ieee80211_free_node(ni); + } BWI_UNLOCK(sc); return error; } diff --git a/sys/dev/bwn/if_bwn.c b/sys/dev/bwn/if_bwn.c index 15f6f27..0746a8e 100644 --- a/sys/dev/bwn/if_bwn.c +++ b/sys/dev/bwn/if_bwn.c @@ -2684,29 +2684,26 @@ bwn_raw_xmit(struct ieee80211_node *ni, struct mbuf *m, struct ieee80211com *ic = ni->ni_ic; struct bwn_softc *sc = ic->ic_softc; struct bwn_mac *mac = sc->sc_curmac; + int error; if ((sc->sc_flags & BWN_FLAG_RUNNING) == 0 || mac->mac_status < BWN_MAC_STATUS_STARTED) { - ieee80211_free_node(ni); m_freem(m); return (ENETDOWN); } BWN_LOCK(sc); if (bwn_tx_isfull(sc, m)) { - ieee80211_free_node(ni); m_freem(m); BWN_UNLOCK(sc); return (ENOBUFS); } - if (bwn_tx_start(sc, ni, m) != 0) { - if (ni != NULL) - ieee80211_free_node(ni); - } - sc->sc_watchdog_timer = 5; + error = bwn_tx_start(sc, ni, m); + if (error == 0) + sc->sc_watchdog_timer = 5; BWN_UNLOCK(sc); - return (0); + return (error); } /* diff --git a/sys/dev/iwm/if_iwm.c b/sys/dev/iwm/if_iwm.c index cd2ccd2..df17f93 100644 --- a/sys/dev/iwm/if_iwm.c +++ b/sys/dev/iwm/if_iwm.c @@ -2877,7 +2877,6 @@ iwm_raw_xmit(struct ieee80211_node *ni, struct mbuf *m, "->%s begin\n", __func__); if ((sc->sc_flags & IWM_FLAG_HW_INITED) == 0) { - ieee80211_free_node(ni); m_freem(m); IWM_DPRINTF(sc, IWM_DEBUG_XMIT, "<-%s not RUNNING\n", __func__); @@ -2891,10 +2890,6 @@ iwm_raw_xmit(struct ieee80211_node *ni, struct mbuf *m, } else { error = iwm_tx(sc, m, ni, 0); } - if (error != 0) { - /* NB: m is reclaimed on tx failure */ - ieee80211_free_node(ni); - } sc->sc_tx_timer = 5; IWM_UNLOCK(sc); diff --git a/sys/dev/iwm/if_iwmvar.h b/sys/dev/iwm/if_iwmvar.h index ead6904..9434b83 100644 --- a/sys/dev/iwm/if_iwmvar.h +++ b/sys/dev/iwm/if_iwmvar.h @@ -496,14 +496,12 @@ struct iwm_softc { uint8_t pad[IEEE80211_RADIOTAP_HDRLEN]; } sc_rxtapu; #define sc_rxtap sc_rxtapu.th - int sc_rxtap_len; union { struct iwm_tx_radiotap_header th; uint8_t pad[IEEE80211_RADIOTAP_HDRLEN]; } sc_txtapu; #define sc_txtap sc_txtapu.th - int sc_txtap_len; int sc_max_rssi; }; diff --git a/sys/dev/iwn/if_iwn.c b/sys/dev/iwn/if_iwn.c index c1ed6ab..0cdeafb 100644 --- a/sys/dev/iwn/if_iwn.c +++ b/sys/dev/iwn/if_iwn.c @@ -4875,7 +4875,6 @@ iwn_raw_xmit(struct ieee80211_node *ni, struct mbuf *m, DPRINTF(sc, IWN_DEBUG_XMIT | IWN_DEBUG_TRACE, "->%s begin\n", __func__); if ((sc->sc_flags & IWN_FLAG_RUNNING) == 0) { - ieee80211_free_node(ni); m_freem(m); return ENETDOWN; } @@ -4889,9 +4888,6 @@ iwn_raw_xmit(struct ieee80211_node *ni, struct mbuf *m, if (sc->sc_beacon_wait) { if (iwn_xmit_queue_enqueue(sc, m) != 0) { m_freem(m); - if_inc_counter(ni->ni_vap->iv_ifp, - IFCOUNTER_OERRORS, 1); - ieee80211_free_node(ni); IWN_UNLOCK(sc); return (ENOBUFS); } @@ -4913,10 +4909,7 @@ iwn_raw_xmit(struct ieee80211_node *ni, struct mbuf *m, */ error = iwn_tx_data_raw(sc, m, ni, params); } - if (error != 0) { - /* NB: m is reclaimed on tx failure */ - ieee80211_free_node(ni); - } else + if (error == 0) sc->sc_tx_timer = 5; IWN_UNLOCK(sc); @@ -4950,9 +4943,7 @@ iwn_transmit(struct ieee80211com *ic, struct mbuf *m) } error = iwn_tx_data(sc, m, ni); - if (error) { - if_inc_counter(ni->ni_vap->iv_ifp, IFCOUNTER_OERRORS, 1); - } else + if (!error) sc->sc_tx_timer = 5; IWN_UNLOCK(sc); return (error); diff --git a/sys/dev/malo/if_malo.c b/sys/dev/malo/if_malo.c index 251ddc6..d02b6d5 100644 --- a/sys/dev/malo/if_malo.c +++ b/sys/dev/malo/if_malo.c @@ -1786,7 +1786,6 @@ malo_raw_xmit(struct ieee80211_node *ni, struct mbuf *m, struct malo_txq *txq; if (!sc->malo_running || sc->malo_invalid) { - ieee80211_free_node(ni); m_freem(m); return ENETDOWN; } @@ -1800,7 +1799,6 @@ malo_raw_xmit(struct ieee80211_node *ni, struct mbuf *m, txq = &sc->malo_txq[0]; bf = malo_getbuf(sc, txq); if (bf == NULL) { - ieee80211_free_node(ni); m_freem(m); return ENOBUFS; } @@ -1816,7 +1814,6 @@ malo_raw_xmit(struct ieee80211_node *ni, struct mbuf *m, txq->nfree++; MALO_TXQ_UNLOCK(txq); - ieee80211_free_node(ni); return EIO; /* XXX */ } diff --git a/sys/dev/mwl/if_mwl.c b/sys/dev/mwl/if_mwl.c index 7f9d8e0..d01165c 100644 --- a/sys/dev/mwl/if_mwl.c +++ b/sys/dev/mwl/if_mwl.c @@ -1422,7 +1422,6 @@ mwl_raw_xmit(struct ieee80211_node *ni, struct mbuf *m, struct mwl_txq *txq; if (!sc->sc_running || sc->sc_invalid) { - ieee80211_free_node(ni); m_freem(m); return ENETDOWN; } @@ -1438,7 +1437,6 @@ mwl_raw_xmit(struct ieee80211_node *ni, struct mbuf *m, bf = mwl_gettxbuf(sc, txq); if (bf == NULL) { sc->sc_stats.mst_tx_qstop++; - ieee80211_free_node(ni); m_freem(m); return ENOBUFS; } @@ -1448,7 +1446,6 @@ mwl_raw_xmit(struct ieee80211_node *ni, struct mbuf *m, if (mwl_tx_start(sc, ni, bf, m)) { mwl_puttxbuf_head(txq, bf); - ieee80211_free_node(ni); return EIO; /* XXX */ } /* diff --git a/sys/dev/ntb/if_ntb/if_ntb.c b/sys/dev/ntb/if_ntb/if_ntb.c index 84716d9..461a4a3 100644 --- a/sys/dev/ntb/if_ntb/if_ntb.c +++ b/sys/dev/ntb/if_ntb/if_ntb.c @@ -194,11 +194,22 @@ struct ntb_payload_header { }; enum { + /* + * The order of this enum is part of the if_ntb remote protocol. Do + * not reorder without bumping protocol version (and it's probably best + * to keep the protocol in lock-step with the Linux NTB driver. + */ IF_NTB_VERSION = 0, - IF_NTB_MW0_SZ, - IF_NTB_MW1_SZ, - IF_NTB_NUM_QPS, IF_NTB_QP_LINKS, + IF_NTB_NUM_QPS, + IF_NTB_NUM_MWS, + /* + * N.B.: transport_link_work assumes MW1 enums = MW0 + 2. + */ + IF_NTB_MW0_SZ_HIGH, + IF_NTB_MW0_SZ_LOW, + IF_NTB_MW1_SZ_HIGH, + IF_NTB_MW1_SZ_LOW, IF_NTB_MAX_SPAD, }; @@ -242,6 +253,7 @@ static void ntb_rx_completion_task(void *arg, int pending); static void ntb_transport_event_callback(void *data, enum ntb_hw_event event); static void ntb_transport_link_work(void *arg); static int ntb_set_mw(struct ntb_netdev *nt, int num_mw, unsigned int size); +static void ntb_free_mw(struct ntb_netdev *nt, int num_mw); static void ntb_transport_setup_qp_mw(struct ntb_netdev *nt, unsigned int qp_num); static void ntb_qp_link_work(void *arg); @@ -514,9 +526,7 @@ ntb_transport_free(void *transport) ntb_unregister_event_callback(ntb); for (i = 0; i < NTB_NUM_MW; i++) - if (nt->mw[i].virt_addr != NULL) - contigfree(nt->mw[i].virt_addr, nt->mw[i].size, - M_NTB_IF); + ntb_free_mw(nt, i); free(nt->qps, M_NTB_IF); ntb_unregister_transport(ntb); @@ -548,11 +558,11 @@ ntb_transport_init_queue(struct ntb_netdev *nt, unsigned int qp_num) (qp_num / NTB_NUM_MW * tx_size)); tx_size -= sizeof(struct ntb_rx_info); - qp->tx_mw = qp->rx_info + sizeof(struct ntb_rx_info); + qp->tx_mw = qp->rx_info + 1; + /* Due to house-keeping, there must be at least 2 buffs */ qp->tx_max_frame = min(transport_mtu + sizeof(struct ntb_payload_header), - tx_size); + tx_size / 2); qp->tx_max_entry = tx_size / qp->tx_max_frame; - qp->tx_index = 0; callout_init(&qp->link_work, 0); callout_init(&qp->queue_full, 1); @@ -843,7 +853,8 @@ ntb_rx_pendq_full(void *arg) static void ntb_transport_rx(struct ntb_transport_qp *qp) { - int rc, i; + uint64_t i; + int rc; /* * Limit the number of packets processed in a single interrupt to @@ -851,7 +862,7 @@ ntb_transport_rx(struct ntb_transport_qp *qp) */ mtx_lock(&qp->transport->rx_lock); CTR0(KTR_NTB, "RX: transport_rx"); - for (i = 0; i < NTB_RX_MAX_PKTS; i++) { + for (i = 0; i < qp->rx_max_entry; i++) { rc = ntb_process_rxc(qp); if (rc != 0) { CTR0(KTR_NTB, "RX: process_rxc failed"); @@ -1019,19 +1030,24 @@ ntb_transport_link_work(void *arg) struct ntb_netdev *nt = arg; struct ntb_softc *ntb = nt->ntb; struct ntb_transport_qp *qp; + uint64_t val64; uint32_t val; int rc, i; - /* send the local info */ - rc = ntb_write_remote_spad(ntb, IF_NTB_VERSION, NTB_TRANSPORT_VERSION); - if (rc != 0) - goto out; - - rc = ntb_write_remote_spad(ntb, IF_NTB_MW0_SZ, ntb_get_mw_size(ntb, 0)); - if (rc != 0) - goto out; + /* send the local info, in the opposite order of the way we read it */ + for (i = 0; i < NTB_NUM_MW; i++) { + rc = ntb_write_remote_spad(ntb, IF_NTB_MW0_SZ_HIGH + (i * 2), + ntb_get_mw_size(ntb, i) >> 32); + if (rc != 0) + goto out; + + rc = ntb_write_remote_spad(ntb, IF_NTB_MW0_SZ_LOW + (i * 2), + (uint32_t)ntb_get_mw_size(ntb, i)); + if (rc != 0) + goto out; + } - rc = ntb_write_remote_spad(ntb, IF_NTB_MW1_SZ, ntb_get_mw_size(ntb, 1)); + rc = ntb_write_remote_spad(ntb, IF_NTB_NUM_MWS, NTB_NUM_MW); if (rc != 0) goto out; @@ -1039,11 +1055,7 @@ ntb_transport_link_work(void *arg) if (rc != 0) goto out; - rc = ntb_read_remote_spad(ntb, IF_NTB_QP_LINKS, &val); - if (rc != 0) - goto out; - - rc = ntb_write_remote_spad(ntb, IF_NTB_QP_LINKS, val); + rc = ntb_write_remote_spad(ntb, IF_NTB_VERSION, NTB_TRANSPORT_VERSION); if (rc != 0) goto out; @@ -1062,27 +1074,32 @@ ntb_transport_link_work(void *arg) if (val != nt->max_qps) goto out; - rc = ntb_read_local_spad(ntb, IF_NTB_MW0_SZ, &val); + rc = ntb_read_local_spad(ntb, IF_NTB_NUM_MWS, &val); if (rc != 0) goto out; - if (val == 0) + if (val != NTB_NUM_MW) goto out; - rc = ntb_set_mw(nt, 0, val); - if (rc != 0) - return; + for (i = 0; i < NTB_NUM_MW; i++) { + rc = ntb_read_local_spad(ntb, IF_NTB_MW0_SZ_HIGH + (i * 2), + &val); + if (rc != 0) + goto free_mws; - rc = ntb_read_local_spad(ntb, IF_NTB_MW1_SZ, &val); - if (rc != 0) - goto out; + val64 = (uint64_t)val << 32; - if (val == 0) - goto out; + rc = ntb_read_local_spad(ntb, IF_NTB_MW0_SZ_LOW + (i * 2), + &val); + if (rc != 0) + goto free_mws; - rc = ntb_set_mw(nt, 1, val); - if (rc != 0) - return; + val64 |= val; + + rc = ntb_set_mw(nt, i, val64); + if (rc != 0) + goto free_mws; + } nt->transport_link = NTB_LINK_UP; if (bootverbose) @@ -1099,10 +1116,13 @@ ntb_transport_link_work(void *arg) return; +free_mws: + for (i = 0; i < NTB_NUM_MW; i++) + ntb_free_mw(nt, i); out: if (ntb_query_link_status(ntb)) callout_reset(&nt->link_work, - NTB_LINK_DOWN_TIMEOUT * hz / 1000, ntb_transport_link_work, nt); + NTB_LINK_DOWN_TIMEOUT * hz / 1000, ntb_transport_link_work, nt); } static int @@ -1110,12 +1130,20 @@ ntb_set_mw(struct ntb_netdev *nt, int num_mw, unsigned int size) { struct ntb_transport_mw *mw = &nt->mw[num_mw]; + /* No need to re-setup */ + if (mw->size == size) + return (0); + + if (mw->size != 0) + ntb_free_mw(nt, num_mw); + /* Alloc memory for receiving data. Must be 4k aligned */ mw->size = size; mw->virt_addr = contigmalloc(mw->size, M_NTB_IF, M_ZERO, 0, BUS_SPACE_MAXADDR, mw->size, 0); if (mw->virt_addr == NULL) { + mw->size = 0; printf("ntb: Unable to allocate MW buffer of size %d\n", (int)mw->size); return (ENOMEM); @@ -1130,6 +1158,18 @@ ntb_set_mw(struct ntb_netdev *nt, int num_mw, unsigned int size) } static void +ntb_free_mw(struct ntb_netdev *nt, int num_mw) +{ + struct ntb_transport_mw *mw = &nt->mw[num_mw]; + + if (mw->virt_addr == NULL) + return; + + contigfree(mw->virt_addr, mw->size, M_NTB_IF); + mw->virt_addr = NULL; +} + +static void ntb_transport_setup_qp_mw(struct ntb_netdev *nt, unsigned int qp_num) { struct ntb_transport_qp *qp = &nt->qps[qp_num]; @@ -1148,14 +1188,14 @@ ntb_transport_setup_qp_mw(struct ntb_netdev *nt, unsigned int qp_num) (qp_num / NTB_NUM_MW * rx_size)); rx_size -= sizeof(struct ntb_rx_info); - qp->rx_buff = qp->remote_rx_info + sizeof(struct ntb_rx_info); + qp->rx_buff = qp->remote_rx_info + 1; + /* Due to house-keeping, there must be at least 2 buffs */ qp->rx_max_frame = min(transport_mtu + sizeof(struct ntb_payload_header), - rx_size); + rx_size / 2); qp->rx_max_entry = rx_size / qp->rx_max_frame; qp->rx_index = 0; - qp->tx_index = 0; - qp->remote_rx_info->entry = qp->rx_max_entry; + qp->remote_rx_info->entry = qp->rx_max_entry - 1; /* setup the hdr offsets with 0's */ for (i = 0; i < qp->rx_max_entry; i++) { @@ -1167,6 +1207,7 @@ ntb_transport_setup_qp_mw(struct ntb_netdev *nt, unsigned int qp_num) qp->rx_pkts = 0; qp->tx_pkts = 0; + qp->tx_index = 0; } static void diff --git a/sys/dev/otus/if_otus.c b/sys/dev/otus/if_otus.c index e60157a..1808c95 100644 --- a/sys/dev/otus/if_otus.c +++ b/sys/dev/otus/if_otus.c @@ -567,7 +567,6 @@ error: if (bf) otus_freebuf(sc, bf); OTUS_UNLOCK(sc); - ieee80211_free_node(ni); m_freem(m); return (ENXIO); } @@ -1713,7 +1712,6 @@ otus_sub_rxeof(struct otus_softc *sc, uint8_t *buf, int len, struct mbufq *rxq) break; } mb.m_data = (caddr_t)tap; - mb.m_len = sc->sc_rxtap_len; mb.m_next = m; mb.m_nextpkt = NULL; mb.m_type = 0; diff --git a/sys/dev/otus/if_otusreg.h b/sys/dev/otus/if_otusreg.h index 9f62ebd..4352778 100644 --- a/sys/dev/otus/if_otusreg.h +++ b/sys/dev/otus/if_otusreg.h @@ -1017,14 +1017,12 @@ struct otus_softc { uint8_t pad[64]; } sc_rxtapu; #define sc_rxtap sc_rxtapu.th - int sc_rxtap_len; union { struct otus_tx_radiotap_header th; uint8_t pad[64]; } sc_txtapu; #define sc_txtap sc_txtapu.th - int sc_txtap_len; }; #endif /* __IF_OTUSREG_H__ */ diff --git a/sys/dev/ral/rt2560.c b/sys/dev/ral/rt2560.c index b03e8fa..e5d7518 100644 --- a/sys/dev/ral/rt2560.c +++ b/sys/dev/ral/rt2560.c @@ -2711,13 +2711,11 @@ rt2560_raw_xmit(struct ieee80211_node *ni, struct mbuf *m, if (!(sc->sc_flags & RT2560_F_RUNNING)) { RAL_UNLOCK(sc); m_freem(m); - ieee80211_free_node(ni); return ENETDOWN; } if (sc->prioq.queued >= RT2560_PRIO_RING_COUNT) { RAL_UNLOCK(sc); m_freem(m); - ieee80211_free_node(ni); return ENOBUFS; /* XXX */ } @@ -2742,7 +2740,6 @@ rt2560_raw_xmit(struct ieee80211_node *ni, struct mbuf *m, return 0; bad: - ieee80211_free_node(ni); RAL_UNLOCK(sc); return EIO; /* XXX */ } diff --git a/sys/dev/ral/rt2560var.h b/sys/dev/ral/rt2560var.h index 12601d8..9d7ed53 100644 --- a/sys/dev/ral/rt2560var.h +++ b/sys/dev/ral/rt2560var.h @@ -146,10 +146,8 @@ struct rt2560_softc { int nb_ant; struct rt2560_rx_radiotap_header sc_rxtap; - int sc_rxtap_len; - struct rt2560_tx_radiotap_header sc_txtap; - int sc_txtap_len; + #define RT2560_F_INPUT_RUNNING 0x1 #define RT2560_F_RUNNING 0x2 int sc_flags; diff --git a/sys/dev/ral/rt2661.c b/sys/dev/ral/rt2661.c index 100b5d6..cff64b1 100644 --- a/sys/dev/ral/rt2661.c +++ b/sys/dev/ral/rt2661.c @@ -1636,13 +1636,11 @@ rt2661_raw_xmit(struct ieee80211_node *ni, struct mbuf *m, if (!(sc->sc_flags & RAL_RUNNING)) { RAL_UNLOCK(sc); m_freem(m); - ieee80211_free_node(ni); return ENETDOWN; } if (sc->mgtq.queued >= RT2661_MGT_RING_COUNT) { RAL_UNLOCK(sc); m_freem(m); - ieee80211_free_node(ni); return ENOBUFS; /* XXX */ } @@ -1659,7 +1657,6 @@ rt2661_raw_xmit(struct ieee80211_node *ni, struct mbuf *m, return 0; bad: - ieee80211_free_node(ni); RAL_UNLOCK(sc); return EIO; /* XXX */ } diff --git a/sys/dev/ral/rt2661var.h b/sys/dev/ral/rt2661var.h index 7ea16f6..93810a6 100644 --- a/sys/dev/ral/rt2661var.h +++ b/sys/dev/ral/rt2661var.h @@ -157,9 +157,7 @@ struct rt2661_softc { int dwelltime; struct rt2661_rx_radiotap_header sc_rxtap; - int sc_rxtap_len; struct rt2661_tx_radiotap_header sc_txtap; - int sc_txtap_len; }; int rt2661_attach(device_t, int); diff --git a/sys/dev/ral/rt2860.c b/sys/dev/ral/rt2860.c index 9c7fa53..d233315 100644 --- a/sys/dev/ral/rt2860.c +++ b/sys/dev/ral/rt2860.c @@ -1702,7 +1702,6 @@ rt2860_raw_xmit(struct ieee80211_node *ni, struct mbuf *m, if (!(sc->sc_flags & RT2860_RUNNNING)) { RAL_UNLOCK(sc); m_freem(m); - ieee80211_free_node(ni); return ENETDOWN; } if (params == NULL) { @@ -1718,10 +1717,6 @@ rt2860_raw_xmit(struct ieee80211_node *ni, struct mbuf *m, */ error = rt2860_tx_raw(sc, m, ni, params); } - if (error != 0) { - /* NB: m is reclaimed on tx failure */ - ieee80211_free_node(ni); - } sc->sc_tx_timer = 5; RAL_UNLOCK(sc); return error; diff --git a/sys/dev/ral/rt2860var.h b/sys/dev/ral/rt2860var.h index 3779e5b..f7fd218 100644 --- a/sys/dev/ral/rt2860var.h +++ b/sys/dev/ral/rt2860var.h @@ -194,9 +194,7 @@ struct rt2860_softc { uint32_t txpow40mhz_5ghz[5]; struct rt2860_rx_radiotap_header sc_rxtap; - int sc_rxtap_len; struct rt2860_tx_radiotap_header sc_txtap; - int sc_txtap_len; }; int rt2860_attach(device_t, int); diff --git a/sys/dev/usb/wlan/if_rsu.c b/sys/dev/usb/wlan/if_rsu.c index 4fb9d85..6558c93 100644 --- a/sys/dev/usb/wlan/if_rsu.c +++ b/sys/dev/usb/wlan/if_rsu.c @@ -2793,19 +2793,16 @@ rsu_raw_xmit(struct ieee80211_node *ni, struct mbuf *m, /* prevent management frames from being sent if we're not ready */ if (!sc->sc_running) { m_freem(m); - ieee80211_free_node(ni); return (ENETDOWN); } RSU_LOCK(sc); bf = rsu_getbuf(sc); if (bf == NULL) { - ieee80211_free_node(ni); m_freem(m); RSU_UNLOCK(sc); return (ENOBUFS); } if (rsu_tx_start(sc, ni, m, bf) != 0) { - ieee80211_free_node(ni); m_freem(m); rsu_freebuf(sc, bf); RSU_UNLOCK(sc); diff --git a/sys/dev/usb/wlan/if_rsureg.h b/sys/dev/usb/wlan/if_rsureg.h index ddb29a3..c40f28d 100644 --- a/sys/dev/usb/wlan/if_rsureg.h +++ b/sys/dev/usb/wlan/if_rsureg.h @@ -793,12 +793,10 @@ struct rsu_softc { uint8_t pad[64]; } sc_rxtapu; #define sc_rxtap sc_rxtapu.th - int sc_rxtap_len; union { struct rsu_tx_radiotap_header th; uint8_t pad[64]; } sc_txtapu; #define sc_txtap sc_txtapu.th - int sc_txtap_len; }; diff --git a/sys/dev/usb/wlan/if_rum.c b/sys/dev/usb/wlan/if_rum.c index f1c9cdf..de7b880 100644 --- a/sys/dev/usb/wlan/if_rum.c +++ b/sys/dev/usb/wlan/if_rum.c @@ -2850,7 +2850,6 @@ rum_raw_xmit(struct ieee80211_node *ni, struct mbuf *m, bad: RUM_UNLOCK(sc); m_freem(m); - ieee80211_free_node(ni); return ret; } diff --git a/sys/dev/usb/wlan/if_run.c b/sys/dev/usb/wlan/if_run.c index be43755..3a8c020 100644 --- a/sys/dev/usb/wlan/if_run.c +++ b/sys/dev/usb/wlan/if_run.c @@ -3707,7 +3707,6 @@ done: if (error != 0) { if(m != NULL) m_freem(m); - ieee80211_free_node(ni); } return (error); diff --git a/sys/dev/usb/wlan/if_runvar.h b/sys/dev/usb/wlan/if_runvar.h index 3af5b22..aabdaf1 100644 --- a/sys/dev/usb/wlan/if_runvar.h +++ b/sys/dev/usb/wlan/if_runvar.h @@ -253,14 +253,12 @@ struct run_softc { uint8_t pad[64]; } sc_rxtapu; #define sc_rxtap sc_rxtapu.th - int sc_rxtap_len; union { struct run_tx_radiotap_header th; uint8_t pad[64]; } sc_txtapu; #define sc_txtap sc_txtapu.th - int sc_txtap_len; }; #define RUN_LOCK(sc) mtx_lock(&(sc)->sc_mtx) diff --git a/sys/dev/usb/wlan/if_uath.c b/sys/dev/usb/wlan/if_uath.c index 39fa71b..ec5b54c 100644 --- a/sys/dev/usb/wlan/if_uath.c +++ b/sys/dev/usb/wlan/if_uath.c @@ -1663,22 +1663,6 @@ uath_txfrag_setup(struct uath_softc *sc, uath_datahead *frags, return !STAILQ_EMPTY(frags); } -/* - * Reclaim mbuf resources. For fragmented frames we need to claim each frag - * chained with m_nextpkt. - */ -static void -uath_freetx(struct mbuf *m) -{ - struct mbuf *next; - - do { - next = m->m_nextpkt; - m->m_nextpkt = NULL; - m_freem(m); - } while ((m = next) != NULL); -} - static int uath_transmit(struct ieee80211com *ic, struct mbuf *m) { @@ -1735,7 +1719,7 @@ uath_start(struct uath_softc *sc) !uath_txfrag_setup(sc, &frags, m, ni)) { DPRINTF(sc, UATH_DEBUG_XMIT, "%s: out of txfrag buffers\n", __func__); - uath_freetx(m); + ieee80211_free_mbuf(m); goto bad; } sc->sc_seqnum = 0; @@ -1770,7 +1754,7 @@ uath_start(struct uath_softc *sc) "%s: flush fragmented packet, state %s\n", __func__, ieee80211_state_name[ni->ni_vap->iv_state]); - uath_freetx(next); + ieee80211_free_mbuf(next); goto reclaim; } m = next; @@ -1797,7 +1781,6 @@ uath_raw_xmit(struct ieee80211_node *ni, struct mbuf *m, if ((sc->sc_flags & UATH_FLAG_INVALID) || !(sc->sc_flags & UATH_FLAG_INITDONE)) { m_freem(m); - ieee80211_free_node(ni); UATH_UNLOCK(sc); return (ENETDOWN); } @@ -1805,7 +1788,6 @@ uath_raw_xmit(struct ieee80211_node *ni, struct mbuf *m, /* grab a TX buffer */ bf = uath_getbuf(sc); if (bf == NULL) { - ieee80211_free_node(ni); m_freem(m); UATH_UNLOCK(sc); return (ENOBUFS); @@ -1813,7 +1795,6 @@ uath_raw_xmit(struct ieee80211_node *ni, struct mbuf *m, sc->sc_seqnum = 0; if (uath_tx_start(sc, m, ni, bf) != 0) { - ieee80211_free_node(ni); STAILQ_INSERT_HEAD(&sc->sc_tx_inactive, bf, next); UATH_STAT_INC(sc, st_tx_inactive); UATH_UNLOCK(sc); diff --git a/sys/dev/usb/wlan/if_uathvar.h b/sys/dev/usb/wlan/if_uathvar.h index 4b4d9fc..a38f54f 100644 --- a/sys/dev/usb/wlan/if_uathvar.h +++ b/sys/dev/usb/wlan/if_uathvar.h @@ -230,9 +230,7 @@ struct uath_softc { #define UATH_FLAG_INITDONE (1 << 2) struct uath_rx_radiotap_header sc_rxtap; - int sc_rxtap_len; struct uath_tx_radiotap_header sc_txtap; - int sc_txtap_len; }; #define UATH_LOCK(sc) mtx_lock(&(sc)->sc_mtx) diff --git a/sys/dev/usb/wlan/if_upgt.c b/sys/dev/usb/wlan/if_upgt.c index 516caf0..2689ae0 100644 --- a/sys/dev/usb/wlan/if_upgt.c +++ b/sys/dev/usb/wlan/if_upgt.c @@ -798,14 +798,12 @@ upgt_raw_xmit(struct ieee80211_node *ni, struct mbuf *m, /* prevent management frames from being sent if we're not ready */ if (!(sc->sc_flags & UPGT_FLAG_INITDONE)) { m_freem(m); - ieee80211_free_node(ni); UPGT_UNLOCK(sc); return ENETDOWN; } data_tx = upgt_gettxbuf(sc); if (data_tx == NULL) { - ieee80211_free_node(ni); m_freem(m); UPGT_UNLOCK(sc); return (ENOBUFS); @@ -814,7 +812,6 @@ upgt_raw_xmit(struct ieee80211_node *ni, struct mbuf *m, if (upgt_tx_start(sc, m, ni, data_tx) != 0) { STAILQ_INSERT_HEAD(&sc->sc_tx_inactive, data_tx, next); UPGT_STAT_INC(sc, st_tx_inactive); - ieee80211_free_node(ni); UPGT_UNLOCK(sc); return (EIO); } diff --git a/sys/dev/usb/wlan/if_upgtvar.h b/sys/dev/usb/wlan/if_upgtvar.h index 3dcd335..ce996f6 100644 --- a/sys/dev/usb/wlan/if_upgtvar.h +++ b/sys/dev/usb/wlan/if_upgtvar.h @@ -472,9 +472,7 @@ struct upgt_softc { /* BPF */ struct upgt_rx_radiotap_header sc_rxtap; - int sc_rxtap_len; struct upgt_tx_radiotap_header sc_txtap; - int sc_txtap_len; }; #define UPGT_LOCK(sc) mtx_lock(&(sc)->sc_mtx) diff --git a/sys/dev/usb/wlan/if_ural.c b/sys/dev/usb/wlan/if_ural.c index 6f6686f..3fb03bd 100644 --- a/sys/dev/usb/wlan/if_ural.c +++ b/sys/dev/usb/wlan/if_ural.c @@ -2123,13 +2123,11 @@ ural_raw_xmit(struct ieee80211_node *ni, struct mbuf *m, if (!sc->sc_running) { RAL_UNLOCK(sc); m_freem(m); - ieee80211_free_node(ni); return ENETDOWN; } if (sc->tx_nfree < RAL_TX_MINFREE) { RAL_UNLOCK(sc); m_freem(m); - ieee80211_free_node(ni); return EIO; } @@ -2152,7 +2150,6 @@ ural_raw_xmit(struct ieee80211_node *ni, struct mbuf *m, return 0; bad: RAL_UNLOCK(sc); - ieee80211_free_node(ni); return EIO; /* XXX */ } diff --git a/sys/dev/usb/wlan/if_uralvar.h b/sys/dev/usb/wlan/if_uralvar.h index 5461e87..208a969 100644 --- a/sys/dev/usb/wlan/if_uralvar.h +++ b/sys/dev/usb/wlan/if_uralvar.h @@ -125,10 +125,7 @@ struct ural_softc { int nb_ant; struct ural_rx_radiotap_header sc_rxtap; - int sc_rxtap_len; - struct ural_tx_radiotap_header sc_txtap; - int sc_txtap_len; }; #define RAL_LOCK(sc) mtx_lock(&(sc)->sc_mtx) diff --git a/sys/dev/usb/wlan/if_urtw.c b/sys/dev/usb/wlan/if_urtw.c index 040ba86..a9aac3a 100644 --- a/sys/dev/usb/wlan/if_urtw.c +++ b/sys/dev/usb/wlan/if_urtw.c @@ -1527,20 +1527,17 @@ urtw_raw_xmit(struct ieee80211_node *ni, struct mbuf *m, /* prevent management frames from being sent if we're not ready */ if (!(sc->sc_flags & URTW_RUNNING)) { m_freem(m); - ieee80211_free_node(ni); return ENETDOWN; } URTW_LOCK(sc); bf = urtw_getbuf(sc); if (bf == NULL) { - ieee80211_free_node(ni); m_freem(m); URTW_UNLOCK(sc); return (ENOBUFS); /* XXX */ } if (urtw_tx_start(sc, ni, m, bf, URTW_PRIORITY_LOW) != 0) { - ieee80211_free_node(ni); STAILQ_INSERT_HEAD(&sc->sc_tx_inactive, bf, next); URTW_UNLOCK(sc); return (EIO); diff --git a/sys/dev/usb/wlan/if_urtwn.c b/sys/dev/usb/wlan/if_urtwn.c index f680edc..5aca1a4 100644 --- a/sys/dev/usb/wlan/if_urtwn.c +++ b/sys/dev/usb/wlan/if_urtwn.c @@ -76,6 +76,7 @@ __FBSDID("$FreeBSD$"); #include <dev/usb/usb_debug.h> #include <dev/usb/wlan/if_urtwnreg.h> +#include <dev/usb/wlan/if_urtwnvar.h> #ifdef USB_DEBUG static int urtwn_debug = 0; @@ -1631,6 +1632,19 @@ urtwn_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) /* Enable Rx of data frames. */ urtwn_write_2(sc, R92C_RXFLTMAP2, 0xffff); + /* Enable Rx of ctrl frames. */ + urtwn_write_2(sc, R92C_RXFLTMAP1, 0xffff); + + /* + * Accept data/control/management frames + * from any BSSID. + */ + urtwn_write_4(sc, R92C_RCR, + (urtwn_read_4(sc, R92C_RCR) & ~(R92C_RCR_APM | + R92C_RCR_CBSSID_DATA | R92C_RCR_CBSSID_BCN)) | + R92C_RCR_ADF | R92C_RCR_ACF | R92C_RCR_AMF | + R92C_RCR_AAP); + /* Turn link LED on. */ urtwn_set_led(sc, URTWN_LED_LINK, 1); break; @@ -3460,13 +3474,11 @@ urtwn_raw_xmit(struct ieee80211_node *ni, struct mbuf *m, /* prevent management frames from being sent if we're not ready */ if (!(sc->sc_flags & URTWN_RUNNING)) { m_freem(m); - ieee80211_free_node(ni); return (ENETDOWN); } URTWN_LOCK(sc); bf = urtwn_getbuf(sc); if (bf == NULL) { - ieee80211_free_node(ni); m_freem(m); URTWN_UNLOCK(sc); return (ENOBUFS); @@ -3474,7 +3486,6 @@ urtwn_raw_xmit(struct ieee80211_node *ni, struct mbuf *m, if (urtwn_tx_start(sc, ni, m, bf) != 0) { m_freem(m); - ieee80211_free_node(ni); STAILQ_INSERT_HEAD(&sc->sc_tx_inactive, bf, next); URTWN_UNLOCK(sc); return (EIO); diff --git a/sys/dev/usb/wlan/if_urtwnreg.h b/sys/dev/usb/wlan/if_urtwnreg.h index ece356d..628b50e 100644 --- a/sys/dev/usb/wlan/if_urtwnreg.h +++ b/sys/dev/usb/wlan/if_urtwnreg.h @@ -1061,197 +1061,6 @@ struct r92c_tx_desc { /* - * Driver definitions. - */ -#define URTWN_RX_LIST_COUNT 1 -#define URTWN_TX_LIST_COUNT 8 -#define URTWN_HOST_CMD_RING_COUNT 32 - -#define URTWN_RXBUFSZ (16 * 1024) -#define URTWN_TXBUFSZ (sizeof(struct r92c_tx_desc) + IEEE80211_MAX_LEN) -#define URTWN_RX_DESC_SIZE (sizeof(struct r92c_rx_stat)) -#define URTWN_TX_DESC_SIZE (sizeof(struct r92c_tx_desc)) - -#define URTWN_RIDX_COUNT 28 - -#define URTWN_TX_TIMEOUT 5000 /* ms */ - -#define URTWN_LED_LINK 0 -#define URTWN_LED_DATA 1 - -struct urtwn_rx_radiotap_header { - struct ieee80211_radiotap_header wr_ihdr; - uint8_t wr_flags; - uint8_t wr_rate; - uint16_t wr_chan_freq; - uint16_t wr_chan_flags; - uint8_t wr_dbm_antsignal; -} __packed __aligned(8); - -#define URTWN_RX_RADIOTAP_PRESENT \ - (1 << IEEE80211_RADIOTAP_FLAGS | \ - 1 << IEEE80211_RADIOTAP_RATE | \ - 1 << IEEE80211_RADIOTAP_CHANNEL | \ - 1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL) - -struct urtwn_tx_radiotap_header { - struct ieee80211_radiotap_header wt_ihdr; - uint8_t wt_flags; - uint16_t wt_chan_freq; - uint16_t wt_chan_flags; -} __packed __aligned(8); - -#define URTWN_TX_RADIOTAP_PRESENT \ - (1 << IEEE80211_RADIOTAP_FLAGS | \ - 1 << IEEE80211_RADIOTAP_CHANNEL) - -struct urtwn_softc; - -struct urtwn_data { - struct urtwn_softc *sc; - uint8_t *buf; - uint16_t buflen; - struct mbuf *m; - struct ieee80211_node *ni; - STAILQ_ENTRY(urtwn_data) next; -}; -typedef STAILQ_HEAD(, urtwn_data) urtwn_datahead; - -struct urtwn_cmdq { - void *arg0; - void *arg1; - void (*func)(void *); - struct ieee80211_key *k; - struct ieee80211_key key; - uint8_t mac[IEEE80211_ADDR_LEN]; - uint8_t wcid; -}; - -struct urtwn_fw_info { - const uint8_t *data; - size_t size; -}; - -struct urtwn_vap { - struct ieee80211vap vap; - - int (*newstate)(struct ieee80211vap *, - enum ieee80211_state, int); -}; -#define URTWN_VAP(vap) ((struct urtwn_vap *)(vap)) - -struct urtwn_host_cmd { - void (*cb)(struct urtwn_softc *, void *); - uint8_t data[256]; -}; - -struct urtwn_cmd_newstate { - enum ieee80211_state state; - int arg; -}; - -struct urtwn_cmd_key { - struct ieee80211_key key; - uint16_t associd; -}; - -enum { - URTWN_BULK_RX, - URTWN_BULK_TX_BE, /* = WME_AC_BE */ - URTWN_BULK_TX_BK, /* = WME_AC_BK */ - URTWN_BULK_TX_VI, /* = WME_AC_VI */ - URTWN_BULK_TX_VO, /* = WME_AC_VI */ - URTWN_N_TRANSFER = 5, -}; - -#define URTWN_EP_QUEUES URTWN_BULK_RX - -struct urtwn_softc { - struct ieee80211com sc_ic; - struct mbufq sc_snd; - device_t sc_dev; - struct usb_device *sc_udev; - - int ac2idx[WME_NUM_AC]; - u_int sc_flags; -#define URTWN_FLAG_CCK_HIPWR 0x01 -#define URTWN_DETACHED 0x02 -#define URTWN_RUNNING 0x04 - - u_int chip; -#define URTWN_CHIP_92C 0x01 -#define URTWN_CHIP_92C_1T2R 0x02 -#define URTWN_CHIP_UMC 0x04 -#define URTWN_CHIP_UMC_A_CUT 0x08 -#define URTWN_CHIP_88E 0x10 - - void (*sc_rf_write)(struct urtwn_softc *, - int, uint8_t, uint32_t); - int (*sc_power_on)(struct urtwn_softc *); - int (*sc_dma_init)(struct urtwn_softc *); - - uint8_t board_type; - uint8_t regulatory; - uint8_t pa_setting; - int avg_pwdb; - int thcal_state; - int thcal_lctemp; - int ntxchains; - int nrxchains; - int ledlink; - int sc_txtimer; - - int fwcur; - struct urtwn_data sc_rx[URTWN_RX_LIST_COUNT]; - urtwn_datahead sc_rx_active; - urtwn_datahead sc_rx_inactive; - struct urtwn_data sc_tx[URTWN_TX_LIST_COUNT]; - urtwn_datahead sc_tx_active; - urtwn_datahead sc_tx_inactive; - urtwn_datahead sc_tx_pending; - - const char *fwname; - const struct firmware *fw_fp; - struct urtwn_fw_info fw; - void *fw_virtaddr; - - struct r92c_rom rom; - uint8_t r88e_rom[512]; - uint8_t cck_tx_pwr[6]; - uint8_t ht40_tx_pwr[5]; - int8_t bw20_tx_pwr_diff; - int8_t ofdm_tx_pwr_diff; - - struct callout sc_watchdog_ch; - struct mtx sc_mtx; - -/* need to be power of 2, otherwise URTWN_CMDQ_GET fails */ -#define URTWN_CMDQ_MAX 16 -#define URTWN_CMDQ_MASQ (URTWN_CMDQ_MAX - 1) - struct urtwn_cmdq cmdq[URTWN_CMDQ_MAX]; - struct task cmdq_task; - uint32_t cmdq_store; - uint8_t cmdq_exec; - uint8_t cmdq_run; - uint8_t cmdq_key_set; -#define URTWN_CMDQ_ABORT 0 -#define URTWN_CMDQ_GO 1 - - uint32_t rf_chnlbw[R92C_MAX_CHAINS]; - struct usb_xfer *sc_xfer[URTWN_N_TRANSFER]; - - struct urtwn_rx_radiotap_header sc_rxtap; - int sc_rxtap_len; - - struct urtwn_tx_radiotap_header sc_txtap; - int sc_txtap_len; -}; - -#define URTWN_LOCK(sc) mtx_lock(&(sc)->sc_mtx) -#define URTWN_UNLOCK(sc) mtx_unlock(&(sc)->sc_mtx) -#define URTWN_ASSERT_LOCKED(sc) mtx_assert(&(sc)->sc_mtx, MA_OWNED) - -/* * MAC initialization values. */ static const struct { diff --git a/sys/dev/usb/wlan/if_urtwnvar.h b/sys/dev/usb/wlan/if_urtwnvar.h new file mode 100644 index 0000000..5186b38 --- /dev/null +++ b/sys/dev/usb/wlan/if_urtwnvar.h @@ -0,0 +1,203 @@ +/*- + * Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $OpenBSD: if_urtwnreg.h,v 1.3 2010/11/16 18:02:59 damien Exp $ + * $FreeBSD$ + */ + +#define URTWN_RX_LIST_COUNT 1 +#define URTWN_TX_LIST_COUNT 8 +#define URTWN_HOST_CMD_RING_COUNT 32 + +#define URTWN_RXBUFSZ (16 * 1024) +#define URTWN_TXBUFSZ (sizeof(struct r92c_tx_desc) + IEEE80211_MAX_LEN) +#define URTWN_RX_DESC_SIZE (sizeof(struct r92c_rx_stat)) +#define URTWN_TX_DESC_SIZE (sizeof(struct r92c_tx_desc)) + +#define URTWN_RIDX_COUNT 28 + +#define URTWN_TX_TIMEOUT 5000 /* ms */ + +#define URTWN_LED_LINK 0 +#define URTWN_LED_DATA 1 + +struct urtwn_rx_radiotap_header { + struct ieee80211_radiotap_header wr_ihdr; + uint8_t wr_flags; + uint8_t wr_rate; + uint16_t wr_chan_freq; + uint16_t wr_chan_flags; + uint8_t wr_dbm_antsignal; +} __packed __aligned(8); + +#define URTWN_RX_RADIOTAP_PRESENT \ + (1 << IEEE80211_RADIOTAP_FLAGS | \ + 1 << IEEE80211_RADIOTAP_RATE | \ + 1 << IEEE80211_RADIOTAP_CHANNEL | \ + 1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL) + +struct urtwn_tx_radiotap_header { + struct ieee80211_radiotap_header wt_ihdr; + uint8_t wt_flags; + uint16_t wt_chan_freq; + uint16_t wt_chan_flags; +} __packed __aligned(8); + +#define URTWN_TX_RADIOTAP_PRESENT \ + (1 << IEEE80211_RADIOTAP_FLAGS | \ + 1 << IEEE80211_RADIOTAP_CHANNEL) + +struct urtwn_softc; + +struct urtwn_data { + struct urtwn_softc *sc; + uint8_t *buf; + uint16_t buflen; + struct mbuf *m; + struct ieee80211_node *ni; + STAILQ_ENTRY(urtwn_data) next; +}; +typedef STAILQ_HEAD(, urtwn_data) urtwn_datahead; + +struct urtwn_cmdq { + void *arg0; + void *arg1; + void (*func)(void *); + struct ieee80211_key *k; + struct ieee80211_key key; + uint8_t mac[IEEE80211_ADDR_LEN]; + uint8_t wcid; +}; + +struct urtwn_fw_info { + const uint8_t *data; + size_t size; +}; + +struct urtwn_vap { + struct ieee80211vap vap; + + int (*newstate)(struct ieee80211vap *, + enum ieee80211_state, int); +}; +#define URTWN_VAP(vap) ((struct urtwn_vap *)(vap)) + +struct urtwn_host_cmd { + void (*cb)(struct urtwn_softc *, void *); + uint8_t data[256]; +}; + +struct urtwn_cmd_newstate { + enum ieee80211_state state; + int arg; +}; + +struct urtwn_cmd_key { + struct ieee80211_key key; + uint16_t associd; +}; + +enum { + URTWN_BULK_RX, + URTWN_BULK_TX_BE, /* = WME_AC_BE */ + URTWN_BULK_TX_BK, /* = WME_AC_BK */ + URTWN_BULK_TX_VI, /* = WME_AC_VI */ + URTWN_BULK_TX_VO, /* = WME_AC_VI */ + URTWN_N_TRANSFER = 5, +}; + +#define URTWN_EP_QUEUES URTWN_BULK_RX + +struct urtwn_softc { + struct ieee80211com sc_ic; + struct mbufq sc_snd; + device_t sc_dev; + struct usb_device *sc_udev; + + int ac2idx[WME_NUM_AC]; + u_int sc_flags; +#define URTWN_FLAG_CCK_HIPWR 0x01 +#define URTWN_DETACHED 0x02 +#define URTWN_RUNNING 0x04 + + u_int chip; +#define URTWN_CHIP_92C 0x01 +#define URTWN_CHIP_92C_1T2R 0x02 +#define URTWN_CHIP_UMC 0x04 +#define URTWN_CHIP_UMC_A_CUT 0x08 +#define URTWN_CHIP_88E 0x10 + + void (*sc_rf_write)(struct urtwn_softc *, + int, uint8_t, uint32_t); + int (*sc_power_on)(struct urtwn_softc *); + int (*sc_dma_init)(struct urtwn_softc *); + + uint8_t board_type; + uint8_t regulatory; + uint8_t pa_setting; + int avg_pwdb; + int thcal_state; + int thcal_lctemp; + int ntxchains; + int nrxchains; + int ledlink; + int sc_txtimer; + + int fwcur; + struct urtwn_data sc_rx[URTWN_RX_LIST_COUNT]; + urtwn_datahead sc_rx_active; + urtwn_datahead sc_rx_inactive; + struct urtwn_data sc_tx[URTWN_TX_LIST_COUNT]; + urtwn_datahead sc_tx_active; + urtwn_datahead sc_tx_inactive; + urtwn_datahead sc_tx_pending; + + const char *fwname; + const struct firmware *fw_fp; + struct urtwn_fw_info fw; + void *fw_virtaddr; + + struct r92c_rom rom; + uint8_t r88e_rom[512]; + uint8_t cck_tx_pwr[6]; + uint8_t ht40_tx_pwr[5]; + int8_t bw20_tx_pwr_diff; + int8_t ofdm_tx_pwr_diff; + + struct callout sc_watchdog_ch; + struct mtx sc_mtx; + +/* need to be power of 2, otherwise URTWN_CMDQ_GET fails */ +#define URTWN_CMDQ_MAX 16 +#define URTWN_CMDQ_MASQ (URTWN_CMDQ_MAX - 1) + struct urtwn_cmdq cmdq[URTWN_CMDQ_MAX]; + struct task cmdq_task; + uint32_t cmdq_store; + uint8_t cmdq_exec; + uint8_t cmdq_run; + uint8_t cmdq_key_set; +#define URTWN_CMDQ_ABORT 0 +#define URTWN_CMDQ_GO 1 + + uint32_t rf_chnlbw[R92C_MAX_CHAINS]; + struct usb_xfer *sc_xfer[URTWN_N_TRANSFER]; + + struct urtwn_rx_radiotap_header sc_rxtap; + struct urtwn_tx_radiotap_header sc_txtap; +}; + +#define URTWN_LOCK(sc) mtx_lock(&(sc)->sc_mtx) +#define URTWN_UNLOCK(sc) mtx_unlock(&(sc)->sc_mtx) +#define URTWN_ASSERT_LOCKED(sc) mtx_assert(&(sc)->sc_mtx, MA_OWNED) diff --git a/sys/dev/usb/wlan/if_urtwvar.h b/sys/dev/usb/wlan/if_urtwvar.h index a423214..08ffc8f 100644 --- a/sys/dev/usb/wlan/if_urtwvar.h +++ b/sys/dev/usb/wlan/if_urtwvar.h @@ -178,9 +178,7 @@ struct urtw_softc { struct urtw_stats sc_stats; struct urtw_rx_radiotap_header sc_rxtap; - int sc_rxtap_len; struct urtw_tx_radiotap_header sc_txtap; - int sc_txtap_len; }; #define URTW_LOCK(sc) mtx_lock(&(sc)->sc_mtx) diff --git a/sys/dev/usb/wlan/if_zyd.c b/sys/dev/usb/wlan/if_zyd.c index ed70d19..dc7a87f 100644 --- a/sys/dev/usb/wlan/if_zyd.c +++ b/sys/dev/usb/wlan/if_zyd.c @@ -2590,13 +2590,11 @@ zyd_raw_xmit(struct ieee80211_node *ni, struct mbuf *m, if (!(sc->sc_flags & ZYD_FLAG_RUNNING)) { ZYD_UNLOCK(sc); m_freem(m); - ieee80211_free_node(ni); return (ENETDOWN); } if (sc->tx_nfree == 0) { ZYD_UNLOCK(sc); m_freem(m); - ieee80211_free_node(ni); return (ENOBUFS); /* XXX */ } @@ -2607,7 +2605,6 @@ zyd_raw_xmit(struct ieee80211_node *ni, struct mbuf *m, */ if (zyd_tx_start(sc, m, ni) != 0) { ZYD_UNLOCK(sc); - ieee80211_free_node(ni); m_freem(m); return (EIO); } diff --git a/sys/dev/usb/wlan/if_zydreg.h b/sys/dev/usb/wlan/if_zydreg.h index ec61d06..86c7ff3 100644 --- a/sys/dev/usb/wlan/if_zydreg.h +++ b/sys/dev/usb/wlan/if_zydreg.h @@ -1304,9 +1304,7 @@ struct zyd_softc { struct zyd_cmd sc_ibuf; struct zyd_rx_radiotap_header sc_rxtap; - int sc_rxtap_len; struct zyd_tx_radiotap_header sc_txtap; - int sc_txtap_len; }; #define ZYD_LOCK(sc) mtx_lock(&(sc)->sc_mtx) diff --git a/sys/dev/wi/if_wi.c b/sys/dev/wi/if_wi.c index f8af231..832e6aa 100644 --- a/sys/dev/wi/if_wi.c +++ b/sys/dev/wi/if_wi.c @@ -1077,6 +1077,7 @@ wi_raw_xmit(struct ieee80211_node *ni, struct mbuf *m0, goto out; } m0 = NULL; + ieee80211_free_node(ni); sc->sc_txnext = cur = (cur + 1) % sc->sc_ntxbuf; out: @@ -1084,7 +1085,6 @@ out: if (m0 != NULL) m_freem(m0); - ieee80211_free_node(ni); return rc; } diff --git a/sys/dev/wpi/if_wpi.c b/sys/dev/wpi/if_wpi.c index dfd6424..7932bce 100644 --- a/sys/dev/wpi/if_wpi.c +++ b/sys/dev/wpi/if_wpi.c @@ -196,6 +196,7 @@ static void wpi_debug_registers(struct wpi_softc *); #endif static void wpi_fatal_intr(struct wpi_softc *); static void wpi_intr(void *); +static void wpi_free_txfrags(struct wpi_softc *, uint16_t); static int wpi_cmd2(struct wpi_softc *, struct wpi_buf *); static int wpi_tx_data(struct wpi_softc *, struct mbuf *, struct ieee80211_node *); @@ -458,6 +459,7 @@ wpi_attach(device_t dev) | IEEE80211_C_MONITOR /* monitor mode supported */ | IEEE80211_C_AHDEMO /* adhoc demo mode */ | IEEE80211_C_BGSCAN /* capable of bg scanning */ + | IEEE80211_C_TXFRAG /* handle tx frags */ | IEEE80211_C_TXPMGT /* tx power management */ | IEEE80211_C_SHSLOT /* short slot time supported */ | IEEE80211_C_WPA /* 802.11i */ @@ -1168,6 +1170,7 @@ wpi_alloc_tx_ring(struct wpi_softc *sc, struct wpi_tx_ring *ring, uint8_t qid) ring->qid = qid; ring->queued = 0; ring->cur = 0; + ring->pending = 0; ring->update = 0; DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_BEGIN, __func__); @@ -1288,6 +1291,7 @@ wpi_reset_tx_ring(struct wpi_softc *sc, struct wpi_tx_ring *ring) BUS_DMASYNC_PREWRITE); ring->queued = 0; ring->cur = 0; + ring->pending = 0; ring->update = 0; } @@ -2572,6 +2576,34 @@ done: end: WPI_UNLOCK(sc); } +static void +wpi_free_txfrags(struct wpi_softc *sc, uint16_t ac) +{ + struct wpi_tx_ring *ring; + struct wpi_tx_data *data; + uint8_t cur; + + WPI_TXQ_LOCK(sc); + ring = &sc->txq[ac]; + + while (ring->pending != 0) { + ring->pending--; + cur = (ring->cur + ring->pending) % WPI_TX_RING_COUNT; + data = &ring->data[cur]; + + bus_dmamap_sync(ring->data_dmat, data->map, + BUS_DMASYNC_POSTWRITE); + bus_dmamap_unload(ring->data_dmat, data->map); + m_freem(data->m); + data->m = NULL; + + ieee80211_node_decref(data->ni); + data->ni = NULL; + } + + WPI_TXQ_UNLOCK(sc); +} + static int wpi_cmd2(struct wpi_softc *sc, struct wpi_buf *buf) { @@ -2582,9 +2614,9 @@ wpi_cmd2(struct wpi_softc *sc, struct wpi_buf *buf) struct wpi_tx_ring *ring; struct mbuf *m1; bus_dma_segment_t *seg, segs[WPI_MAX_SCATTER]; - uint8_t pad; + uint8_t cur, pad; uint16_t hdrlen; - int error, i, nsegs, totlen; + int error, i, nsegs, totlen, frag; WPI_TXQ_LOCK(sc); @@ -2601,6 +2633,7 @@ wpi_cmd2(struct wpi_softc *sc, struct wpi_buf *buf) wh = mtod(buf->m, struct ieee80211_frame *); hdrlen = ieee80211_anyhdrsize(wh); totlen = buf->m->m_pkthdr.len; + frag = ((buf->m->m_flags & (M_FRAG | M_LASTFRAG)) == M_FRAG); if (__predict_false(totlen < sizeof(struct ieee80211_frame_min))) { error = EINVAL; @@ -2614,15 +2647,16 @@ wpi_cmd2(struct wpi_softc *sc, struct wpi_buf *buf) pad = 0; ring = &sc->txq[buf->ac]; - desc = &ring->desc[ring->cur]; - data = &ring->data[ring->cur]; + cur = (ring->cur + ring->pending) % WPI_TX_RING_COUNT; + desc = &ring->desc[cur]; + data = &ring->data[cur]; /* Prepare TX firmware command. */ - cmd = &ring->cmd[ring->cur]; + cmd = &ring->cmd[cur]; cmd->code = buf->code; cmd->flags = 0; cmd->qid = ring->qid; - cmd->idx = ring->cur; + cmd->idx = cur; memcpy(cmd->data, buf->data, buf->size); @@ -2662,7 +2696,8 @@ wpi_cmd2(struct wpi_softc *sc, struct wpi_buf *buf) if (ring->qid < WPI_CMD_QUEUE_NUM) { if_inc_counter(buf->ni->ni_vap->iv_ifp, IFCOUNTER_OERRORS, 1); - ieee80211_free_node(buf->ni); + if (!frag) + ieee80211_free_node(buf->ni); } m_freem(buf->m); error = 0; @@ -2678,7 +2713,7 @@ wpi_cmd2(struct wpi_softc *sc, struct wpi_buf *buf) data->ni = buf->ni; DPRINTF(sc, WPI_DEBUG_XMIT, "%s: qid %d idx %d len %d nsegs %d\n", - __func__, ring->qid, ring->cur, totlen, nsegs); + __func__, ring->qid, cur, totlen, nsegs); /* Fill TX descriptor. */ desc->nsegs = WPI_PAD32(totlen + pad) << 4 | (1 + nsegs); @@ -2699,16 +2734,23 @@ wpi_cmd2(struct wpi_softc *sc, struct wpi_buf *buf) bus_dmamap_sync(ring->desc_dma.tag, ring->desc_dma.map, BUS_DMASYNC_PREWRITE); - /* Kick TX ring. */ - ring->cur = (ring->cur + 1) % WPI_TX_RING_COUNT; - sc->sc_update_tx_ring(sc, ring); + ring->pending += 1; - if (ring->qid < WPI_CMD_QUEUE_NUM) { - WPI_TXQ_STATE_LOCK(sc); - ring->queued++; - callout_reset(&sc->tx_timeout, 5*hz, wpi_tx_timeout, sc); - WPI_TXQ_STATE_UNLOCK(sc); - } + if (!frag) { + if (ring->qid < WPI_CMD_QUEUE_NUM) { + WPI_TXQ_STATE_LOCK(sc); + ring->queued += ring->pending; + callout_reset(&sc->tx_timeout, 5*hz, wpi_tx_timeout, + sc); + WPI_TXQ_STATE_UNLOCK(sc); + } + + /* Kick TX ring. */ + ring->cur = (ring->cur + ring->pending) % WPI_TX_RING_COUNT; + ring->pending = 0; + sc->sc_update_tx_ring(sc, ring); + } else + ieee80211_node_incref(data->ni); end: DPRINTF(sc, WPI_DEBUG_TRACE, error ? TRACE_STR_END_ERR : TRACE_STR_END, __func__); @@ -2793,6 +2835,8 @@ wpi_tx_data(struct wpi_softc *sc, struct mbuf *m, struct ieee80211_node *ni) tap->wt_rate = rate; if (k != NULL) tap->wt_flags |= IEEE80211_RADIOTAP_F_WEP; + if (wh->i_fc[1] & IEEE80211_FC1_MORE_FRAG) + tap->wt_flags |= IEEE80211_RADIOTAP_F_FRAG; ieee80211_radiotap_tx(vap, m); } @@ -2808,7 +2852,7 @@ wpi_tx_data(struct wpi_softc *sc, struct mbuf *m, struct ieee80211_node *ni) if (!IEEE80211_QOS_HAS_SEQ(wh)) flags |= WPI_TX_AUTO_SEQ; if (wh->i_fc[1] & IEEE80211_FC1_MORE_FRAG) - flags |= WPI_TX_MORE_FRAG; /* Cannot happen yet. */ + flags |= WPI_TX_MORE_FRAG; /* Check if frame must be protected using RTS/CTS or CTS-to-self. */ if (!ismcast) { @@ -2866,6 +2910,15 @@ wpi_tx_data(struct wpi_softc *sc, struct mbuf *m, struct ieee80211_node *ni) memcpy(tx->key, k->wk_key, k->wk_keylen); } + if (wh->i_fc[1] & IEEE80211_FC1_MORE_FRAG) { + struct mbuf *next = m->m_nextpkt; + + tx->lnext = htole16(next->m_pkthdr.len); + tx->fnext = htole32(tx->security | + (flags & WPI_TX_NEED_ACK) | + WPI_NEXT_STA_ID(tx->id)); + } + tx->len = htole16(totlen); tx->flags = htole32(flags); tx->plcp = rate2plcp(rate); @@ -2989,13 +3042,13 @@ wpi_tx_data_raw(struct wpi_softc *sc, struct mbuf *m, } static __inline int -wpi_tx_ring_is_full(struct wpi_softc *sc, uint16_t ac) +wpi_tx_ring_free_space(struct wpi_softc *sc, uint16_t ac) { struct wpi_tx_ring *ring = &sc->txq[ac]; int retval; WPI_TXQ_STATE_LOCK(sc); - retval = (ring->queued > WPI_TX_RING_HIMARK); + retval = WPI_TX_RING_HIMARK - ring->queued; WPI_TXQ_STATE_UNLOCK(sc); return retval; @@ -3016,7 +3069,8 @@ wpi_raw_xmit(struct ieee80211_node *ni, struct mbuf *m, WPI_TX_LOCK(sc); - if (sc->sc_running == 0 || wpi_tx_ring_is_full(sc, ac)) { + /* NB: no fragments here */ + if (sc->sc_running == 0 || wpi_tx_ring_free_space(sc, ac) < 1) { error = sc->sc_running ? ENOBUFS : ENETDOWN; goto unlock; } @@ -3039,7 +3093,6 @@ unlock: WPI_TX_UNLOCK(sc); if (error != 0) { m_freem(m); - ieee80211_free_node(ni); DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_END_ERR, __func__); return error; @@ -3055,8 +3108,9 @@ wpi_transmit(struct ieee80211com *ic, struct mbuf *m) { struct wpi_softc *sc = ic->ic_softc; struct ieee80211_node *ni; + struct mbuf *mnext; uint16_t ac; - int error; + int error, nmbufs; WPI_TX_LOCK(sc); DPRINTF(sc, WPI_DEBUG_XMIT, "%s: called\n", __func__); @@ -3067,20 +3121,30 @@ wpi_transmit(struct ieee80211com *ic, struct mbuf *m) goto unlock; } + nmbufs = 1; + for (mnext = m->m_nextpkt; mnext != NULL; mnext = mnext->m_nextpkt) + nmbufs++; + /* Check for available space. */ ac = M_WME_GETAC(m); - if (wpi_tx_ring_is_full(sc, ac)) { + if (wpi_tx_ring_free_space(sc, ac) < nmbufs) { error = ENOBUFS; goto unlock; } error = 0; ni = (struct ieee80211_node *)m->m_pkthdr.rcvif; - if (wpi_tx_data(sc, m, ni) != 0) { - if_inc_counter(ni->ni_vap->iv_ifp, IFCOUNTER_OERRORS, 1); - ieee80211_free_node(ni); - m_freem(m); - } + do { + mnext = m->m_nextpkt; + if (wpi_tx_data(sc, m, ni) != 0) { + if_inc_counter(ni->ni_vap->iv_ifp, IFCOUNTER_OERRORS, + nmbufs); + wpi_free_txfrags(sc, ac); + ieee80211_free_mbuf(m); + ieee80211_free_node(ni); + break; + } + } while((m = mnext) != NULL); DPRINTF(sc, WPI_DEBUG_XMIT, "%s: done\n", __func__); diff --git a/sys/dev/wpi/if_wpireg.h b/sys/dev/wpi/if_wpireg.h index f36dd25..b0154f2 100644 --- a/sys/dev/wpi/if_wpireg.h +++ b/sys/dev/wpi/if_wpireg.h @@ -520,6 +520,8 @@ struct wpi_cmd_data { uint8_t key[IEEE80211_KEYBUF_SIZE]; uint8_t tkip[IEEE80211_WEP_MICLEN]; uint32_t fnext; +#define WPI_NEXT_STA_ID(id) ((id) << 8) + uint32_t lifetime; #define WPI_LIFETIME_INFINITE 0xffffffff diff --git a/sys/dev/wpi/if_wpivar.h b/sys/dev/wpi/if_wpivar.h index fb566b5..1957740 100644 --- a/sys/dev/wpi/if_wpivar.h +++ b/sys/dev/wpi/if_wpivar.h @@ -74,6 +74,7 @@ struct wpi_tx_ring { bus_dma_tag_t data_dmat; uint8_t qid; uint8_t cur; + uint8_t pending; int16_t queued; int update:1; }; diff --git a/sys/modules/usb/urtwn/Makefile b/sys/modules/usb/urtwn/Makefile index d965294..656fab9 100644 --- a/sys/modules/usb/urtwn/Makefile +++ b/sys/modules/usb/urtwn/Makefile @@ -3,7 +3,7 @@ .PATH: ${.CURDIR}/../../../dev/usb/wlan KMOD = if_urtwn -SRCS = if_urtwn.c if_urtwnreg.h \ +SRCS = if_urtwn.c if_urtwnreg.h if_urtwnvar.h \ bus_if.h device_if.h \ opt_bus.h opt_usb.h opt_wlan.h usb_if.h usbdevs.h diff --git a/sys/net80211/ieee80211_freebsd.c b/sys/net80211/ieee80211_freebsd.c index 6fdfb5c..7f2eae5 100644 --- a/sys/net80211/ieee80211_freebsd.c +++ b/sys/net80211/ieee80211_freebsd.c @@ -529,9 +529,6 @@ ieee80211_get_rx_params(struct mbuf *m, struct ieee80211_rx_stats *rxs) /* * Transmit a frame to the parent interface. - * - * TODO: if the transmission fails, make sure the parent node is freed - * (the callers will first need modifying.) */ int ieee80211_parent_xmitpkt(struct ieee80211com *ic, struct mbuf *m) @@ -544,8 +541,16 @@ ieee80211_parent_xmitpkt(struct ieee80211com *ic, struct mbuf *m) */ IEEE80211_TX_LOCK_ASSERT(ic); error = ic->ic_transmit(ic, m); - if (error) - m_freem(m); + if (error) { + struct ieee80211_node *ni; + + ni = (struct ieee80211_node *)m->m_pkthdr.rcvif; + + /* XXX number of fragments */ + if_inc_counter(ni->ni_vap->iv_ifp, IFCOUNTER_OERRORS, 1); + ieee80211_free_node(ni); + ieee80211_free_mbuf(m); + } return (error); } diff --git a/sys/net80211/ieee80211_hostap.c b/sys/net80211/ieee80211_hostap.c index ccb31ab..34d1b4e 100644 --- a/sys/net80211/ieee80211_hostap.c +++ b/sys/net80211/ieee80211_hostap.c @@ -2327,12 +2327,11 @@ ieee80211_recv_pspoll(struct ieee80211_node *ni, struct mbuf *m0) /* * Do the right thing; if it's an encap'ed frame then - * call ieee80211_parent_xmitpkt() (and free the ref) else + * call ieee80211_parent_xmitpkt() else * call ieee80211_vap_xmitpkt(). */ if (m->m_flags & M_ENCAP) { - if (ieee80211_parent_xmitpkt(ic, m) != 0) - ieee80211_free_node(ni); + (void) ieee80211_parent_xmitpkt(ic, m); } else { (void) ieee80211_vap_xmitpkt(vap, m); } diff --git a/sys/net80211/ieee80211_mesh.c b/sys/net80211/ieee80211_mesh.c index cb6ab81..1778c09 100644 --- a/sys/net80211/ieee80211_mesh.c +++ b/sys/net80211/ieee80211_mesh.c @@ -1239,12 +1239,8 @@ mesh_forward(struct ieee80211vap *vap, struct mbuf *m, IEEE80211_TX_LOCK(ic); err = ieee80211_parent_xmitpkt(ic, mcopy); IEEE80211_TX_UNLOCK(ic); - if (err != 0) { - /* NB: IFQ_HANDOFF reclaims mbuf */ - ieee80211_free_node(ni); - } else { + if (!err) if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1); - } } static struct mbuf * diff --git a/sys/net80211/ieee80211_output.c b/sys/net80211/ieee80211_output.c index 19af613..322491d 100644 --- a/sys/net80211/ieee80211_output.c +++ b/sys/net80211/ieee80211_output.c @@ -132,7 +132,7 @@ ieee80211_vap_pkt_send_dest(struct ieee80211vap *vap, struct mbuf *m, { struct ieee80211com *ic = vap->iv_ic; struct ifnet *ifp = vap->iv_ifp; - int error, len, mcast; + int len, mcast; if ((ni->ni_flags & IEEE80211_NODE_PWR_MGT) && (m->m_flags & M_PWR_SAV) == 0) { @@ -264,18 +264,13 @@ ieee80211_vap_pkt_send_dest(struct ieee80211vap *vap, struct mbuf *m, return (ENOBUFS); } } - error = ieee80211_parent_xmitpkt(ic, m); + (void) ieee80211_parent_xmitpkt(ic, m); /* * Unlock at this point - no need to hold it across * ieee80211_free_node() (ie, the comlock) */ IEEE80211_TX_UNLOCK(ic); - if (error != 0) { - /* NB: IFQ_HANDOFF reclaims mbuf */ - ieee80211_free_node(ni); - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); - } ic->ic_lastdata = ticks; return (0); @@ -536,8 +531,10 @@ ieee80211_raw_output(struct ieee80211vap *vap, struct ieee80211_node *ni, (void) ieee80211_add_xmit_params(m, params); error = ic->ic_raw_xmit(ni, m, params); - if (error) + if (error) { if_inc_counter(vap->iv_ifp, IFCOUNTER_OERRORS, 1); + ieee80211_free_node(ni); + } return (error); } @@ -1583,6 +1580,21 @@ bad: #undef MC01 } +void +ieee80211_free_mbuf(struct mbuf *m) +{ + struct mbuf *next; + + if (m == NULL) + return; + + do { + next = m->m_nextpkt; + m->m_nextpkt = NULL; + m_freem(m); + } while ((m = next) != NULL); +} + /* * Fragment the frame according to the specified mtu. * The size of the 802.11 header (w/o padding) is provided @@ -1597,7 +1609,7 @@ ieee80211_fragment(struct ieee80211vap *vap, struct mbuf *m0, { struct ieee80211com *ic = vap->iv_ic; struct ieee80211_frame *wh, *whf; - struct mbuf *m, *prev, *next; + struct mbuf *m, *prev; u_int totalhdrsize, fragno, fragsize, off, remainder, payload; u_int hdrspace; @@ -1692,11 +1704,7 @@ ieee80211_fragment(struct ieee80211vap *vap, struct mbuf *m0, return 1; bad: /* reclaim fragments but leave original frame for caller to free */ - for (m = m0->m_nextpkt; m != NULL; m = next) { - next = m->m_nextpkt; - m->m_nextpkt = NULL; /* XXX paranoid */ - m_freem(m); - } + ieee80211_free_mbuf(m0->m_nextpkt); m0->m_nextpkt = NULL; return 0; } diff --git a/sys/net80211/ieee80211_power.c b/sys/net80211/ieee80211_power.c index 2d216c2..73c1382 100644 --- a/sys/net80211/ieee80211_power.c +++ b/sys/net80211/ieee80211_power.c @@ -457,12 +457,7 @@ pwrsave_flushq(struct ieee80211_node *ni) KASSERT((m->m_flags & M_ENCAP), ("%s: parentq with non-M_ENCAP frame!\n", __func__)); - /* - * For encaped frames, we need to free the node - * reference upon failure. - */ - if (ieee80211_parent_xmitpkt(ic, m) != 0) - ieee80211_free_node(ni); + (void) ieee80211_parent_xmitpkt(ic, m); } /* VAP frames, aren't encapsulated */ diff --git a/sys/net80211/ieee80211_proto.h b/sys/net80211/ieee80211_proto.h index 4305863..38bd3d6 100644 --- a/sys/net80211/ieee80211_proto.h +++ b/sys/net80211/ieee80211_proto.h @@ -93,6 +93,7 @@ struct mbuf *ieee80211_mbuf_adjust(struct ieee80211vap *, int, struct ieee80211_key *, struct mbuf *); struct mbuf *ieee80211_encap(struct ieee80211vap *, struct ieee80211_node *, struct mbuf *); +void ieee80211_free_mbuf(struct mbuf *); int ieee80211_send_mgmt(struct ieee80211_node *, int, int); struct ieee80211_appie; int ieee80211_send_probereq(struct ieee80211_node *ni, diff --git a/sys/net80211/ieee80211_superg.c b/sys/net80211/ieee80211_superg.c index e91da01..8be098a 100644 --- a/sys/net80211/ieee80211_superg.c +++ b/sys/net80211/ieee80211_superg.c @@ -475,13 +475,9 @@ ff_transmit(struct ieee80211_node *ni, struct mbuf *m) if (m != NULL) { struct ifnet *ifp = vap->iv_ifp; - error = ieee80211_parent_xmitpkt(ic, m);; - if (error != 0) { - /* NB: IFQ_HANDOFF reclaims mbuf */ - ieee80211_free_node(ni); - } else { + error = ieee80211_parent_xmitpkt(ic, m); + if (!error) if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1); - } } else ieee80211_free_node(ni); } diff --git a/sys/net80211/ieee80211_wds.c b/sys/net80211/ieee80211_wds.c index 1d3f30a..a444b79 100644 --- a/sys/net80211/ieee80211_wds.c +++ b/sys/net80211/ieee80211_wds.c @@ -298,11 +298,7 @@ ieee80211_dwds_mcast(struct ieee80211vap *vap0, struct mbuf *m) mcopy->m_pkthdr.rcvif = (void *) ni; err = ieee80211_parent_xmitpkt(ic, mcopy); - if (err) { - /* NB: IFQ_HANDOFF reclaims mbuf */ - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); - ieee80211_free_node(ni); - } else { + if (!err) { if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1); if_inc_counter(ifp, IFCOUNTER_OMCASTS, 1); if_inc_counter(ifp, IFCOUNTER_OBYTES, |