updating to mainline 4.13.4

This commit is contained in:
Jake Day 2017-09-27 10:37:37 -04:00
parent 0bcdae08d9
commit e4647daec4
107 changed files with 1459 additions and 690 deletions

View file

@ -31,11 +31,13 @@ Setup
CONFIG_DEBUG_INFO_REDUCED off. If your architecture supports
CONFIG_FRAME_POINTER, keep it enabled.
- Install that kernel on the guest.
- Install that kernel on the guest, turn off KASLR if necessary by adding
"nokaslr" to the kernel command line.
Alternatively, QEMU allows to boot the kernel directly using -kernel,
-append, -initrd command line switches. This is generally only useful if
you do not depend on modules. See QEMU documentation for more details on
this mode.
this mode. In this case, you should build the kernel with
CONFIG_RANDOMIZE_BASE disabled if the architecture supports KASLR.
- Enable the gdb stub of QEMU/KVM, either

View file

@ -1,6 +1,6 @@
VERSION = 4
PATCHLEVEL = 13
SUBLEVEL = 3
SUBLEVEL = 4
EXTRAVERSION =
NAME = Fearless Coyote

View file

@ -92,6 +92,12 @@ ENTRY(EV_MachineCheck)
lr r0, [efa]
mov r1, sp
; hardware auto-disables MMU, re-enable it to allow kernel vaddr
; access for say stack unwinding of modules for crash dumps
lr r3, [ARC_REG_PID]
or r3, r3, MMU_ENABLE
sr r3, [ARC_REG_PID]
lsr r3, r2, 8
bmsk r3, r3, 7
brne r3, ECR_C_MCHK_DUP_TLB, 1f

View file

@ -908,9 +908,6 @@ void do_tlb_overlap_fault(unsigned long cause, unsigned long address,
local_irq_save(flags);
/* re-enable the MMU */
write_aux_reg(ARC_REG_PID, MMU_ENABLE | read_aux_reg(ARC_REG_PID));
/* loop thru all sets of TLB */
for (set = 0; set < mmu->sets; set++) {

View file

@ -47,14 +47,26 @@ union ieee754dp ieee754dp_fmax(union ieee754dp x, union ieee754dp y)
case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
return ieee754dp_nanxcpt(x);
/* numbers are preferred to NaNs */
/*
* Quiet NaN handling
*/
/*
* The case of both inputs quiet NaNs
*/
case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN):
return x;
/*
* The cases of exactly one input quiet NaN (numbers
* are here preferred as returned values to NaNs)
*/
case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):
case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN):
case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN):
return x;
case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN):
case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO):
case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM):
case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM):
@ -80,9 +92,7 @@ union ieee754dp ieee754dp_fmax(union ieee754dp x, union ieee754dp y)
return ys ? x : y;
case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
if (xs == ys)
return x;
return ieee754dp_zero(1);
return ieee754dp_zero(xs & ys);
case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
DPDNORMX;
@ -106,16 +116,32 @@ union ieee754dp ieee754dp_fmax(union ieee754dp x, union ieee754dp y)
else if (xs < ys)
return x;
/* Compare exponent */
if (xe > ye)
return x;
else if (xe < ye)
return y;
/* Signs of inputs are equal, let's compare exponents */
if (xs == 0) {
/* Inputs are both positive */
if (xe > ye)
return x;
else if (xe < ye)
return y;
} else {
/* Inputs are both negative */
if (xe > ye)
return y;
else if (xe < ye)
return x;
}
/* Compare mantissa */
/* Signs and exponents of inputs are equal, let's compare mantissas */
if (xs == 0) {
/* Inputs are both positive, with equal signs and exponents */
if (xm <= ym)
return y;
return x;
}
/* Inputs are both negative, with equal signs and exponents */
if (xm <= ym)
return y;
return x;
return x;
return y;
}
union ieee754dp ieee754dp_fmaxa(union ieee754dp x, union ieee754dp y)
@ -147,14 +173,26 @@ union ieee754dp ieee754dp_fmaxa(union ieee754dp x, union ieee754dp y)
case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
return ieee754dp_nanxcpt(x);
/* numbers are preferred to NaNs */
/*
* Quiet NaN handling
*/
/*
* The case of both inputs quiet NaNs
*/
case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN):
return x;
/*
* The cases of exactly one input quiet NaN (numbers
* are here preferred as returned values to NaNs)
*/
case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):
case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN):
case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN):
return x;
case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN):
case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO):
case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM):
case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM):
@ -164,6 +202,9 @@ union ieee754dp ieee754dp_fmaxa(union ieee754dp x, union ieee754dp y)
/*
* Infinity and zero handling
*/
case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF):
return ieee754dp_inf(xs & ys);
case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO):
case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM):
case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM):
@ -171,7 +212,6 @@ union ieee754dp ieee754dp_fmaxa(union ieee754dp x, union ieee754dp y)
case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO):
return x;
case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF):
case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF):
case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF):
case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF):
@ -180,9 +220,7 @@ union ieee754dp ieee754dp_fmaxa(union ieee754dp x, union ieee754dp y)
return y;
case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
if (xs == ys)
return x;
return ieee754dp_zero(1);
return ieee754dp_zero(xs & ys);
case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
DPDNORMX;
@ -207,7 +245,11 @@ union ieee754dp ieee754dp_fmaxa(union ieee754dp x, union ieee754dp y)
return y;
/* Compare mantissa */
if (xm <= ym)
if (xm < ym)
return y;
return x;
else if (xm > ym)
return x;
else if (xs == 0)
return x;
return y;
}

View file

@ -47,14 +47,26 @@ union ieee754dp ieee754dp_fmin(union ieee754dp x, union ieee754dp y)
case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
return ieee754dp_nanxcpt(x);
/* numbers are preferred to NaNs */
/*
* Quiet NaN handling
*/
/*
* The case of both inputs quiet NaNs
*/
case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN):
return x;
/*
* The cases of exactly one input quiet NaN (numbers
* are here preferred as returned values to NaNs)
*/
case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):
case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN):
case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN):
return x;
case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN):
case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO):
case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM):
case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM):
@ -80,9 +92,7 @@ union ieee754dp ieee754dp_fmin(union ieee754dp x, union ieee754dp y)
return ys ? y : x;
case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
if (xs == ys)
return x;
return ieee754dp_zero(1);
return ieee754dp_zero(xs | ys);
case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
DPDNORMX;
@ -106,16 +116,32 @@ union ieee754dp ieee754dp_fmin(union ieee754dp x, union ieee754dp y)
else if (xs < ys)
return y;
/* Compare exponent */
if (xe > ye)
return y;
else if (xe < ye)
return x;
/* Signs of inputs are the same, let's compare exponents */
if (xs == 0) {
/* Inputs are both positive */
if (xe > ye)
return y;
else if (xe < ye)
return x;
} else {
/* Inputs are both negative */
if (xe > ye)
return x;
else if (xe < ye)
return y;
}
/* Compare mantissa */
/* Signs and exponents of inputs are equal, let's compare mantissas */
if (xs == 0) {
/* Inputs are both positive, with equal signs and exponents */
if (xm <= ym)
return x;
return y;
}
/* Inputs are both negative, with equal signs and exponents */
if (xm <= ym)
return x;
return y;
return y;
return x;
}
union ieee754dp ieee754dp_fmina(union ieee754dp x, union ieee754dp y)
@ -147,14 +173,26 @@ union ieee754dp ieee754dp_fmina(union ieee754dp x, union ieee754dp y)
case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
return ieee754dp_nanxcpt(x);
/* numbers are preferred to NaNs */
/*
* Quiet NaN handling
*/
/*
* The case of both inputs quiet NaNs
*/
case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN):
return x;
/*
* The cases of exactly one input quiet NaN (numbers
* are here preferred as returned values to NaNs)
*/
case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):
case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN):
case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN):
return x;
case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN):
case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO):
case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM):
case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM):
@ -164,25 +202,25 @@ union ieee754dp ieee754dp_fmina(union ieee754dp x, union ieee754dp y)
/*
* Infinity and zero handling
*/
case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF):
return ieee754dp_inf(xs | ys);
case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO):
case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM):
case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM):
case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO):
case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO):
return x;
return y;
case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF):
case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF):
case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF):
case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF):
case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM):
case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM):
return y;
return x;
case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
if (xs == ys)
return x;
return ieee754dp_zero(1);
return ieee754dp_zero(xs | ys);
case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
DPDNORMX;
@ -207,7 +245,11 @@ union ieee754dp ieee754dp_fmina(union ieee754dp x, union ieee754dp y)
return x;
/* Compare mantissa */
if (xm <= ym)
if (xm < ym)
return x;
else if (xm > ym)
return y;
else if (xs == 1)
return x;
return y;
}

View file

@ -14,22 +14,45 @@
#include "ieee754dp.h"
enum maddf_flags {
maddf_negate_product = 1 << 0,
};
/* 128 bits shift right logical with rounding. */
void srl128(u64 *hptr, u64 *lptr, int count)
{
u64 low;
if (count >= 128) {
*lptr = *hptr != 0 || *lptr != 0;
*hptr = 0;
} else if (count >= 64) {
if (count == 64) {
*lptr = *hptr | (*lptr != 0);
} else {
low = *lptr;
*lptr = *hptr >> (count - 64);
*lptr |= (*hptr << (128 - count)) != 0 || low != 0;
}
*hptr = 0;
} else {
low = *lptr;
*lptr = low >> count | *hptr << (64 - count);
*lptr |= (low << (64 - count)) != 0;
*hptr = *hptr >> count;
}
}
static union ieee754dp _dp_maddf(union ieee754dp z, union ieee754dp x,
union ieee754dp y, enum maddf_flags flags)
{
int re;
int rs;
u64 rm;
unsigned lxm;
unsigned hxm;
unsigned lym;
unsigned hym;
u64 lrm;
u64 hrm;
u64 lzm;
u64 hzm;
u64 t;
u64 at;
int s;
@ -48,52 +71,34 @@ static union ieee754dp _dp_maddf(union ieee754dp z, union ieee754dp x,
ieee754_clearcx();
switch (zc) {
case IEEE754_CLASS_SNAN:
ieee754_setcx(IEEE754_INVALID_OPERATION);
/*
* Handle the cases when at least one of x, y or z is a NaN.
* Order of precedence is sNaN, qNaN and z, x, y.
*/
if (zc == IEEE754_CLASS_SNAN)
return ieee754dp_nanxcpt(z);
case IEEE754_CLASS_DNORM:
DPDNORMZ;
/* QNAN and ZERO cases are handled separately below */
}
switch (CLPAIR(xc, yc)) {
case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN):
case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN):
case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN):
case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN):
case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN):
return ieee754dp_nanxcpt(y);
case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN):
case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN):
case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO):
case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM):
case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM):
case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
if (xc == IEEE754_CLASS_SNAN)
return ieee754dp_nanxcpt(x);
case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):
case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN):
case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN):
if (yc == IEEE754_CLASS_SNAN)
return ieee754dp_nanxcpt(y);
if (zc == IEEE754_CLASS_QNAN)
return z;
if (xc == IEEE754_CLASS_QNAN)
return x;
if (yc == IEEE754_CLASS_QNAN)
return y;
case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN):
case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO):
case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM):
case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM):
case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_INF):
return x;
if (zc == IEEE754_CLASS_DNORM)
DPDNORMZ;
/* ZERO z cases are handled separately below */
switch (CLPAIR(xc, yc)) {
/*
* Infinity handling
*/
case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO):
case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF):
if (zc == IEEE754_CLASS_QNAN)
return z;
ieee754_setcx(IEEE754_INVALID_OPERATION);
return ieee754dp_indef();
@ -102,9 +107,27 @@ static union ieee754dp _dp_maddf(union ieee754dp z, union ieee754dp x,
case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM):
case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM):
case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF):
if (zc == IEEE754_CLASS_QNAN)
return z;
return ieee754dp_inf(xs ^ ys);
if ((zc == IEEE754_CLASS_INF) &&
((!(flags & MADDF_NEGATE_PRODUCT) && (zs != (xs ^ ys))) ||
((flags & MADDF_NEGATE_PRODUCT) && (zs == (xs ^ ys))))) {
/*
* Cases of addition of infinities with opposite signs
* or subtraction of infinities with same signs.
*/
ieee754_setcx(IEEE754_INVALID_OPERATION);
return ieee754dp_indef();
}
/*
* z is here either not an infinity, or an infinity having the
* same sign as product (x*y) (in case of MADDF.D instruction)
* or product -(x*y) (in MSUBF.D case). The result must be an
* infinity, and its sign is determined only by the value of
* (flags & MADDF_NEGATE_PRODUCT) and the signs of x and y.
*/
if (flags & MADDF_NEGATE_PRODUCT)
return ieee754dp_inf(1 ^ (xs ^ ys));
else
return ieee754dp_inf(xs ^ ys);
case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM):
@ -113,32 +136,42 @@ static union ieee754dp _dp_maddf(union ieee754dp z, union ieee754dp x,
case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO):
if (zc == IEEE754_CLASS_INF)
return ieee754dp_inf(zs);
/* Multiplication is 0 so just return z */
if (zc == IEEE754_CLASS_ZERO) {
/* Handle cases +0 + (-0) and similar ones. */
if ((!(flags & MADDF_NEGATE_PRODUCT)
&& (zs == (xs ^ ys))) ||
((flags & MADDF_NEGATE_PRODUCT)
&& (zs != (xs ^ ys))))
/*
* Cases of addition of zeros of equal signs
* or subtraction of zeroes of opposite signs.
* The sign of the resulting zero is in any
* such case determined only by the sign of z.
*/
return z;
return ieee754dp_zero(ieee754_csr.rm == FPU_CSR_RD);
}
/* x*y is here 0, and z is not 0, so just return z */
return z;
case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
DPDNORMX;
case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
if (zc == IEEE754_CLASS_QNAN)
return z;
else if (zc == IEEE754_CLASS_INF)
if (zc == IEEE754_CLASS_INF)
return ieee754dp_inf(zs);
DPDNORMY;
break;
case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM):
if (zc == IEEE754_CLASS_QNAN)
return z;
else if (zc == IEEE754_CLASS_INF)
if (zc == IEEE754_CLASS_INF)
return ieee754dp_inf(zs);
DPDNORMX;
break;
case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_NORM):
if (zc == IEEE754_CLASS_QNAN)
return z;
else if (zc == IEEE754_CLASS_INF)
if (zc == IEEE754_CLASS_INF)
return ieee754dp_inf(zs);
/* fall through to real computations */
}
@ -157,7 +190,7 @@ static union ieee754dp _dp_maddf(union ieee754dp z, union ieee754dp x,
re = xe + ye;
rs = xs ^ ys;
if (flags & maddf_negate_product)
if (flags & MADDF_NEGATE_PRODUCT)
rs ^= 1;
/* shunt to top of word */
@ -165,7 +198,7 @@ static union ieee754dp _dp_maddf(union ieee754dp z, union ieee754dp x,
ym <<= 64 - (DP_FBITS + 1);
/*
* Multiply 64 bits xm, ym to give high 64 bits rm with stickness.
* Multiply 64 bits xm and ym to give 128 bits result in hrm:lrm.
*/
/* 32 * 32 => 64 */
@ -195,81 +228,110 @@ static union ieee754dp _dp_maddf(union ieee754dp z, union ieee754dp x,
hrm = hrm + (t >> 32);
rm = hrm | (lrm != 0);
/*
* Sticky shift down to normal rounding precision.
*/
if ((s64) rm < 0) {
rm = (rm >> (64 - (DP_FBITS + 1 + 3))) |
((rm << (DP_FBITS + 1 + 3)) != 0);
/* Put explicit bit at bit 126 if necessary */
if ((int64_t)hrm < 0) {
lrm = (hrm << 63) | (lrm >> 1);
hrm = hrm >> 1;
re++;
} else {
rm = (rm >> (64 - (DP_FBITS + 1 + 3 + 1))) |
((rm << (DP_FBITS + 1 + 3 + 1)) != 0);
}
assert(rm & (DP_HIDDEN_BIT << 3));
if (zc == IEEE754_CLASS_ZERO)
return ieee754dp_format(rs, re, rm);
assert(hrm & (1 << 62));
/* And now the addition */
assert(zm & DP_HIDDEN_BIT);
if (zc == IEEE754_CLASS_ZERO) {
/*
* Move explicit bit from bit 126 to bit 55 since the
* ieee754dp_format code expects the mantissa to be
* 56 bits wide (53 + 3 rounding bits).
*/
srl128(&hrm, &lrm, (126 - 55));
return ieee754dp_format(rs, re, lrm);
}
/*
* Provide guard,round and stick bit space.
*/
zm <<= 3;
/* Move explicit bit from bit 52 to bit 126 */
lzm = 0;
hzm = zm << 10;
assert(hzm & (1 << 62));
/* Make the exponents the same */
if (ze > re) {
/*
* Have to shift y fraction right to align.
*/
s = ze - re;
rm = XDPSRS(rm, s);
srl128(&hrm, &lrm, s);
re += s;
} else if (re > ze) {
/*
* Have to shift x fraction right to align.
*/
s = re - ze;
zm = XDPSRS(zm, s);
srl128(&hzm, &lzm, s);
ze += s;
}
assert(ze == re);
assert(ze <= DP_EMAX);
/* Do the addition */
if (zs == rs) {
/*
* Generate 28 bit result of adding two 27 bit numbers
* leaving result in xm, xs and xe.
* Generate 128 bit result by adding two 127 bit numbers
* leaving result in hzm:lzm, zs and ze.
*/
zm = zm + rm;
if (zm >> (DP_FBITS + 1 + 3)) { /* carry out */
zm = XDPSRS1(zm);
hzm = hzm + hrm + (lzm > (lzm + lrm));
lzm = lzm + lrm;
if ((int64_t)hzm < 0) { /* carry out */
srl128(&hzm, &lzm, 1);
ze++;
}
} else {
if (zm >= rm) {
zm = zm - rm;
if (hzm > hrm || (hzm == hrm && lzm >= lrm)) {
hzm = hzm - hrm - (lzm < lrm);
lzm = lzm - lrm;
} else {
zm = rm - zm;
hzm = hrm - hzm - (lrm < lzm);
lzm = lrm - lzm;
zs = rs;
}
if (zm == 0)
if (lzm == 0 && hzm == 0)
return ieee754dp_zero(ieee754_csr.rm == FPU_CSR_RD);
/*
* Normalize to rounding precision.
* Put explicit bit at bit 126 if necessary.
*/
while ((zm >> (DP_FBITS + 3)) == 0) {
zm <<= 1;
ze--;
if (hzm == 0) {
/* left shift by 63 or 64 bits */
if ((int64_t)lzm < 0) {
/* MSB of lzm is the explicit bit */
hzm = lzm >> 1;
lzm = lzm << 63;
ze -= 63;
} else {
hzm = lzm;
lzm = 0;
ze -= 64;
}
}
t = 0;
while ((hzm >> (62 - t)) == 0)
t++;
assert(t <= 62);
if (t) {
hzm = hzm << t | lzm >> (64 - t);
lzm = lzm << t;
ze -= t;
}
}
return ieee754dp_format(zs, ze, zm);
/*
* Move explicit bit from bit 126 to bit 55 since the
* ieee754dp_format code expects the mantissa to be
* 56 bits wide (53 + 3 rounding bits).
*/
srl128(&hzm, &lzm, (126 - 55));
return ieee754dp_format(zs, ze, lzm);
}
union ieee754dp ieee754dp_maddf(union ieee754dp z, union ieee754dp x,
@ -281,5 +343,5 @@ union ieee754dp ieee754dp_maddf(union ieee754dp z, union ieee754dp x,
union ieee754dp ieee754dp_msubf(union ieee754dp z, union ieee754dp x,
union ieee754dp y)
{
return _dp_maddf(z, x, y, maddf_negate_product);
return _dp_maddf(z, x, y, MADDF_NEGATE_PRODUCT);
}

View file

@ -26,6 +26,10 @@
#define CLPAIR(x, y) ((x)*6+(y))
enum maddf_flags {
MADDF_NEGATE_PRODUCT = 1 << 0,
};
static inline void ieee754_clearcx(void)
{
ieee754_csr.cx = 0;

View file

@ -45,6 +45,10 @@ static inline int ieee754sp_finite(union ieee754sp x)
return SPBEXP(x) != SP_EMAX + 1 + SP_EBIAS;
}
/* 64 bit right shift with rounding */
#define XSPSRS64(v, rs) \
(((rs) >= 64) ? ((v) != 0) : ((v) >> (rs)) | ((v) << (64-(rs)) != 0))
/* 3bit extended single precision sticky right shift */
#define XSPSRS(v, rs) \
((rs > (SP_FBITS+3))?1:((v) >> (rs)) | ((v) << (32-(rs)) != 0))

View file

@ -47,14 +47,26 @@ union ieee754sp ieee754sp_fmax(union ieee754sp x, union ieee754sp y)
case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
return ieee754sp_nanxcpt(x);
/* numbers are preferred to NaNs */
/*
* Quiet NaN handling
*/
/*
* The case of both inputs quiet NaNs
*/
case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN):
return x;
/*
* The cases of exactly one input quiet NaN (numbers
* are here preferred as returned values to NaNs)
*/
case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):
case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN):
case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN):
return x;
case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN):
case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO):
case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM):
case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM):
@ -80,9 +92,7 @@ union ieee754sp ieee754sp_fmax(union ieee754sp x, union ieee754sp y)
return ys ? x : y;
case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
if (xs == ys)
return x;
return ieee754sp_zero(1);
return ieee754sp_zero(xs & ys);
case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
SPDNORMX;
@ -106,16 +116,32 @@ union ieee754sp ieee754sp_fmax(union ieee754sp x, union ieee754sp y)
else if (xs < ys)
return x;
/* Compare exponent */
if (xe > ye)
return x;
else if (xe < ye)
return y;
/* Signs of inputs are equal, let's compare exponents */
if (xs == 0) {
/* Inputs are both positive */
if (xe > ye)
return x;
else if (xe < ye)
return y;
} else {
/* Inputs are both negative */
if (xe > ye)
return y;
else if (xe < ye)
return x;
}
/* Compare mantissa */
/* Signs and exponents of inputs are equal, let's compare mantissas */
if (xs == 0) {
/* Inputs are both positive, with equal signs and exponents */
if (xm <= ym)
return y;
return x;
}
/* Inputs are both negative, with equal signs and exponents */
if (xm <= ym)
return y;
return x;
return x;
return y;
}
union ieee754sp ieee754sp_fmaxa(union ieee754sp x, union ieee754sp y)
@ -147,14 +173,26 @@ union ieee754sp ieee754sp_fmaxa(union ieee754sp x, union ieee754sp y)
case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
return ieee754sp_nanxcpt(x);
/* numbers are preferred to NaNs */
/*
* Quiet NaN handling
*/
/*
* The case of both inputs quiet NaNs
*/
case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN):
return x;
/*
* The cases of exactly one input quiet NaN (numbers
* are here preferred as returned values to NaNs)
*/
case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):
case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN):
case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN):
return x;
case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN):
case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO):
case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM):
case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM):
@ -164,6 +202,9 @@ union ieee754sp ieee754sp_fmaxa(union ieee754sp x, union ieee754sp y)
/*
* Infinity and zero handling
*/
case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF):
return ieee754sp_inf(xs & ys);
case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO):
case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM):
case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM):
@ -171,7 +212,6 @@ union ieee754sp ieee754sp_fmaxa(union ieee754sp x, union ieee754sp y)
case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO):
return x;
case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF):
case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF):
case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF):
case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF):
@ -180,9 +220,7 @@ union ieee754sp ieee754sp_fmaxa(union ieee754sp x, union ieee754sp y)
return y;
case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
if (xs == ys)
return x;
return ieee754sp_zero(1);
return ieee754sp_zero(xs & ys);
case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
SPDNORMX;
@ -207,7 +245,11 @@ union ieee754sp ieee754sp_fmaxa(union ieee754sp x, union ieee754sp y)
return y;
/* Compare mantissa */
if (xm <= ym)
if (xm < ym)
return y;
return x;
else if (xm > ym)
return x;
else if (xs == 0)
return x;
return y;
}

View file

@ -47,14 +47,26 @@ union ieee754sp ieee754sp_fmin(union ieee754sp x, union ieee754sp y)
case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
return ieee754sp_nanxcpt(x);
/* numbers are preferred to NaNs */
/*
* Quiet NaN handling
*/
/*
* The case of both inputs quiet NaNs
*/
case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN):
return x;
/*
* The cases of exactly one input quiet NaN (numbers
* are here preferred as returned values to NaNs)
*/
case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):
case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN):
case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN):
return x;
case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN):
case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO):
case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM):
case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM):
@ -80,9 +92,7 @@ union ieee754sp ieee754sp_fmin(union ieee754sp x, union ieee754sp y)
return ys ? y : x;
case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
if (xs == ys)
return x;
return ieee754sp_zero(1);
return ieee754sp_zero(xs | ys);
case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
SPDNORMX;
@ -106,16 +116,32 @@ union ieee754sp ieee754sp_fmin(union ieee754sp x, union ieee754sp y)
else if (xs < ys)
return y;
/* Compare exponent */
if (xe > ye)
return y;
else if (xe < ye)
return x;
/* Signs of inputs are the same, let's compare exponents */
if (xs == 0) {
/* Inputs are both positive */
if (xe > ye)
return y;
else if (xe < ye)
return x;
} else {
/* Inputs are both negative */
if (xe > ye)
return x;
else if (xe < ye)
return y;
}
/* Compare mantissa */
/* Signs and exponents of inputs are equal, let's compare mantissas */
if (xs == 0) {
/* Inputs are both positive, with equal signs and exponents */
if (xm <= ym)
return x;
return y;
}
/* Inputs are both negative, with equal signs and exponents */
if (xm <= ym)
return x;
return y;
return y;
return x;
}
union ieee754sp ieee754sp_fmina(union ieee754sp x, union ieee754sp y)
@ -147,14 +173,26 @@ union ieee754sp ieee754sp_fmina(union ieee754sp x, union ieee754sp y)
case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
return ieee754sp_nanxcpt(x);
/* numbers are preferred to NaNs */
/*
* Quiet NaN handling
*/
/*
* The case of both inputs quiet NaNs
*/
case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN):
return x;
/*
* The cases of exactly one input quiet NaN (numbers
* are here preferred as returned values to NaNs)
*/
case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):
case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN):
case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN):
return x;
case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN):
case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO):
case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM):
case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM):
@ -164,25 +202,25 @@ union ieee754sp ieee754sp_fmina(union ieee754sp x, union ieee754sp y)
/*
* Infinity and zero handling
*/
case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF):
return ieee754sp_inf(xs | ys);
case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO):
case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM):
case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM):
case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO):
case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO):
return x;
return y;
case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF):
case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF):
case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF):
case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF):
case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM):
case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM):
return y;
return x;
case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
if (xs == ys)
return x;
return ieee754sp_zero(1);
return ieee754sp_zero(xs | ys);
case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
SPDNORMX;
@ -207,7 +245,11 @@ union ieee754sp ieee754sp_fmina(union ieee754sp x, union ieee754sp y)
return x;
/* Compare mantissa */
if (xm <= ym)
if (xm < ym)
return x;
else if (xm > ym)
return y;
else if (xs == 1)
return x;
return y;
}

View file

@ -14,9 +14,6 @@
#include "ieee754sp.h"
enum maddf_flags {
maddf_negate_product = 1 << 0,
};
static union ieee754sp _sp_maddf(union ieee754sp z, union ieee754sp x,
union ieee754sp y, enum maddf_flags flags)
@ -24,14 +21,8 @@ static union ieee754sp _sp_maddf(union ieee754sp z, union ieee754sp x,
int re;
int rs;
unsigned rm;
unsigned short lxm;
unsigned short hxm;
unsigned short lym;
unsigned short hym;
unsigned lrm;
unsigned hrm;
unsigned t;
unsigned at;
uint64_t rm64;
uint64_t zm64;
int s;
COMPXSP;
@ -48,51 +39,35 @@ static union ieee754sp _sp_maddf(union ieee754sp z, union ieee754sp x,
ieee754_clearcx();
switch (zc) {
case IEEE754_CLASS_SNAN:
ieee754_setcx(IEEE754_INVALID_OPERATION);
/*
* Handle the cases when at least one of x, y or z is a NaN.
* Order of precedence is sNaN, qNaN and z, x, y.
*/
if (zc == IEEE754_CLASS_SNAN)
return ieee754sp_nanxcpt(z);
case IEEE754_CLASS_DNORM:
SPDNORMZ;
/* QNAN and ZERO cases are handled separately below */
}
switch (CLPAIR(xc, yc)) {
case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN):
case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN):
case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN):
case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN):
case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN):
return ieee754sp_nanxcpt(y);
case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN):
case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN):
case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO):
case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM):
case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM):
case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
if (xc == IEEE754_CLASS_SNAN)
return ieee754sp_nanxcpt(x);
case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):
case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN):
case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN):
if (yc == IEEE754_CLASS_SNAN)
return ieee754sp_nanxcpt(y);
if (zc == IEEE754_CLASS_QNAN)
return z;
if (xc == IEEE754_CLASS_QNAN)
return x;
if (yc == IEEE754_CLASS_QNAN)
return y;
case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN):
case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO):
case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM):
case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM):
case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_INF):
return x;
if (zc == IEEE754_CLASS_DNORM)
SPDNORMZ;
/* ZERO z cases are handled separately below */
switch (CLPAIR(xc, yc)) {
/*
* Infinity handling
*/
case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO):
case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF):
if (zc == IEEE754_CLASS_QNAN)
return z;
ieee754_setcx(IEEE754_INVALID_OPERATION);
return ieee754sp_indef();
@ -101,9 +76,27 @@ static union ieee754sp _sp_maddf(union ieee754sp z, union ieee754sp x,
case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM):
case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM):
case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF):
if (zc == IEEE754_CLASS_QNAN)
return z;
return ieee754sp_inf(xs ^ ys);
if ((zc == IEEE754_CLASS_INF) &&
((!(flags & MADDF_NEGATE_PRODUCT) && (zs != (xs ^ ys))) ||
((flags & MADDF_NEGATE_PRODUCT) && (zs == (xs ^ ys))))) {
/*
* Cases of addition of infinities with opposite signs
* or subtraction of infinities with same signs.
*/
ieee754_setcx(IEEE754_INVALID_OPERATION);
return ieee754sp_indef();
}
/*
* z is here either not an infinity, or an infinity having the
* same sign as product (x*y) (in case of MADDF.D instruction)
* or product -(x*y) (in MSUBF.D case). The result must be an
* infinity, and its sign is determined only by the value of
* (flags & MADDF_NEGATE_PRODUCT) and the signs of x and y.
*/
if (flags & MADDF_NEGATE_PRODUCT)
return ieee754sp_inf(1 ^ (xs ^ ys));
else
return ieee754sp_inf(xs ^ ys);
case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM):
@ -112,32 +105,42 @@ static union ieee754sp _sp_maddf(union ieee754sp z, union ieee754sp x,
case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO):
if (zc == IEEE754_CLASS_INF)
return ieee754sp_inf(zs);
/* Multiplication is 0 so just return z */
if (zc == IEEE754_CLASS_ZERO) {
/* Handle cases +0 + (-0) and similar ones. */
if ((!(flags & MADDF_NEGATE_PRODUCT)
&& (zs == (xs ^ ys))) ||
((flags & MADDF_NEGATE_PRODUCT)
&& (zs != (xs ^ ys))))
/*
* Cases of addition of zeros of equal signs
* or subtraction of zeroes of opposite signs.
* The sign of the resulting zero is in any
* such case determined only by the sign of z.
*/
return z;
return ieee754sp_zero(ieee754_csr.rm == FPU_CSR_RD);
}
/* x*y is here 0, and z is not 0, so just return z */
return z;
case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
SPDNORMX;
case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
if (zc == IEEE754_CLASS_QNAN)
return z;
else if (zc == IEEE754_CLASS_INF)
if (zc == IEEE754_CLASS_INF)
return ieee754sp_inf(zs);
SPDNORMY;
break;
case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM):
if (zc == IEEE754_CLASS_QNAN)
return z;
else if (zc == IEEE754_CLASS_INF)
if (zc == IEEE754_CLASS_INF)
return ieee754sp_inf(zs);
SPDNORMX;
break;
case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_NORM):
if (zc == IEEE754_CLASS_QNAN)
return z;
else if (zc == IEEE754_CLASS_INF)
if (zc == IEEE754_CLASS_INF)
return ieee754sp_inf(zs);
/* fall through to real computations */
}
@ -158,111 +161,93 @@ static union ieee754sp _sp_maddf(union ieee754sp z, union ieee754sp x,
re = xe + ye;
rs = xs ^ ys;
if (flags & maddf_negate_product)
if (flags & MADDF_NEGATE_PRODUCT)
rs ^= 1;
/* shunt to top of word */
xm <<= 32 - (SP_FBITS + 1);
ym <<= 32 - (SP_FBITS + 1);
/* Multiple 24 bit xm and ym to give 48 bit results */
rm64 = (uint64_t)xm * ym;
/*
* Multiply 32 bits xm, ym to give high 32 bits rm with stickness.
*/
lxm = xm & 0xffff;
hxm = xm >> 16;
lym = ym & 0xffff;
hym = ym >> 16;
/* Shunt to top of word */
rm64 = rm64 << 16;
lrm = lxm * lym; /* 16 * 16 => 32 */
hrm = hxm * hym; /* 16 * 16 => 32 */
t = lxm * hym; /* 16 * 16 => 32 */
at = lrm + (t << 16);
hrm += at < lrm;
lrm = at;
hrm = hrm + (t >> 16);
t = hxm * lym; /* 16 * 16 => 32 */
at = lrm + (t << 16);
hrm += at < lrm;
lrm = at;
hrm = hrm + (t >> 16);
rm = hrm | (lrm != 0);
/*
* Sticky shift down to normal rounding precision.
*/
if ((int) rm < 0) {
rm = (rm >> (32 - (SP_FBITS + 1 + 3))) |
((rm << (SP_FBITS + 1 + 3)) != 0);
/* Put explicit bit at bit 62 if necessary */
if ((int64_t) rm64 < 0) {
rm64 = rm64 >> 1;
re++;
} else {
rm = (rm >> (32 - (SP_FBITS + 1 + 3 + 1))) |
((rm << (SP_FBITS + 1 + 3 + 1)) != 0);
}
assert(rm & (SP_HIDDEN_BIT << 3));
if (zc == IEEE754_CLASS_ZERO)
assert(rm64 & (1 << 62));
if (zc == IEEE754_CLASS_ZERO) {
/*
* Move explicit bit from bit 62 to bit 26 since the
* ieee754sp_format code expects the mantissa to be
* 27 bits wide (24 + 3 rounding bits).
*/
rm = XSPSRS64(rm64, (62 - 26));
return ieee754sp_format(rs, re, rm);
}
/* And now the addition */
assert(zm & SP_HIDDEN_BIT);
/*
* Provide guard,round and stick bit space.
*/
zm <<= 3;
/* Move explicit bit from bit 23 to bit 62 */
zm64 = (uint64_t)zm << (62 - 23);
assert(zm64 & (1 << 62));
/* Make the exponents the same */
if (ze > re) {
/*
* Have to shift r fraction right to align.
*/
s = ze - re;
rm = XSPSRS(rm, s);
rm64 = XSPSRS64(rm64, s);
re += s;
} else if (re > ze) {
/*
* Have to shift z fraction right to align.
*/
s = re - ze;
zm = XSPSRS(zm, s);
zm64 = XSPSRS64(zm64, s);
ze += s;
}
assert(ze == re);
assert(ze <= SP_EMAX);
/* Do the addition */
if (zs == rs) {
/*
* Generate 28 bit result of adding two 27 bit numbers
* leaving result in zm, zs and ze.
* Generate 64 bit result by adding two 63 bit numbers
* leaving result in zm64, zs and ze.
*/
zm = zm + rm;
if (zm >> (SP_FBITS + 1 + 3)) { /* carry out */
zm = XSPSRS1(zm);
zm64 = zm64 + rm64;
if ((int64_t)zm64 < 0) { /* carry out */
zm64 = XSPSRS1(zm64);
ze++;
}
} else {
if (zm >= rm) {
zm = zm - rm;
if (zm64 >= rm64) {
zm64 = zm64 - rm64;
} else {
zm = rm - zm;
zm64 = rm64 - zm64;
zs = rs;
}
if (zm == 0)
if (zm64 == 0)
return ieee754sp_zero(ieee754_csr.rm == FPU_CSR_RD);
/*
* Normalize in extended single precision
* Put explicit bit at bit 62 if necessary.
*/
while ((zm >> (SP_MBITS + 3)) == 0) {
zm <<= 1;
while ((zm64 >> 62) == 0) {
zm64 <<= 1;
ze--;
}
}
/*
* Move explicit bit from bit 62 to bit 26 since the
* ieee754sp_format code expects the mantissa to be
* 27 bits wide (24 + 3 rounding bits).
*/
zm = XSPSRS64(zm64, (62 - 26));
return ieee754sp_format(zs, ze, zm);
}
@ -275,5 +260,5 @@ union ieee754sp ieee754sp_maddf(union ieee754sp z, union ieee754sp x,
union ieee754sp ieee754sp_msubf(union ieee754sp z, union ieee754sp x,
union ieee754sp y)
{
return _sp_maddf(z, x, y, maddf_negate_product);
return _sp_maddf(z, x, y, MADDF_NEGATE_PRODUCT);
}

View file

@ -235,6 +235,28 @@ static int emulate_dcbz(struct pt_regs *regs, unsigned char __user *addr)
#define SWIZ_PTR(p) ((unsigned char __user *)((p) ^ swiz))
#define __get_user_or_set_dar(_regs, _dest, _addr) \
({ \
int rc = 0; \
typeof(_addr) __addr = (_addr); \
if (__get_user_inatomic(_dest, __addr)) { \
_regs->dar = (unsigned long)__addr; \
rc = -EFAULT; \
} \
rc; \
})
#define __put_user_or_set_dar(_regs, _src, _addr) \
({ \
int rc = 0; \
typeof(_addr) __addr = (_addr); \
if (__put_user_inatomic(_src, __addr)) { \
_regs->dar = (unsigned long)__addr; \
rc = -EFAULT; \
} \
rc; \
})
static int emulate_multiple(struct pt_regs *regs, unsigned char __user *addr,
unsigned int reg, unsigned int nb,
unsigned int flags, unsigned int instr,
@ -263,9 +285,10 @@ static int emulate_multiple(struct pt_regs *regs, unsigned char __user *addr,
} else {
unsigned long pc = regs->nip ^ (swiz & 4);
if (__get_user_inatomic(instr,
(unsigned int __user *)pc))
if (__get_user_or_set_dar(regs, instr,
(unsigned int __user *)pc))
return -EFAULT;
if (swiz == 0 && (flags & SW))
instr = cpu_to_le32(instr);
nb = (instr >> 11) & 0x1f;
@ -309,31 +332,31 @@ static int emulate_multiple(struct pt_regs *regs, unsigned char __user *addr,
((nb0 + 3) / 4) * sizeof(unsigned long));
for (i = 0; i < nb; ++i, ++p)
if (__get_user_inatomic(REG_BYTE(rptr, i ^ bswiz),
SWIZ_PTR(p)))
if (__get_user_or_set_dar(regs, REG_BYTE(rptr, i ^ bswiz),
SWIZ_PTR(p)))
return -EFAULT;
if (nb0 > 0) {
rptr = &regs->gpr[0];
addr += nb;
for (i = 0; i < nb0; ++i, ++p)
if (__get_user_inatomic(REG_BYTE(rptr,
i ^ bswiz),
SWIZ_PTR(p)))
if (__get_user_or_set_dar(regs,
REG_BYTE(rptr, i ^ bswiz),
SWIZ_PTR(p)))
return -EFAULT;
}
} else {
for (i = 0; i < nb; ++i, ++p)
if (__put_user_inatomic(REG_BYTE(rptr, i ^ bswiz),
SWIZ_PTR(p)))
if (__put_user_or_set_dar(regs, REG_BYTE(rptr, i ^ bswiz),
SWIZ_PTR(p)))
return -EFAULT;
if (nb0 > 0) {
rptr = &regs->gpr[0];
addr += nb;
for (i = 0; i < nb0; ++i, ++p)
if (__put_user_inatomic(REG_BYTE(rptr,
i ^ bswiz),
SWIZ_PTR(p)))
if (__put_user_or_set_dar(regs,
REG_BYTE(rptr, i ^ bswiz),
SWIZ_PTR(p)))
return -EFAULT;
}
}
@ -345,29 +368,32 @@ static int emulate_multiple(struct pt_regs *regs, unsigned char __user *addr,
* Only POWER6 has these instructions, and it does true little-endian,
* so we don't need the address swizzling.
*/
static int emulate_fp_pair(unsigned char __user *addr, unsigned int reg,
unsigned int flags)
static int emulate_fp_pair(struct pt_regs *regs, unsigned char __user *addr,
unsigned int reg, unsigned int flags)
{
char *ptr0 = (char *) &current->thread.TS_FPR(reg);
char *ptr1 = (char *) &current->thread.TS_FPR(reg+1);
int i, ret, sw = 0;
int i, sw = 0;
if (reg & 1)
return 0; /* invalid form: FRS/FRT must be even */
if (flags & SW)
sw = 7;
ret = 0;
for (i = 0; i < 8; ++i) {
if (!(flags & ST)) {
ret |= __get_user(ptr0[i^sw], addr + i);
ret |= __get_user(ptr1[i^sw], addr + i + 8);
if (__get_user_or_set_dar(regs, ptr0[i^sw], addr + i))
return -EFAULT;
if (__get_user_or_set_dar(regs, ptr1[i^sw], addr + i + 8))
return -EFAULT;
} else {
ret |= __put_user(ptr0[i^sw], addr + i);
ret |= __put_user(ptr1[i^sw], addr + i + 8);
if (__put_user_or_set_dar(regs, ptr0[i^sw], addr + i))
return -EFAULT;
if (__put_user_or_set_dar(regs, ptr1[i^sw], addr + i + 8))
return -EFAULT;
}
}
if (ret)
return -EFAULT;
return 1; /* exception handled and fixed up */
}
@ -377,24 +403,27 @@ static int emulate_lq_stq(struct pt_regs *regs, unsigned char __user *addr,
{
char *ptr0 = (char *)&regs->gpr[reg];
char *ptr1 = (char *)&regs->gpr[reg+1];
int i, ret, sw = 0;
int i, sw = 0;
if (reg & 1)
return 0; /* invalid form: GPR must be even */
if (flags & SW)
sw = 7;
ret = 0;
for (i = 0; i < 8; ++i) {
if (!(flags & ST)) {
ret |= __get_user(ptr0[i^sw], addr + i);
ret |= __get_user(ptr1[i^sw], addr + i + 8);
if (__get_user_or_set_dar(regs, ptr0[i^sw], addr + i))
return -EFAULT;
if (__get_user_or_set_dar(regs, ptr1[i^sw], addr + i + 8))
return -EFAULT;
} else {
ret |= __put_user(ptr0[i^sw], addr + i);
ret |= __put_user(ptr1[i^sw], addr + i + 8);
if (__put_user_or_set_dar(regs, ptr0[i^sw], addr + i))
return -EFAULT;
if (__put_user_or_set_dar(regs, ptr1[i^sw], addr + i + 8))
return -EFAULT;
}
}
if (ret)
return -EFAULT;
return 1; /* exception handled and fixed up */
}
#endif /* CONFIG_PPC64 */
@ -687,9 +716,14 @@ static int emulate_vsx(unsigned char __user *addr, unsigned int reg,
for (j = 0; j < length; j += elsize) {
for (i = 0; i < elsize; ++i) {
if (flags & ST)
ret |= __put_user(ptr[i^sw], addr + i);
ret = __put_user_or_set_dar(regs, ptr[i^sw],
addr + i);
else
ret |= __get_user(ptr[i^sw], addr + i);
ret = __get_user_or_set_dar(regs, ptr[i^sw],
addr + i);
if (ret)
return ret;
}
ptr += elsize;
#ifdef __LITTLE_ENDIAN__
@ -739,7 +773,7 @@ int fix_alignment(struct pt_regs *regs)
unsigned int dsisr;
unsigned char __user *addr;
unsigned long p, swiz;
int ret, i;
int i;
union data {
u64 ll;
double dd;
@ -936,7 +970,7 @@ int fix_alignment(struct pt_regs *regs)
if (flags & F) {
/* Special case for 16-byte FP loads and stores */
PPC_WARN_ALIGNMENT(fp_pair, regs);
return emulate_fp_pair(addr, reg, flags);
return emulate_fp_pair(regs, addr, reg, flags);
} else {
#ifdef CONFIG_PPC64
/* Special case for 16-byte loads and stores */
@ -966,15 +1000,12 @@ int fix_alignment(struct pt_regs *regs)
}
data.ll = 0;
ret = 0;
p = (unsigned long)addr;
for (i = 0; i < nb; i++)
ret |= __get_user_inatomic(data.v[start + i],
SWIZ_PTR(p++));
if (unlikely(ret))
return -EFAULT;
if (__get_user_or_set_dar(regs, data.v[start + i],
SWIZ_PTR(p++)))
return -EFAULT;
} else if (flags & F) {
data.ll = current->thread.TS_FPR(reg);
@ -1046,15 +1077,13 @@ int fix_alignment(struct pt_regs *regs)
break;
}
ret = 0;
p = (unsigned long)addr;
for (i = 0; i < nb; i++)
ret |= __put_user_inatomic(data.v[start + i],
SWIZ_PTR(p++));
if (__put_user_or_set_dar(regs, data.v[start + i],
SWIZ_PTR(p++)))
return -EFAULT;
if (unlikely(ret))
return -EFAULT;
} else if (flags & F)
current->thread.TS_FPR(reg) = data.ll;
else

View file

@ -545,6 +545,12 @@ static void mmio_invalidate(struct npu_context *npu_context, int va,
struct mmio_atsd_reg mmio_atsd_reg[NV_MAX_NPUS];
unsigned long pid = npu_context->mm->context.id;
/*
* Unfortunately the nest mmu does not support flushing specific
* addresses so we have to flush the whole mm.
*/
flush_tlb_mm(npu_context->mm);
/*
* Loop over all the NPUs this process is active on and launch
* an invalidate.
@ -576,12 +582,6 @@ static void mmio_invalidate(struct npu_context *npu_context, int va,
}
}
/*
* Unfortunately the nest mmu does not support flushing specific
* addresses so we have to flush the whole mm.
*/
flush_tlb_mm(npu_context->mm);
mmio_invalidate_wait(mmio_atsd_reg, flush);
if (flush)
/* Wait for the flush to complete */

View file

@ -817,6 +817,9 @@ static int dlpar_memory_add_by_count(u32 lmbs_to_add, struct property *prop)
return -EINVAL;
for (i = 0; i < num_lmbs && lmbs_to_add != lmbs_added; i++) {
if (lmbs[i].flags & DRCONF_MEM_ASSIGNED)
continue;
rc = dlpar_acquire_drc(lmbs[i].drc_index);
if (rc)
continue;
@ -859,6 +862,7 @@ static int dlpar_memory_add_by_count(u32 lmbs_to_add, struct property *prop)
lmbs[i].base_addr, lmbs[i].drc_index);
lmbs[i].reserved = 0;
}
rc = 0;
}
return rc;

View file

@ -5,6 +5,7 @@
#include <linux/errno.h>
typedef struct {
spinlock_t lock;
cpumask_t cpu_attach_mask;
atomic_t flush_count;
unsigned int flush_mm;
@ -27,6 +28,7 @@ typedef struct {
} mm_context_t;
#define INIT_MM_CONTEXT(name) \
.context.lock = __SPIN_LOCK_UNLOCKED(name.context.lock), \
.context.pgtable_lock = \
__SPIN_LOCK_UNLOCKED(name.context.pgtable_lock), \
.context.pgtable_list = LIST_HEAD_INIT(name.context.pgtable_list), \

View file

@ -16,6 +16,7 @@
static inline int init_new_context(struct task_struct *tsk,
struct mm_struct *mm)
{
spin_lock_init(&mm->context.lock);
spin_lock_init(&mm->context.pgtable_lock);
INIT_LIST_HEAD(&mm->context.pgtable_list);
spin_lock_init(&mm->context.gmap_lock);
@ -102,7 +103,6 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
if (prev == next)
return;
cpumask_set_cpu(cpu, &next->context.cpu_attach_mask);
cpumask_set_cpu(cpu, mm_cpumask(next));
/* Clear old ASCE by loading the kernel ASCE. */
__ctl_load(S390_lowcore.kernel_asce, 1, 1);
__ctl_load(S390_lowcore.kernel_asce, 7, 7);
@ -120,9 +120,8 @@ static inline void finish_arch_post_lock_switch(void)
preempt_disable();
while (atomic_read(&mm->context.flush_count))
cpu_relax();
if (mm->context.flush_mm)
__tlb_flush_mm(mm);
cpumask_set_cpu(smp_processor_id(), mm_cpumask(mm));
__tlb_flush_mm_lazy(mm);
preempt_enable();
}
set_fs(current->thread.mm_segment);
@ -135,6 +134,7 @@ static inline void activate_mm(struct mm_struct *prev,
struct mm_struct *next)
{
switch_mm(prev, next, current);
cpumask_set_cpu(smp_processor_id(), mm_cpumask(next));
set_user_asce(next);
}

View file

@ -43,23 +43,6 @@ static inline void __tlb_flush_global(void)
* Flush TLB entries for a specific mm on all CPUs (in case gmap is used
* this implicates multiple ASCEs!).
*/
static inline void __tlb_flush_full(struct mm_struct *mm)
{
preempt_disable();
atomic_inc(&mm->context.flush_count);
if (cpumask_equal(mm_cpumask(mm), cpumask_of(smp_processor_id()))) {
/* Local TLB flush */
__tlb_flush_local();
} else {
/* Global TLB flush */
__tlb_flush_global();
/* Reset TLB flush mask */
cpumask_copy(mm_cpumask(mm), &mm->context.cpu_attach_mask);
}
atomic_dec(&mm->context.flush_count);
preempt_enable();
}
static inline void __tlb_flush_mm(struct mm_struct *mm)
{
unsigned long gmap_asce;
@ -71,16 +54,18 @@ static inline void __tlb_flush_mm(struct mm_struct *mm)
*/
preempt_disable();
atomic_inc(&mm->context.flush_count);
/* Reset TLB flush mask */
cpumask_copy(mm_cpumask(mm), &mm->context.cpu_attach_mask);
barrier();
gmap_asce = READ_ONCE(mm->context.gmap_asce);
if (MACHINE_HAS_IDTE && gmap_asce != -1UL) {
if (gmap_asce)
__tlb_flush_idte(gmap_asce);
__tlb_flush_idte(mm->context.asce);
} else {
__tlb_flush_full(mm);
/* Global TLB flush */
__tlb_flush_global();
}
/* Reset TLB flush mask */
cpumask_copy(mm_cpumask(mm), &mm->context.cpu_attach_mask);
atomic_dec(&mm->context.flush_count);
preempt_enable();
}
@ -94,7 +79,6 @@ static inline void __tlb_flush_kernel(void)
}
#else
#define __tlb_flush_global() __tlb_flush_local()
#define __tlb_flush_full(mm) __tlb_flush_local()
/*
* Flush TLB entries for a specific ASCE on all CPUs.
@ -112,10 +96,12 @@ static inline void __tlb_flush_kernel(void)
static inline void __tlb_flush_mm_lazy(struct mm_struct * mm)
{
spin_lock(&mm->context.lock);
if (mm->context.flush_mm) {
__tlb_flush_mm(mm);
mm->context.flush_mm = 0;
__tlb_flush_mm(mm);
}
spin_unlock(&mm->context.lock);
}
/*

View file

@ -280,7 +280,7 @@ EXPORT_SYMBOL(blk_start_queue_async);
void blk_start_queue(struct request_queue *q)
{
lockdep_assert_held(q->queue_lock);
WARN_ON(!irqs_disabled());
WARN_ON(!in_interrupt() && !irqs_disabled());
WARN_ON_ONCE(q->mq_ops);
queue_flag_clear(QUEUE_FLAG_STOPPED, q);
@ -2330,7 +2330,12 @@ blk_status_t blk_insert_cloned_request(struct request_queue *q, struct request *
if (q->mq_ops) {
if (blk_queue_io_stat(q))
blk_account_io_start(rq, true);
blk_mq_sched_insert_request(rq, false, true, false, false);
/*
* Since we have a scheduler attached on the top device,
* bypass a potential scheduler on the bottom device for
* insert.
*/
blk_mq_request_bypass_insert(rq);
return BLK_STS_OK;
}

View file

@ -1357,6 +1357,22 @@ void __blk_mq_insert_request(struct blk_mq_hw_ctx *hctx, struct request *rq,
blk_mq_hctx_mark_pending(hctx, ctx);
}
/*
* Should only be used carefully, when the caller knows we want to
* bypass a potential IO scheduler on the target device.
*/
void blk_mq_request_bypass_insert(struct request *rq)
{
struct blk_mq_ctx *ctx = rq->mq_ctx;
struct blk_mq_hw_ctx *hctx = blk_mq_map_queue(rq->q, ctx->cpu);
spin_lock(&hctx->lock);
list_add_tail(&rq->queuelist, &hctx->dispatch);
spin_unlock(&hctx->lock);
blk_mq_run_hw_queue(hctx, false);
}
void blk_mq_insert_requests(struct blk_mq_hw_ctx *hctx, struct blk_mq_ctx *ctx,
struct list_head *list)

View file

@ -54,6 +54,7 @@ int blk_mq_alloc_rqs(struct blk_mq_tag_set *set, struct blk_mq_tags *tags,
*/
void __blk_mq_insert_request(struct blk_mq_hw_ctx *hctx, struct request *rq,
bool at_head);
void blk_mq_request_bypass_insert(struct request *rq);
void blk_mq_insert_requests(struct blk_mq_hw_ctx *hctx, struct blk_mq_ctx *ctx,
struct list_head *list);

View file

@ -144,8 +144,10 @@ static int skcipher_alloc_sgl(struct sock *sk)
sg_init_table(sgl->sg, MAX_SGL_ENTS + 1);
sgl->cur = 0;
if (sg)
if (sg) {
sg_chain(sg, MAX_SGL_ENTS + 1, sgl->sg);
sg_unmark_end(sg + (MAX_SGL_ENTS - 1));
}
list_add_tail(&sgl->list, &ctx->tsgl);
}

View file

@ -211,9 +211,7 @@ static int scomp_acomp_comp_decomp(struct acomp_req *req, int dir)
scratch_dst, &req->dlen, *ctx);
if (!ret) {
if (!req->dst) {
req->dst = crypto_scomp_sg_alloc(req->dlen,
req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP ?
GFP_KERNEL : GFP_ATOMIC);
req->dst = crypto_scomp_sg_alloc(req->dlen, GFP_ATOMIC);
if (!req->dst)
goto out;
}

View file

@ -2160,6 +2160,9 @@ static void skd_send_fitmsg(struct skd_device *skdev,
*/
qcmd |= FIT_QCMD_MSGSIZE_64;
/* Make sure skd_msg_buf is written before the doorbell is triggered. */
smp_wmb();
SKD_WRITEQ(skdev, qcmd, FIT_Q_COMMAND);
}
@ -2202,6 +2205,9 @@ static void skd_send_special_fitmsg(struct skd_device *skdev,
qcmd = skspcl->mb_dma_address;
qcmd |= FIT_QCMD_QID_NORMAL + FIT_QCMD_MSGSIZE_128;
/* Make sure skd_msg_buf is written before the doorbell is triggered. */
smp_wmb();
SKD_WRITEQ(skdev, qcmd, FIT_Q_COMMAND);
}
@ -4539,15 +4545,16 @@ static void skd_free_disk(struct skd_device *skdev)
{
struct gendisk *disk = skdev->disk;
if (disk != NULL) {
struct request_queue *q = disk->queue;
if (disk && (disk->flags & GENHD_FL_UP))
del_gendisk(disk);
if (disk->flags & GENHD_FL_UP)
del_gendisk(disk);
if (q)
blk_cleanup_queue(q);
put_disk(disk);
if (skdev->queue) {
blk_cleanup_queue(skdev->queue);
skdev->queue = NULL;
disk->queue = NULL;
}
put_disk(disk);
skdev->disk = NULL;
}

View file

@ -776,9 +776,9 @@ static void ablkcipher_done(struct caam_drv_req *drv_req, u32 status)
struct crypto_ablkcipher *ablkcipher = crypto_ablkcipher_reqtfm(req);
struct caam_ctx *caam_ctx = crypto_ablkcipher_ctx(ablkcipher);
struct device *qidev = caam_ctx->qidev;
#ifdef DEBUG
int ivsize = crypto_ablkcipher_ivsize(ablkcipher);
#ifdef DEBUG
dev_err(qidev, "%s %d: status 0x%x\n", __func__, __LINE__, status);
#endif
@ -799,6 +799,13 @@ static void ablkcipher_done(struct caam_drv_req *drv_req, u32 status)
ablkcipher_unmap(qidev, edesc, req);
qi_cache_free(edesc);
/*
* The crypto API expects us to set the IV (req->info) to the last
* ciphertext block. This is used e.g. by the CTS mode.
*/
scatterwalk_map_and_copy(req->info, req->dst, req->nbytes - ivsize,
ivsize, 0);
ablkcipher_request_complete(req, status);
}
@ -1968,7 +1975,7 @@ static struct caam_aead_alg driver_aeads[] = {
.cra_name = "echainiv(authenc(hmac(sha256),"
"cbc(des)))",
.cra_driver_name = "echainiv-authenc-"
"hmac-sha256-cbc-desi-"
"hmac-sha256-cbc-des-"
"caam-qi",
.cra_blocksize = DES_BLOCK_SIZE,
},

View file

@ -1,8 +1,9 @@
/*
* AMD Cryptographic Coprocessor (CCP) AES XTS crypto API support
*
* Copyright (C) 2013 Advanced Micro Devices, Inc.
* Copyright (C) 2013,2017 Advanced Micro Devices, Inc.
*
* Author: Gary R Hook <gary.hook@amd.com>
* Author: Tom Lendacky <thomas.lendacky@amd.com>
*
* This program is free software; you can redistribute it and/or modify
@ -164,6 +165,7 @@ static int ccp_aes_xts_crypt(struct ablkcipher_request *req,
memset(&rctx->cmd, 0, sizeof(rctx->cmd));
INIT_LIST_HEAD(&rctx->cmd.entry);
rctx->cmd.engine = CCP_ENGINE_XTS_AES_128;
rctx->cmd.u.xts.type = CCP_AES_TYPE_128;
rctx->cmd.u.xts.action = (encrypt) ? CCP_AES_ACTION_ENCRYPT
: CCP_AES_ACTION_DECRYPT;
rctx->cmd.u.xts.unit_size = unit_size;

View file

@ -145,6 +145,7 @@ union ccp_function {
#define CCP_AES_MODE(p) ((p)->aes.mode)
#define CCP_AES_TYPE(p) ((p)->aes.type)
#define CCP_XTS_SIZE(p) ((p)->aes_xts.size)
#define CCP_XTS_TYPE(p) ((p)->aes_xts.type)
#define CCP_XTS_ENCRYPT(p) ((p)->aes_xts.encrypt)
#define CCP_DES3_SIZE(p) ((p)->des3.size)
#define CCP_DES3_ENCRYPT(p) ((p)->des3.encrypt)
@ -344,6 +345,7 @@ static int ccp5_perform_xts_aes(struct ccp_op *op)
CCP5_CMD_PROT(&desc) = 0;
function.raw = 0;
CCP_XTS_TYPE(&function) = op->u.xts.type;
CCP_XTS_ENCRYPT(&function) = op->u.xts.action;
CCP_XTS_SIZE(&function) = op->u.xts.unit_size;
CCP5_CMD_FUNCTION(&desc) = function.raw;

View file

@ -192,6 +192,7 @@
#define CCP_AES_CTX_SB_COUNT 1
#define CCP_XTS_AES_KEY_SB_COUNT 1
#define CCP5_XTS_AES_KEY_SB_COUNT 2
#define CCP_XTS_AES_CTX_SB_COUNT 1
#define CCP_DES3_KEY_SB_COUNT 1
@ -497,6 +498,7 @@ struct ccp_aes_op {
};
struct ccp_xts_aes_op {
enum ccp_aes_type type;
enum ccp_aes_action action;
enum ccp_xts_aes_unit_size unit_size;
};

View file

@ -1038,6 +1038,8 @@ static int ccp_run_xts_aes_cmd(struct ccp_cmd_queue *cmd_q,
struct ccp_op op;
unsigned int unit_size, dm_offset;
bool in_place = false;
unsigned int sb_count;
enum ccp_aes_type aestype;
int ret;
switch (xts->unit_size) {
@ -1061,7 +1063,9 @@ static int ccp_run_xts_aes_cmd(struct ccp_cmd_queue *cmd_q,
return -EINVAL;
}
if (xts->key_len != AES_KEYSIZE_128)
if (xts->key_len == AES_KEYSIZE_128)
aestype = CCP_AES_TYPE_128;
else
return -EINVAL;
if (!xts->final && (xts->src_len & (AES_BLOCK_SIZE - 1)))
@ -1083,23 +1087,44 @@ static int ccp_run_xts_aes_cmd(struct ccp_cmd_queue *cmd_q,
op.sb_key = cmd_q->sb_key;
op.sb_ctx = cmd_q->sb_ctx;
op.init = 1;
op.u.xts.type = aestype;
op.u.xts.action = xts->action;
op.u.xts.unit_size = xts->unit_size;
/* All supported key sizes fit in a single (32-byte) SB entry
* and must be in little endian format. Use the 256-bit byte
* swap passthru option to convert from big endian to little
* endian.
/* A version 3 device only supports 128-bit keys, which fits into a
* single SB entry. A version 5 device uses a 512-bit vector, so two
* SB entries.
*/
if (cmd_q->ccp->vdata->version == CCP_VERSION(3, 0))
sb_count = CCP_XTS_AES_KEY_SB_COUNT;
else
sb_count = CCP5_XTS_AES_KEY_SB_COUNT;
ret = ccp_init_dm_workarea(&key, cmd_q,
CCP_XTS_AES_KEY_SB_COUNT * CCP_SB_BYTES,
sb_count * CCP_SB_BYTES,
DMA_TO_DEVICE);
if (ret)
return ret;
dm_offset = CCP_SB_BYTES - AES_KEYSIZE_128;
ccp_set_dm_area(&key, dm_offset, xts->key, 0, xts->key_len);
ccp_set_dm_area(&key, 0, xts->key, dm_offset, xts->key_len);
if (cmd_q->ccp->vdata->version == CCP_VERSION(3, 0)) {
/* All supported key sizes must be in little endian format.
* Use the 256-bit byte swap passthru option to convert from
* big endian to little endian.
*/
dm_offset = CCP_SB_BYTES - AES_KEYSIZE_128;
ccp_set_dm_area(&key, dm_offset, xts->key, 0, xts->key_len);
ccp_set_dm_area(&key, 0, xts->key, xts->key_len, xts->key_len);
} else {
/* Version 5 CCPs use a 512-bit space for the key: each portion
* occupies 256 bits, or one entire slot, and is zero-padded.
*/
unsigned int pad;
dm_offset = CCP_SB_BYTES;
pad = dm_offset - xts->key_len;
ccp_set_dm_area(&key, pad, xts->key, 0, xts->key_len);
ccp_set_dm_area(&key, dm_offset + pad, xts->key, xts->key_len,
xts->key_len);
}
ret = ccp_copy_to_sb(cmd_q, &key, op.jobid, op.sb_key,
CCP_PASSTHRU_BYTESWAP_256BIT);
if (ret) {

View file

@ -564,7 +564,7 @@ struct devfreq *devfreq_add_device(struct device *dev,
err = device_register(&devfreq->dev);
if (err) {
mutex_unlock(&devfreq->lock);
goto err_out;
goto err_dev;
}
devfreq->trans_table = devm_kzalloc(&devfreq->dev,
@ -610,6 +610,9 @@ err_init:
mutex_unlock(&devfreq_list_lock);
device_unregister(&devfreq->dev);
err_dev:
if (devfreq)
kfree(devfreq);
err_out:
return ERR_PTR(err);
}

View file

@ -95,9 +95,8 @@ int psp_wait_for(struct psp_context *psp, uint32_t reg_index,
int i;
struct amdgpu_device *adev = psp->adev;
val = RREG32(reg_index);
for (i = 0; i < adev->usec_timeout; i++) {
val = RREG32(reg_index);
if (check_changed) {
if (val != reg_val)
return 0;

View file

@ -237,11 +237,9 @@ int psp_v3_1_bootloader_load_sos(struct psp_context *psp)
/* there might be handshake issue with hardware which needs delay */
mdelay(20);
#if 0
ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_81),
RREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_81),
0, true);
#endif
return ret;
}

View file

@ -483,7 +483,6 @@ void hfi1_init_pportdata(struct pci_dev *pdev, struct hfi1_pportdata *ppd,
ppd->pkeys[default_pkey_idx] = DEFAULT_P_KEY;
ppd->part_enforce |= HFI1_PART_ENFORCE_IN;
ppd->part_enforce |= HFI1_PART_ENFORCE_OUT;
if (loopback) {
hfi1_early_err(&pdev->dev,

View file

@ -425,7 +425,7 @@ int hfi1_make_rc_req(struct rvt_qp *qp, struct hfi1_pkt_state *ps)
case IB_WR_RDMA_WRITE:
if (newreq && !(qp->s_flags & RVT_S_UNLIMITED_CREDIT))
qp->s_lsn++;
/* FALLTHROUGH */
goto no_flow_control;
case IB_WR_RDMA_WRITE_WITH_IMM:
/* If no credit, return. */
if (!(qp->s_flags & RVT_S_UNLIMITED_CREDIT) &&
@ -433,6 +433,7 @@ int hfi1_make_rc_req(struct rvt_qp *qp, struct hfi1_pkt_state *ps)
qp->s_flags |= RVT_S_WAIT_SSN_CREDIT;
goto bail;
}
no_flow_control:
put_ib_reth_vaddr(
wqe->rdma_wr.remote_addr,
&ohdr->u.rc.reth);

View file

@ -48,6 +48,7 @@ enum {
#define MLX5_UMR_ALIGN 2048
static int clean_mr(struct mlx5_ib_mr *mr);
static int max_umr_order(struct mlx5_ib_dev *dev);
static int use_umr(struct mlx5_ib_dev *dev, int order);
static int unreg_umr(struct mlx5_ib_dev *dev, struct mlx5_ib_mr *mr);
@ -491,16 +492,18 @@ static struct mlx5_ib_mr *alloc_cached_mr(struct mlx5_ib_dev *dev, int order)
struct mlx5_mr_cache *cache = &dev->cache;
struct mlx5_ib_mr *mr = NULL;
struct mlx5_cache_ent *ent;
int last_umr_cache_entry;
int c;
int i;
c = order2idx(dev, order);
if (c < 0 || c > MAX_UMR_CACHE_ENTRY) {
last_umr_cache_entry = order2idx(dev, max_umr_order(dev));
if (c < 0 || c > last_umr_cache_entry) {
mlx5_ib_warn(dev, "order %d, cache index %d\n", order, c);
return NULL;
}
for (i = c; i < MAX_UMR_CACHE_ENTRY; i++) {
for (i = c; i <= last_umr_cache_entry; i++) {
ent = &cache->ent[i];
mlx5_ib_dbg(dev, "order %d, cache index %d\n", ent->order, i);
@ -816,11 +819,16 @@ static int get_octo_len(u64 addr, u64 len, int page_size)
return (npages + 1) / 2;
}
static int use_umr(struct mlx5_ib_dev *dev, int order)
static int max_umr_order(struct mlx5_ib_dev *dev)
{
if (MLX5_CAP_GEN(dev->mdev, umr_extended_translation_offset))
return order <= MAX_UMR_CACHE_ENTRY + 2;
return order <= MLX5_MAX_UMR_SHIFT;
return MAX_UMR_CACHE_ENTRY + 2;
return MLX5_MAX_UMR_SHIFT;
}
static int use_umr(struct mlx5_ib_dev *dev, int order)
{
return order <= max_umr_order(dev);
}
static int mr_umem_get(struct ib_pd *pd, u64 start, u64 length,

View file

@ -348,7 +348,7 @@ int qib_make_rc_req(struct rvt_qp *qp, unsigned long *flags)
case IB_WR_RDMA_WRITE:
if (newreq && !(qp->s_flags & RVT_S_UNLIMITED_CREDIT))
qp->s_lsn++;
/* FALLTHROUGH */
goto no_flow_control;
case IB_WR_RDMA_WRITE_WITH_IMM:
/* If no credit, return. */
if (!(qp->s_flags & RVT_S_UNLIMITED_CREDIT) &&
@ -356,7 +356,7 @@ int qib_make_rc_req(struct rvt_qp *qp, unsigned long *flags)
qp->s_flags |= RVT_S_WAIT_SSN_CREDIT;
goto bail;
}
no_flow_control:
ohdr->u.rc.reth.vaddr =
cpu_to_be64(wqe->rdma_wr.remote_addr);
ohdr->u.rc.reth.rkey =

View file

@ -1764,10 +1764,12 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id
struct usb_endpoint_descriptor *ep =
&intf->cur_altsetting->endpoint[i].desc;
if (usb_endpoint_dir_in(ep))
ep_irq_in = ep;
else
ep_irq_out = ep;
if (usb_endpoint_xfer_int(ep)) {
if (usb_endpoint_dir_in(ep))
ep_irq_in = ep;
else
ep_irq_out = ep;
}
}
if (!ep_irq_in || !ep_irq_out) {

View file

@ -839,6 +839,13 @@ static const struct dmi_system_id __initconst i8042_dmi_kbdreset_table[] = {
DMI_MATCH(DMI_PRODUCT_NAME, "P34"),
},
},
{
/* Gigabyte P57 - Elantech touchpad */
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "GIGABYTE"),
DMI_MATCH(DMI_PRODUCT_NAME, "P57"),
},
},
{
/* Schenker XMG C504 - Elantech touchpad */
.matches = {

View file

@ -95,7 +95,7 @@
/* Register RING_CMPL_START_ADDR fields */
#define CMPL_START_ADDR_VALUE(pa) \
((u32)((((u64)(pa)) >> RING_CMPL_ALIGN_ORDER) & 0x03ffffff))
((u32)((((u64)(pa)) >> RING_CMPL_ALIGN_ORDER) & 0x07ffffff))
/* Register RING_CONTROL fields */
#define CONTROL_MASK_DISABLE_CONTROL 12

View file

@ -333,6 +333,7 @@ struct cached_dev {
/* Limit number of writeback bios in flight */
struct semaphore in_flight;
struct task_struct *writeback_thread;
struct workqueue_struct *writeback_write_wq;
struct keybuf writeback_keys;

View file

@ -196,12 +196,12 @@ static void bch_data_insert_start(struct closure *cl)
struct data_insert_op *op = container_of(cl, struct data_insert_op, cl);
struct bio *bio = op->bio, *n;
if (atomic_sub_return(bio_sectors(bio), &op->c->sectors_to_gc) < 0)
wake_up_gc(op->c);
if (op->bypass)
return bch_data_invalidate(cl);
if (atomic_sub_return(bio_sectors(bio), &op->c->sectors_to_gc) < 0)
wake_up_gc(op->c);
/*
* Journal writes are marked REQ_PREFLUSH; if the original write was a
* flush, it'll wait on the journal write.
@ -400,12 +400,6 @@ static bool check_should_bypass(struct cached_dev *dc, struct bio *bio)
if (!congested && !dc->sequential_cutoff)
goto rescale;
if (!congested &&
mode == CACHE_MODE_WRITEBACK &&
op_is_write(bio->bi_opf) &&
op_is_sync(bio->bi_opf))
goto rescale;
spin_lock(&dc->io_lock);
hlist_for_each_entry(i, iohash(dc, bio->bi_iter.bi_sector), hash)

View file

@ -1026,7 +1026,7 @@ int bch_cached_dev_attach(struct cached_dev *dc, struct cache_set *c)
}
if (BDEV_STATE(&dc->sb) == BDEV_STATE_DIRTY) {
bch_sectors_dirty_init(dc);
bch_sectors_dirty_init(&dc->disk);
atomic_set(&dc->has_dirty, 1);
atomic_inc(&dc->count);
bch_writeback_queue(dc);
@ -1059,6 +1059,8 @@ static void cached_dev_free(struct closure *cl)
cancel_delayed_work_sync(&dc->writeback_rate_update);
if (!IS_ERR_OR_NULL(dc->writeback_thread))
kthread_stop(dc->writeback_thread);
if (dc->writeback_write_wq)
destroy_workqueue(dc->writeback_write_wq);
mutex_lock(&bch_register_lock);
@ -1228,6 +1230,7 @@ static int flash_dev_run(struct cache_set *c, struct uuid_entry *u)
goto err;
bcache_device_attach(d, c, u - c->uuids);
bch_sectors_dirty_init(d);
bch_flash_dev_request_init(d);
add_disk(d->disk);
@ -1964,6 +1967,8 @@ static ssize_t register_bcache(struct kobject *k, struct kobj_attribute *attr,
else
err = "device busy";
mutex_unlock(&bch_register_lock);
if (!IS_ERR(bdev))
bdput(bdev);
if (attr == &ksysfs_register_quiet)
goto out;
}

View file

@ -192,7 +192,7 @@ STORE(__cached_dev)
{
struct cached_dev *dc = container_of(kobj, struct cached_dev,
disk.kobj);
unsigned v = size;
ssize_t v = size;
struct cache_set *c;
struct kobj_uevent_env *env;
@ -227,7 +227,7 @@ STORE(__cached_dev)
bch_cached_dev_run(dc);
if (attr == &sysfs_cache_mode) {
ssize_t v = bch_read_string_list(buf, bch_cache_modes + 1);
v = bch_read_string_list(buf, bch_cache_modes + 1);
if (v < 0)
return v;

View file

@ -74,24 +74,44 @@ STRTO_H(strtouint, unsigned int)
STRTO_H(strtoll, long long)
STRTO_H(strtoull, unsigned long long)
/**
* bch_hprint() - formats @v to human readable string for sysfs.
*
* @v - signed 64 bit integer
* @buf - the (at least 8 byte) buffer to format the result into.
*
* Returns the number of bytes used by format.
*/
ssize_t bch_hprint(char *buf, int64_t v)
{
static const char units[] = "?kMGTPEZY";
char dec[4] = "";
int u, t = 0;
int u = 0, t;
for (u = 0; v >= 1024 || v <= -1024; u++) {
t = v & ~(~0 << 10);
v >>= 10;
}
uint64_t q;
if (!u)
return sprintf(buf, "%llu", v);
if (v < 0)
q = -v;
else
q = v;
if (v < 100 && v > -100)
snprintf(dec, sizeof(dec), ".%i", t / 100);
/* For as long as the number is more than 3 digits, but at least
* once, shift right / divide by 1024. Keep the remainder for
* a digit after the decimal point.
*/
do {
u++;
return sprintf(buf, "%lli%s%c", v, dec, units[u]);
t = q & ~(~0 << 10);
q >>= 10;
} while (q >= 1000);
if (v < 0)
/* '-', up to 3 digits, '.', 1 digit, 1 character, null;
* yields 8 bytes.
*/
return sprintf(buf, "-%llu.%i%c", q, t * 10 / 1024, units[u]);
else
return sprintf(buf, "%llu.%i%c", q, t * 10 / 1024, units[u]);
}
ssize_t bch_snprint_string_list(char *buf, size_t size, const char * const list[],

View file

@ -21,7 +21,8 @@
static void __update_writeback_rate(struct cached_dev *dc)
{
struct cache_set *c = dc->disk.c;
uint64_t cache_sectors = c->nbuckets * c->sb.bucket_size;
uint64_t cache_sectors = c->nbuckets * c->sb.bucket_size -
bcache_flash_devs_sectors_dirty(c);
uint64_t cache_dirty_target =
div_u64(cache_sectors * dc->writeback_percent, 100);
@ -186,7 +187,7 @@ static void write_dirty(struct closure *cl)
closure_bio_submit(&io->bio, cl);
continue_at(cl, write_dirty_finish, system_wq);
continue_at(cl, write_dirty_finish, io->dc->writeback_write_wq);
}
static void read_dirty_endio(struct bio *bio)
@ -206,7 +207,7 @@ static void read_dirty_submit(struct closure *cl)
closure_bio_submit(&io->bio, cl);
continue_at(cl, write_dirty, system_wq);
continue_at(cl, write_dirty, io->dc->writeback_write_wq);
}
static void read_dirty(struct cached_dev *dc)
@ -482,17 +483,17 @@ static int sectors_dirty_init_fn(struct btree_op *_op, struct btree *b,
return MAP_CONTINUE;
}
void bch_sectors_dirty_init(struct cached_dev *dc)
void bch_sectors_dirty_init(struct bcache_device *d)
{
struct sectors_dirty_init op;
bch_btree_op_init(&op.op, -1);
op.inode = dc->disk.id;
op.inode = d->id;
bch_btree_map_keys(&op.op, dc->disk.c, &KEY(op.inode, 0, 0),
bch_btree_map_keys(&op.op, d->c, &KEY(op.inode, 0, 0),
sectors_dirty_init_fn, 0);
dc->disk.sectors_dirty_last = bcache_dev_sectors_dirty(&dc->disk);
d->sectors_dirty_last = bcache_dev_sectors_dirty(d);
}
void bch_cached_dev_writeback_init(struct cached_dev *dc)
@ -516,6 +517,11 @@ void bch_cached_dev_writeback_init(struct cached_dev *dc)
int bch_cached_dev_writeback_start(struct cached_dev *dc)
{
dc->writeback_write_wq = alloc_workqueue("bcache_writeback_wq",
WQ_MEM_RECLAIM, 0);
if (!dc->writeback_write_wq)
return -ENOMEM;
dc->writeback_thread = kthread_create(bch_writeback_thread, dc,
"bcache_writeback");
if (IS_ERR(dc->writeback_thread))

View file

@ -14,6 +14,25 @@ static inline uint64_t bcache_dev_sectors_dirty(struct bcache_device *d)
return ret;
}
static inline uint64_t bcache_flash_devs_sectors_dirty(struct cache_set *c)
{
uint64_t i, ret = 0;
mutex_lock(&bch_register_lock);
for (i = 0; i < c->nr_uuids; i++) {
struct bcache_device *d = c->devices[i];
if (!d || !UUID_FLASH_ONLY(&c->uuids[i]))
continue;
ret += bcache_dev_sectors_dirty(d);
}
mutex_unlock(&bch_register_lock);
return ret;
}
static inline unsigned offset_to_stripe(struct bcache_device *d,
uint64_t offset)
{
@ -84,7 +103,7 @@ static inline void bch_writeback_add(struct cached_dev *dc)
void bcache_dev_sectors_dirty_add(struct cache_set *, unsigned, uint64_t, int);
void bch_sectors_dirty_init(struct cached_dev *dc);
void bch_sectors_dirty_init(struct bcache_device *);
void bch_cached_dev_writeback_init(struct cached_dev *);
int bch_cached_dev_writeback_start(struct cached_dev *);

View file

@ -625,7 +625,7 @@ re_read:
err = read_sb_page(bitmap->mddev,
offset,
sb_page,
0, sizeof(bitmap_super_t));
0, PAGE_SIZE);
}
if (err)
return err;
@ -2058,6 +2058,11 @@ int bitmap_resize(struct bitmap *bitmap, sector_t blocks,
long pages;
struct bitmap_page *new_bp;
if (bitmap->storage.file && !init) {
pr_info("md: cannot resize file-based bitmap\n");
return -EINVAL;
}
if (chunksize == 0) {
/* If there is enough space, leave the chunk size unchanged,
* else increase by factor of two until there is enough space.
@ -2118,7 +2123,7 @@ int bitmap_resize(struct bitmap *bitmap, sector_t blocks,
if (store.sb_page && bitmap->storage.sb_page)
memcpy(page_address(store.sb_page),
page_address(bitmap->storage.sb_page),
sizeof(bitmap_super_t));
PAGE_SIZE);
bitmap_file_unmap(&bitmap->storage);
bitmap->storage = store;

View file

@ -1402,6 +1402,8 @@ static int adv7180_remove(struct i2c_client *client)
static const struct i2c_device_id adv7180_id[] = {
{ "adv7180", (kernel_ulong_t)&adv7180_info },
{ "adv7180cp", (kernel_ulong_t)&adv7180_info },
{ "adv7180st", (kernel_ulong_t)&adv7180_info },
{ "adv7182", (kernel_ulong_t)&adv7182_info },
{ "adv7280", (kernel_ulong_t)&adv7280_info },
{ "adv7280-m", (kernel_ulong_t)&adv7280_m_info },

View file

@ -243,7 +243,7 @@ static void return_buf_error(struct venus_inst *inst,
if (vbuf->vb2_buf.type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
v4l2_m2m_src_buf_remove_by_buf(m2m_ctx, vbuf);
else
v4l2_m2m_src_buf_remove_by_buf(m2m_ctx, vbuf);
v4l2_m2m_dst_buf_remove_by_buf(m2m_ctx, vbuf);
v4l2_m2m_buf_done(vbuf, VB2_BUF_STATE_ERROR);
}

View file

@ -59,6 +59,8 @@ static void lirc_release(struct device *ld)
{
struct irctl *ir = container_of(ld, struct irctl, dev);
put_device(ir->dev.parent);
if (ir->buf_internal) {
lirc_buffer_free(ir->buf);
kfree(ir->buf);
@ -218,6 +220,8 @@ int lirc_register_driver(struct lirc_driver *d)
mutex_unlock(&lirc_dev_lock);
get_device(ir->dev.parent);
dev_info(ir->d.dev, "lirc_dev: driver %s registered at minor = %d\n",
ir->d.name, ir->d.minor);

View file

@ -2002,6 +2002,13 @@ int uvc_ctrl_add_mapping(struct uvc_video_chain *chain,
goto done;
}
/* Validate the user-provided bit-size and offset */
if (mapping->size > 32 ||
mapping->offset + mapping->size > ctrl->info.size * 8) {
ret = -EINVAL;
goto done;
}
list_for_each_entry(map, &ctrl->info.mappings, list) {
if (mapping->id == map->id) {
uvc_trace(UVC_TRACE_CONTROL, "Can't add mapping '%s', "

View file

@ -796,7 +796,8 @@ static int put_v4l2_event32(struct v4l2_event *kp, struct v4l2_event32 __user *u
copy_to_user(&up->u, &kp->u, sizeof(kp->u)) ||
put_user(kp->pending, &up->pending) ||
put_user(kp->sequence, &up->sequence) ||
compat_put_timespec(&kp->timestamp, &up->timestamp) ||
put_user(kp->timestamp.tv_sec, &up->timestamp.tv_sec) ||
put_user(kp->timestamp.tv_nsec, &up->timestamp.tv_nsec) ||
put_user(kp->id, &up->id) ||
copy_to_user(up->reserved, kp->reserved, 8 * sizeof(__u32)))
return -EFAULT;

View file

@ -336,6 +336,10 @@ int cxl_start_context(struct cxl_context *ctx, u64 wed,
mmput(ctx->mm);
}
/*
* Increment driver use count. Enables global TLBIs for hash
* and callbacks to handle the segment table
*/
cxl_ctx_get();
if ((rc = cxl_ops->attach_process(ctx, kernel, wed, 0))) {

View file

@ -95,7 +95,6 @@ static int __afu_open(struct inode *inode, struct file *file, bool master)
pr_devel("afu_open pe: %i\n", ctx->pe);
file->private_data = ctx;
cxl_ctx_get();
/* indicate success */
rc = 0;
@ -225,6 +224,12 @@ static long afu_ioctl_start_work(struct cxl_context *ctx,
if (ctx->mm)
mmput(ctx->mm);
/*
* Increment driver use count. Enables global TLBIs for hash
* and callbacks to handle the segment table
*/
cxl_ctx_get();
trace_cxl_attach(ctx, work.work_element_descriptor, work.num_interrupts, amr);
if ((rc = cxl_ops->attach_process(ctx, false, work.work_element_descriptor,
@ -233,6 +238,7 @@ static long afu_ioctl_start_work(struct cxl_context *ctx,
cxl_adapter_context_put(ctx->afu->adapter);
put_pid(ctx->pid);
ctx->pid = NULL;
cxl_ctx_put();
cxl_context_mm_count_put(ctx);
goto out;
}

View file

@ -372,6 +372,8 @@ static int wcn36xx_config(struct ieee80211_hw *hw, u32 changed)
wcn36xx_dbg(WCN36XX_DBG_MAC, "mac config changed 0x%08x\n", changed);
mutex_lock(&wcn->conf_mutex);
if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
int ch = WCN36XX_HW_CHANNEL(wcn);
wcn36xx_dbg(WCN36XX_DBG_MAC, "wcn36xx_config channel switch=%d\n",
@ -382,6 +384,8 @@ static int wcn36xx_config(struct ieee80211_hw *hw, u32 changed)
}
}
mutex_unlock(&wcn->conf_mutex);
return 0;
}
@ -396,6 +400,8 @@ static void wcn36xx_configure_filter(struct ieee80211_hw *hw,
wcn36xx_dbg(WCN36XX_DBG_MAC, "mac configure filter\n");
mutex_lock(&wcn->conf_mutex);
*total &= FIF_ALLMULTI;
fp = (void *)(unsigned long)multicast;
@ -408,6 +414,8 @@ static void wcn36xx_configure_filter(struct ieee80211_hw *hw,
else if (NL80211_IFTYPE_STATION == vif->type && tmp->sta_assoc)
wcn36xx_smd_set_mc_list(wcn, vif, fp);
}
mutex_unlock(&wcn->conf_mutex);
kfree(fp);
}
@ -471,6 +479,8 @@ static int wcn36xx_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
key_conf->key,
key_conf->keylen);
mutex_lock(&wcn->conf_mutex);
switch (key_conf->cipher) {
case WLAN_CIPHER_SUITE_WEP40:
vif_priv->encrypt_type = WCN36XX_HAL_ED_WEP40;
@ -565,6 +575,8 @@ static int wcn36xx_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
}
out:
mutex_unlock(&wcn->conf_mutex);
return ret;
}
@ -725,6 +737,8 @@ static void wcn36xx_bss_info_changed(struct ieee80211_hw *hw,
wcn36xx_dbg(WCN36XX_DBG_MAC, "mac bss info changed vif %p changed 0x%08x\n",
vif, changed);
mutex_lock(&wcn->conf_mutex);
if (changed & BSS_CHANGED_BEACON_INFO) {
wcn36xx_dbg(WCN36XX_DBG_MAC,
"mac bss changed dtim period %d\n",
@ -787,7 +801,13 @@ static void wcn36xx_bss_info_changed(struct ieee80211_hw *hw,
bss_conf->aid);
vif_priv->sta_assoc = true;
rcu_read_lock();
/*
* Holding conf_mutex ensures mutal exclusion with
* wcn36xx_sta_remove() and as such ensures that sta
* won't be freed while we're operating on it. As such
* we do not need to hold the rcu_read_lock().
*/
sta = ieee80211_find_sta(vif, bss_conf->bssid);
if (!sta) {
wcn36xx_err("sta %pM is not found\n",
@ -811,7 +831,6 @@ static void wcn36xx_bss_info_changed(struct ieee80211_hw *hw,
* place where AID is available.
*/
wcn36xx_smd_config_sta(wcn, vif, sta);
rcu_read_unlock();
} else {
wcn36xx_dbg(WCN36XX_DBG_MAC,
"disassociated bss %pM vif %pM AID=%d\n",
@ -873,6 +892,9 @@ static void wcn36xx_bss_info_changed(struct ieee80211_hw *hw,
}
}
out:
mutex_unlock(&wcn->conf_mutex);
return;
}
@ -882,7 +904,10 @@ static int wcn36xx_set_rts_threshold(struct ieee80211_hw *hw, u32 value)
struct wcn36xx *wcn = hw->priv;
wcn36xx_dbg(WCN36XX_DBG_MAC, "mac set RTS threshold %d\n", value);
mutex_lock(&wcn->conf_mutex);
wcn36xx_smd_update_cfg(wcn, WCN36XX_HAL_CFG_RTS_THRESHOLD, value);
mutex_unlock(&wcn->conf_mutex);
return 0;
}
@ -893,8 +918,12 @@ static void wcn36xx_remove_interface(struct ieee80211_hw *hw,
struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
wcn36xx_dbg(WCN36XX_DBG_MAC, "mac remove interface vif %p\n", vif);
mutex_lock(&wcn->conf_mutex);
list_del(&vif_priv->list);
wcn36xx_smd_delete_sta_self(wcn, vif->addr);
mutex_unlock(&wcn->conf_mutex);
}
static int wcn36xx_add_interface(struct ieee80211_hw *hw,
@ -915,9 +944,13 @@ static int wcn36xx_add_interface(struct ieee80211_hw *hw,
return -EOPNOTSUPP;
}
mutex_lock(&wcn->conf_mutex);
list_add(&vif_priv->list, &wcn->vif_list);
wcn36xx_smd_add_sta_self(wcn, vif);
mutex_unlock(&wcn->conf_mutex);
return 0;
}
@ -930,6 +963,8 @@ static int wcn36xx_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
wcn36xx_dbg(WCN36XX_DBG_MAC, "mac sta add vif %p sta %pM\n",
vif, sta->addr);
mutex_lock(&wcn->conf_mutex);
spin_lock_init(&sta_priv->ampdu_lock);
sta_priv->vif = vif_priv;
/*
@ -941,6 +976,9 @@ static int wcn36xx_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
sta_priv->aid = sta->aid;
wcn36xx_smd_config_sta(wcn, vif, sta);
}
mutex_unlock(&wcn->conf_mutex);
return 0;
}
@ -954,8 +992,13 @@ static int wcn36xx_sta_remove(struct ieee80211_hw *hw,
wcn36xx_dbg(WCN36XX_DBG_MAC, "mac sta remove vif %p sta %pM index %d\n",
vif, sta->addr, sta_priv->sta_index);
mutex_lock(&wcn->conf_mutex);
wcn36xx_smd_delete_sta(wcn, sta_priv->sta_index);
sta_priv->vif = NULL;
mutex_unlock(&wcn->conf_mutex);
return 0;
}
@ -999,6 +1042,8 @@ static int wcn36xx_ampdu_action(struct ieee80211_hw *hw,
wcn36xx_dbg(WCN36XX_DBG_MAC, "mac ampdu action action %d tid %d\n",
action, tid);
mutex_lock(&wcn->conf_mutex);
switch (action) {
case IEEE80211_AMPDU_RX_START:
sta_priv->tid = tid;
@ -1038,6 +1083,8 @@ static int wcn36xx_ampdu_action(struct ieee80211_hw *hw,
wcn36xx_err("Unknown AMPDU action\n");
}
mutex_unlock(&wcn->conf_mutex);
return 0;
}
@ -1216,6 +1263,7 @@ static int wcn36xx_probe(struct platform_device *pdev)
wcn = hw->priv;
wcn->hw = hw;
wcn->dev = &pdev->dev;
mutex_init(&wcn->conf_mutex);
mutex_init(&wcn->hal_mutex);
mutex_init(&wcn->scan_lock);

View file

@ -202,6 +202,9 @@ struct wcn36xx {
struct qcom_smem_state *tx_rings_empty_state;
unsigned tx_rings_empty_state_bit;
/* prevents concurrent FW reconfiguration */
struct mutex conf_mutex;
/*
* smd_buf must be protected with smd_mutex to garantee
* that all messages are sent one after another

View file

@ -79,6 +79,7 @@
/* NVM offsets (in words) definitions */
enum wkp_nvm_offsets {
/* NVM HW-Section offset (in words) definitions */
SUBSYSTEM_ID = 0x0A,
HW_ADDR = 0x15,
/* NVM SW-Section offset (in words) definitions */
@ -254,13 +255,12 @@ static u32 iwl_get_channel_flags(u8 ch_num, int ch_idx, bool is_5ghz,
static int iwl_init_channel_map(struct device *dev, const struct iwl_cfg *cfg,
struct iwl_nvm_data *data,
const __le16 * const nvm_ch_flags,
bool lar_supported)
bool lar_supported, bool no_wide_in_5ghz)
{
int ch_idx;
int n_channels = 0;
struct ieee80211_channel *channel;
u16 ch_flags;
bool is_5ghz;
int num_of_ch, num_2ghz_channels;
const u8 *nvm_chan;
@ -275,12 +275,20 @@ static int iwl_init_channel_map(struct device *dev, const struct iwl_cfg *cfg,
}
for (ch_idx = 0; ch_idx < num_of_ch; ch_idx++) {
bool is_5ghz = (ch_idx >= num_2ghz_channels);
ch_flags = __le16_to_cpup(nvm_ch_flags + ch_idx);
if (ch_idx >= num_2ghz_channels &&
!data->sku_cap_band_52GHz_enable)
if (is_5ghz && !data->sku_cap_band_52GHz_enable)
continue;
/* workaround to disable wide channels in 5GHz */
if (no_wide_in_5ghz && is_5ghz) {
ch_flags &= ~(NVM_CHANNEL_40MHZ |
NVM_CHANNEL_80MHZ |
NVM_CHANNEL_160MHZ);
}
if (ch_flags & NVM_CHANNEL_160MHZ)
data->vht160_supported = true;
@ -303,8 +311,8 @@ static int iwl_init_channel_map(struct device *dev, const struct iwl_cfg *cfg,
n_channels++;
channel->hw_value = nvm_chan[ch_idx];
channel->band = (ch_idx < num_2ghz_channels) ?
NL80211_BAND_2GHZ : NL80211_BAND_5GHZ;
channel->band = is_5ghz ?
NL80211_BAND_5GHZ : NL80211_BAND_2GHZ;
channel->center_freq =
ieee80211_channel_to_frequency(
channel->hw_value, channel->band);
@ -316,7 +324,6 @@ static int iwl_init_channel_map(struct device *dev, const struct iwl_cfg *cfg,
* is not used in mvm, and is used for backwards compatibility
*/
channel->max_power = IWL_DEFAULT_MAX_TX_POWER;
is_5ghz = channel->band == NL80211_BAND_5GHZ;
/* don't put limitations in case we're using LAR */
if (!lar_supported)
@ -432,14 +439,15 @@ static void iwl_init_vht_hw_capab(const struct iwl_cfg *cfg,
void iwl_init_sbands(struct device *dev, const struct iwl_cfg *cfg,
struct iwl_nvm_data *data, const __le16 *nvm_ch_flags,
u8 tx_chains, u8 rx_chains, bool lar_supported)
u8 tx_chains, u8 rx_chains, bool lar_supported,
bool no_wide_in_5ghz)
{
int n_channels;
int n_used = 0;
struct ieee80211_supported_band *sband;
n_channels = iwl_init_channel_map(dev, cfg, data, nvm_ch_flags,
lar_supported);
lar_supported, no_wide_in_5ghz);
sband = &data->bands[NL80211_BAND_2GHZ];
sband->band = NL80211_BAND_2GHZ;
sband->bitrates = &iwl_cfg80211_rates[RATES_24_OFFS];
@ -645,6 +653,39 @@ static int iwl_set_hw_address(struct iwl_trans *trans,
return 0;
}
static bool
iwl_nvm_no_wide_in_5ghz(struct device *dev, const struct iwl_cfg *cfg,
const __le16 *nvm_hw)
{
/*
* Workaround a bug in Indonesia SKUs where the regulatory in
* some 7000-family OTPs erroneously allow wide channels in
* 5GHz. To check for Indonesia, we take the SKU value from
* bits 1-4 in the subsystem ID and check if it is either 5 or
* 9. In those cases, we need to force-disable wide channels
* in 5GHz otherwise the FW will throw a sysassert when we try
* to use them.
*/
if (cfg->device_family == IWL_DEVICE_FAMILY_7000) {
/*
* Unlike the other sections in the NVM, the hw
* section uses big-endian.
*/
u16 subsystem_id = be16_to_cpup((const __be16 *)nvm_hw
+ SUBSYSTEM_ID);
u8 sku = (subsystem_id & 0x1e) >> 1;
if (sku == 5 || sku == 9) {
IWL_DEBUG_EEPROM(dev,
"disabling wide channels in 5GHz (0x%0x %d)\n",
subsystem_id, sku);
return true;
}
}
return false;
}
struct iwl_nvm_data *
iwl_parse_nvm_data(struct iwl_trans *trans, const struct iwl_cfg *cfg,
const __le16 *nvm_hw, const __le16 *nvm_sw,
@ -655,6 +696,7 @@ iwl_parse_nvm_data(struct iwl_trans *trans, const struct iwl_cfg *cfg,
struct device *dev = trans->dev;
struct iwl_nvm_data *data;
bool lar_enabled;
bool no_wide_in_5ghz = iwl_nvm_no_wide_in_5ghz(dev, cfg, nvm_hw);
u32 sku, radio_cfg;
u16 lar_config;
const __le16 *ch_section;
@ -725,7 +767,7 @@ iwl_parse_nvm_data(struct iwl_trans *trans, const struct iwl_cfg *cfg,
}
iwl_init_sbands(dev, cfg, data, ch_section, tx_chains, rx_chains,
lar_fw_supported && lar_enabled);
lar_fw_supported && lar_enabled, no_wide_in_5ghz);
data->calib_version = 255;
return data;

View file

@ -93,7 +93,8 @@ void iwl_set_hw_address_from_csr(struct iwl_trans *trans,
*/
void iwl_init_sbands(struct device *dev, const struct iwl_cfg *cfg,
struct iwl_nvm_data *data, const __le16 *nvm_ch_flags,
u8 tx_chains, u8 rx_chains, bool lar_supported);
u8 tx_chains, u8 rx_chains, bool lar_supported,
bool no_wide_in_5ghz);
/**
* iwl_parse_mcc_info - parse MCC (mobile country code) info coming from FW

View file

@ -628,7 +628,8 @@ int iwl_mvm_nvm_get_from_fw(struct iwl_mvm *mvm)
rsp->regulatory.channel_profile,
mvm->nvm_data->valid_tx_ant & mvm->fw->valid_tx_ant,
mvm->nvm_data->valid_rx_ant & mvm->fw->valid_rx_ant,
rsp->regulatory.lar_enabled && lar_fw_supported);
rsp->regulatory.lar_enabled && lar_fw_supported,
false);
iwl_free_resp(&hcmd);
return 0;

View file

@ -586,6 +586,14 @@ static irqreturn_t pciehp_isr(int irq, void *dev_id)
events = status & (PCI_EXP_SLTSTA_ABP | PCI_EXP_SLTSTA_PFD |
PCI_EXP_SLTSTA_PDC | PCI_EXP_SLTSTA_CC |
PCI_EXP_SLTSTA_DLLSC);
/*
* If we've already reported a power fault, don't report it again
* until we've done something to handle it.
*/
if (ctrl->power_fault_detected)
events &= ~PCI_EXP_SLTSTA_PFD;
if (!events)
return IRQ_NONE;

View file

@ -1062,6 +1062,8 @@ int shpc_init(struct controller *ctrl, struct pci_dev *pdev)
if (rc) {
ctrl_info(ctrl, "Can't get msi for the hotplug controller\n");
ctrl_info(ctrl, "Use INTx for the hotplug controller\n");
} else {
pci_set_master(pdev);
}
rc = request_irq(ctrl->pci_dev->irq, shpc_isr, IRQF_SHARED,

View file

@ -36,6 +36,7 @@
#include <linux/pinctrl/pinconf.h>
#include <linux/pinctrl/pinconf-generic.h>
#include "core.h"
#include "pinctrl-utils.h"
#include "pinctrl-amd.h"
@ -725,6 +726,69 @@ static const struct pinconf_ops amd_pinconf_ops = {
.pin_config_group_set = amd_pinconf_group_set,
};
#ifdef CONFIG_PM_SLEEP
static bool amd_gpio_should_save(struct amd_gpio *gpio_dev, unsigned int pin)
{
const struct pin_desc *pd = pin_desc_get(gpio_dev->pctrl, pin);
if (!pd)
return false;
/*
* Only restore the pin if it is actually in use by the kernel (or
* by userspace).
*/
if (pd->mux_owner || pd->gpio_owner ||
gpiochip_line_is_irq(&gpio_dev->gc, pin))
return true;
return false;
}
int amd_gpio_suspend(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct amd_gpio *gpio_dev = platform_get_drvdata(pdev);
struct pinctrl_desc *desc = gpio_dev->pctrl->desc;
int i;
for (i = 0; i < desc->npins; i++) {
int pin = desc->pins[i].number;
if (!amd_gpio_should_save(gpio_dev, pin))
continue;
gpio_dev->saved_regs[i] = readl(gpio_dev->base + pin*4);
}
return 0;
}
int amd_gpio_resume(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct amd_gpio *gpio_dev = platform_get_drvdata(pdev);
struct pinctrl_desc *desc = gpio_dev->pctrl->desc;
int i;
for (i = 0; i < desc->npins; i++) {
int pin = desc->pins[i].number;
if (!amd_gpio_should_save(gpio_dev, pin))
continue;
writel(gpio_dev->saved_regs[i], gpio_dev->base + pin*4);
}
return 0;
}
static const struct dev_pm_ops amd_gpio_pm_ops = {
SET_LATE_SYSTEM_SLEEP_PM_OPS(amd_gpio_suspend,
amd_gpio_resume)
};
#endif
static struct pinctrl_desc amd_pinctrl_desc = {
.pins = kerncz_pins,
.npins = ARRAY_SIZE(kerncz_pins),
@ -764,6 +828,14 @@ static int amd_gpio_probe(struct platform_device *pdev)
return -EINVAL;
}
#ifdef CONFIG_PM_SLEEP
gpio_dev->saved_regs = devm_kcalloc(&pdev->dev, amd_pinctrl_desc.npins,
sizeof(*gpio_dev->saved_regs),
GFP_KERNEL);
if (!gpio_dev->saved_regs)
return -ENOMEM;
#endif
gpio_dev->pdev = pdev;
gpio_dev->gc.direction_input = amd_gpio_direction_input;
gpio_dev->gc.direction_output = amd_gpio_direction_output;
@ -853,6 +925,9 @@ static struct platform_driver amd_gpio_driver = {
.driver = {
.name = "amd_gpio",
.acpi_match_table = ACPI_PTR(amd_gpio_acpi_match),
#ifdef CONFIG_PM_SLEEP
.pm = &amd_gpio_pm_ops,
#endif
},
.probe = amd_gpio_probe,
.remove = amd_gpio_remove,

View file

@ -97,6 +97,7 @@ struct amd_gpio {
unsigned int hwbank_num;
struct resource *res;
struct platform_device *pdev;
u32 *saved_regs;
};
/* KERNCZ configuration*/

View file

@ -174,10 +174,10 @@ static int exynos_irq_request_resources(struct irq_data *irqd)
spin_lock_irqsave(&bank->slock, flags);
con = readl(bank->eint_base + reg_con);
con = readl(bank->pctl_base + reg_con);
con &= ~(mask << shift);
con |= EXYNOS_EINT_FUNC << shift;
writel(con, bank->eint_base + reg_con);
writel(con, bank->pctl_base + reg_con);
spin_unlock_irqrestore(&bank->slock, flags);
@ -202,10 +202,10 @@ static void exynos_irq_release_resources(struct irq_data *irqd)
spin_lock_irqsave(&bank->slock, flags);
con = readl(bank->eint_base + reg_con);
con = readl(bank->pctl_base + reg_con);
con &= ~(mask << shift);
con |= FUNC_INPUT << shift;
writel(con, bank->eint_base + reg_con);
writel(con, bank->pctl_base + reg_con);
spin_unlock_irqrestore(&bank->slock, flags);

View file

@ -151,7 +151,7 @@ static void s3c24xx_eint_set_function(struct samsung_pinctrl_drv_data *d,
u32 val;
/* Make sure that pin is configured as interrupt */
reg = bank->pctl_base + bank->pctl_offset;
reg = d->virt_base + bank->pctl_offset;
shift = pin * bank_type->fld_width[PINCFG_TYPE_FUNC];
mask = (1 << bank_type->fld_width[PINCFG_TYPE_FUNC]) - 1;
@ -184,7 +184,7 @@ static int s3c24xx_eint_type(struct irq_data *data, unsigned int type)
s3c24xx_eint_set_handler(data, type);
/* Set up interrupt trigger */
reg = bank->eint_base + EINT_REG(index);
reg = d->virt_base + EINT_REG(index);
shift = EINT_OFFS(index);
val = readl(reg);
@ -259,29 +259,32 @@ static void s3c2410_demux_eint0_3(struct irq_desc *desc)
static void s3c2412_eint0_3_ack(struct irq_data *data)
{
struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(data);
struct samsung_pinctrl_drv_data *d = bank->drvdata;
unsigned long bitval = 1UL << data->hwirq;
writel(bitval, bank->eint_base + EINTPEND_REG);
writel(bitval, d->virt_base + EINTPEND_REG);
}
static void s3c2412_eint0_3_mask(struct irq_data *data)
{
struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(data);
struct samsung_pinctrl_drv_data *d = bank->drvdata;
unsigned long mask;
mask = readl(bank->eint_base + EINTMASK_REG);
mask = readl(d->virt_base + EINTMASK_REG);
mask |= (1UL << data->hwirq);
writel(mask, bank->eint_base + EINTMASK_REG);
writel(mask, d->virt_base + EINTMASK_REG);
}
static void s3c2412_eint0_3_unmask(struct irq_data *data)
{
struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(data);
struct samsung_pinctrl_drv_data *d = bank->drvdata;
unsigned long mask;
mask = readl(bank->eint_base + EINTMASK_REG);
mask = readl(d->virt_base + EINTMASK_REG);
mask &= ~(1UL << data->hwirq);
writel(mask, bank->eint_base + EINTMASK_REG);
writel(mask, d->virt_base + EINTMASK_REG);
}
static struct irq_chip s3c2412_eint0_3_chip = {
@ -316,31 +319,34 @@ static void s3c2412_demux_eint0_3(struct irq_desc *desc)
static void s3c24xx_eint_ack(struct irq_data *data)
{
struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(data);
struct samsung_pinctrl_drv_data *d = bank->drvdata;
unsigned char index = bank->eint_offset + data->hwirq;
writel(1UL << index, bank->eint_base + EINTPEND_REG);
writel(1UL << index, d->virt_base + EINTPEND_REG);
}
static void s3c24xx_eint_mask(struct irq_data *data)
{
struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(data);
struct samsung_pinctrl_drv_data *d = bank->drvdata;
unsigned char index = bank->eint_offset + data->hwirq;
unsigned long mask;
mask = readl(bank->eint_base + EINTMASK_REG);
mask = readl(d->virt_base + EINTMASK_REG);
mask |= (1UL << index);
writel(mask, bank->eint_base + EINTMASK_REG);
writel(mask, d->virt_base + EINTMASK_REG);
}
static void s3c24xx_eint_unmask(struct irq_data *data)
{
struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(data);
struct samsung_pinctrl_drv_data *d = bank->drvdata;
unsigned char index = bank->eint_offset + data->hwirq;
unsigned long mask;
mask = readl(bank->eint_base + EINTMASK_REG);
mask = readl(d->virt_base + EINTMASK_REG);
mask &= ~(1UL << index);
writel(mask, bank->eint_base + EINTMASK_REG);
writel(mask, d->virt_base + EINTMASK_REG);
}
static struct irq_chip s3c24xx_eint_chip = {
@ -356,14 +362,13 @@ static inline void s3c24xx_demux_eint(struct irq_desc *desc,
{
struct s3c24xx_eint_data *data = irq_desc_get_handler_data(desc);
struct irq_chip *chip = irq_desc_get_chip(desc);
struct irq_data *irqd = irq_desc_get_irq_data(desc);
struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd);
struct samsung_pinctrl_drv_data *d = data->drvdata;
unsigned int pend, mask;
chained_irq_enter(chip, desc);
pend = readl(bank->eint_base + EINTPEND_REG);
mask = readl(bank->eint_base + EINTMASK_REG);
pend = readl(d->virt_base + EINTPEND_REG);
mask = readl(d->virt_base + EINTMASK_REG);
pend &= ~mask;
pend &= range;

View file

@ -280,7 +280,7 @@ static void s3c64xx_irq_set_function(struct samsung_pinctrl_drv_data *d,
u32 val;
/* Make sure that pin is configured as interrupt */
reg = bank->pctl_base + bank->pctl_offset;
reg = d->virt_base + bank->pctl_offset;
shift = pin;
if (bank_type->fld_width[PINCFG_TYPE_FUNC] * shift >= 32) {
/* 4-bit bank type with 2 con regs */
@ -308,8 +308,9 @@ static void s3c64xx_irq_set_function(struct samsung_pinctrl_drv_data *d,
static inline void s3c64xx_gpio_irq_set_mask(struct irq_data *irqd, bool mask)
{
struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd);
struct samsung_pinctrl_drv_data *d = bank->drvdata;
unsigned char index = EINT_OFFS(bank->eint_offset) + irqd->hwirq;
void __iomem *reg = bank->eint_base + EINTMASK_REG(bank->eint_offset);
void __iomem *reg = d->virt_base + EINTMASK_REG(bank->eint_offset);
u32 val;
val = readl(reg);
@ -333,8 +334,9 @@ static void s3c64xx_gpio_irq_mask(struct irq_data *irqd)
static void s3c64xx_gpio_irq_ack(struct irq_data *irqd)
{
struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd);
struct samsung_pinctrl_drv_data *d = bank->drvdata;
unsigned char index = EINT_OFFS(bank->eint_offset) + irqd->hwirq;
void __iomem *reg = bank->eint_base + EINTPEND_REG(bank->eint_offset);
void __iomem *reg = d->virt_base + EINTPEND_REG(bank->eint_offset);
writel(1 << index, reg);
}
@ -357,7 +359,7 @@ static int s3c64xx_gpio_irq_set_type(struct irq_data *irqd, unsigned int type)
s3c64xx_irq_set_handler(irqd, type);
/* Set up interrupt trigger */
reg = bank->eint_base + EINTCON_REG(bank->eint_offset);
reg = d->virt_base + EINTCON_REG(bank->eint_offset);
shift = EINT_OFFS(bank->eint_offset) + irqd->hwirq;
shift = 4 * (shift / 4); /* 4 EINTs per trigger selector */
@ -409,8 +411,7 @@ static void s3c64xx_eint_gpio_irq(struct irq_desc *desc)
{
struct irq_chip *chip = irq_desc_get_chip(desc);
struct s3c64xx_eint_gpio_data *data = irq_desc_get_handler_data(desc);
struct irq_data *irqd = irq_desc_get_irq_data(desc);
struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd);
struct samsung_pinctrl_drv_data *drvdata = data->drvdata;
chained_irq_enter(chip, desc);
@ -420,7 +421,7 @@ static void s3c64xx_eint_gpio_irq(struct irq_desc *desc)
unsigned int pin;
unsigned int virq;
svc = readl(bank->eint_base + SERVICE_REG);
svc = readl(drvdata->virt_base + SERVICE_REG);
group = SVC_GROUP(svc);
pin = svc & SVC_NUM_MASK;
@ -515,15 +516,15 @@ static inline void s3c64xx_eint0_irq_set_mask(struct irq_data *irqd, bool mask)
{
struct s3c64xx_eint0_domain_data *ddata =
irq_data_get_irq_chip_data(irqd);
struct samsung_pin_bank *bank = ddata->bank;
struct samsung_pinctrl_drv_data *d = ddata->bank->drvdata;
u32 val;
val = readl(bank->eint_base + EINT0MASK_REG);
val = readl(d->virt_base + EINT0MASK_REG);
if (mask)
val |= 1 << ddata->eints[irqd->hwirq];
else
val &= ~(1 << ddata->eints[irqd->hwirq]);
writel(val, bank->eint_base + EINT0MASK_REG);
writel(val, d->virt_base + EINT0MASK_REG);
}
static void s3c64xx_eint0_irq_unmask(struct irq_data *irqd)
@ -540,10 +541,10 @@ static void s3c64xx_eint0_irq_ack(struct irq_data *irqd)
{
struct s3c64xx_eint0_domain_data *ddata =
irq_data_get_irq_chip_data(irqd);
struct samsung_pin_bank *bank = ddata->bank;
struct samsung_pinctrl_drv_data *d = ddata->bank->drvdata;
writel(1 << ddata->eints[irqd->hwirq],
bank->eint_base + EINT0PEND_REG);
d->virt_base + EINT0PEND_REG);
}
static int s3c64xx_eint0_irq_set_type(struct irq_data *irqd, unsigned int type)
@ -551,7 +552,7 @@ static int s3c64xx_eint0_irq_set_type(struct irq_data *irqd, unsigned int type)
struct s3c64xx_eint0_domain_data *ddata =
irq_data_get_irq_chip_data(irqd);
struct samsung_pin_bank *bank = ddata->bank;
struct samsung_pinctrl_drv_data *d = ddata->bank->drvdata;
struct samsung_pinctrl_drv_data *d = bank->drvdata;
void __iomem *reg;
int trigger;
u8 shift;
@ -566,7 +567,7 @@ static int s3c64xx_eint0_irq_set_type(struct irq_data *irqd, unsigned int type)
s3c64xx_irq_set_handler(irqd, type);
/* Set up interrupt trigger */
reg = bank->eint_base + EINT0CON0_REG;
reg = d->virt_base + EINT0CON0_REG;
shift = ddata->eints[irqd->hwirq];
if (shift >= EINT_MAX_PER_REG) {
reg += 4;
@ -598,19 +599,14 @@ static struct irq_chip s3c64xx_eint0_irq_chip = {
static inline void s3c64xx_irq_demux_eint(struct irq_desc *desc, u32 range)
{
struct irq_chip *chip = irq_desc_get_chip(desc);
struct irq_data *irqd = irq_desc_get_irq_data(desc);
struct s3c64xx_eint0_domain_data *ddata =
irq_data_get_irq_chip_data(irqd);
struct samsung_pin_bank *bank = ddata->bank;
struct s3c64xx_eint0_data *data = irq_desc_get_handler_data(desc);
struct samsung_pinctrl_drv_data *drvdata = data->drvdata;
unsigned int pend, mask;
chained_irq_enter(chip, desc);
pend = readl(bank->eint_base + EINT0PEND_REG);
mask = readl(bank->eint_base + EINT0MASK_REG);
pend = readl(drvdata->virt_base + EINT0PEND_REG);
mask = readl(drvdata->virt_base + EINT0MASK_REG);
pend = pend & range & ~mask;
pend &= range;

View file

@ -1013,6 +1013,12 @@ samsung_pinctrl_get_soc_data(struct samsung_pinctrl_drv_data *d,
bank->eint_base = virt_base[0];
bank->pctl_base = virt_base[bdata->pctl_res_idx];
}
/*
* Legacy platforms should provide only one resource with IO memory.
* Store it as virt_base because legacy driver needs to access it
* through samsung_pinctrl_drv_data.
*/
d->virt_base = virt_base[0];
for_each_child_of_node(node, np) {
if (!of_find_property(np, "gpio-controller", NULL))

View file

@ -247,6 +247,10 @@ struct samsung_pin_ctrl {
/**
* struct samsung_pinctrl_drv_data: wrapper for holding driver data together.
* @node: global list node
* @virt_base: register base address of the controller; this will be equal
* to each bank samsung_pin_bank->pctl_base and used on legacy
* platforms (like S3C24XX or S3C64XX) which has to access the base
* through samsung_pinctrl_drv_data, not samsung_pin_bank).
* @dev: device instance representing the controller.
* @irq: interrpt number used by the controller to notify gpio interrupts.
* @ctrl: pin controller instance managed by the driver.
@ -262,6 +266,7 @@ struct samsung_pin_ctrl {
*/
struct samsung_pinctrl_drv_data {
struct list_head node;
void __iomem *virt_base;
struct device *dev;
int irq;

View file

@ -77,6 +77,8 @@
#define CPCAP_BIT_VAUDIO_MODE0 BIT(1)
#define CPCAP_BIT_V_AUDIO_EN BIT(0)
#define CPCAP_BIT_AUDIO_NORMAL_MODE 0x00
/*
* Off mode configuration bit. Used currently only by SW5 on omap4. There's
* the following comment in Motorola Linux kernel tree for it:
@ -217,7 +219,7 @@ static unsigned int cpcap_regulator_get_mode(struct regulator_dev *rdev)
regmap_read(rdev->regmap, rdev->desc->enable_reg, &value);
if (!(value & CPCAP_BIT_AUDIO_LOW_PWR))
if (value & CPCAP_BIT_AUDIO_LOW_PWR)
return REGULATOR_MODE_STANDBY;
return REGULATOR_MODE_NORMAL;
@ -230,10 +232,10 @@ static int cpcap_regulator_set_mode(struct regulator_dev *rdev,
switch (mode) {
case REGULATOR_MODE_NORMAL:
value = CPCAP_BIT_AUDIO_LOW_PWR;
value = CPCAP_BIT_AUDIO_NORMAL_MODE;
break;
case REGULATOR_MODE_STANDBY:
value = 0;
value = CPCAP_BIT_AUDIO_LOW_PWR;
break;
default:
return -EINVAL;

View file

@ -3,7 +3,7 @@
*
* Debug traces for zfcp.
*
* Copyright IBM Corp. 2002, 2016
* Copyright IBM Corp. 2002, 2017
*/
#define KMSG_COMPONENT "zfcp"
@ -447,6 +447,7 @@ static u16 zfcp_dbf_san_res_cap_len_if_gpn_ft(char *tag,
struct fc_ct_hdr *reqh = sg_virt(ct_els->req);
struct fc_ns_gid_ft *reqn = (struct fc_ns_gid_ft *)(reqh + 1);
struct scatterlist *resp_entry = ct_els->resp;
struct fc_ct_hdr *resph;
struct fc_gpn_ft_resp *acc;
int max_entries, x, last = 0;
@ -473,6 +474,13 @@ static u16 zfcp_dbf_san_res_cap_len_if_gpn_ft(char *tag,
return len; /* not GPN_FT response so do not cap */
acc = sg_virt(resp_entry);
/* cap all but accept CT responses to at least the CT header */
resph = (struct fc_ct_hdr *)acc;
if ((ct_els->status) ||
(resph->ct_cmd != cpu_to_be16(FC_FS_ACC)))
return max(FC_CT_HDR_LEN, ZFCP_DBF_SAN_MAX_PAYLOAD);
max_entries = (reqh->ct_mr_size * 4 / sizeof(struct fc_gpn_ft_resp))
+ 1 /* zfcp_fc_scan_ports: bytes correct, entries off-by-one
* to account for header as 1st pseudo "entry" */;
@ -555,8 +563,8 @@ void zfcp_dbf_scsi(char *tag, int level, struct scsi_cmnd *sc,
rec->scsi_retries = sc->retries;
rec->scsi_allowed = sc->allowed;
rec->scsi_id = sc->device->id;
/* struct zfcp_dbf_scsi needs to be updated to handle 64bit LUNs */
rec->scsi_lun = (u32)sc->device->lun;
rec->scsi_lun_64_hi = (u32)(sc->device->lun >> 32);
rec->host_scribble = (unsigned long)sc->host_scribble;
memcpy(rec->scsi_opcode, sc->cmnd,
@ -564,19 +572,32 @@ void zfcp_dbf_scsi(char *tag, int level, struct scsi_cmnd *sc,
if (fsf) {
rec->fsf_req_id = fsf->req_id;
rec->pl_len = FCP_RESP_WITH_EXT;
fcp_rsp = (struct fcp_resp_with_ext *)
&(fsf->qtcb->bottom.io.fcp_rsp);
/* mandatory parts of FCP_RSP IU in this SCSI record */
memcpy(&rec->fcp_rsp, fcp_rsp, FCP_RESP_WITH_EXT);
if (fcp_rsp->resp.fr_flags & FCP_RSP_LEN_VAL) {
fcp_rsp_info = (struct fcp_resp_rsp_info *) &fcp_rsp[1];
rec->fcp_rsp_info = fcp_rsp_info->rsp_code;
rec->pl_len += be32_to_cpu(fcp_rsp->ext.fr_rsp_len);
}
if (fcp_rsp->resp.fr_flags & FCP_SNS_LEN_VAL) {
rec->pl_len = min((u16)SCSI_SENSE_BUFFERSIZE,
(u16)ZFCP_DBF_PAY_MAX_REC);
zfcp_dbf_pl_write(dbf, sc->sense_buffer, rec->pl_len,
"fcp_sns", fsf->req_id);
rec->pl_len += be32_to_cpu(fcp_rsp->ext.fr_sns_len);
}
/* complete FCP_RSP IU in associated PAYload record
* but only if there are optional parts
*/
if (fcp_rsp->resp.fr_flags != 0)
zfcp_dbf_pl_write(
dbf, fcp_rsp,
/* at least one full PAY record
* but not beyond hardware response field
*/
min_t(u16, max_t(u16, rec->pl_len,
ZFCP_DBF_PAY_MAX_REC),
FSF_FCP_RSP_SIZE),
"fcp_riu", fsf->req_id);
}
debug_event(dbf->scsi, level, rec, sizeof(*rec));

View file

@ -2,7 +2,7 @@
* zfcp device driver
* debug feature declarations
*
* Copyright IBM Corp. 2008, 2016
* Copyright IBM Corp. 2008, 2017
*/
#ifndef ZFCP_DBF_H
@ -204,7 +204,7 @@ enum zfcp_dbf_scsi_id {
* @id: unique number of recovery record type
* @tag: identifier string specifying the location of initiation
* @scsi_id: scsi device id
* @scsi_lun: scsi device logical unit number
* @scsi_lun: scsi device logical unit number, low part of 64 bit, old 32 bit
* @scsi_result: scsi result
* @scsi_retries: current retry number of scsi request
* @scsi_allowed: allowed retries
@ -214,6 +214,7 @@ enum zfcp_dbf_scsi_id {
* @host_scribble: LLD specific data attached to SCSI request
* @pl_len: length of paload stored as zfcp_dbf_pay
* @fsf_rsp: response for fsf request
* @scsi_lun_64_hi: scsi device logical unit number, high part of 64 bit
*/
struct zfcp_dbf_scsi {
u8 id;
@ -230,6 +231,7 @@ struct zfcp_dbf_scsi {
u64 host_scribble;
u16 pl_len;
struct fcp_resp_with_ext fcp_rsp;
u32 scsi_lun_64_hi;
} __packed;
/**
@ -323,7 +325,11 @@ void zfcp_dbf_hba_fsf_response(struct zfcp_fsf_req *req)
{
struct fsf_qtcb *qtcb = req->qtcb;
if ((qtcb->prefix.prot_status != FSF_PROT_GOOD) &&
if (unlikely(req->status & (ZFCP_STATUS_FSFREQ_DISMISSED |
ZFCP_STATUS_FSFREQ_ERROR))) {
zfcp_dbf_hba_fsf_resp("fs_rerr", 3, req);
} else if ((qtcb->prefix.prot_status != FSF_PROT_GOOD) &&
(qtcb->prefix.prot_status != FSF_PROT_FSF_STATUS_PRESENTED)) {
zfcp_dbf_hba_fsf_resp("fs_perr", 1, req);
@ -401,7 +407,8 @@ void zfcp_dbf_scsi_abort(char *tag, struct scsi_cmnd *scmd,
* @flag: indicates type of reset (Target Reset, Logical Unit Reset)
*/
static inline
void zfcp_dbf_scsi_devreset(char *tag, struct scsi_cmnd *scmnd, u8 flag)
void zfcp_dbf_scsi_devreset(char *tag, struct scsi_cmnd *scmnd, u8 flag,
struct zfcp_fsf_req *fsf_req)
{
char tmp_tag[ZFCP_DBF_TAG_LEN];
@ -411,7 +418,7 @@ void zfcp_dbf_scsi_devreset(char *tag, struct scsi_cmnd *scmnd, u8 flag)
memcpy(tmp_tag, "lr_", 3);
memcpy(&tmp_tag[3], tag, 4);
_zfcp_dbf_scsi(tmp_tag, 1, scmnd, NULL);
_zfcp_dbf_scsi(tmp_tag, 1, scmnd, fsf_req);
}
/**

View file

@ -4,7 +4,7 @@
* Fibre Channel related definitions and inline functions for the zfcp
* device driver
*
* Copyright IBM Corp. 2009
* Copyright IBM Corp. 2009, 2017
*/
#ifndef ZFCP_FC_H
@ -279,6 +279,10 @@ void zfcp_fc_eval_fcp_rsp(struct fcp_resp_with_ext *fcp_rsp,
!(rsp_flags & FCP_SNS_LEN_VAL) &&
fcp_rsp->resp.fr_status == SAM_STAT_GOOD)
set_host_byte(scsi, DID_ERROR);
} else if (unlikely(rsp_flags & FCP_RESID_OVER)) {
/* FCP_DL was not sufficient for SCSI data length */
if (fcp_rsp->resp.fr_status == SAM_STAT_GOOD)
set_host_byte(scsi, DID_ERROR);
}
}

View file

@ -928,8 +928,8 @@ static void zfcp_fsf_send_ct_handler(struct zfcp_fsf_req *req)
switch (header->fsf_status) {
case FSF_GOOD:
zfcp_dbf_san_res("fsscth2", req);
ct->status = 0;
zfcp_dbf_san_res("fsscth2", req);
break;
case FSF_SERVICE_CLASS_NOT_SUPPORTED:
zfcp_fsf_class_not_supp(req);
@ -1109,8 +1109,8 @@ static void zfcp_fsf_send_els_handler(struct zfcp_fsf_req *req)
switch (header->fsf_status) {
case FSF_GOOD:
zfcp_dbf_san_res("fsselh1", req);
send_els->status = 0;
zfcp_dbf_san_res("fsselh1", req);
break;
case FSF_SERVICE_CLASS_NOT_SUPPORTED:
zfcp_fsf_class_not_supp(req);
@ -2258,7 +2258,8 @@ int zfcp_fsf_fcp_cmnd(struct scsi_cmnd *scsi_cmnd)
fcp_cmnd = (struct fcp_cmnd *) &req->qtcb->bottom.io.fcp_cmnd;
zfcp_fc_scsi_to_fcp(fcp_cmnd, scsi_cmnd, 0);
if (scsi_prot_sg_count(scsi_cmnd)) {
if ((scsi_get_prot_op(scsi_cmnd) != SCSI_PROT_NORMAL) &&
scsi_prot_sg_count(scsi_cmnd)) {
zfcp_qdio_set_data_div(qdio, &req->qdio_req,
scsi_prot_sg_count(scsi_cmnd));
retval = zfcp_qdio_sbals_from_sg(qdio, &req->qdio_req,

View file

@ -3,7 +3,7 @@
*
* Interface to Linux SCSI midlayer.
*
* Copyright IBM Corp. 2002, 2016
* Copyright IBM Corp. 2002, 2017
*/
#define KMSG_COMPONENT "zfcp"
@ -273,25 +273,29 @@ static int zfcp_task_mgmt_function(struct scsi_cmnd *scpnt, u8 tm_flags)
zfcp_erp_wait(adapter);
ret = fc_block_scsi_eh(scpnt);
if (ret)
if (ret) {
zfcp_dbf_scsi_devreset("fiof", scpnt, tm_flags, NULL);
return ret;
}
if (!(atomic_read(&adapter->status) &
ZFCP_STATUS_COMMON_RUNNING)) {
zfcp_dbf_scsi_devreset("nres", scpnt, tm_flags);
zfcp_dbf_scsi_devreset("nres", scpnt, tm_flags, NULL);
return SUCCESS;
}
}
if (!fsf_req)
if (!fsf_req) {
zfcp_dbf_scsi_devreset("reqf", scpnt, tm_flags, NULL);
return FAILED;
}
wait_for_completion(&fsf_req->completion);
if (fsf_req->status & ZFCP_STATUS_FSFREQ_TMFUNCFAILED) {
zfcp_dbf_scsi_devreset("fail", scpnt, tm_flags);
zfcp_dbf_scsi_devreset("fail", scpnt, tm_flags, fsf_req);
retval = FAILED;
} else {
zfcp_dbf_scsi_devreset("okay", scpnt, tm_flags);
zfcp_dbf_scsi_devreset("okay", scpnt, tm_flags, fsf_req);
zfcp_scsi_forget_cmnds(zfcp_sdev, tm_flags);
}

View file

@ -594,6 +594,7 @@ static int aac_get_container_name(struct scsi_cmnd * scsicmd)
aac_fib_init(cmd_fibcontext);
dinfo = (struct aac_get_name *) fib_data(cmd_fibcontext);
scsicmd->SCp.phase = AAC_OWNER_FIRMWARE;
dinfo->command = cpu_to_le32(VM_ContainerConfig);
dinfo->type = cpu_to_le32(CT_READ_NAME);
@ -611,10 +612,8 @@ static int aac_get_container_name(struct scsi_cmnd * scsicmd)
/*
* Check that the command queued to the controller
*/
if (status == -EINPROGRESS) {
scsicmd->SCp.phase = AAC_OWNER_FIRMWARE;
if (status == -EINPROGRESS)
return 0;
}
printk(KERN_WARNING "aac_get_container_name: aac_fib_send failed with status: %d.\n", status);
aac_fib_complete(cmd_fibcontext);
@ -725,6 +724,7 @@ static void _aac_probe_container1(void * context, struct fib * fibptr)
dinfo->count = cpu_to_le32(scmd_id(scsicmd));
dinfo->type = cpu_to_le32(FT_FILESYS);
scsicmd->SCp.phase = AAC_OWNER_FIRMWARE;
status = aac_fib_send(ContainerCommand,
fibptr,
@ -736,9 +736,7 @@ static void _aac_probe_container1(void * context, struct fib * fibptr)
/*
* Check that the command queued to the controller
*/
if (status == -EINPROGRESS)
scsicmd->SCp.phase = AAC_OWNER_FIRMWARE;
else if (status < 0) {
if (status < 0 && status != -EINPROGRESS) {
/* Inherit results from VM_NameServe, if any */
dresp->status = cpu_to_le32(ST_OK);
_aac_probe_container2(context, fibptr);
@ -766,6 +764,7 @@ static int _aac_probe_container(struct scsi_cmnd * scsicmd, int (*callback)(stru
dinfo->count = cpu_to_le32(scmd_id(scsicmd));
dinfo->type = cpu_to_le32(FT_FILESYS);
scsicmd->SCp.ptr = (char *)callback;
scsicmd->SCp.phase = AAC_OWNER_FIRMWARE;
status = aac_fib_send(ContainerCommand,
fibptr,
@ -777,10 +776,9 @@ static int _aac_probe_container(struct scsi_cmnd * scsicmd, int (*callback)(stru
/*
* Check that the command queued to the controller
*/
if (status == -EINPROGRESS) {
scsicmd->SCp.phase = AAC_OWNER_FIRMWARE;
if (status == -EINPROGRESS)
return 0;
}
if (status < 0) {
scsicmd->SCp.ptr = NULL;
aac_fib_complete(fibptr);
@ -1126,6 +1124,7 @@ static int aac_get_container_serial(struct scsi_cmnd * scsicmd)
dinfo->command = cpu_to_le32(VM_ContainerConfig);
dinfo->type = cpu_to_le32(CT_CID_TO_32BITS_UID);
dinfo->cid = cpu_to_le32(scmd_id(scsicmd));
scsicmd->SCp.phase = AAC_OWNER_FIRMWARE;
status = aac_fib_send(ContainerCommand,
cmd_fibcontext,
@ -1138,10 +1137,8 @@ static int aac_get_container_serial(struct scsi_cmnd * scsicmd)
/*
* Check that the command queued to the controller
*/
if (status == -EINPROGRESS) {
scsicmd->SCp.phase = AAC_OWNER_FIRMWARE;
if (status == -EINPROGRESS)
return 0;
}
printk(KERN_WARNING "aac_get_container_serial: aac_fib_send failed with status: %d.\n", status);
aac_fib_complete(cmd_fibcontext);
@ -2335,16 +2332,14 @@ static int aac_read(struct scsi_cmnd * scsicmd)
* Alocate and initialize a Fib
*/
cmd_fibcontext = aac_fib_alloc_tag(dev, scsicmd);
scsicmd->SCp.phase = AAC_OWNER_FIRMWARE;
status = aac_adapter_read(cmd_fibcontext, scsicmd, lba, count);
/*
* Check that the command queued to the controller
*/
if (status == -EINPROGRESS) {
scsicmd->SCp.phase = AAC_OWNER_FIRMWARE;
if (status == -EINPROGRESS)
return 0;
}
printk(KERN_WARNING "aac_read: aac_fib_send failed with status: %d.\n", status);
/*
@ -2429,16 +2424,14 @@ static int aac_write(struct scsi_cmnd * scsicmd)
* Allocate and initialize a Fib then setup a BlockWrite command
*/
cmd_fibcontext = aac_fib_alloc_tag(dev, scsicmd);
scsicmd->SCp.phase = AAC_OWNER_FIRMWARE;
status = aac_adapter_write(cmd_fibcontext, scsicmd, lba, count, fua);
/*
* Check that the command queued to the controller
*/
if (status == -EINPROGRESS) {
scsicmd->SCp.phase = AAC_OWNER_FIRMWARE;
if (status == -EINPROGRESS)
return 0;
}
printk(KERN_WARNING "aac_write: aac_fib_send failed with status: %d\n", status);
/*
@ -2588,6 +2581,7 @@ static int aac_synchronize(struct scsi_cmnd *scsicmd)
synchronizecmd->cid = cpu_to_le32(scmd_id(scsicmd));
synchronizecmd->count =
cpu_to_le32(sizeof(((struct aac_synchronize_reply *)NULL)->data));
scsicmd->SCp.phase = AAC_OWNER_FIRMWARE;
/*
* Now send the Fib to the adapter
@ -2603,10 +2597,8 @@ static int aac_synchronize(struct scsi_cmnd *scsicmd)
/*
* Check that the command queued to the controller
*/
if (status == -EINPROGRESS) {
scsicmd->SCp.phase = AAC_OWNER_FIRMWARE;
if (status == -EINPROGRESS)
return 0;
}
printk(KERN_WARNING
"aac_synchronize: aac_fib_send failed with status: %d.\n", status);
@ -2666,6 +2658,7 @@ static int aac_start_stop(struct scsi_cmnd *scsicmd)
pmcmd->cid = cpu_to_le32(sdev_id(sdev));
pmcmd->parm = (scsicmd->cmnd[1] & 1) ?
cpu_to_le32(CT_PM_UNIT_IMMEDIATE) : 0;
scsicmd->SCp.phase = AAC_OWNER_FIRMWARE;
/*
* Now send the Fib to the adapter
@ -2681,10 +2674,8 @@ static int aac_start_stop(struct scsi_cmnd *scsicmd)
/*
* Check that the command queued to the controller
*/
if (status == -EINPROGRESS) {
scsicmd->SCp.phase = AAC_OWNER_FIRMWARE;
if (status == -EINPROGRESS)
return 0;
}
aac_fib_complete(cmd_fibcontext);
aac_fib_free(cmd_fibcontext);
@ -3692,16 +3683,14 @@ static int aac_send_srb_fib(struct scsi_cmnd* scsicmd)
* Allocate and initialize a Fib then setup a BlockWrite command
*/
cmd_fibcontext = aac_fib_alloc_tag(dev, scsicmd);
scsicmd->SCp.phase = AAC_OWNER_FIRMWARE;
status = aac_adapter_scsi(cmd_fibcontext, scsicmd);
/*
* Check that the command queued to the controller
*/
if (status == -EINPROGRESS) {
scsicmd->SCp.phase = AAC_OWNER_FIRMWARE;
if (status == -EINPROGRESS)
return 0;
}
printk(KERN_WARNING "aac_srb: aac_fib_send failed with status: %d\n", status);
aac_fib_complete(cmd_fibcontext);
@ -3739,15 +3728,14 @@ static int aac_send_hba_fib(struct scsi_cmnd *scsicmd)
if (!cmd_fibcontext)
return -1;
scsicmd->SCp.phase = AAC_OWNER_FIRMWARE;
status = aac_adapter_hba(cmd_fibcontext, scsicmd);
/*
* Check that the command queued to the controller
*/
if (status == -EINPROGRESS) {
scsicmd->SCp.phase = AAC_OWNER_FIRMWARE;
if (status == -EINPROGRESS)
return 0;
}
pr_warn("aac_hba_cmd_req: aac_fib_send failed with status: %d\n",
status);

View file

@ -1995,9 +1995,12 @@ static void megasas_complete_outstanding_ioctls(struct megasas_instance *instanc
if (cmd_fusion->sync_cmd_idx != (u32)ULONG_MAX) {
cmd_mfi = instance->cmd_list[cmd_fusion->sync_cmd_idx];
if (cmd_mfi->sync_cmd &&
cmd_mfi->frame->hdr.cmd != MFI_CMD_ABORT)
(cmd_mfi->frame->hdr.cmd != MFI_CMD_ABORT)) {
cmd_mfi->frame->hdr.cmd_status =
MFI_STAT_WRONG_STATE;
megasas_complete_cmd(instance,
cmd_mfi, DID_OK);
}
}
}
} else {
@ -5478,7 +5481,8 @@ static int megasas_init_fw(struct megasas_instance *instance)
instance->throttlequeuedepth =
MEGASAS_THROTTLE_QUEUE_DEPTH;
if (resetwaittime > MEGASAS_RESET_WAIT_TIME)
if ((resetwaittime < 1) ||
(resetwaittime > MEGASAS_RESET_WAIT_TIME))
resetwaittime = MEGASAS_RESET_WAIT_TIME;
if ((scmd_timeout < 10) || (scmd_timeout > MEGASAS_DEFAULT_CMD_TIMEOUT))
@ -5649,6 +5653,14 @@ megasas_register_aen(struct megasas_instance *instance, u32 seq_num,
prev_aen.word =
le32_to_cpu(instance->aen_cmd->frame->dcmd.mbox.w[1]);
if ((curr_aen.members.class < MFI_EVT_CLASS_DEBUG) ||
(curr_aen.members.class > MFI_EVT_CLASS_DEAD)) {
dev_info(&instance->pdev->dev,
"%s %d out of range class %d send by application\n",
__func__, __LINE__, curr_aen.members.class);
return 0;
}
/*
* A class whose enum value is smaller is inclusive of all
* higher values. If a PROGRESS (= -1) was previously

View file

@ -3287,7 +3287,7 @@ build_mpt_mfi_pass_thru(struct megasas_instance *instance,
mpi25_ieee_chain->Flags = IEEE_SGE_FLAGS_CHAIN_ELEMENT |
MPI2_IEEE_SGE_FLAGS_IOCPLBNTA_ADDR;
mpi25_ieee_chain->Length = cpu_to_le32(instance->max_chain_frame_sz);
mpi25_ieee_chain->Length = cpu_to_le32(instance->mfi_frame_size);
}
/**

View file

@ -1575,7 +1575,7 @@ struct qedi_cmd *qedi_get_cmd_from_tid(struct qedi_ctx *qedi, u32 tid)
{
struct qedi_cmd *cmd = NULL;
if (tid > MAX_ISCSI_TASK_ENTRIES)
if (tid >= MAX_ISCSI_TASK_ENTRIES)
return NULL;
cmd = qedi->itt_map[tid].p_cmd;

View file

@ -318,6 +318,8 @@ qla2x00_sysfs_write_optrom_ctl(struct file *filp, struct kobject *kobj,
return -EINVAL;
if (start > ha->optrom_size)
return -EINVAL;
if (size > ha->optrom_size - start)
size = ha->optrom_size - start;
mutex_lock(&ha->optrom_mutex);
switch (val) {
@ -343,8 +345,7 @@ qla2x00_sysfs_write_optrom_ctl(struct file *filp, struct kobject *kobj,
}
ha->optrom_region_start = start;
ha->optrom_region_size = start + size > ha->optrom_size ?
ha->optrom_size - start : size;
ha->optrom_region_size = start + size;
ha->optrom_state = QLA_SREADING;
ha->optrom_buffer = vmalloc(ha->optrom_region_size);
@ -417,8 +418,7 @@ qla2x00_sysfs_write_optrom_ctl(struct file *filp, struct kobject *kobj,
}
ha->optrom_region_start = start;
ha->optrom_region_size = start + size > ha->optrom_size ?
ha->optrom_size - start : size;
ha->optrom_region_size = start + size;
ha->optrom_state = QLA_SWRITING;
ha->optrom_buffer = vmalloc(ha->optrom_region_size);

View file

@ -3080,7 +3080,7 @@ int qla24xx_async_gpsc(scsi_qla_host_t *vha, fc_port_t *fcport)
GPSC_RSP_SIZE);
/* GPSC req */
memcpy(ct_req->req.gpsc.port_name, fcport->port_name,
memcpy(ct_req->req.gpsc.port_name, fcport->fabric_port_name,
WWN_SIZE);
sp->u.iocb_cmd.u.ctarg.req = fcport->ct_desc.ct_sns;

View file

@ -7804,6 +7804,7 @@ struct qla_qpair *qla2xxx_create_qpair(struct scsi_qla_host *vha, int qos,
ha->queue_pair_map[qpair_id] = qpair;
qpair->id = qpair_id;
qpair->vp_idx = vp_idx;
qpair->fw_started = ha->flags.fw_started;
INIT_LIST_HEAD(&qpair->hints_list);
qpair->chip_reset = ha->base_qpair->chip_reset;
qpair->enable_class_2 = ha->base_qpair->enable_class_2;

View file

@ -3429,7 +3429,7 @@ msix_register_fail:
}
/* Enable MSI-X vector for response queue update for queue 0 */
if (IS_QLA25XX(ha) || IS_QLA83XX(ha) || IS_QLA27XX(ha)) {
if (IS_QLA83XX(ha) || IS_QLA27XX(ha)) {
if (ha->msixbase && ha->mqiobase &&
(ha->max_rsp_queues > 1 || ha->max_req_queues > 1 ||
ql2xmqsupport))

View file

@ -54,6 +54,7 @@ static struct rom_cmd {
{ MBC_GET_MEM_OFFLOAD_CNTRL_STAT },
{ MBC_GET_RETRY_COUNT },
{ MBC_TRACE_CONTROL },
{ MBC_INITIALIZE_MULTIQ },
};
static int is_rom_cmd(uint16_t cmd)
@ -3689,7 +3690,7 @@ qla24xx_report_id_acquisition(scsi_qla_host_t *vha,
if (qla_ini_mode_enabled(vha) &&
ha->flags.fawwpn_enabled &&
(rptid_entry->u.f1.flags &
VP_FLAGS_NAME_VALID)) {
BIT_6)) {
memcpy(vha->port_name,
rptid_entry->u.f1.port_name,
WWN_SIZE);

View file

@ -74,7 +74,7 @@ qla24xx_deallocate_vp_id(scsi_qla_host_t *vha)
* ensures no active vp_list traversal while the vport is removed
* from the queue)
*/
wait_event_timeout(vha->vref_waitq, atomic_read(&vha->vref_count),
wait_event_timeout(vha->vref_waitq, !atomic_read(&vha->vref_count),
10*HZ);
spin_lock_irqsave(&ha->vport_slock, flags);

View file

@ -6796,7 +6796,7 @@ qlt_probe_one_stage1(struct scsi_qla_host *base_vha, struct qla_hw_data *ha)
if (!QLA_TGT_MODE_ENABLED())
return;
if (ha->mqenable || IS_QLA83XX(ha) || IS_QLA27XX(ha)) {
if (IS_QLA83XX(ha) || IS_QLA27XX(ha)) {
ISP_ATIO_Q_IN(base_vha) = &ha->mqiobase->isp25mq.atio_q_in;
ISP_ATIO_Q_OUT(base_vha) = &ha->mqiobase->isp25mq.atio_q_out;
} else {

View file

@ -828,6 +828,39 @@ static int max_sectors_bytes(struct request_queue *q)
return max_sectors << 9;
}
static void
sg_fill_request_table(Sg_fd *sfp, sg_req_info_t *rinfo)
{
Sg_request *srp;
int val;
unsigned int ms;
val = 0;
list_for_each_entry(srp, &sfp->rq_list, entry) {
if (val > SG_MAX_QUEUE)
break;
rinfo[val].req_state = srp->done + 1;
rinfo[val].problem =
srp->header.masked_status &
srp->header.host_status &
srp->header.driver_status;
if (srp->done)
rinfo[val].duration =
srp->header.duration;
else {
ms = jiffies_to_msecs(jiffies);
rinfo[val].duration =
(ms > srp->header.duration) ?
(ms - srp->header.duration) : 0;
}
rinfo[val].orphan = srp->orphan;
rinfo[val].sg_io_owned = srp->sg_io_owned;
rinfo[val].pack_id = srp->header.pack_id;
rinfo[val].usr_ptr = srp->header.usr_ptr;
val++;
}
}
static long
sg_ioctl(struct file *filp, unsigned int cmd_in, unsigned long arg)
{
@ -1012,38 +1045,13 @@ sg_ioctl(struct file *filp, unsigned int cmd_in, unsigned long arg)
return -EFAULT;
else {
sg_req_info_t *rinfo;
unsigned int ms;
rinfo = kmalloc(SZ_SG_REQ_INFO * SG_MAX_QUEUE,
GFP_KERNEL);
rinfo = kzalloc(SZ_SG_REQ_INFO * SG_MAX_QUEUE,
GFP_KERNEL);
if (!rinfo)
return -ENOMEM;
read_lock_irqsave(&sfp->rq_list_lock, iflags);
val = 0;
list_for_each_entry(srp, &sfp->rq_list, entry) {
if (val >= SG_MAX_QUEUE)
break;
memset(&rinfo[val], 0, SZ_SG_REQ_INFO);
rinfo[val].req_state = srp->done + 1;
rinfo[val].problem =
srp->header.masked_status &
srp->header.host_status &
srp->header.driver_status;
if (srp->done)
rinfo[val].duration =
srp->header.duration;
else {
ms = jiffies_to_msecs(jiffies);
rinfo[val].duration =
(ms > srp->header.duration) ?
(ms - srp->header.duration) : 0;
}
rinfo[val].orphan = srp->orphan;
rinfo[val].sg_io_owned = srp->sg_io_owned;
rinfo[val].pack_id = srp->header.pack_id;
rinfo[val].usr_ptr = srp->header.usr_ptr;
val++;
}
sg_fill_request_table(sfp, rinfo);
read_unlock_irqrestore(&sfp->rq_list_lock, iflags);
result = __copy_to_user(p, rinfo,
SZ_SG_REQ_INFO * SG_MAX_QUEUE);

View file

@ -1640,6 +1640,8 @@ static int storvsc_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scmnd)
put_cpu();
if (ret == -EAGAIN) {
if (payload_sz > sizeof(cmd_request->mpb))
kfree(payload);
/* no more space */
return SCSI_MLQUEUE_DEVICE_BUSY;
}

View file

@ -361,6 +361,32 @@ int tty_insert_flip_string_flags(struct tty_port *port,
}
EXPORT_SYMBOL(tty_insert_flip_string_flags);
/**
* __tty_insert_flip_char - Add one character to the tty buffer
* @port: tty port
* @ch: character
* @flag: flag byte
*
* Queue a single byte to the tty buffering, with an optional flag.
* This is the slow path of tty_insert_flip_char.
*/
int __tty_insert_flip_char(struct tty_port *port, unsigned char ch, char flag)
{
struct tty_buffer *tb;
int flags = (flag == TTY_NORMAL) ? TTYB_NORMAL : 0;
if (!__tty_buffer_request_room(port, 1, flags))
return 0;
tb = port->buf.tail;
if (~tb->flags & TTYB_NORMAL)
*flag_buf_ptr(tb, tb->used) = flag;
*char_buf_ptr(tb, tb->used++) = ch;
return 1;
}
EXPORT_SYMBOL(__tty_insert_flip_char);
/**
* tty_schedule_flip - push characters to ldisc
* @port: tty port to push from

View file

@ -595,7 +595,7 @@ static loff_t ext4_seek_data(struct file *file, loff_t offset, loff_t maxsize)
inode_lock(inode);
isize = i_size_read(inode);
if (offset >= isize) {
if (offset < 0 || offset >= isize) {
inode_unlock(inode);
return -ENXIO;
}
@ -658,7 +658,7 @@ static loff_t ext4_seek_hole(struct file *file, loff_t offset, loff_t maxsize)
inode_lock(inode);
isize = i_size_read(inode);
if (offset >= isize) {
if (offset < 0 || offset >= isize) {
inode_unlock(inode);
return -ENXIO;
}

View file

@ -2404,6 +2404,7 @@ static void ext4_orphan_cleanup(struct super_block *sb,
unsigned int s_flags = sb->s_flags;
int ret, nr_orphans = 0, nr_truncates = 0;
#ifdef CONFIG_QUOTA
int quota_update = 0;
int i;
#endif
if (!es->s_last_orphan) {
@ -2442,14 +2443,32 @@ static void ext4_orphan_cleanup(struct super_block *sb,
#ifdef CONFIG_QUOTA
/* Needed for iput() to work correctly and not trash data */
sb->s_flags |= MS_ACTIVE;
/* Turn on quotas so that they are updated correctly */
/*
* Turn on quotas which were not enabled for read-only mounts if
* filesystem has quota feature, so that they are updated correctly.
*/
if (ext4_has_feature_quota(sb) && (s_flags & MS_RDONLY)) {
int ret = ext4_enable_quotas(sb);
if (!ret)
quota_update = 1;
else
ext4_msg(sb, KERN_ERR,
"Cannot turn on quotas: error %d", ret);
}
/* Turn on journaled quotas used for old sytle */
for (i = 0; i < EXT4_MAXQUOTAS; i++) {
if (EXT4_SB(sb)->s_qf_names[i]) {
int ret = ext4_quota_on_mount(sb, i);
if (ret < 0)
if (!ret)
quota_update = 1;
else
ext4_msg(sb, KERN_ERR,
"Cannot turn on journaled "
"quota: error %d", ret);
"quota: type %d: error %d", i, ret);
}
}
#endif
@ -2510,10 +2529,12 @@ static void ext4_orphan_cleanup(struct super_block *sb,
ext4_msg(sb, KERN_INFO, "%d truncate%s cleaned up",
PLURAL(nr_truncates));
#ifdef CONFIG_QUOTA
/* Turn quotas off */
for (i = 0; i < EXT4_MAXQUOTAS; i++) {
if (sb_dqopt(sb)->files[i])
dquot_quota_off(sb, i);
/* Turn off quotas if they were enabled for orphan cleanup */
if (quota_update) {
for (i = 0; i < EXT4_MAXQUOTAS; i++) {
if (sb_dqopt(sb)->files[i])
dquot_quota_off(sb, i);
}
}
#endif
sb->s_flags = s_flags; /* Restore MS_RDONLY status */
@ -5512,6 +5533,9 @@ static int ext4_enable_quotas(struct super_block *sb)
DQUOT_USAGE_ENABLED |
(quota_mopt[type] ? DQUOT_LIMITS_ENABLED : 0));
if (err) {
for (type--; type >= 0; type--)
dquot_quota_off(sb, type);
ext4_warning(sb,
"Failed to enable quota tracking "
"(type=%d, err=%d). Please run "

View file

@ -61,9 +61,9 @@ struct posix_acl *orangefs_get_acl(struct inode *inode, int type)
return acl;
}
int orangefs_set_acl(struct inode *inode, struct posix_acl *acl, int type)
static int __orangefs_set_acl(struct inode *inode, struct posix_acl *acl,
int type)
{
struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode);
int error = 0;
void *value = NULL;
size_t size = 0;
@ -72,22 +72,6 @@ int orangefs_set_acl(struct inode *inode, struct posix_acl *acl, int type)
switch (type) {
case ACL_TYPE_ACCESS:
name = XATTR_NAME_POSIX_ACL_ACCESS;
if (acl) {
umode_t mode;
error = posix_acl_update_mode(inode, &mode, &acl);
if (error) {
gossip_err("%s: posix_acl_update_mode err: %d\n",
__func__,
error);
return error;
}
if (inode->i_mode != mode)
SetModeFlag(orangefs_inode);
inode->i_mode = mode;
mark_inode_dirty_sync(inode);
}
break;
case ACL_TYPE_DEFAULT:
name = XATTR_NAME_POSIX_ACL_DEFAULT;
@ -132,6 +116,29 @@ out:
return error;
}
int orangefs_set_acl(struct inode *inode, struct posix_acl *acl, int type)
{
int error;
if (type == ACL_TYPE_ACCESS && acl) {
umode_t mode;
error = posix_acl_update_mode(inode, &mode, &acl);
if (error) {
gossip_err("%s: posix_acl_update_mode err: %d\n",
__func__,
error);
return error;
}
if (inode->i_mode != mode)
SetModeFlag(ORANGEFS_I(inode));
inode->i_mode = mode;
mark_inode_dirty_sync(inode);
}
return __orangefs_set_acl(inode, acl, type);
}
int orangefs_init_acl(struct inode *inode, struct inode *dir)
{
struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode);
@ -146,13 +153,14 @@ int orangefs_init_acl(struct inode *inode, struct inode *dir)
return error;
if (default_acl) {
error = orangefs_set_acl(inode, default_acl, ACL_TYPE_DEFAULT);
error = __orangefs_set_acl(inode, default_acl,
ACL_TYPE_DEFAULT);
posix_acl_release(default_acl);
}
if (acl) {
if (!error)
error = orangefs_set_acl(inode, acl, ACL_TYPE_ACCESS);
error = __orangefs_set_acl(inode, acl, ACL_TYPE_ACCESS);
posix_acl_release(acl);
}

View file

@ -1,7 +1,7 @@
/*
* AMD Cryptographic Coprocessor (CCP) driver
*
* Copyright (C) 2013,2016 Advanced Micro Devices, Inc.
* Copyright (C) 2013,2017 Advanced Micro Devices, Inc.
*
* Author: Tom Lendacky <thomas.lendacky@amd.com>
* Author: Gary R Hook <gary.hook@amd.com>
@ -231,6 +231,7 @@ enum ccp_xts_aes_unit_size {
* AES operation the new IV overwrites the old IV.
*/
struct ccp_xts_aes_engine {
enum ccp_aes_type type;
enum ccp_aes_action action;
enum ccp_xts_aes_unit_size unit_size;

View file

@ -57,7 +57,9 @@ static inline void cpuset_dec(void)
extern int cpuset_init(void);
extern void cpuset_init_smp(void);
extern void cpuset_force_rebuild(void);
extern void cpuset_update_active_cpus(void);
extern void cpuset_wait_for_hotplug(void);
extern void cpuset_cpus_allowed(struct task_struct *p, struct cpumask *mask);
extern void cpuset_cpus_allowed_fallback(struct task_struct *p);
extern nodemask_t cpuset_mems_allowed(struct task_struct *p);
@ -170,11 +172,15 @@ static inline bool cpusets_enabled(void) { return false; }
static inline int cpuset_init(void) { return 0; }
static inline void cpuset_init_smp(void) {}
static inline void cpuset_force_rebuild(void) { }
static inline void cpuset_update_active_cpus(void)
{
partition_sched_domains(1, NULL, NULL);
}
static inline void cpuset_wait_for_hotplug(void) { }
static inline void cpuset_cpus_allowed(struct task_struct *p,
struct cpumask *mask)
{

View file

@ -307,7 +307,7 @@ DECLARE_PER_CPU(int, disable_stack_tracer);
static inline void stack_tracer_disable(void)
{
/* Preemption or interupts must be disabled */
if (IS_ENABLED(CONFIG_PREEMPT_DEBUG))
if (IS_ENABLED(CONFIG_DEBUG_PREEMPT))
WARN_ON_ONCE(!preempt_count() || !irqs_disabled());
this_cpu_inc(disable_stack_tracer);
}
@ -320,7 +320,7 @@ static inline void stack_tracer_disable(void)
*/
static inline void stack_tracer_enable(void)
{
if (IS_ENABLED(CONFIG_PREEMPT_DEBUG))
if (IS_ENABLED(CONFIG_DEBUG_PREEMPT))
WARN_ON_ONCE(!preempt_count() || !irqs_disabled());
this_cpu_dec(disable_stack_tracer);
}

View file

@ -12,6 +12,7 @@ extern int tty_prepare_flip_string(struct tty_port *port,
unsigned char **chars, size_t size);
extern void tty_flip_buffer_push(struct tty_port *port);
void tty_schedule_flip(struct tty_port *port);
int __tty_insert_flip_char(struct tty_port *port, unsigned char ch, char flag);
static inline int tty_insert_flip_char(struct tty_port *port,
unsigned char ch, char flag)
@ -26,7 +27,7 @@ static inline int tty_insert_flip_char(struct tty_port *port,
*char_buf_ptr(tb, tb->used++) = ch;
return 1;
}
return tty_insert_flip_string_flags(port, &ch, &flag, 1);
return __tty_insert_flip_char(port, ch, flag);
}
static inline int tty_insert_flip_string(struct tty_port *port,

View file

@ -156,7 +156,7 @@ copy_to_user(void __user *to, const void *from, unsigned long n)
}
#ifdef CONFIG_COMPAT
static __always_inline unsigned long __must_check
copy_in_user(void __user *to, const void *from, unsigned long n)
copy_in_user(void __user *to, const void __user *from, unsigned long n)
{
might_fault();
if (access_ok(VERIFY_WRITE, to, n) && access_ok(VERIFY_READ, from, n))

View file

@ -2260,6 +2260,13 @@ retry:
mutex_unlock(&cpuset_mutex);
}
static bool force_rebuild;
void cpuset_force_rebuild(void)
{
force_rebuild = true;
}
/**
* cpuset_hotplug_workfn - handle CPU/memory hotunplug for a cpuset
*
@ -2334,8 +2341,10 @@ static void cpuset_hotplug_workfn(struct work_struct *work)
}
/* rebuild sched domains if cpus_allowed has changed */
if (cpus_updated)
if (cpus_updated || force_rebuild) {
force_rebuild = false;
rebuild_sched_domains();
}
}
void cpuset_update_active_cpus(void)
@ -2354,6 +2363,11 @@ void cpuset_update_active_cpus(void)
schedule_work(&cpuset_hotplug_work);
}
void cpuset_wait_for_hotplug(void)
{
flush_work(&cpuset_hotplug_work);
}
/*
* Keep top_cpuset.mems_allowed tracking node_states[N_MEMORY].
* Call this routine anytime after node_states[N_MEMORY] changes.

View file

@ -1252,7 +1252,17 @@ static int cpuhp_store_callbacks(enum cpuhp_state state, const char *name,
struct cpuhp_step *sp;
int ret = 0;
if (state == CPUHP_AP_ONLINE_DYN || state == CPUHP_BP_PREPARE_DYN) {
/*
* If name is NULL, then the state gets removed.
*
* CPUHP_AP_ONLINE_DYN and CPUHP_BP_PREPARE_DYN are handed out on
* the first allocation from these dynamic ranges, so the removal
* would trigger a new allocation and clear the wrong (already
* empty) state, leaving the callbacks of the to be cleared state
* dangling, which causes wreckage on the next hotplug operation.
*/
if (name && (state == CPUHP_AP_ONLINE_DYN ||
state == CPUHP_BP_PREPARE_DYN)) {
ret = cpuhp_reserve_state(state);
if (ret < 0)
return ret;

View file

@ -20,8 +20,9 @@
#include <linux/workqueue.h>
#include <linux/kmod.h>
#include <trace/events/power.h>
#include <linux/cpuset.h>
/*
/*
* Timeout for stopping processes
*/
unsigned int __read_mostly freeze_timeout_msecs = 20 * MSEC_PER_SEC;
@ -202,6 +203,8 @@ void thaw_processes(void)
__usermodehelper_set_disable_depth(UMH_FREEZING);
thaw_workqueues();
cpuset_wait_for_hotplug();
read_lock(&tasklist_lock);
for_each_process_thread(g, p) {
/* No other threads should have PF_SUSPEND_TASK set */

View file

@ -896,6 +896,15 @@ static void __synchronize_srcu(struct srcu_struct *sp, bool do_norm)
__call_srcu(sp, &rcu.head, wakeme_after_rcu, do_norm);
wait_for_completion(&rcu.completion);
destroy_rcu_head_on_stack(&rcu.head);
/*
* Make sure that later code is ordered after the SRCU grace
* period. This pairs with the raw_spin_lock_irq_rcu_node()
* in srcu_invoke_callbacks(). Unlike Tree RCU, this is needed
* because the current CPU might have been totally uninvolved with
* (and thus unordered against) that grace period.
*/
smp_mb();
}
/**

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