updating to mainline 4.13.4
This commit is contained in:
parent
0bcdae08d9
commit
e4647daec4
|
@ -31,11 +31,13 @@ Setup
|
||||||
CONFIG_DEBUG_INFO_REDUCED off. If your architecture supports
|
CONFIG_DEBUG_INFO_REDUCED off. If your architecture supports
|
||||||
CONFIG_FRAME_POINTER, keep it enabled.
|
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,
|
Alternatively, QEMU allows to boot the kernel directly using -kernel,
|
||||||
-append, -initrd command line switches. This is generally only useful if
|
-append, -initrd command line switches. This is generally only useful if
|
||||||
you do not depend on modules. See QEMU documentation for more details on
|
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
|
- Enable the gdb stub of QEMU/KVM, either
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
VERSION = 4
|
VERSION = 4
|
||||||
PATCHLEVEL = 13
|
PATCHLEVEL = 13
|
||||||
SUBLEVEL = 3
|
SUBLEVEL = 4
|
||||||
EXTRAVERSION =
|
EXTRAVERSION =
|
||||||
NAME = Fearless Coyote
|
NAME = Fearless Coyote
|
||||||
|
|
||||||
|
|
|
@ -92,6 +92,12 @@ ENTRY(EV_MachineCheck)
|
||||||
lr r0, [efa]
|
lr r0, [efa]
|
||||||
mov r1, sp
|
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
|
lsr r3, r2, 8
|
||||||
bmsk r3, r3, 7
|
bmsk r3, r3, 7
|
||||||
brne r3, ECR_C_MCHK_DUP_TLB, 1f
|
brne r3, ECR_C_MCHK_DUP_TLB, 1f
|
||||||
|
|
|
@ -908,9 +908,6 @@ void do_tlb_overlap_fault(unsigned long cause, unsigned long address,
|
||||||
|
|
||||||
local_irq_save(flags);
|
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 */
|
/* loop thru all sets of TLB */
|
||||||
for (set = 0; set < mmu->sets; set++) {
|
for (set = 0; set < mmu->sets; set++) {
|
||||||
|
|
||||||
|
|
|
@ -47,14 +47,26 @@ union ieee754dp ieee754dp_fmax(union ieee754dp x, union ieee754dp y)
|
||||||
case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
|
case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
|
||||||
return ieee754dp_nanxcpt(x);
|
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_ZERO, IEEE754_CLASS_QNAN):
|
||||||
case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
|
case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
|
||||||
case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN):
|
case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN):
|
||||||
case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN):
|
case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN):
|
||||||
return x;
|
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_ZERO):
|
||||||
case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM):
|
case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM):
|
||||||
case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM):
|
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;
|
return ys ? x : y;
|
||||||
|
|
||||||
case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
|
case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
|
||||||
if (xs == ys)
|
return ieee754dp_zero(xs & ys);
|
||||||
return x;
|
|
||||||
return ieee754dp_zero(1);
|
|
||||||
|
|
||||||
case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
|
case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
|
||||||
DPDNORMX;
|
DPDNORMX;
|
||||||
|
@ -106,16 +116,32 @@ union ieee754dp ieee754dp_fmax(union ieee754dp x, union ieee754dp y)
|
||||||
else if (xs < ys)
|
else if (xs < ys)
|
||||||
return x;
|
return x;
|
||||||
|
|
||||||
/* Compare exponent */
|
/* Signs of inputs are equal, let's compare exponents */
|
||||||
if (xe > ye)
|
if (xs == 0) {
|
||||||
return x;
|
/* Inputs are both positive */
|
||||||
else if (xe < ye)
|
if (xe > ye)
|
||||||
return y;
|
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)
|
if (xm <= ym)
|
||||||
return y;
|
return x;
|
||||||
return x;
|
return y;
|
||||||
}
|
}
|
||||||
|
|
||||||
union ieee754dp ieee754dp_fmaxa(union ieee754dp x, union ieee754dp 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):
|
case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
|
||||||
return ieee754dp_nanxcpt(x);
|
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_ZERO, IEEE754_CLASS_QNAN):
|
||||||
case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
|
case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
|
||||||
case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN):
|
case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN):
|
||||||
case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN):
|
case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN):
|
||||||
return x;
|
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_ZERO):
|
||||||
case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM):
|
case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM):
|
||||||
case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM):
|
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
|
* 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_ZERO):
|
||||||
case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM):
|
case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM):
|
||||||
case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM):
|
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):
|
case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO):
|
||||||
return x;
|
return x;
|
||||||
|
|
||||||
case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF):
|
|
||||||
case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF):
|
case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF):
|
||||||
case CLPAIR(IEEE754_CLASS_DNORM, 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_INF):
|
||||||
|
@ -180,9 +220,7 @@ union ieee754dp ieee754dp_fmaxa(union ieee754dp x, union ieee754dp y)
|
||||||
return y;
|
return y;
|
||||||
|
|
||||||
case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
|
case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
|
||||||
if (xs == ys)
|
return ieee754dp_zero(xs & ys);
|
||||||
return x;
|
|
||||||
return ieee754dp_zero(1);
|
|
||||||
|
|
||||||
case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
|
case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
|
||||||
DPDNORMX;
|
DPDNORMX;
|
||||||
|
@ -207,7 +245,11 @@ union ieee754dp ieee754dp_fmaxa(union ieee754dp x, union ieee754dp y)
|
||||||
return y;
|
return y;
|
||||||
|
|
||||||
/* Compare mantissa */
|
/* Compare mantissa */
|
||||||
if (xm <= ym)
|
if (xm < ym)
|
||||||
return y;
|
return y;
|
||||||
return x;
|
else if (xm > ym)
|
||||||
|
return x;
|
||||||
|
else if (xs == 0)
|
||||||
|
return x;
|
||||||
|
return y;
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,14 +47,26 @@ union ieee754dp ieee754dp_fmin(union ieee754dp x, union ieee754dp y)
|
||||||
case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
|
case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
|
||||||
return ieee754dp_nanxcpt(x);
|
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_ZERO, IEEE754_CLASS_QNAN):
|
||||||
case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
|
case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
|
||||||
case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN):
|
case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN):
|
||||||
case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN):
|
case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN):
|
||||||
return x;
|
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_ZERO):
|
||||||
case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM):
|
case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM):
|
||||||
case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM):
|
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;
|
return ys ? y : x;
|
||||||
|
|
||||||
case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
|
case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
|
||||||
if (xs == ys)
|
return ieee754dp_zero(xs | ys);
|
||||||
return x;
|
|
||||||
return ieee754dp_zero(1);
|
|
||||||
|
|
||||||
case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
|
case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
|
||||||
DPDNORMX;
|
DPDNORMX;
|
||||||
|
@ -106,16 +116,32 @@ union ieee754dp ieee754dp_fmin(union ieee754dp x, union ieee754dp y)
|
||||||
else if (xs < ys)
|
else if (xs < ys)
|
||||||
return y;
|
return y;
|
||||||
|
|
||||||
/* Compare exponent */
|
/* Signs of inputs are the same, let's compare exponents */
|
||||||
if (xe > ye)
|
if (xs == 0) {
|
||||||
return y;
|
/* Inputs are both positive */
|
||||||
else if (xe < ye)
|
if (xe > ye)
|
||||||
return x;
|
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)
|
if (xm <= ym)
|
||||||
return x;
|
return y;
|
||||||
return y;
|
return x;
|
||||||
}
|
}
|
||||||
|
|
||||||
union ieee754dp ieee754dp_fmina(union ieee754dp x, union ieee754dp y)
|
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):
|
case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
|
||||||
return ieee754dp_nanxcpt(x);
|
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_ZERO, IEEE754_CLASS_QNAN):
|
||||||
case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
|
case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
|
||||||
case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN):
|
case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN):
|
||||||
case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN):
|
case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN):
|
||||||
return x;
|
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_ZERO):
|
||||||
case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM):
|
case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM):
|
||||||
case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM):
|
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
|
* 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_ZERO):
|
||||||
case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM):
|
case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM):
|
||||||
case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM):
|
case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM):
|
||||||
case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO):
|
case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO):
|
||||||
case CLPAIR(IEEE754_CLASS_DNORM, 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_NORM, IEEE754_CLASS_INF):
|
||||||
case CLPAIR(IEEE754_CLASS_DNORM, 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_INF):
|
||||||
case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM):
|
case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM):
|
||||||
case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM):
|
case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM):
|
||||||
return y;
|
return x;
|
||||||
|
|
||||||
case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
|
case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
|
||||||
if (xs == ys)
|
return ieee754dp_zero(xs | ys);
|
||||||
return x;
|
|
||||||
return ieee754dp_zero(1);
|
|
||||||
|
|
||||||
case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
|
case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
|
||||||
DPDNORMX;
|
DPDNORMX;
|
||||||
|
@ -207,7 +245,11 @@ union ieee754dp ieee754dp_fmina(union ieee754dp x, union ieee754dp y)
|
||||||
return x;
|
return x;
|
||||||
|
|
||||||
/* Compare mantissa */
|
/* Compare mantissa */
|
||||||
if (xm <= ym)
|
if (xm < ym)
|
||||||
|
return x;
|
||||||
|
else if (xm > ym)
|
||||||
|
return y;
|
||||||
|
else if (xs == 1)
|
||||||
return x;
|
return x;
|
||||||
return y;
|
return y;
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,22 +14,45 @@
|
||||||
|
|
||||||
#include "ieee754dp.h"
|
#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,
|
static union ieee754dp _dp_maddf(union ieee754dp z, union ieee754dp x,
|
||||||
union ieee754dp y, enum maddf_flags flags)
|
union ieee754dp y, enum maddf_flags flags)
|
||||||
{
|
{
|
||||||
int re;
|
int re;
|
||||||
int rs;
|
int rs;
|
||||||
u64 rm;
|
|
||||||
unsigned lxm;
|
unsigned lxm;
|
||||||
unsigned hxm;
|
unsigned hxm;
|
||||||
unsigned lym;
|
unsigned lym;
|
||||||
unsigned hym;
|
unsigned hym;
|
||||||
u64 lrm;
|
u64 lrm;
|
||||||
u64 hrm;
|
u64 hrm;
|
||||||
|
u64 lzm;
|
||||||
|
u64 hzm;
|
||||||
u64 t;
|
u64 t;
|
||||||
u64 at;
|
u64 at;
|
||||||
int s;
|
int s;
|
||||||
|
@ -48,52 +71,34 @@ static union ieee754dp _dp_maddf(union ieee754dp z, union ieee754dp x,
|
||||||
|
|
||||||
ieee754_clearcx();
|
ieee754_clearcx();
|
||||||
|
|
||||||
switch (zc) {
|
/*
|
||||||
case IEEE754_CLASS_SNAN:
|
* Handle the cases when at least one of x, y or z is a NaN.
|
||||||
ieee754_setcx(IEEE754_INVALID_OPERATION);
|
* Order of precedence is sNaN, qNaN and z, x, y.
|
||||||
|
*/
|
||||||
|
if (zc == IEEE754_CLASS_SNAN)
|
||||||
return ieee754dp_nanxcpt(z);
|
return ieee754dp_nanxcpt(z);
|
||||||
case IEEE754_CLASS_DNORM:
|
if (xc == IEEE754_CLASS_SNAN)
|
||||||
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):
|
|
||||||
return ieee754dp_nanxcpt(x);
|
return ieee754dp_nanxcpt(x);
|
||||||
|
if (yc == IEEE754_CLASS_SNAN)
|
||||||
case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):
|
return ieee754dp_nanxcpt(y);
|
||||||
case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
|
if (zc == IEEE754_CLASS_QNAN)
|
||||||
case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN):
|
return z;
|
||||||
case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN):
|
if (xc == IEEE754_CLASS_QNAN)
|
||||||
|
return x;
|
||||||
|
if (yc == IEEE754_CLASS_QNAN)
|
||||||
return y;
|
return y;
|
||||||
|
|
||||||
case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN):
|
if (zc == IEEE754_CLASS_DNORM)
|
||||||
case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO):
|
DPDNORMZ;
|
||||||
case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM):
|
/* ZERO z cases are handled separately below */
|
||||||
case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM):
|
|
||||||
case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_INF):
|
|
||||||
return x;
|
|
||||||
|
|
||||||
|
switch (CLPAIR(xc, yc)) {
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Infinity handling
|
* Infinity handling
|
||||||
*/
|
*/
|
||||||
case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO):
|
case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO):
|
||||||
case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF):
|
case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF):
|
||||||
if (zc == IEEE754_CLASS_QNAN)
|
|
||||||
return z;
|
|
||||||
ieee754_setcx(IEEE754_INVALID_OPERATION);
|
ieee754_setcx(IEEE754_INVALID_OPERATION);
|
||||||
return ieee754dp_indef();
|
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_NORM):
|
||||||
case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM):
|
case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM):
|
||||||
case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF):
|
case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF):
|
||||||
if (zc == IEEE754_CLASS_QNAN)
|
if ((zc == IEEE754_CLASS_INF) &&
|
||||||
return z;
|
((!(flags & MADDF_NEGATE_PRODUCT) && (zs != (xs ^ ys))) ||
|
||||||
return ieee754dp_inf(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_ZERO):
|
||||||
case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM):
|
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):
|
case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO):
|
||||||
if (zc == IEEE754_CLASS_INF)
|
if (zc == IEEE754_CLASS_INF)
|
||||||
return ieee754dp_inf(zs);
|
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;
|
return z;
|
||||||
|
|
||||||
case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
|
case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
|
||||||
DPDNORMX;
|
DPDNORMX;
|
||||||
|
|
||||||
case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
|
case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
|
||||||
if (zc == IEEE754_CLASS_QNAN)
|
if (zc == IEEE754_CLASS_INF)
|
||||||
return z;
|
|
||||||
else if (zc == IEEE754_CLASS_INF)
|
|
||||||
return ieee754dp_inf(zs);
|
return ieee754dp_inf(zs);
|
||||||
DPDNORMY;
|
DPDNORMY;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM):
|
case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM):
|
||||||
if (zc == IEEE754_CLASS_QNAN)
|
if (zc == IEEE754_CLASS_INF)
|
||||||
return z;
|
|
||||||
else if (zc == IEEE754_CLASS_INF)
|
|
||||||
return ieee754dp_inf(zs);
|
return ieee754dp_inf(zs);
|
||||||
DPDNORMX;
|
DPDNORMX;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_NORM):
|
case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_NORM):
|
||||||
if (zc == IEEE754_CLASS_QNAN)
|
if (zc == IEEE754_CLASS_INF)
|
||||||
return z;
|
|
||||||
else if (zc == IEEE754_CLASS_INF)
|
|
||||||
return ieee754dp_inf(zs);
|
return ieee754dp_inf(zs);
|
||||||
/* fall through to real computations */
|
/* fall through to real computations */
|
||||||
}
|
}
|
||||||
|
@ -157,7 +190,7 @@ static union ieee754dp _dp_maddf(union ieee754dp z, union ieee754dp x,
|
||||||
|
|
||||||
re = xe + ye;
|
re = xe + ye;
|
||||||
rs = xs ^ ys;
|
rs = xs ^ ys;
|
||||||
if (flags & maddf_negate_product)
|
if (flags & MADDF_NEGATE_PRODUCT)
|
||||||
rs ^= 1;
|
rs ^= 1;
|
||||||
|
|
||||||
/* shunt to top of word */
|
/* 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);
|
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 */
|
/* 32 * 32 => 64 */
|
||||||
|
@ -195,81 +228,110 @@ static union ieee754dp _dp_maddf(union ieee754dp z, union ieee754dp x,
|
||||||
|
|
||||||
hrm = hrm + (t >> 32);
|
hrm = hrm + (t >> 32);
|
||||||
|
|
||||||
rm = hrm | (lrm != 0);
|
/* Put explicit bit at bit 126 if necessary */
|
||||||
|
if ((int64_t)hrm < 0) {
|
||||||
/*
|
lrm = (hrm << 63) | (lrm >> 1);
|
||||||
* Sticky shift down to normal rounding precision.
|
hrm = hrm >> 1;
|
||||||
*/
|
|
||||||
if ((s64) rm < 0) {
|
|
||||||
rm = (rm >> (64 - (DP_FBITS + 1 + 3))) |
|
|
||||||
((rm << (DP_FBITS + 1 + 3)) != 0);
|
|
||||||
re++;
|
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)
|
assert(hrm & (1 << 62));
|
||||||
return ieee754dp_format(rs, re, rm);
|
|
||||||
|
|
||||||
/* And now the addition */
|
if (zc == IEEE754_CLASS_ZERO) {
|
||||||
assert(zm & DP_HIDDEN_BIT);
|
/*
|
||||||
|
* 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);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/* Move explicit bit from bit 52 to bit 126 */
|
||||||
* Provide guard,round and stick bit space.
|
lzm = 0;
|
||||||
*/
|
hzm = zm << 10;
|
||||||
zm <<= 3;
|
assert(hzm & (1 << 62));
|
||||||
|
|
||||||
|
/* Make the exponents the same */
|
||||||
if (ze > re) {
|
if (ze > re) {
|
||||||
/*
|
/*
|
||||||
* Have to shift y fraction right to align.
|
* Have to shift y fraction right to align.
|
||||||
*/
|
*/
|
||||||
s = ze - re;
|
s = ze - re;
|
||||||
rm = XDPSRS(rm, s);
|
srl128(&hrm, &lrm, s);
|
||||||
re += s;
|
re += s;
|
||||||
} else if (re > ze) {
|
} else if (re > ze) {
|
||||||
/*
|
/*
|
||||||
* Have to shift x fraction right to align.
|
* Have to shift x fraction right to align.
|
||||||
*/
|
*/
|
||||||
s = re - ze;
|
s = re - ze;
|
||||||
zm = XDPSRS(zm, s);
|
srl128(&hzm, &lzm, s);
|
||||||
ze += s;
|
ze += s;
|
||||||
}
|
}
|
||||||
assert(ze == re);
|
assert(ze == re);
|
||||||
assert(ze <= DP_EMAX);
|
assert(ze <= DP_EMAX);
|
||||||
|
|
||||||
|
/* Do the addition */
|
||||||
if (zs == rs) {
|
if (zs == rs) {
|
||||||
/*
|
/*
|
||||||
* Generate 28 bit result of adding two 27 bit numbers
|
* Generate 128 bit result by adding two 127 bit numbers
|
||||||
* leaving result in xm, xs and xe.
|
* leaving result in hzm:lzm, zs and ze.
|
||||||
*/
|
*/
|
||||||
zm = zm + rm;
|
hzm = hzm + hrm + (lzm > (lzm + lrm));
|
||||||
|
lzm = lzm + lrm;
|
||||||
if (zm >> (DP_FBITS + 1 + 3)) { /* carry out */
|
if ((int64_t)hzm < 0) { /* carry out */
|
||||||
zm = XDPSRS1(zm);
|
srl128(&hzm, &lzm, 1);
|
||||||
ze++;
|
ze++;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (zm >= rm) {
|
if (hzm > hrm || (hzm == hrm && lzm >= lrm)) {
|
||||||
zm = zm - rm;
|
hzm = hzm - hrm - (lzm < lrm);
|
||||||
|
lzm = lzm - lrm;
|
||||||
} else {
|
} else {
|
||||||
zm = rm - zm;
|
hzm = hrm - hzm - (lrm < lzm);
|
||||||
|
lzm = lrm - lzm;
|
||||||
zs = rs;
|
zs = rs;
|
||||||
}
|
}
|
||||||
if (zm == 0)
|
if (lzm == 0 && hzm == 0)
|
||||||
return ieee754dp_zero(ieee754_csr.rm == FPU_CSR_RD);
|
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) {
|
if (hzm == 0) {
|
||||||
zm <<= 1;
|
/* left shift by 63 or 64 bits */
|
||||||
ze--;
|
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,
|
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 ieee754dp_msubf(union ieee754dp z, union ieee754dp x,
|
||||||
union ieee754dp y)
|
union ieee754dp y)
|
||||||
{
|
{
|
||||||
return _dp_maddf(z, x, y, maddf_negate_product);
|
return _dp_maddf(z, x, y, MADDF_NEGATE_PRODUCT);
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,6 +26,10 @@
|
||||||
|
|
||||||
#define CLPAIR(x, y) ((x)*6+(y))
|
#define CLPAIR(x, y) ((x)*6+(y))
|
||||||
|
|
||||||
|
enum maddf_flags {
|
||||||
|
MADDF_NEGATE_PRODUCT = 1 << 0,
|
||||||
|
};
|
||||||
|
|
||||||
static inline void ieee754_clearcx(void)
|
static inline void ieee754_clearcx(void)
|
||||||
{
|
{
|
||||||
ieee754_csr.cx = 0;
|
ieee754_csr.cx = 0;
|
||||||
|
|
|
@ -45,6 +45,10 @@ static inline int ieee754sp_finite(union ieee754sp x)
|
||||||
return SPBEXP(x) != SP_EMAX + 1 + SP_EBIAS;
|
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 */
|
/* 3bit extended single precision sticky right shift */
|
||||||
#define XSPSRS(v, rs) \
|
#define XSPSRS(v, rs) \
|
||||||
((rs > (SP_FBITS+3))?1:((v) >> (rs)) | ((v) << (32-(rs)) != 0))
|
((rs > (SP_FBITS+3))?1:((v) >> (rs)) | ((v) << (32-(rs)) != 0))
|
||||||
|
|
|
@ -47,14 +47,26 @@ union ieee754sp ieee754sp_fmax(union ieee754sp x, union ieee754sp y)
|
||||||
case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
|
case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
|
||||||
return ieee754sp_nanxcpt(x);
|
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_ZERO, IEEE754_CLASS_QNAN):
|
||||||
case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
|
case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
|
||||||
case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN):
|
case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN):
|
||||||
case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN):
|
case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN):
|
||||||
return x;
|
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_ZERO):
|
||||||
case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM):
|
case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM):
|
||||||
case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM):
|
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;
|
return ys ? x : y;
|
||||||
|
|
||||||
case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
|
case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
|
||||||
if (xs == ys)
|
return ieee754sp_zero(xs & ys);
|
||||||
return x;
|
|
||||||
return ieee754sp_zero(1);
|
|
||||||
|
|
||||||
case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
|
case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
|
||||||
SPDNORMX;
|
SPDNORMX;
|
||||||
|
@ -106,16 +116,32 @@ union ieee754sp ieee754sp_fmax(union ieee754sp x, union ieee754sp y)
|
||||||
else if (xs < ys)
|
else if (xs < ys)
|
||||||
return x;
|
return x;
|
||||||
|
|
||||||
/* Compare exponent */
|
/* Signs of inputs are equal, let's compare exponents */
|
||||||
if (xe > ye)
|
if (xs == 0) {
|
||||||
return x;
|
/* Inputs are both positive */
|
||||||
else if (xe < ye)
|
if (xe > ye)
|
||||||
return y;
|
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)
|
if (xm <= ym)
|
||||||
return y;
|
return x;
|
||||||
return x;
|
return y;
|
||||||
}
|
}
|
||||||
|
|
||||||
union ieee754sp ieee754sp_fmaxa(union ieee754sp x, union ieee754sp 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):
|
case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
|
||||||
return ieee754sp_nanxcpt(x);
|
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_ZERO, IEEE754_CLASS_QNAN):
|
||||||
case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
|
case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
|
||||||
case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN):
|
case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN):
|
||||||
case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN):
|
case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN):
|
||||||
return x;
|
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_ZERO):
|
||||||
case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM):
|
case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM):
|
||||||
case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM):
|
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
|
* 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_ZERO):
|
||||||
case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM):
|
case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM):
|
||||||
case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM):
|
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):
|
case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO):
|
||||||
return x;
|
return x;
|
||||||
|
|
||||||
case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF):
|
|
||||||
case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF):
|
case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF):
|
||||||
case CLPAIR(IEEE754_CLASS_DNORM, 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_INF):
|
||||||
|
@ -180,9 +220,7 @@ union ieee754sp ieee754sp_fmaxa(union ieee754sp x, union ieee754sp y)
|
||||||
return y;
|
return y;
|
||||||
|
|
||||||
case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
|
case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
|
||||||
if (xs == ys)
|
return ieee754sp_zero(xs & ys);
|
||||||
return x;
|
|
||||||
return ieee754sp_zero(1);
|
|
||||||
|
|
||||||
case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
|
case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
|
||||||
SPDNORMX;
|
SPDNORMX;
|
||||||
|
@ -207,7 +245,11 @@ union ieee754sp ieee754sp_fmaxa(union ieee754sp x, union ieee754sp y)
|
||||||
return y;
|
return y;
|
||||||
|
|
||||||
/* Compare mantissa */
|
/* Compare mantissa */
|
||||||
if (xm <= ym)
|
if (xm < ym)
|
||||||
return y;
|
return y;
|
||||||
return x;
|
else if (xm > ym)
|
||||||
|
return x;
|
||||||
|
else if (xs == 0)
|
||||||
|
return x;
|
||||||
|
return y;
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,14 +47,26 @@ union ieee754sp ieee754sp_fmin(union ieee754sp x, union ieee754sp y)
|
||||||
case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
|
case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
|
||||||
return ieee754sp_nanxcpt(x);
|
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_ZERO, IEEE754_CLASS_QNAN):
|
||||||
case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
|
case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
|
||||||
case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN):
|
case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN):
|
||||||
case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN):
|
case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN):
|
||||||
return x;
|
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_ZERO):
|
||||||
case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM):
|
case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM):
|
||||||
case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM):
|
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;
|
return ys ? y : x;
|
||||||
|
|
||||||
case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
|
case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
|
||||||
if (xs == ys)
|
return ieee754sp_zero(xs | ys);
|
||||||
return x;
|
|
||||||
return ieee754sp_zero(1);
|
|
||||||
|
|
||||||
case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
|
case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
|
||||||
SPDNORMX;
|
SPDNORMX;
|
||||||
|
@ -106,16 +116,32 @@ union ieee754sp ieee754sp_fmin(union ieee754sp x, union ieee754sp y)
|
||||||
else if (xs < ys)
|
else if (xs < ys)
|
||||||
return y;
|
return y;
|
||||||
|
|
||||||
/* Compare exponent */
|
/* Signs of inputs are the same, let's compare exponents */
|
||||||
if (xe > ye)
|
if (xs == 0) {
|
||||||
return y;
|
/* Inputs are both positive */
|
||||||
else if (xe < ye)
|
if (xe > ye)
|
||||||
return x;
|
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)
|
if (xm <= ym)
|
||||||
return x;
|
return y;
|
||||||
return y;
|
return x;
|
||||||
}
|
}
|
||||||
|
|
||||||
union ieee754sp ieee754sp_fmina(union ieee754sp x, union ieee754sp y)
|
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):
|
case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
|
||||||
return ieee754sp_nanxcpt(x);
|
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_ZERO, IEEE754_CLASS_QNAN):
|
||||||
case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
|
case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
|
||||||
case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN):
|
case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN):
|
||||||
case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN):
|
case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN):
|
||||||
return x;
|
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_ZERO):
|
||||||
case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM):
|
case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM):
|
||||||
case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM):
|
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
|
* 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_ZERO):
|
||||||
case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM):
|
case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM):
|
||||||
case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM):
|
case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM):
|
||||||
case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO):
|
case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO):
|
||||||
case CLPAIR(IEEE754_CLASS_DNORM, 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_NORM, IEEE754_CLASS_INF):
|
||||||
case CLPAIR(IEEE754_CLASS_DNORM, 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_INF):
|
||||||
case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM):
|
case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM):
|
||||||
case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM):
|
case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM):
|
||||||
return y;
|
return x;
|
||||||
|
|
||||||
case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
|
case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
|
||||||
if (xs == ys)
|
return ieee754sp_zero(xs | ys);
|
||||||
return x;
|
|
||||||
return ieee754sp_zero(1);
|
|
||||||
|
|
||||||
case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
|
case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
|
||||||
SPDNORMX;
|
SPDNORMX;
|
||||||
|
@ -207,7 +245,11 @@ union ieee754sp ieee754sp_fmina(union ieee754sp x, union ieee754sp y)
|
||||||
return x;
|
return x;
|
||||||
|
|
||||||
/* Compare mantissa */
|
/* Compare mantissa */
|
||||||
if (xm <= ym)
|
if (xm < ym)
|
||||||
|
return x;
|
||||||
|
else if (xm > ym)
|
||||||
|
return y;
|
||||||
|
else if (xs == 1)
|
||||||
return x;
|
return x;
|
||||||
return y;
|
return y;
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,9 +14,6 @@
|
||||||
|
|
||||||
#include "ieee754sp.h"
|
#include "ieee754sp.h"
|
||||||
|
|
||||||
enum maddf_flags {
|
|
||||||
maddf_negate_product = 1 << 0,
|
|
||||||
};
|
|
||||||
|
|
||||||
static union ieee754sp _sp_maddf(union ieee754sp z, union ieee754sp x,
|
static union ieee754sp _sp_maddf(union ieee754sp z, union ieee754sp x,
|
||||||
union ieee754sp y, enum maddf_flags flags)
|
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 re;
|
||||||
int rs;
|
int rs;
|
||||||
unsigned rm;
|
unsigned rm;
|
||||||
unsigned short lxm;
|
uint64_t rm64;
|
||||||
unsigned short hxm;
|
uint64_t zm64;
|
||||||
unsigned short lym;
|
|
||||||
unsigned short hym;
|
|
||||||
unsigned lrm;
|
|
||||||
unsigned hrm;
|
|
||||||
unsigned t;
|
|
||||||
unsigned at;
|
|
||||||
int s;
|
int s;
|
||||||
|
|
||||||
COMPXSP;
|
COMPXSP;
|
||||||
|
@ -48,51 +39,35 @@ static union ieee754sp _sp_maddf(union ieee754sp z, union ieee754sp x,
|
||||||
|
|
||||||
ieee754_clearcx();
|
ieee754_clearcx();
|
||||||
|
|
||||||
switch (zc) {
|
/*
|
||||||
case IEEE754_CLASS_SNAN:
|
* Handle the cases when at least one of x, y or z is a NaN.
|
||||||
ieee754_setcx(IEEE754_INVALID_OPERATION);
|
* Order of precedence is sNaN, qNaN and z, x, y.
|
||||||
|
*/
|
||||||
|
if (zc == IEEE754_CLASS_SNAN)
|
||||||
return ieee754sp_nanxcpt(z);
|
return ieee754sp_nanxcpt(z);
|
||||||
case IEEE754_CLASS_DNORM:
|
if (xc == IEEE754_CLASS_SNAN)
|
||||||
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):
|
|
||||||
return ieee754sp_nanxcpt(x);
|
return ieee754sp_nanxcpt(x);
|
||||||
|
if (yc == IEEE754_CLASS_SNAN)
|
||||||
case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):
|
return ieee754sp_nanxcpt(y);
|
||||||
case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
|
if (zc == IEEE754_CLASS_QNAN)
|
||||||
case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN):
|
return z;
|
||||||
case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN):
|
if (xc == IEEE754_CLASS_QNAN)
|
||||||
|
return x;
|
||||||
|
if (yc == IEEE754_CLASS_QNAN)
|
||||||
return y;
|
return y;
|
||||||
|
|
||||||
case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN):
|
if (zc == IEEE754_CLASS_DNORM)
|
||||||
case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO):
|
SPDNORMZ;
|
||||||
case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM):
|
/* ZERO z cases are handled separately below */
|
||||||
case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM):
|
|
||||||
case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_INF):
|
switch (CLPAIR(xc, yc)) {
|
||||||
return x;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Infinity handling
|
* Infinity handling
|
||||||
*/
|
*/
|
||||||
case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO):
|
case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO):
|
||||||
case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF):
|
case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF):
|
||||||
if (zc == IEEE754_CLASS_QNAN)
|
|
||||||
return z;
|
|
||||||
ieee754_setcx(IEEE754_INVALID_OPERATION);
|
ieee754_setcx(IEEE754_INVALID_OPERATION);
|
||||||
return ieee754sp_indef();
|
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_NORM):
|
||||||
case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM):
|
case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM):
|
||||||
case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF):
|
case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF):
|
||||||
if (zc == IEEE754_CLASS_QNAN)
|
if ((zc == IEEE754_CLASS_INF) &&
|
||||||
return z;
|
((!(flags & MADDF_NEGATE_PRODUCT) && (zs != (xs ^ ys))) ||
|
||||||
return ieee754sp_inf(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_ZERO):
|
||||||
case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM):
|
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):
|
case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO):
|
||||||
if (zc == IEEE754_CLASS_INF)
|
if (zc == IEEE754_CLASS_INF)
|
||||||
return ieee754sp_inf(zs);
|
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;
|
return z;
|
||||||
|
|
||||||
case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
|
case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
|
||||||
SPDNORMX;
|
SPDNORMX;
|
||||||
|
|
||||||
case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
|
case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
|
||||||
if (zc == IEEE754_CLASS_QNAN)
|
if (zc == IEEE754_CLASS_INF)
|
||||||
return z;
|
|
||||||
else if (zc == IEEE754_CLASS_INF)
|
|
||||||
return ieee754sp_inf(zs);
|
return ieee754sp_inf(zs);
|
||||||
SPDNORMY;
|
SPDNORMY;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM):
|
case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM):
|
||||||
if (zc == IEEE754_CLASS_QNAN)
|
if (zc == IEEE754_CLASS_INF)
|
||||||
return z;
|
|
||||||
else if (zc == IEEE754_CLASS_INF)
|
|
||||||
return ieee754sp_inf(zs);
|
return ieee754sp_inf(zs);
|
||||||
SPDNORMX;
|
SPDNORMX;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_NORM):
|
case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_NORM):
|
||||||
if (zc == IEEE754_CLASS_QNAN)
|
if (zc == IEEE754_CLASS_INF)
|
||||||
return z;
|
|
||||||
else if (zc == IEEE754_CLASS_INF)
|
|
||||||
return ieee754sp_inf(zs);
|
return ieee754sp_inf(zs);
|
||||||
/* fall through to real computations */
|
/* fall through to real computations */
|
||||||
}
|
}
|
||||||
|
@ -158,111 +161,93 @@ static union ieee754sp _sp_maddf(union ieee754sp z, union ieee754sp x,
|
||||||
|
|
||||||
re = xe + ye;
|
re = xe + ye;
|
||||||
rs = xs ^ ys;
|
rs = xs ^ ys;
|
||||||
if (flags & maddf_negate_product)
|
if (flags & MADDF_NEGATE_PRODUCT)
|
||||||
rs ^= 1;
|
rs ^= 1;
|
||||||
|
|
||||||
/* shunt to top of word */
|
/* Multiple 24 bit xm and ym to give 48 bit results */
|
||||||
xm <<= 32 - (SP_FBITS + 1);
|
rm64 = (uint64_t)xm * ym;
|
||||||
ym <<= 32 - (SP_FBITS + 1);
|
|
||||||
|
|
||||||
/*
|
/* Shunt to top of word */
|
||||||
* Multiply 32 bits xm, ym to give high 32 bits rm with stickness.
|
rm64 = rm64 << 16;
|
||||||
*/
|
|
||||||
lxm = xm & 0xffff;
|
|
||||||
hxm = xm >> 16;
|
|
||||||
lym = ym & 0xffff;
|
|
||||||
hym = ym >> 16;
|
|
||||||
|
|
||||||
lrm = lxm * lym; /* 16 * 16 => 32 */
|
/* Put explicit bit at bit 62 if necessary */
|
||||||
hrm = hxm * hym; /* 16 * 16 => 32 */
|
if ((int64_t) rm64 < 0) {
|
||||||
|
rm64 = rm64 >> 1;
|
||||||
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);
|
|
||||||
re++;
|
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);
|
return ieee754sp_format(rs, re, rm);
|
||||||
|
}
|
||||||
|
|
||||||
/* And now the addition */
|
/* Move explicit bit from bit 23 to bit 62 */
|
||||||
|
zm64 = (uint64_t)zm << (62 - 23);
|
||||||
assert(zm & SP_HIDDEN_BIT);
|
assert(zm64 & (1 << 62));
|
||||||
|
|
||||||
/*
|
|
||||||
* Provide guard,round and stick bit space.
|
|
||||||
*/
|
|
||||||
zm <<= 3;
|
|
||||||
|
|
||||||
|
/* Make the exponents the same */
|
||||||
if (ze > re) {
|
if (ze > re) {
|
||||||
/*
|
/*
|
||||||
* Have to shift r fraction right to align.
|
* Have to shift r fraction right to align.
|
||||||
*/
|
*/
|
||||||
s = ze - re;
|
s = ze - re;
|
||||||
rm = XSPSRS(rm, s);
|
rm64 = XSPSRS64(rm64, s);
|
||||||
re += s;
|
re += s;
|
||||||
} else if (re > ze) {
|
} else if (re > ze) {
|
||||||
/*
|
/*
|
||||||
* Have to shift z fraction right to align.
|
* Have to shift z fraction right to align.
|
||||||
*/
|
*/
|
||||||
s = re - ze;
|
s = re - ze;
|
||||||
zm = XSPSRS(zm, s);
|
zm64 = XSPSRS64(zm64, s);
|
||||||
ze += s;
|
ze += s;
|
||||||
}
|
}
|
||||||
assert(ze == re);
|
assert(ze == re);
|
||||||
assert(ze <= SP_EMAX);
|
assert(ze <= SP_EMAX);
|
||||||
|
|
||||||
|
/* Do the addition */
|
||||||
if (zs == rs) {
|
if (zs == rs) {
|
||||||
/*
|
/*
|
||||||
* Generate 28 bit result of adding two 27 bit numbers
|
* Generate 64 bit result by adding two 63 bit numbers
|
||||||
* leaving result in zm, zs and ze.
|
* leaving result in zm64, zs and ze.
|
||||||
*/
|
*/
|
||||||
zm = zm + rm;
|
zm64 = zm64 + rm64;
|
||||||
|
if ((int64_t)zm64 < 0) { /* carry out */
|
||||||
if (zm >> (SP_FBITS + 1 + 3)) { /* carry out */
|
zm64 = XSPSRS1(zm64);
|
||||||
zm = XSPSRS1(zm);
|
|
||||||
ze++;
|
ze++;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (zm >= rm) {
|
if (zm64 >= rm64) {
|
||||||
zm = zm - rm;
|
zm64 = zm64 - rm64;
|
||||||
} else {
|
} else {
|
||||||
zm = rm - zm;
|
zm64 = rm64 - zm64;
|
||||||
zs = rs;
|
zs = rs;
|
||||||
}
|
}
|
||||||
if (zm == 0)
|
if (zm64 == 0)
|
||||||
return ieee754sp_zero(ieee754_csr.rm == FPU_CSR_RD);
|
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) {
|
while ((zm64 >> 62) == 0) {
|
||||||
zm <<= 1;
|
zm64 <<= 1;
|
||||||
ze--;
|
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);
|
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 ieee754sp_msubf(union ieee754sp z, union ieee754sp x,
|
||||||
union ieee754sp y)
|
union ieee754sp y)
|
||||||
{
|
{
|
||||||
return _sp_maddf(z, x, y, maddf_negate_product);
|
return _sp_maddf(z, x, y, MADDF_NEGATE_PRODUCT);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 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,
|
static int emulate_multiple(struct pt_regs *regs, unsigned char __user *addr,
|
||||||
unsigned int reg, unsigned int nb,
|
unsigned int reg, unsigned int nb,
|
||||||
unsigned int flags, unsigned int instr,
|
unsigned int flags, unsigned int instr,
|
||||||
|
@ -263,9 +285,10 @@ static int emulate_multiple(struct pt_regs *regs, unsigned char __user *addr,
|
||||||
} else {
|
} else {
|
||||||
unsigned long pc = regs->nip ^ (swiz & 4);
|
unsigned long pc = regs->nip ^ (swiz & 4);
|
||||||
|
|
||||||
if (__get_user_inatomic(instr,
|
if (__get_user_or_set_dar(regs, instr,
|
||||||
(unsigned int __user *)pc))
|
(unsigned int __user *)pc))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
|
|
||||||
if (swiz == 0 && (flags & SW))
|
if (swiz == 0 && (flags & SW))
|
||||||
instr = cpu_to_le32(instr);
|
instr = cpu_to_le32(instr);
|
||||||
nb = (instr >> 11) & 0x1f;
|
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));
|
((nb0 + 3) / 4) * sizeof(unsigned long));
|
||||||
|
|
||||||
for (i = 0; i < nb; ++i, ++p)
|
for (i = 0; i < nb; ++i, ++p)
|
||||||
if (__get_user_inatomic(REG_BYTE(rptr, i ^ bswiz),
|
if (__get_user_or_set_dar(regs, REG_BYTE(rptr, i ^ bswiz),
|
||||||
SWIZ_PTR(p)))
|
SWIZ_PTR(p)))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
if (nb0 > 0) {
|
if (nb0 > 0) {
|
||||||
rptr = ®s->gpr[0];
|
rptr = ®s->gpr[0];
|
||||||
addr += nb;
|
addr += nb;
|
||||||
for (i = 0; i < nb0; ++i, ++p)
|
for (i = 0; i < nb0; ++i, ++p)
|
||||||
if (__get_user_inatomic(REG_BYTE(rptr,
|
if (__get_user_or_set_dar(regs,
|
||||||
i ^ bswiz),
|
REG_BYTE(rptr, i ^ bswiz),
|
||||||
SWIZ_PTR(p)))
|
SWIZ_PTR(p)))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
for (i = 0; i < nb; ++i, ++p)
|
for (i = 0; i < nb; ++i, ++p)
|
||||||
if (__put_user_inatomic(REG_BYTE(rptr, i ^ bswiz),
|
if (__put_user_or_set_dar(regs, REG_BYTE(rptr, i ^ bswiz),
|
||||||
SWIZ_PTR(p)))
|
SWIZ_PTR(p)))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
if (nb0 > 0) {
|
if (nb0 > 0) {
|
||||||
rptr = ®s->gpr[0];
|
rptr = ®s->gpr[0];
|
||||||
addr += nb;
|
addr += nb;
|
||||||
for (i = 0; i < nb0; ++i, ++p)
|
for (i = 0; i < nb0; ++i, ++p)
|
||||||
if (__put_user_inatomic(REG_BYTE(rptr,
|
if (__put_user_or_set_dar(regs,
|
||||||
i ^ bswiz),
|
REG_BYTE(rptr, i ^ bswiz),
|
||||||
SWIZ_PTR(p)))
|
SWIZ_PTR(p)))
|
||||||
return -EFAULT;
|
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,
|
* Only POWER6 has these instructions, and it does true little-endian,
|
||||||
* so we don't need the address swizzling.
|
* so we don't need the address swizzling.
|
||||||
*/
|
*/
|
||||||
static int emulate_fp_pair(unsigned char __user *addr, unsigned int reg,
|
static int emulate_fp_pair(struct pt_regs *regs, unsigned char __user *addr,
|
||||||
unsigned int flags)
|
unsigned int reg, unsigned int flags)
|
||||||
{
|
{
|
||||||
char *ptr0 = (char *) ¤t->thread.TS_FPR(reg);
|
char *ptr0 = (char *) ¤t->thread.TS_FPR(reg);
|
||||||
char *ptr1 = (char *) ¤t->thread.TS_FPR(reg+1);
|
char *ptr1 = (char *) ¤t->thread.TS_FPR(reg+1);
|
||||||
int i, ret, sw = 0;
|
int i, sw = 0;
|
||||||
|
|
||||||
if (reg & 1)
|
if (reg & 1)
|
||||||
return 0; /* invalid form: FRS/FRT must be even */
|
return 0; /* invalid form: FRS/FRT must be even */
|
||||||
if (flags & SW)
|
if (flags & SW)
|
||||||
sw = 7;
|
sw = 7;
|
||||||
ret = 0;
|
|
||||||
for (i = 0; i < 8; ++i) {
|
for (i = 0; i < 8; ++i) {
|
||||||
if (!(flags & ST)) {
|
if (!(flags & ST)) {
|
||||||
ret |= __get_user(ptr0[i^sw], addr + i);
|
if (__get_user_or_set_dar(regs, ptr0[i^sw], addr + i))
|
||||||
ret |= __get_user(ptr1[i^sw], addr + i + 8);
|
return -EFAULT;
|
||||||
|
if (__get_user_or_set_dar(regs, ptr1[i^sw], addr + i + 8))
|
||||||
|
return -EFAULT;
|
||||||
} else {
|
} else {
|
||||||
ret |= __put_user(ptr0[i^sw], addr + i);
|
if (__put_user_or_set_dar(regs, ptr0[i^sw], addr + i))
|
||||||
ret |= __put_user(ptr1[i^sw], addr + i + 8);
|
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 */
|
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 *)®s->gpr[reg];
|
char *ptr0 = (char *)®s->gpr[reg];
|
||||||
char *ptr1 = (char *)®s->gpr[reg+1];
|
char *ptr1 = (char *)®s->gpr[reg+1];
|
||||||
int i, ret, sw = 0;
|
int i, sw = 0;
|
||||||
|
|
||||||
if (reg & 1)
|
if (reg & 1)
|
||||||
return 0; /* invalid form: GPR must be even */
|
return 0; /* invalid form: GPR must be even */
|
||||||
if (flags & SW)
|
if (flags & SW)
|
||||||
sw = 7;
|
sw = 7;
|
||||||
ret = 0;
|
|
||||||
for (i = 0; i < 8; ++i) {
|
for (i = 0; i < 8; ++i) {
|
||||||
if (!(flags & ST)) {
|
if (!(flags & ST)) {
|
||||||
ret |= __get_user(ptr0[i^sw], addr + i);
|
if (__get_user_or_set_dar(regs, ptr0[i^sw], addr + i))
|
||||||
ret |= __get_user(ptr1[i^sw], addr + i + 8);
|
return -EFAULT;
|
||||||
|
if (__get_user_or_set_dar(regs, ptr1[i^sw], addr + i + 8))
|
||||||
|
return -EFAULT;
|
||||||
} else {
|
} else {
|
||||||
ret |= __put_user(ptr0[i^sw], addr + i);
|
if (__put_user_or_set_dar(regs, ptr0[i^sw], addr + i))
|
||||||
ret |= __put_user(ptr1[i^sw], addr + i + 8);
|
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 */
|
return 1; /* exception handled and fixed up */
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_PPC64 */
|
#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 (j = 0; j < length; j += elsize) {
|
||||||
for (i = 0; i < elsize; ++i) {
|
for (i = 0; i < elsize; ++i) {
|
||||||
if (flags & ST)
|
if (flags & ST)
|
||||||
ret |= __put_user(ptr[i^sw], addr + i);
|
ret = __put_user_or_set_dar(regs, ptr[i^sw],
|
||||||
|
addr + i);
|
||||||
else
|
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;
|
ptr += elsize;
|
||||||
#ifdef __LITTLE_ENDIAN__
|
#ifdef __LITTLE_ENDIAN__
|
||||||
|
@ -739,7 +773,7 @@ int fix_alignment(struct pt_regs *regs)
|
||||||
unsigned int dsisr;
|
unsigned int dsisr;
|
||||||
unsigned char __user *addr;
|
unsigned char __user *addr;
|
||||||
unsigned long p, swiz;
|
unsigned long p, swiz;
|
||||||
int ret, i;
|
int i;
|
||||||
union data {
|
union data {
|
||||||
u64 ll;
|
u64 ll;
|
||||||
double dd;
|
double dd;
|
||||||
|
@ -936,7 +970,7 @@ int fix_alignment(struct pt_regs *regs)
|
||||||
if (flags & F) {
|
if (flags & F) {
|
||||||
/* Special case for 16-byte FP loads and stores */
|
/* Special case for 16-byte FP loads and stores */
|
||||||
PPC_WARN_ALIGNMENT(fp_pair, regs);
|
PPC_WARN_ALIGNMENT(fp_pair, regs);
|
||||||
return emulate_fp_pair(addr, reg, flags);
|
return emulate_fp_pair(regs, addr, reg, flags);
|
||||||
} else {
|
} else {
|
||||||
#ifdef CONFIG_PPC64
|
#ifdef CONFIG_PPC64
|
||||||
/* Special case for 16-byte loads and stores */
|
/* Special case for 16-byte loads and stores */
|
||||||
|
@ -966,15 +1000,12 @@ int fix_alignment(struct pt_regs *regs)
|
||||||
}
|
}
|
||||||
|
|
||||||
data.ll = 0;
|
data.ll = 0;
|
||||||
ret = 0;
|
|
||||||
p = (unsigned long)addr;
|
p = (unsigned long)addr;
|
||||||
|
|
||||||
for (i = 0; i < nb; i++)
|
for (i = 0; i < nb; i++)
|
||||||
ret |= __get_user_inatomic(data.v[start + i],
|
if (__get_user_or_set_dar(regs, data.v[start + i],
|
||||||
SWIZ_PTR(p++));
|
SWIZ_PTR(p++)))
|
||||||
|
return -EFAULT;
|
||||||
if (unlikely(ret))
|
|
||||||
return -EFAULT;
|
|
||||||
|
|
||||||
} else if (flags & F) {
|
} else if (flags & F) {
|
||||||
data.ll = current->thread.TS_FPR(reg);
|
data.ll = current->thread.TS_FPR(reg);
|
||||||
|
@ -1046,15 +1077,13 @@ int fix_alignment(struct pt_regs *regs)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = 0;
|
|
||||||
p = (unsigned long)addr;
|
p = (unsigned long)addr;
|
||||||
|
|
||||||
for (i = 0; i < nb; i++)
|
for (i = 0; i < nb; i++)
|
||||||
ret |= __put_user_inatomic(data.v[start + i],
|
if (__put_user_or_set_dar(regs, data.v[start + i],
|
||||||
SWIZ_PTR(p++));
|
SWIZ_PTR(p++)))
|
||||||
|
return -EFAULT;
|
||||||
|
|
||||||
if (unlikely(ret))
|
|
||||||
return -EFAULT;
|
|
||||||
} else if (flags & F)
|
} else if (flags & F)
|
||||||
current->thread.TS_FPR(reg) = data.ll;
|
current->thread.TS_FPR(reg) = data.ll;
|
||||||
else
|
else
|
||||||
|
|
|
@ -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];
|
struct mmio_atsd_reg mmio_atsd_reg[NV_MAX_NPUS];
|
||||||
unsigned long pid = npu_context->mm->context.id;
|
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
|
* Loop over all the NPUs this process is active on and launch
|
||||||
* an invalidate.
|
* 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);
|
mmio_invalidate_wait(mmio_atsd_reg, flush);
|
||||||
if (flush)
|
if (flush)
|
||||||
/* Wait for the flush to complete */
|
/* Wait for the flush to complete */
|
||||||
|
|
|
@ -817,6 +817,9 @@ static int dlpar_memory_add_by_count(u32 lmbs_to_add, struct property *prop)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
for (i = 0; i < num_lmbs && lmbs_to_add != lmbs_added; i++) {
|
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);
|
rc = dlpar_acquire_drc(lmbs[i].drc_index);
|
||||||
if (rc)
|
if (rc)
|
||||||
continue;
|
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].base_addr, lmbs[i].drc_index);
|
||||||
lmbs[i].reserved = 0;
|
lmbs[i].reserved = 0;
|
||||||
}
|
}
|
||||||
|
rc = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
#include <linux/errno.h>
|
#include <linux/errno.h>
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
spinlock_t lock;
|
||||||
cpumask_t cpu_attach_mask;
|
cpumask_t cpu_attach_mask;
|
||||||
atomic_t flush_count;
|
atomic_t flush_count;
|
||||||
unsigned int flush_mm;
|
unsigned int flush_mm;
|
||||||
|
@ -27,6 +28,7 @@ typedef struct {
|
||||||
} mm_context_t;
|
} mm_context_t;
|
||||||
|
|
||||||
#define INIT_MM_CONTEXT(name) \
|
#define INIT_MM_CONTEXT(name) \
|
||||||
|
.context.lock = __SPIN_LOCK_UNLOCKED(name.context.lock), \
|
||||||
.context.pgtable_lock = \
|
.context.pgtable_lock = \
|
||||||
__SPIN_LOCK_UNLOCKED(name.context.pgtable_lock), \
|
__SPIN_LOCK_UNLOCKED(name.context.pgtable_lock), \
|
||||||
.context.pgtable_list = LIST_HEAD_INIT(name.context.pgtable_list), \
|
.context.pgtable_list = LIST_HEAD_INIT(name.context.pgtable_list), \
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
static inline int init_new_context(struct task_struct *tsk,
|
static inline int init_new_context(struct task_struct *tsk,
|
||||||
struct mm_struct *mm)
|
struct mm_struct *mm)
|
||||||
{
|
{
|
||||||
|
spin_lock_init(&mm->context.lock);
|
||||||
spin_lock_init(&mm->context.pgtable_lock);
|
spin_lock_init(&mm->context.pgtable_lock);
|
||||||
INIT_LIST_HEAD(&mm->context.pgtable_list);
|
INIT_LIST_HEAD(&mm->context.pgtable_list);
|
||||||
spin_lock_init(&mm->context.gmap_lock);
|
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)
|
if (prev == next)
|
||||||
return;
|
return;
|
||||||
cpumask_set_cpu(cpu, &next->context.cpu_attach_mask);
|
cpumask_set_cpu(cpu, &next->context.cpu_attach_mask);
|
||||||
cpumask_set_cpu(cpu, mm_cpumask(next));
|
|
||||||
/* Clear old ASCE by loading the kernel ASCE. */
|
/* Clear old ASCE by loading the kernel ASCE. */
|
||||||
__ctl_load(S390_lowcore.kernel_asce, 1, 1);
|
__ctl_load(S390_lowcore.kernel_asce, 1, 1);
|
||||||
__ctl_load(S390_lowcore.kernel_asce, 7, 7);
|
__ctl_load(S390_lowcore.kernel_asce, 7, 7);
|
||||||
|
@ -120,9 +120,8 @@ static inline void finish_arch_post_lock_switch(void)
|
||||||
preempt_disable();
|
preempt_disable();
|
||||||
while (atomic_read(&mm->context.flush_count))
|
while (atomic_read(&mm->context.flush_count))
|
||||||
cpu_relax();
|
cpu_relax();
|
||||||
|
cpumask_set_cpu(smp_processor_id(), mm_cpumask(mm));
|
||||||
if (mm->context.flush_mm)
|
__tlb_flush_mm_lazy(mm);
|
||||||
__tlb_flush_mm(mm);
|
|
||||||
preempt_enable();
|
preempt_enable();
|
||||||
}
|
}
|
||||||
set_fs(current->thread.mm_segment);
|
set_fs(current->thread.mm_segment);
|
||||||
|
@ -135,6 +134,7 @@ static inline void activate_mm(struct mm_struct *prev,
|
||||||
struct mm_struct *next)
|
struct mm_struct *next)
|
||||||
{
|
{
|
||||||
switch_mm(prev, next, current);
|
switch_mm(prev, next, current);
|
||||||
|
cpumask_set_cpu(smp_processor_id(), mm_cpumask(next));
|
||||||
set_user_asce(next);
|
set_user_asce(next);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
* Flush TLB entries for a specific mm on all CPUs (in case gmap is used
|
||||||
* this implicates multiple ASCEs!).
|
* 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)
|
static inline void __tlb_flush_mm(struct mm_struct *mm)
|
||||||
{
|
{
|
||||||
unsigned long gmap_asce;
|
unsigned long gmap_asce;
|
||||||
|
@ -71,16 +54,18 @@ static inline void __tlb_flush_mm(struct mm_struct *mm)
|
||||||
*/
|
*/
|
||||||
preempt_disable();
|
preempt_disable();
|
||||||
atomic_inc(&mm->context.flush_count);
|
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);
|
gmap_asce = READ_ONCE(mm->context.gmap_asce);
|
||||||
if (MACHINE_HAS_IDTE && gmap_asce != -1UL) {
|
if (MACHINE_HAS_IDTE && gmap_asce != -1UL) {
|
||||||
if (gmap_asce)
|
if (gmap_asce)
|
||||||
__tlb_flush_idte(gmap_asce);
|
__tlb_flush_idte(gmap_asce);
|
||||||
__tlb_flush_idte(mm->context.asce);
|
__tlb_flush_idte(mm->context.asce);
|
||||||
} else {
|
} 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);
|
atomic_dec(&mm->context.flush_count);
|
||||||
preempt_enable();
|
preempt_enable();
|
||||||
}
|
}
|
||||||
|
@ -94,7 +79,6 @@ static inline void __tlb_flush_kernel(void)
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
#define __tlb_flush_global() __tlb_flush_local()
|
#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.
|
* 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)
|
static inline void __tlb_flush_mm_lazy(struct mm_struct * mm)
|
||||||
{
|
{
|
||||||
|
spin_lock(&mm->context.lock);
|
||||||
if (mm->context.flush_mm) {
|
if (mm->context.flush_mm) {
|
||||||
__tlb_flush_mm(mm);
|
|
||||||
mm->context.flush_mm = 0;
|
mm->context.flush_mm = 0;
|
||||||
|
__tlb_flush_mm(mm);
|
||||||
}
|
}
|
||||||
|
spin_unlock(&mm->context.lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -280,7 +280,7 @@ EXPORT_SYMBOL(blk_start_queue_async);
|
||||||
void blk_start_queue(struct request_queue *q)
|
void blk_start_queue(struct request_queue *q)
|
||||||
{
|
{
|
||||||
lockdep_assert_held(q->queue_lock);
|
lockdep_assert_held(q->queue_lock);
|
||||||
WARN_ON(!irqs_disabled());
|
WARN_ON(!in_interrupt() && !irqs_disabled());
|
||||||
WARN_ON_ONCE(q->mq_ops);
|
WARN_ON_ONCE(q->mq_ops);
|
||||||
|
|
||||||
queue_flag_clear(QUEUE_FLAG_STOPPED, q);
|
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 (q->mq_ops) {
|
||||||
if (blk_queue_io_stat(q))
|
if (blk_queue_io_stat(q))
|
||||||
blk_account_io_start(rq, true);
|
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;
|
return BLK_STS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
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,
|
void blk_mq_insert_requests(struct blk_mq_hw_ctx *hctx, struct blk_mq_ctx *ctx,
|
||||||
struct list_head *list)
|
struct list_head *list)
|
||||||
|
|
||||||
|
|
|
@ -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,
|
void __blk_mq_insert_request(struct blk_mq_hw_ctx *hctx, struct request *rq,
|
||||||
bool at_head);
|
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,
|
void blk_mq_insert_requests(struct blk_mq_hw_ctx *hctx, struct blk_mq_ctx *ctx,
|
||||||
struct list_head *list);
|
struct list_head *list);
|
||||||
|
|
||||||
|
|
|
@ -144,8 +144,10 @@ static int skcipher_alloc_sgl(struct sock *sk)
|
||||||
sg_init_table(sgl->sg, MAX_SGL_ENTS + 1);
|
sg_init_table(sgl->sg, MAX_SGL_ENTS + 1);
|
||||||
sgl->cur = 0;
|
sgl->cur = 0;
|
||||||
|
|
||||||
if (sg)
|
if (sg) {
|
||||||
sg_chain(sg, MAX_SGL_ENTS + 1, sgl->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);
|
list_add_tail(&sgl->list, &ctx->tsgl);
|
||||||
}
|
}
|
||||||
|
|
|
@ -211,9 +211,7 @@ static int scomp_acomp_comp_decomp(struct acomp_req *req, int dir)
|
||||||
scratch_dst, &req->dlen, *ctx);
|
scratch_dst, &req->dlen, *ctx);
|
||||||
if (!ret) {
|
if (!ret) {
|
||||||
if (!req->dst) {
|
if (!req->dst) {
|
||||||
req->dst = crypto_scomp_sg_alloc(req->dlen,
|
req->dst = crypto_scomp_sg_alloc(req->dlen, GFP_ATOMIC);
|
||||||
req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP ?
|
|
||||||
GFP_KERNEL : GFP_ATOMIC);
|
|
||||||
if (!req->dst)
|
if (!req->dst)
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2160,6 +2160,9 @@ static void skd_send_fitmsg(struct skd_device *skdev,
|
||||||
*/
|
*/
|
||||||
qcmd |= FIT_QCMD_MSGSIZE_64;
|
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);
|
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 = skspcl->mb_dma_address;
|
||||||
qcmd |= FIT_QCMD_QID_NORMAL + FIT_QCMD_MSGSIZE_128;
|
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);
|
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;
|
struct gendisk *disk = skdev->disk;
|
||||||
|
|
||||||
if (disk != NULL) {
|
if (disk && (disk->flags & GENHD_FL_UP))
|
||||||
struct request_queue *q = disk->queue;
|
del_gendisk(disk);
|
||||||
|
|
||||||
if (disk->flags & GENHD_FL_UP)
|
if (skdev->queue) {
|
||||||
del_gendisk(disk);
|
blk_cleanup_queue(skdev->queue);
|
||||||
if (q)
|
skdev->queue = NULL;
|
||||||
blk_cleanup_queue(q);
|
disk->queue = NULL;
|
||||||
put_disk(disk);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
put_disk(disk);
|
||||||
skdev->disk = NULL;
|
skdev->disk = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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 crypto_ablkcipher *ablkcipher = crypto_ablkcipher_reqtfm(req);
|
||||||
struct caam_ctx *caam_ctx = crypto_ablkcipher_ctx(ablkcipher);
|
struct caam_ctx *caam_ctx = crypto_ablkcipher_ctx(ablkcipher);
|
||||||
struct device *qidev = caam_ctx->qidev;
|
struct device *qidev = caam_ctx->qidev;
|
||||||
#ifdef DEBUG
|
|
||||||
int ivsize = crypto_ablkcipher_ivsize(ablkcipher);
|
int ivsize = crypto_ablkcipher_ivsize(ablkcipher);
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
dev_err(qidev, "%s %d: status 0x%x\n", __func__, __LINE__, status);
|
dev_err(qidev, "%s %d: status 0x%x\n", __func__, __LINE__, status);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -799,6 +799,13 @@ static void ablkcipher_done(struct caam_drv_req *drv_req, u32 status)
|
||||||
ablkcipher_unmap(qidev, edesc, req);
|
ablkcipher_unmap(qidev, edesc, req);
|
||||||
qi_cache_free(edesc);
|
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);
|
ablkcipher_request_complete(req, status);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1968,7 +1975,7 @@ static struct caam_aead_alg driver_aeads[] = {
|
||||||
.cra_name = "echainiv(authenc(hmac(sha256),"
|
.cra_name = "echainiv(authenc(hmac(sha256),"
|
||||||
"cbc(des)))",
|
"cbc(des)))",
|
||||||
.cra_driver_name = "echainiv-authenc-"
|
.cra_driver_name = "echainiv-authenc-"
|
||||||
"hmac-sha256-cbc-desi-"
|
"hmac-sha256-cbc-des-"
|
||||||
"caam-qi",
|
"caam-qi",
|
||||||
.cra_blocksize = DES_BLOCK_SIZE,
|
.cra_blocksize = DES_BLOCK_SIZE,
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
/*
|
/*
|
||||||
* AMD Cryptographic Coprocessor (CCP) AES XTS crypto API support
|
* 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>
|
* Author: Tom Lendacky <thomas.lendacky@amd.com>
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* 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));
|
memset(&rctx->cmd, 0, sizeof(rctx->cmd));
|
||||||
INIT_LIST_HEAD(&rctx->cmd.entry);
|
INIT_LIST_HEAD(&rctx->cmd.entry);
|
||||||
rctx->cmd.engine = CCP_ENGINE_XTS_AES_128;
|
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
|
rctx->cmd.u.xts.action = (encrypt) ? CCP_AES_ACTION_ENCRYPT
|
||||||
: CCP_AES_ACTION_DECRYPT;
|
: CCP_AES_ACTION_DECRYPT;
|
||||||
rctx->cmd.u.xts.unit_size = unit_size;
|
rctx->cmd.u.xts.unit_size = unit_size;
|
||||||
|
|
|
@ -145,6 +145,7 @@ union ccp_function {
|
||||||
#define CCP_AES_MODE(p) ((p)->aes.mode)
|
#define CCP_AES_MODE(p) ((p)->aes.mode)
|
||||||
#define CCP_AES_TYPE(p) ((p)->aes.type)
|
#define CCP_AES_TYPE(p) ((p)->aes.type)
|
||||||
#define CCP_XTS_SIZE(p) ((p)->aes_xts.size)
|
#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_XTS_ENCRYPT(p) ((p)->aes_xts.encrypt)
|
||||||
#define CCP_DES3_SIZE(p) ((p)->des3.size)
|
#define CCP_DES3_SIZE(p) ((p)->des3.size)
|
||||||
#define CCP_DES3_ENCRYPT(p) ((p)->des3.encrypt)
|
#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;
|
CCP5_CMD_PROT(&desc) = 0;
|
||||||
|
|
||||||
function.raw = 0;
|
function.raw = 0;
|
||||||
|
CCP_XTS_TYPE(&function) = op->u.xts.type;
|
||||||
CCP_XTS_ENCRYPT(&function) = op->u.xts.action;
|
CCP_XTS_ENCRYPT(&function) = op->u.xts.action;
|
||||||
CCP_XTS_SIZE(&function) = op->u.xts.unit_size;
|
CCP_XTS_SIZE(&function) = op->u.xts.unit_size;
|
||||||
CCP5_CMD_FUNCTION(&desc) = function.raw;
|
CCP5_CMD_FUNCTION(&desc) = function.raw;
|
||||||
|
|
|
@ -192,6 +192,7 @@
|
||||||
#define CCP_AES_CTX_SB_COUNT 1
|
#define CCP_AES_CTX_SB_COUNT 1
|
||||||
|
|
||||||
#define CCP_XTS_AES_KEY_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_XTS_AES_CTX_SB_COUNT 1
|
||||||
|
|
||||||
#define CCP_DES3_KEY_SB_COUNT 1
|
#define CCP_DES3_KEY_SB_COUNT 1
|
||||||
|
@ -497,6 +498,7 @@ struct ccp_aes_op {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ccp_xts_aes_op {
|
struct ccp_xts_aes_op {
|
||||||
|
enum ccp_aes_type type;
|
||||||
enum ccp_aes_action action;
|
enum ccp_aes_action action;
|
||||||
enum ccp_xts_aes_unit_size unit_size;
|
enum ccp_xts_aes_unit_size unit_size;
|
||||||
};
|
};
|
||||||
|
|
|
@ -1038,6 +1038,8 @@ static int ccp_run_xts_aes_cmd(struct ccp_cmd_queue *cmd_q,
|
||||||
struct ccp_op op;
|
struct ccp_op op;
|
||||||
unsigned int unit_size, dm_offset;
|
unsigned int unit_size, dm_offset;
|
||||||
bool in_place = false;
|
bool in_place = false;
|
||||||
|
unsigned int sb_count;
|
||||||
|
enum ccp_aes_type aestype;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
switch (xts->unit_size) {
|
switch (xts->unit_size) {
|
||||||
|
@ -1061,7 +1063,9 @@ static int ccp_run_xts_aes_cmd(struct ccp_cmd_queue *cmd_q,
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (xts->key_len != AES_KEYSIZE_128)
|
if (xts->key_len == AES_KEYSIZE_128)
|
||||||
|
aestype = CCP_AES_TYPE_128;
|
||||||
|
else
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
if (!xts->final && (xts->src_len & (AES_BLOCK_SIZE - 1)))
|
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_key = cmd_q->sb_key;
|
||||||
op.sb_ctx = cmd_q->sb_ctx;
|
op.sb_ctx = cmd_q->sb_ctx;
|
||||||
op.init = 1;
|
op.init = 1;
|
||||||
|
op.u.xts.type = aestype;
|
||||||
op.u.xts.action = xts->action;
|
op.u.xts.action = xts->action;
|
||||||
op.u.xts.unit_size = xts->unit_size;
|
op.u.xts.unit_size = xts->unit_size;
|
||||||
|
|
||||||
/* All supported key sizes fit in a single (32-byte) SB entry
|
/* A version 3 device only supports 128-bit keys, which fits into a
|
||||||
* and must be in little endian format. Use the 256-bit byte
|
* single SB entry. A version 5 device uses a 512-bit vector, so two
|
||||||
* swap passthru option to convert from big endian to little
|
* SB entries.
|
||||||
* endian.
|
|
||||||
*/
|
*/
|
||||||
|
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,
|
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);
|
DMA_TO_DEVICE);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
dm_offset = CCP_SB_BYTES - AES_KEYSIZE_128;
|
if (cmd_q->ccp->vdata->version == CCP_VERSION(3, 0)) {
|
||||||
ccp_set_dm_area(&key, dm_offset, xts->key, 0, xts->key_len);
|
/* All supported key sizes must be in little endian format.
|
||||||
ccp_set_dm_area(&key, 0, xts->key, dm_offset, xts->key_len);
|
* 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,
|
ret = ccp_copy_to_sb(cmd_q, &key, op.jobid, op.sb_key,
|
||||||
CCP_PASSTHRU_BYTESWAP_256BIT);
|
CCP_PASSTHRU_BYTESWAP_256BIT);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
|
|
|
@ -564,7 +564,7 @@ struct devfreq *devfreq_add_device(struct device *dev,
|
||||||
err = device_register(&devfreq->dev);
|
err = device_register(&devfreq->dev);
|
||||||
if (err) {
|
if (err) {
|
||||||
mutex_unlock(&devfreq->lock);
|
mutex_unlock(&devfreq->lock);
|
||||||
goto err_out;
|
goto err_dev;
|
||||||
}
|
}
|
||||||
|
|
||||||
devfreq->trans_table = devm_kzalloc(&devfreq->dev,
|
devfreq->trans_table = devm_kzalloc(&devfreq->dev,
|
||||||
|
@ -610,6 +610,9 @@ err_init:
|
||||||
mutex_unlock(&devfreq_list_lock);
|
mutex_unlock(&devfreq_list_lock);
|
||||||
|
|
||||||
device_unregister(&devfreq->dev);
|
device_unregister(&devfreq->dev);
|
||||||
|
err_dev:
|
||||||
|
if (devfreq)
|
||||||
|
kfree(devfreq);
|
||||||
err_out:
|
err_out:
|
||||||
return ERR_PTR(err);
|
return ERR_PTR(err);
|
||||||
}
|
}
|
||||||
|
|
|
@ -95,9 +95,8 @@ int psp_wait_for(struct psp_context *psp, uint32_t reg_index,
|
||||||
int i;
|
int i;
|
||||||
struct amdgpu_device *adev = psp->adev;
|
struct amdgpu_device *adev = psp->adev;
|
||||||
|
|
||||||
val = RREG32(reg_index);
|
|
||||||
|
|
||||||
for (i = 0; i < adev->usec_timeout; i++) {
|
for (i = 0; i < adev->usec_timeout; i++) {
|
||||||
|
val = RREG32(reg_index);
|
||||||
if (check_changed) {
|
if (check_changed) {
|
||||||
if (val != reg_val)
|
if (val != reg_val)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -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 */
|
/* there might be handshake issue with hardware which needs delay */
|
||||||
mdelay(20);
|
mdelay(20);
|
||||||
#if 0
|
|
||||||
ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_81),
|
ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_81),
|
||||||
RREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_81),
|
RREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_81),
|
||||||
0, true);
|
0, true);
|
||||||
#endif
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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->pkeys[default_pkey_idx] = DEFAULT_P_KEY;
|
||||||
ppd->part_enforce |= HFI1_PART_ENFORCE_IN;
|
ppd->part_enforce |= HFI1_PART_ENFORCE_IN;
|
||||||
ppd->part_enforce |= HFI1_PART_ENFORCE_OUT;
|
|
||||||
|
|
||||||
if (loopback) {
|
if (loopback) {
|
||||||
hfi1_early_err(&pdev->dev,
|
hfi1_early_err(&pdev->dev,
|
||||||
|
|
|
@ -425,7 +425,7 @@ int hfi1_make_rc_req(struct rvt_qp *qp, struct hfi1_pkt_state *ps)
|
||||||
case IB_WR_RDMA_WRITE:
|
case IB_WR_RDMA_WRITE:
|
||||||
if (newreq && !(qp->s_flags & RVT_S_UNLIMITED_CREDIT))
|
if (newreq && !(qp->s_flags & RVT_S_UNLIMITED_CREDIT))
|
||||||
qp->s_lsn++;
|
qp->s_lsn++;
|
||||||
/* FALLTHROUGH */
|
goto no_flow_control;
|
||||||
case IB_WR_RDMA_WRITE_WITH_IMM:
|
case IB_WR_RDMA_WRITE_WITH_IMM:
|
||||||
/* If no credit, return. */
|
/* If no credit, return. */
|
||||||
if (!(qp->s_flags & RVT_S_UNLIMITED_CREDIT) &&
|
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;
|
qp->s_flags |= RVT_S_WAIT_SSN_CREDIT;
|
||||||
goto bail;
|
goto bail;
|
||||||
}
|
}
|
||||||
|
no_flow_control:
|
||||||
put_ib_reth_vaddr(
|
put_ib_reth_vaddr(
|
||||||
wqe->rdma_wr.remote_addr,
|
wqe->rdma_wr.remote_addr,
|
||||||
&ohdr->u.rc.reth);
|
&ohdr->u.rc.reth);
|
||||||
|
|
|
@ -48,6 +48,7 @@ enum {
|
||||||
#define MLX5_UMR_ALIGN 2048
|
#define MLX5_UMR_ALIGN 2048
|
||||||
|
|
||||||
static int clean_mr(struct mlx5_ib_mr *mr);
|
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 use_umr(struct mlx5_ib_dev *dev, int order);
|
||||||
static int unreg_umr(struct mlx5_ib_dev *dev, struct mlx5_ib_mr *mr);
|
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_mr_cache *cache = &dev->cache;
|
||||||
struct mlx5_ib_mr *mr = NULL;
|
struct mlx5_ib_mr *mr = NULL;
|
||||||
struct mlx5_cache_ent *ent;
|
struct mlx5_cache_ent *ent;
|
||||||
|
int last_umr_cache_entry;
|
||||||
int c;
|
int c;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
c = order2idx(dev, order);
|
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);
|
mlx5_ib_warn(dev, "order %d, cache index %d\n", order, c);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = c; i < MAX_UMR_CACHE_ENTRY; i++) {
|
for (i = c; i <= last_umr_cache_entry; i++) {
|
||||||
ent = &cache->ent[i];
|
ent = &cache->ent[i];
|
||||||
|
|
||||||
mlx5_ib_dbg(dev, "order %d, cache index %d\n", ent->order, 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;
|
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))
|
if (MLX5_CAP_GEN(dev->mdev, umr_extended_translation_offset))
|
||||||
return order <= MAX_UMR_CACHE_ENTRY + 2;
|
return MAX_UMR_CACHE_ENTRY + 2;
|
||||||
return order <= MLX5_MAX_UMR_SHIFT;
|
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,
|
static int mr_umem_get(struct ib_pd *pd, u64 start, u64 length,
|
||||||
|
|
|
@ -348,7 +348,7 @@ int qib_make_rc_req(struct rvt_qp *qp, unsigned long *flags)
|
||||||
case IB_WR_RDMA_WRITE:
|
case IB_WR_RDMA_WRITE:
|
||||||
if (newreq && !(qp->s_flags & RVT_S_UNLIMITED_CREDIT))
|
if (newreq && !(qp->s_flags & RVT_S_UNLIMITED_CREDIT))
|
||||||
qp->s_lsn++;
|
qp->s_lsn++;
|
||||||
/* FALLTHROUGH */
|
goto no_flow_control;
|
||||||
case IB_WR_RDMA_WRITE_WITH_IMM:
|
case IB_WR_RDMA_WRITE_WITH_IMM:
|
||||||
/* If no credit, return. */
|
/* If no credit, return. */
|
||||||
if (!(qp->s_flags & RVT_S_UNLIMITED_CREDIT) &&
|
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;
|
qp->s_flags |= RVT_S_WAIT_SSN_CREDIT;
|
||||||
goto bail;
|
goto bail;
|
||||||
}
|
}
|
||||||
|
no_flow_control:
|
||||||
ohdr->u.rc.reth.vaddr =
|
ohdr->u.rc.reth.vaddr =
|
||||||
cpu_to_be64(wqe->rdma_wr.remote_addr);
|
cpu_to_be64(wqe->rdma_wr.remote_addr);
|
||||||
ohdr->u.rc.reth.rkey =
|
ohdr->u.rc.reth.rkey =
|
||||||
|
|
|
@ -1764,10 +1764,12 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id
|
||||||
struct usb_endpoint_descriptor *ep =
|
struct usb_endpoint_descriptor *ep =
|
||||||
&intf->cur_altsetting->endpoint[i].desc;
|
&intf->cur_altsetting->endpoint[i].desc;
|
||||||
|
|
||||||
if (usb_endpoint_dir_in(ep))
|
if (usb_endpoint_xfer_int(ep)) {
|
||||||
ep_irq_in = ep;
|
if (usb_endpoint_dir_in(ep))
|
||||||
else
|
ep_irq_in = ep;
|
||||||
ep_irq_out = ep;
|
else
|
||||||
|
ep_irq_out = ep;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ep_irq_in || !ep_irq_out) {
|
if (!ep_irq_in || !ep_irq_out) {
|
||||||
|
|
|
@ -839,6 +839,13 @@ static const struct dmi_system_id __initconst i8042_dmi_kbdreset_table[] = {
|
||||||
DMI_MATCH(DMI_PRODUCT_NAME, "P34"),
|
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 */
|
/* Schenker XMG C504 - Elantech touchpad */
|
||||||
.matches = {
|
.matches = {
|
||||||
|
|
|
@ -95,7 +95,7 @@
|
||||||
|
|
||||||
/* Register RING_CMPL_START_ADDR fields */
|
/* Register RING_CMPL_START_ADDR fields */
|
||||||
#define CMPL_START_ADDR_VALUE(pa) \
|
#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 */
|
/* Register RING_CONTROL fields */
|
||||||
#define CONTROL_MASK_DISABLE_CONTROL 12
|
#define CONTROL_MASK_DISABLE_CONTROL 12
|
||||||
|
|
|
@ -333,6 +333,7 @@ struct cached_dev {
|
||||||
/* Limit number of writeback bios in flight */
|
/* Limit number of writeback bios in flight */
|
||||||
struct semaphore in_flight;
|
struct semaphore in_flight;
|
||||||
struct task_struct *writeback_thread;
|
struct task_struct *writeback_thread;
|
||||||
|
struct workqueue_struct *writeback_write_wq;
|
||||||
|
|
||||||
struct keybuf writeback_keys;
|
struct keybuf writeback_keys;
|
||||||
|
|
||||||
|
|
|
@ -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 data_insert_op *op = container_of(cl, struct data_insert_op, cl);
|
||||||
struct bio *bio = op->bio, *n;
|
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)
|
if (op->bypass)
|
||||||
return bch_data_invalidate(cl);
|
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
|
* Journal writes are marked REQ_PREFLUSH; if the original write was a
|
||||||
* flush, it'll wait on the journal write.
|
* 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)
|
if (!congested && !dc->sequential_cutoff)
|
||||||
goto rescale;
|
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);
|
spin_lock(&dc->io_lock);
|
||||||
|
|
||||||
hlist_for_each_entry(i, iohash(dc, bio->bi_iter.bi_sector), hash)
|
hlist_for_each_entry(i, iohash(dc, bio->bi_iter.bi_sector), hash)
|
||||||
|
|
|
@ -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) {
|
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_set(&dc->has_dirty, 1);
|
||||||
atomic_inc(&dc->count);
|
atomic_inc(&dc->count);
|
||||||
bch_writeback_queue(dc);
|
bch_writeback_queue(dc);
|
||||||
|
@ -1059,6 +1059,8 @@ static void cached_dev_free(struct closure *cl)
|
||||||
cancel_delayed_work_sync(&dc->writeback_rate_update);
|
cancel_delayed_work_sync(&dc->writeback_rate_update);
|
||||||
if (!IS_ERR_OR_NULL(dc->writeback_thread))
|
if (!IS_ERR_OR_NULL(dc->writeback_thread))
|
||||||
kthread_stop(dc->writeback_thread);
|
kthread_stop(dc->writeback_thread);
|
||||||
|
if (dc->writeback_write_wq)
|
||||||
|
destroy_workqueue(dc->writeback_write_wq);
|
||||||
|
|
||||||
mutex_lock(&bch_register_lock);
|
mutex_lock(&bch_register_lock);
|
||||||
|
|
||||||
|
@ -1228,6 +1230,7 @@ static int flash_dev_run(struct cache_set *c, struct uuid_entry *u)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
bcache_device_attach(d, c, u - c->uuids);
|
bcache_device_attach(d, c, u - c->uuids);
|
||||||
|
bch_sectors_dirty_init(d);
|
||||||
bch_flash_dev_request_init(d);
|
bch_flash_dev_request_init(d);
|
||||||
add_disk(d->disk);
|
add_disk(d->disk);
|
||||||
|
|
||||||
|
@ -1964,6 +1967,8 @@ static ssize_t register_bcache(struct kobject *k, struct kobj_attribute *attr,
|
||||||
else
|
else
|
||||||
err = "device busy";
|
err = "device busy";
|
||||||
mutex_unlock(&bch_register_lock);
|
mutex_unlock(&bch_register_lock);
|
||||||
|
if (!IS_ERR(bdev))
|
||||||
|
bdput(bdev);
|
||||||
if (attr == &ksysfs_register_quiet)
|
if (attr == &ksysfs_register_quiet)
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
|
@ -192,7 +192,7 @@ STORE(__cached_dev)
|
||||||
{
|
{
|
||||||
struct cached_dev *dc = container_of(kobj, struct cached_dev,
|
struct cached_dev *dc = container_of(kobj, struct cached_dev,
|
||||||
disk.kobj);
|
disk.kobj);
|
||||||
unsigned v = size;
|
ssize_t v = size;
|
||||||
struct cache_set *c;
|
struct cache_set *c;
|
||||||
struct kobj_uevent_env *env;
|
struct kobj_uevent_env *env;
|
||||||
|
|
||||||
|
@ -227,7 +227,7 @@ STORE(__cached_dev)
|
||||||
bch_cached_dev_run(dc);
|
bch_cached_dev_run(dc);
|
||||||
|
|
||||||
if (attr == &sysfs_cache_mode) {
|
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)
|
if (v < 0)
|
||||||
return v;
|
return v;
|
||||||
|
|
|
@ -74,24 +74,44 @@ STRTO_H(strtouint, unsigned int)
|
||||||
STRTO_H(strtoll, long long)
|
STRTO_H(strtoll, long long)
|
||||||
STRTO_H(strtoull, unsigned 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)
|
ssize_t bch_hprint(char *buf, int64_t v)
|
||||||
{
|
{
|
||||||
static const char units[] = "?kMGTPEZY";
|
static const char units[] = "?kMGTPEZY";
|
||||||
char dec[4] = "";
|
int u = 0, t;
|
||||||
int u, t = 0;
|
|
||||||
|
|
||||||
for (u = 0; v >= 1024 || v <= -1024; u++) {
|
uint64_t q;
|
||||||
t = v & ~(~0 << 10);
|
|
||||||
v >>= 10;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!u)
|
if (v < 0)
|
||||||
return sprintf(buf, "%llu", v);
|
q = -v;
|
||||||
|
else
|
||||||
|
q = v;
|
||||||
|
|
||||||
if (v < 100 && v > -100)
|
/* For as long as the number is more than 3 digits, but at least
|
||||||
snprintf(dec, sizeof(dec), ".%i", t / 100);
|
* 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[],
|
ssize_t bch_snprint_string_list(char *buf, size_t size, const char * const list[],
|
||||||
|
|
|
@ -21,7 +21,8 @@
|
||||||
static void __update_writeback_rate(struct cached_dev *dc)
|
static void __update_writeback_rate(struct cached_dev *dc)
|
||||||
{
|
{
|
||||||
struct cache_set *c = dc->disk.c;
|
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 =
|
uint64_t cache_dirty_target =
|
||||||
div_u64(cache_sectors * dc->writeback_percent, 100);
|
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);
|
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)
|
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);
|
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)
|
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;
|
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;
|
struct sectors_dirty_init op;
|
||||||
|
|
||||||
bch_btree_op_init(&op.op, -1);
|
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);
|
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)
|
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)
|
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,
|
dc->writeback_thread = kthread_create(bch_writeback_thread, dc,
|
||||||
"bcache_writeback");
|
"bcache_writeback");
|
||||||
if (IS_ERR(dc->writeback_thread))
|
if (IS_ERR(dc->writeback_thread))
|
||||||
|
|
|
@ -14,6 +14,25 @@ static inline uint64_t bcache_dev_sectors_dirty(struct bcache_device *d)
|
||||||
return ret;
|
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,
|
static inline unsigned offset_to_stripe(struct bcache_device *d,
|
||||||
uint64_t offset)
|
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 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 *);
|
void bch_cached_dev_writeback_init(struct cached_dev *);
|
||||||
int bch_cached_dev_writeback_start(struct cached_dev *);
|
int bch_cached_dev_writeback_start(struct cached_dev *);
|
||||||
|
|
||||||
|
|
|
@ -625,7 +625,7 @@ re_read:
|
||||||
err = read_sb_page(bitmap->mddev,
|
err = read_sb_page(bitmap->mddev,
|
||||||
offset,
|
offset,
|
||||||
sb_page,
|
sb_page,
|
||||||
0, sizeof(bitmap_super_t));
|
0, PAGE_SIZE);
|
||||||
}
|
}
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
@ -2058,6 +2058,11 @@ int bitmap_resize(struct bitmap *bitmap, sector_t blocks,
|
||||||
long pages;
|
long pages;
|
||||||
struct bitmap_page *new_bp;
|
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 (chunksize == 0) {
|
||||||
/* If there is enough space, leave the chunk size unchanged,
|
/* If there is enough space, leave the chunk size unchanged,
|
||||||
* else increase by factor of two until there is enough space.
|
* 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)
|
if (store.sb_page && bitmap->storage.sb_page)
|
||||||
memcpy(page_address(store.sb_page),
|
memcpy(page_address(store.sb_page),
|
||||||
page_address(bitmap->storage.sb_page),
|
page_address(bitmap->storage.sb_page),
|
||||||
sizeof(bitmap_super_t));
|
PAGE_SIZE);
|
||||||
bitmap_file_unmap(&bitmap->storage);
|
bitmap_file_unmap(&bitmap->storage);
|
||||||
bitmap->storage = store;
|
bitmap->storage = store;
|
||||||
|
|
||||||
|
|
|
@ -1402,6 +1402,8 @@ static int adv7180_remove(struct i2c_client *client)
|
||||||
|
|
||||||
static const struct i2c_device_id adv7180_id[] = {
|
static const struct i2c_device_id adv7180_id[] = {
|
||||||
{ "adv7180", (kernel_ulong_t)&adv7180_info },
|
{ "adv7180", (kernel_ulong_t)&adv7180_info },
|
||||||
|
{ "adv7180cp", (kernel_ulong_t)&adv7180_info },
|
||||||
|
{ "adv7180st", (kernel_ulong_t)&adv7180_info },
|
||||||
{ "adv7182", (kernel_ulong_t)&adv7182_info },
|
{ "adv7182", (kernel_ulong_t)&adv7182_info },
|
||||||
{ "adv7280", (kernel_ulong_t)&adv7280_info },
|
{ "adv7280", (kernel_ulong_t)&adv7280_info },
|
||||||
{ "adv7280-m", (kernel_ulong_t)&adv7280_m_info },
|
{ "adv7280-m", (kernel_ulong_t)&adv7280_m_info },
|
||||||
|
|
|
@ -243,7 +243,7 @@ static void return_buf_error(struct venus_inst *inst,
|
||||||
if (vbuf->vb2_buf.type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
|
if (vbuf->vb2_buf.type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
|
||||||
v4l2_m2m_src_buf_remove_by_buf(m2m_ctx, vbuf);
|
v4l2_m2m_src_buf_remove_by_buf(m2m_ctx, vbuf);
|
||||||
else
|
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);
|
v4l2_m2m_buf_done(vbuf, VB2_BUF_STATE_ERROR);
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,6 +59,8 @@ static void lirc_release(struct device *ld)
|
||||||
{
|
{
|
||||||
struct irctl *ir = container_of(ld, struct irctl, dev);
|
struct irctl *ir = container_of(ld, struct irctl, dev);
|
||||||
|
|
||||||
|
put_device(ir->dev.parent);
|
||||||
|
|
||||||
if (ir->buf_internal) {
|
if (ir->buf_internal) {
|
||||||
lirc_buffer_free(ir->buf);
|
lirc_buffer_free(ir->buf);
|
||||||
kfree(ir->buf);
|
kfree(ir->buf);
|
||||||
|
@ -218,6 +220,8 @@ int lirc_register_driver(struct lirc_driver *d)
|
||||||
|
|
||||||
mutex_unlock(&lirc_dev_lock);
|
mutex_unlock(&lirc_dev_lock);
|
||||||
|
|
||||||
|
get_device(ir->dev.parent);
|
||||||
|
|
||||||
dev_info(ir->d.dev, "lirc_dev: driver %s registered at minor = %d\n",
|
dev_info(ir->d.dev, "lirc_dev: driver %s registered at minor = %d\n",
|
||||||
ir->d.name, ir->d.minor);
|
ir->d.name, ir->d.minor);
|
||||||
|
|
||||||
|
|
|
@ -2002,6 +2002,13 @@ int uvc_ctrl_add_mapping(struct uvc_video_chain *chain,
|
||||||
goto done;
|
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) {
|
list_for_each_entry(map, &ctrl->info.mappings, list) {
|
||||||
if (mapping->id == map->id) {
|
if (mapping->id == map->id) {
|
||||||
uvc_trace(UVC_TRACE_CONTROL, "Can't add mapping '%s', "
|
uvc_trace(UVC_TRACE_CONTROL, "Can't add mapping '%s', "
|
||||||
|
|
|
@ -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)) ||
|
copy_to_user(&up->u, &kp->u, sizeof(kp->u)) ||
|
||||||
put_user(kp->pending, &up->pending) ||
|
put_user(kp->pending, &up->pending) ||
|
||||||
put_user(kp->sequence, &up->sequence) ||
|
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) ||
|
put_user(kp->id, &up->id) ||
|
||||||
copy_to_user(up->reserved, kp->reserved, 8 * sizeof(__u32)))
|
copy_to_user(up->reserved, kp->reserved, 8 * sizeof(__u32)))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
|
|
|
@ -336,6 +336,10 @@ int cxl_start_context(struct cxl_context *ctx, u64 wed,
|
||||||
mmput(ctx->mm);
|
mmput(ctx->mm);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Increment driver use count. Enables global TLBIs for hash
|
||||||
|
* and callbacks to handle the segment table
|
||||||
|
*/
|
||||||
cxl_ctx_get();
|
cxl_ctx_get();
|
||||||
|
|
||||||
if ((rc = cxl_ops->attach_process(ctx, kernel, wed, 0))) {
|
if ((rc = cxl_ops->attach_process(ctx, kernel, wed, 0))) {
|
||||||
|
|
|
@ -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);
|
pr_devel("afu_open pe: %i\n", ctx->pe);
|
||||||
file->private_data = ctx;
|
file->private_data = ctx;
|
||||||
cxl_ctx_get();
|
|
||||||
|
|
||||||
/* indicate success */
|
/* indicate success */
|
||||||
rc = 0;
|
rc = 0;
|
||||||
|
@ -225,6 +224,12 @@ static long afu_ioctl_start_work(struct cxl_context *ctx,
|
||||||
if (ctx->mm)
|
if (ctx->mm)
|
||||||
mmput(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);
|
trace_cxl_attach(ctx, work.work_element_descriptor, work.num_interrupts, amr);
|
||||||
|
|
||||||
if ((rc = cxl_ops->attach_process(ctx, false, work.work_element_descriptor,
|
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);
|
cxl_adapter_context_put(ctx->afu->adapter);
|
||||||
put_pid(ctx->pid);
|
put_pid(ctx->pid);
|
||||||
ctx->pid = NULL;
|
ctx->pid = NULL;
|
||||||
|
cxl_ctx_put();
|
||||||
cxl_context_mm_count_put(ctx);
|
cxl_context_mm_count_put(ctx);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
wcn36xx_dbg(WCN36XX_DBG_MAC, "mac config changed 0x%08x\n", changed);
|
||||||
|
|
||||||
|
mutex_lock(&wcn->conf_mutex);
|
||||||
|
|
||||||
if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
|
if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
|
||||||
int ch = WCN36XX_HW_CHANNEL(wcn);
|
int ch = WCN36XX_HW_CHANNEL(wcn);
|
||||||
wcn36xx_dbg(WCN36XX_DBG_MAC, "wcn36xx_config channel switch=%d\n",
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -396,6 +400,8 @@ static void wcn36xx_configure_filter(struct ieee80211_hw *hw,
|
||||||
|
|
||||||
wcn36xx_dbg(WCN36XX_DBG_MAC, "mac configure filter\n");
|
wcn36xx_dbg(WCN36XX_DBG_MAC, "mac configure filter\n");
|
||||||
|
|
||||||
|
mutex_lock(&wcn->conf_mutex);
|
||||||
|
|
||||||
*total &= FIF_ALLMULTI;
|
*total &= FIF_ALLMULTI;
|
||||||
|
|
||||||
fp = (void *)(unsigned long)multicast;
|
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)
|
else if (NL80211_IFTYPE_STATION == vif->type && tmp->sta_assoc)
|
||||||
wcn36xx_smd_set_mc_list(wcn, vif, fp);
|
wcn36xx_smd_set_mc_list(wcn, vif, fp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mutex_unlock(&wcn->conf_mutex);
|
||||||
kfree(fp);
|
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->key,
|
||||||
key_conf->keylen);
|
key_conf->keylen);
|
||||||
|
|
||||||
|
mutex_lock(&wcn->conf_mutex);
|
||||||
|
|
||||||
switch (key_conf->cipher) {
|
switch (key_conf->cipher) {
|
||||||
case WLAN_CIPHER_SUITE_WEP40:
|
case WLAN_CIPHER_SUITE_WEP40:
|
||||||
vif_priv->encrypt_type = WCN36XX_HAL_ED_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:
|
out:
|
||||||
|
mutex_unlock(&wcn->conf_mutex);
|
||||||
|
|
||||||
return ret;
|
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",
|
wcn36xx_dbg(WCN36XX_DBG_MAC, "mac bss info changed vif %p changed 0x%08x\n",
|
||||||
vif, changed);
|
vif, changed);
|
||||||
|
|
||||||
|
mutex_lock(&wcn->conf_mutex);
|
||||||
|
|
||||||
if (changed & BSS_CHANGED_BEACON_INFO) {
|
if (changed & BSS_CHANGED_BEACON_INFO) {
|
||||||
wcn36xx_dbg(WCN36XX_DBG_MAC,
|
wcn36xx_dbg(WCN36XX_DBG_MAC,
|
||||||
"mac bss changed dtim period %d\n",
|
"mac bss changed dtim period %d\n",
|
||||||
|
@ -787,7 +801,13 @@ static void wcn36xx_bss_info_changed(struct ieee80211_hw *hw,
|
||||||
bss_conf->aid);
|
bss_conf->aid);
|
||||||
|
|
||||||
vif_priv->sta_assoc = true;
|
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);
|
sta = ieee80211_find_sta(vif, bss_conf->bssid);
|
||||||
if (!sta) {
|
if (!sta) {
|
||||||
wcn36xx_err("sta %pM is not found\n",
|
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.
|
* place where AID is available.
|
||||||
*/
|
*/
|
||||||
wcn36xx_smd_config_sta(wcn, vif, sta);
|
wcn36xx_smd_config_sta(wcn, vif, sta);
|
||||||
rcu_read_unlock();
|
|
||||||
} else {
|
} else {
|
||||||
wcn36xx_dbg(WCN36XX_DBG_MAC,
|
wcn36xx_dbg(WCN36XX_DBG_MAC,
|
||||||
"disassociated bss %pM vif %pM AID=%d\n",
|
"disassociated bss %pM vif %pM AID=%d\n",
|
||||||
|
@ -873,6 +892,9 @@ static void wcn36xx_bss_info_changed(struct ieee80211_hw *hw,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
out:
|
out:
|
||||||
|
|
||||||
|
mutex_unlock(&wcn->conf_mutex);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -882,7 +904,10 @@ static int wcn36xx_set_rts_threshold(struct ieee80211_hw *hw, u32 value)
|
||||||
struct wcn36xx *wcn = hw->priv;
|
struct wcn36xx *wcn = hw->priv;
|
||||||
wcn36xx_dbg(WCN36XX_DBG_MAC, "mac set RTS threshold %d\n", value);
|
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);
|
wcn36xx_smd_update_cfg(wcn, WCN36XX_HAL_CFG_RTS_THRESHOLD, value);
|
||||||
|
mutex_unlock(&wcn->conf_mutex);
|
||||||
|
|
||||||
return 0;
|
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);
|
struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
|
||||||
wcn36xx_dbg(WCN36XX_DBG_MAC, "mac remove interface vif %p\n", vif);
|
wcn36xx_dbg(WCN36XX_DBG_MAC, "mac remove interface vif %p\n", vif);
|
||||||
|
|
||||||
|
mutex_lock(&wcn->conf_mutex);
|
||||||
|
|
||||||
list_del(&vif_priv->list);
|
list_del(&vif_priv->list);
|
||||||
wcn36xx_smd_delete_sta_self(wcn, vif->addr);
|
wcn36xx_smd_delete_sta_self(wcn, vif->addr);
|
||||||
|
|
||||||
|
mutex_unlock(&wcn->conf_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int wcn36xx_add_interface(struct ieee80211_hw *hw,
|
static int wcn36xx_add_interface(struct ieee80211_hw *hw,
|
||||||
|
@ -915,9 +944,13 @@ static int wcn36xx_add_interface(struct ieee80211_hw *hw,
|
||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mutex_lock(&wcn->conf_mutex);
|
||||||
|
|
||||||
list_add(&vif_priv->list, &wcn->vif_list);
|
list_add(&vif_priv->list, &wcn->vif_list);
|
||||||
wcn36xx_smd_add_sta_self(wcn, vif);
|
wcn36xx_smd_add_sta_self(wcn, vif);
|
||||||
|
|
||||||
|
mutex_unlock(&wcn->conf_mutex);
|
||||||
|
|
||||||
return 0;
|
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",
|
wcn36xx_dbg(WCN36XX_DBG_MAC, "mac sta add vif %p sta %pM\n",
|
||||||
vif, sta->addr);
|
vif, sta->addr);
|
||||||
|
|
||||||
|
mutex_lock(&wcn->conf_mutex);
|
||||||
|
|
||||||
spin_lock_init(&sta_priv->ampdu_lock);
|
spin_lock_init(&sta_priv->ampdu_lock);
|
||||||
sta_priv->vif = vif_priv;
|
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;
|
sta_priv->aid = sta->aid;
|
||||||
wcn36xx_smd_config_sta(wcn, vif, sta);
|
wcn36xx_smd_config_sta(wcn, vif, sta);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mutex_unlock(&wcn->conf_mutex);
|
||||||
|
|
||||||
return 0;
|
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",
|
wcn36xx_dbg(WCN36XX_DBG_MAC, "mac sta remove vif %p sta %pM index %d\n",
|
||||||
vif, sta->addr, sta_priv->sta_index);
|
vif, sta->addr, sta_priv->sta_index);
|
||||||
|
|
||||||
|
mutex_lock(&wcn->conf_mutex);
|
||||||
|
|
||||||
wcn36xx_smd_delete_sta(wcn, sta_priv->sta_index);
|
wcn36xx_smd_delete_sta(wcn, sta_priv->sta_index);
|
||||||
sta_priv->vif = NULL;
|
sta_priv->vif = NULL;
|
||||||
|
|
||||||
|
mutex_unlock(&wcn->conf_mutex);
|
||||||
|
|
||||||
return 0;
|
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",
|
wcn36xx_dbg(WCN36XX_DBG_MAC, "mac ampdu action action %d tid %d\n",
|
||||||
action, tid);
|
action, tid);
|
||||||
|
|
||||||
|
mutex_lock(&wcn->conf_mutex);
|
||||||
|
|
||||||
switch (action) {
|
switch (action) {
|
||||||
case IEEE80211_AMPDU_RX_START:
|
case IEEE80211_AMPDU_RX_START:
|
||||||
sta_priv->tid = tid;
|
sta_priv->tid = tid;
|
||||||
|
@ -1038,6 +1083,8 @@ static int wcn36xx_ampdu_action(struct ieee80211_hw *hw,
|
||||||
wcn36xx_err("Unknown AMPDU action\n");
|
wcn36xx_err("Unknown AMPDU action\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mutex_unlock(&wcn->conf_mutex);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1216,6 +1263,7 @@ static int wcn36xx_probe(struct platform_device *pdev)
|
||||||
wcn = hw->priv;
|
wcn = hw->priv;
|
||||||
wcn->hw = hw;
|
wcn->hw = hw;
|
||||||
wcn->dev = &pdev->dev;
|
wcn->dev = &pdev->dev;
|
||||||
|
mutex_init(&wcn->conf_mutex);
|
||||||
mutex_init(&wcn->hal_mutex);
|
mutex_init(&wcn->hal_mutex);
|
||||||
mutex_init(&wcn->scan_lock);
|
mutex_init(&wcn->scan_lock);
|
||||||
|
|
||||||
|
|
|
@ -202,6 +202,9 @@ struct wcn36xx {
|
||||||
struct qcom_smem_state *tx_rings_empty_state;
|
struct qcom_smem_state *tx_rings_empty_state;
|
||||||
unsigned tx_rings_empty_state_bit;
|
unsigned tx_rings_empty_state_bit;
|
||||||
|
|
||||||
|
/* prevents concurrent FW reconfiguration */
|
||||||
|
struct mutex conf_mutex;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* smd_buf must be protected with smd_mutex to garantee
|
* smd_buf must be protected with smd_mutex to garantee
|
||||||
* that all messages are sent one after another
|
* that all messages are sent one after another
|
||||||
|
|
|
@ -79,6 +79,7 @@
|
||||||
/* NVM offsets (in words) definitions */
|
/* NVM offsets (in words) definitions */
|
||||||
enum wkp_nvm_offsets {
|
enum wkp_nvm_offsets {
|
||||||
/* NVM HW-Section offset (in words) definitions */
|
/* NVM HW-Section offset (in words) definitions */
|
||||||
|
SUBSYSTEM_ID = 0x0A,
|
||||||
HW_ADDR = 0x15,
|
HW_ADDR = 0x15,
|
||||||
|
|
||||||
/* NVM SW-Section offset (in words) definitions */
|
/* 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,
|
static int iwl_init_channel_map(struct device *dev, const struct iwl_cfg *cfg,
|
||||||
struct iwl_nvm_data *data,
|
struct iwl_nvm_data *data,
|
||||||
const __le16 * const nvm_ch_flags,
|
const __le16 * const nvm_ch_flags,
|
||||||
bool lar_supported)
|
bool lar_supported, bool no_wide_in_5ghz)
|
||||||
{
|
{
|
||||||
int ch_idx;
|
int ch_idx;
|
||||||
int n_channels = 0;
|
int n_channels = 0;
|
||||||
struct ieee80211_channel *channel;
|
struct ieee80211_channel *channel;
|
||||||
u16 ch_flags;
|
u16 ch_flags;
|
||||||
bool is_5ghz;
|
|
||||||
int num_of_ch, num_2ghz_channels;
|
int num_of_ch, num_2ghz_channels;
|
||||||
const u8 *nvm_chan;
|
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++) {
|
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);
|
ch_flags = __le16_to_cpup(nvm_ch_flags + ch_idx);
|
||||||
|
|
||||||
if (ch_idx >= num_2ghz_channels &&
|
if (is_5ghz && !data->sku_cap_band_52GHz_enable)
|
||||||
!data->sku_cap_band_52GHz_enable)
|
|
||||||
continue;
|
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)
|
if (ch_flags & NVM_CHANNEL_160MHZ)
|
||||||
data->vht160_supported = true;
|
data->vht160_supported = true;
|
||||||
|
|
||||||
|
@ -303,8 +311,8 @@ static int iwl_init_channel_map(struct device *dev, const struct iwl_cfg *cfg,
|
||||||
n_channels++;
|
n_channels++;
|
||||||
|
|
||||||
channel->hw_value = nvm_chan[ch_idx];
|
channel->hw_value = nvm_chan[ch_idx];
|
||||||
channel->band = (ch_idx < num_2ghz_channels) ?
|
channel->band = is_5ghz ?
|
||||||
NL80211_BAND_2GHZ : NL80211_BAND_5GHZ;
|
NL80211_BAND_5GHZ : NL80211_BAND_2GHZ;
|
||||||
channel->center_freq =
|
channel->center_freq =
|
||||||
ieee80211_channel_to_frequency(
|
ieee80211_channel_to_frequency(
|
||||||
channel->hw_value, channel->band);
|
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
|
* is not used in mvm, and is used for backwards compatibility
|
||||||
*/
|
*/
|
||||||
channel->max_power = IWL_DEFAULT_MAX_TX_POWER;
|
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 */
|
/* don't put limitations in case we're using LAR */
|
||||||
if (!lar_supported)
|
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,
|
void iwl_init_sbands(struct device *dev, const struct iwl_cfg *cfg,
|
||||||
struct iwl_nvm_data *data, const __le16 *nvm_ch_flags,
|
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_channels;
|
||||||
int n_used = 0;
|
int n_used = 0;
|
||||||
struct ieee80211_supported_band *sband;
|
struct ieee80211_supported_band *sband;
|
||||||
|
|
||||||
n_channels = iwl_init_channel_map(dev, cfg, data, nvm_ch_flags,
|
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 = &data->bands[NL80211_BAND_2GHZ];
|
||||||
sband->band = NL80211_BAND_2GHZ;
|
sband->band = NL80211_BAND_2GHZ;
|
||||||
sband->bitrates = &iwl_cfg80211_rates[RATES_24_OFFS];
|
sband->bitrates = &iwl_cfg80211_rates[RATES_24_OFFS];
|
||||||
|
@ -645,6 +653,39 @@ static int iwl_set_hw_address(struct iwl_trans *trans,
|
||||||
return 0;
|
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 *
|
struct iwl_nvm_data *
|
||||||
iwl_parse_nvm_data(struct iwl_trans *trans, const struct iwl_cfg *cfg,
|
iwl_parse_nvm_data(struct iwl_trans *trans, const struct iwl_cfg *cfg,
|
||||||
const __le16 *nvm_hw, const __le16 *nvm_sw,
|
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 device *dev = trans->dev;
|
||||||
struct iwl_nvm_data *data;
|
struct iwl_nvm_data *data;
|
||||||
bool lar_enabled;
|
bool lar_enabled;
|
||||||
|
bool no_wide_in_5ghz = iwl_nvm_no_wide_in_5ghz(dev, cfg, nvm_hw);
|
||||||
u32 sku, radio_cfg;
|
u32 sku, radio_cfg;
|
||||||
u16 lar_config;
|
u16 lar_config;
|
||||||
const __le16 *ch_section;
|
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,
|
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;
|
data->calib_version = 255;
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
|
|
|
@ -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,
|
void iwl_init_sbands(struct device *dev, const struct iwl_cfg *cfg,
|
||||||
struct iwl_nvm_data *data, const __le16 *nvm_ch_flags,
|
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
|
* iwl_parse_mcc_info - parse MCC (mobile country code) info coming from FW
|
||||||
|
|
|
@ -628,7 +628,8 @@ int iwl_mvm_nvm_get_from_fw(struct iwl_mvm *mvm)
|
||||||
rsp->regulatory.channel_profile,
|
rsp->regulatory.channel_profile,
|
||||||
mvm->nvm_data->valid_tx_ant & mvm->fw->valid_tx_ant,
|
mvm->nvm_data->valid_tx_ant & mvm->fw->valid_tx_ant,
|
||||||
mvm->nvm_data->valid_rx_ant & mvm->fw->valid_rx_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);
|
iwl_free_resp(&hcmd);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -586,6 +586,14 @@ static irqreturn_t pciehp_isr(int irq, void *dev_id)
|
||||||
events = status & (PCI_EXP_SLTSTA_ABP | PCI_EXP_SLTSTA_PFD |
|
events = status & (PCI_EXP_SLTSTA_ABP | PCI_EXP_SLTSTA_PFD |
|
||||||
PCI_EXP_SLTSTA_PDC | PCI_EXP_SLTSTA_CC |
|
PCI_EXP_SLTSTA_PDC | PCI_EXP_SLTSTA_CC |
|
||||||
PCI_EXP_SLTSTA_DLLSC);
|
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)
|
if (!events)
|
||||||
return IRQ_NONE;
|
return IRQ_NONE;
|
||||||
|
|
||||||
|
|
|
@ -1062,6 +1062,8 @@ int shpc_init(struct controller *ctrl, struct pci_dev *pdev)
|
||||||
if (rc) {
|
if (rc) {
|
||||||
ctrl_info(ctrl, "Can't get msi for the hotplug controller\n");
|
ctrl_info(ctrl, "Can't get msi for the hotplug controller\n");
|
||||||
ctrl_info(ctrl, "Use INTx 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,
|
rc = request_irq(ctrl->pci_dev->irq, shpc_isr, IRQF_SHARED,
|
||||||
|
|
|
@ -36,6 +36,7 @@
|
||||||
#include <linux/pinctrl/pinconf.h>
|
#include <linux/pinctrl/pinconf.h>
|
||||||
#include <linux/pinctrl/pinconf-generic.h>
|
#include <linux/pinctrl/pinconf-generic.h>
|
||||||
|
|
||||||
|
#include "core.h"
|
||||||
#include "pinctrl-utils.h"
|
#include "pinctrl-utils.h"
|
||||||
#include "pinctrl-amd.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,
|
.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 = {
|
static struct pinctrl_desc amd_pinctrl_desc = {
|
||||||
.pins = kerncz_pins,
|
.pins = kerncz_pins,
|
||||||
.npins = ARRAY_SIZE(kerncz_pins),
|
.npins = ARRAY_SIZE(kerncz_pins),
|
||||||
|
@ -764,6 +828,14 @@ static int amd_gpio_probe(struct platform_device *pdev)
|
||||||
return -EINVAL;
|
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->pdev = pdev;
|
||||||
gpio_dev->gc.direction_input = amd_gpio_direction_input;
|
gpio_dev->gc.direction_input = amd_gpio_direction_input;
|
||||||
gpio_dev->gc.direction_output = amd_gpio_direction_output;
|
gpio_dev->gc.direction_output = amd_gpio_direction_output;
|
||||||
|
@ -853,6 +925,9 @@ static struct platform_driver amd_gpio_driver = {
|
||||||
.driver = {
|
.driver = {
|
||||||
.name = "amd_gpio",
|
.name = "amd_gpio",
|
||||||
.acpi_match_table = ACPI_PTR(amd_gpio_acpi_match),
|
.acpi_match_table = ACPI_PTR(amd_gpio_acpi_match),
|
||||||
|
#ifdef CONFIG_PM_SLEEP
|
||||||
|
.pm = &amd_gpio_pm_ops,
|
||||||
|
#endif
|
||||||
},
|
},
|
||||||
.probe = amd_gpio_probe,
|
.probe = amd_gpio_probe,
|
||||||
.remove = amd_gpio_remove,
|
.remove = amd_gpio_remove,
|
||||||
|
|
|
@ -97,6 +97,7 @@ struct amd_gpio {
|
||||||
unsigned int hwbank_num;
|
unsigned int hwbank_num;
|
||||||
struct resource *res;
|
struct resource *res;
|
||||||
struct platform_device *pdev;
|
struct platform_device *pdev;
|
||||||
|
u32 *saved_regs;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* KERNCZ configuration*/
|
/* KERNCZ configuration*/
|
||||||
|
|
|
@ -174,10 +174,10 @@ static int exynos_irq_request_resources(struct irq_data *irqd)
|
||||||
|
|
||||||
spin_lock_irqsave(&bank->slock, flags);
|
spin_lock_irqsave(&bank->slock, flags);
|
||||||
|
|
||||||
con = readl(bank->eint_base + reg_con);
|
con = readl(bank->pctl_base + reg_con);
|
||||||
con &= ~(mask << shift);
|
con &= ~(mask << shift);
|
||||||
con |= EXYNOS_EINT_FUNC << 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);
|
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);
|
spin_lock_irqsave(&bank->slock, flags);
|
||||||
|
|
||||||
con = readl(bank->eint_base + reg_con);
|
con = readl(bank->pctl_base + reg_con);
|
||||||
con &= ~(mask << shift);
|
con &= ~(mask << shift);
|
||||||
con |= FUNC_INPUT << 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);
|
spin_unlock_irqrestore(&bank->slock, flags);
|
||||||
|
|
||||||
|
|
|
@ -151,7 +151,7 @@ static void s3c24xx_eint_set_function(struct samsung_pinctrl_drv_data *d,
|
||||||
u32 val;
|
u32 val;
|
||||||
|
|
||||||
/* Make sure that pin is configured as interrupt */
|
/* 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];
|
shift = pin * bank_type->fld_width[PINCFG_TYPE_FUNC];
|
||||||
mask = (1 << bank_type->fld_width[PINCFG_TYPE_FUNC]) - 1;
|
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);
|
s3c24xx_eint_set_handler(data, type);
|
||||||
|
|
||||||
/* Set up interrupt trigger */
|
/* Set up interrupt trigger */
|
||||||
reg = bank->eint_base + EINT_REG(index);
|
reg = d->virt_base + EINT_REG(index);
|
||||||
shift = EINT_OFFS(index);
|
shift = EINT_OFFS(index);
|
||||||
|
|
||||||
val = readl(reg);
|
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)
|
static void s3c2412_eint0_3_ack(struct irq_data *data)
|
||||||
{
|
{
|
||||||
struct samsung_pin_bank *bank = irq_data_get_irq_chip_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;
|
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)
|
static void s3c2412_eint0_3_mask(struct irq_data *data)
|
||||||
{
|
{
|
||||||
struct samsung_pin_bank *bank = irq_data_get_irq_chip_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;
|
unsigned long mask;
|
||||||
|
|
||||||
mask = readl(bank->eint_base + EINTMASK_REG);
|
mask = readl(d->virt_base + EINTMASK_REG);
|
||||||
mask |= (1UL << data->hwirq);
|
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)
|
static void s3c2412_eint0_3_unmask(struct irq_data *data)
|
||||||
{
|
{
|
||||||
struct samsung_pin_bank *bank = irq_data_get_irq_chip_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;
|
unsigned long mask;
|
||||||
|
|
||||||
mask = readl(bank->eint_base + EINTMASK_REG);
|
mask = readl(d->virt_base + EINTMASK_REG);
|
||||||
mask &= ~(1UL << data->hwirq);
|
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 = {
|
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)
|
static void s3c24xx_eint_ack(struct irq_data *data)
|
||||||
{
|
{
|
||||||
struct samsung_pin_bank *bank = irq_data_get_irq_chip_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 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)
|
static void s3c24xx_eint_mask(struct irq_data *data)
|
||||||
{
|
{
|
||||||
struct samsung_pin_bank *bank = irq_data_get_irq_chip_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 char index = bank->eint_offset + data->hwirq;
|
||||||
unsigned long mask;
|
unsigned long mask;
|
||||||
|
|
||||||
mask = readl(bank->eint_base + EINTMASK_REG);
|
mask = readl(d->virt_base + EINTMASK_REG);
|
||||||
mask |= (1UL << index);
|
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)
|
static void s3c24xx_eint_unmask(struct irq_data *data)
|
||||||
{
|
{
|
||||||
struct samsung_pin_bank *bank = irq_data_get_irq_chip_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 char index = bank->eint_offset + data->hwirq;
|
||||||
unsigned long mask;
|
unsigned long mask;
|
||||||
|
|
||||||
mask = readl(bank->eint_base + EINTMASK_REG);
|
mask = readl(d->virt_base + EINTMASK_REG);
|
||||||
mask &= ~(1UL << index);
|
mask &= ~(1UL << index);
|
||||||
writel(mask, bank->eint_base + EINTMASK_REG);
|
writel(mask, d->virt_base + EINTMASK_REG);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct irq_chip s3c24xx_eint_chip = {
|
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 s3c24xx_eint_data *data = irq_desc_get_handler_data(desc);
|
||||||
struct irq_chip *chip = irq_desc_get_chip(desc);
|
struct irq_chip *chip = irq_desc_get_chip(desc);
|
||||||
struct irq_data *irqd = irq_desc_get_irq_data(desc);
|
struct samsung_pinctrl_drv_data *d = data->drvdata;
|
||||||
struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd);
|
|
||||||
unsigned int pend, mask;
|
unsigned int pend, mask;
|
||||||
|
|
||||||
chained_irq_enter(chip, desc);
|
chained_irq_enter(chip, desc);
|
||||||
|
|
||||||
pend = readl(bank->eint_base + EINTPEND_REG);
|
pend = readl(d->virt_base + EINTPEND_REG);
|
||||||
mask = readl(bank->eint_base + EINTMASK_REG);
|
mask = readl(d->virt_base + EINTMASK_REG);
|
||||||
|
|
||||||
pend &= ~mask;
|
pend &= ~mask;
|
||||||
pend &= range;
|
pend &= range;
|
||||||
|
|
|
@ -280,7 +280,7 @@ static void s3c64xx_irq_set_function(struct samsung_pinctrl_drv_data *d,
|
||||||
u32 val;
|
u32 val;
|
||||||
|
|
||||||
/* Make sure that pin is configured as interrupt */
|
/* Make sure that pin is configured as interrupt */
|
||||||
reg = bank->pctl_base + bank->pctl_offset;
|
reg = d->virt_base + bank->pctl_offset;
|
||||||
shift = pin;
|
shift = pin;
|
||||||
if (bank_type->fld_width[PINCFG_TYPE_FUNC] * shift >= 32) {
|
if (bank_type->fld_width[PINCFG_TYPE_FUNC] * shift >= 32) {
|
||||||
/* 4-bit bank type with 2 con regs */
|
/* 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)
|
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_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;
|
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;
|
u32 val;
|
||||||
|
|
||||||
val = readl(reg);
|
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)
|
static void s3c64xx_gpio_irq_ack(struct irq_data *irqd)
|
||||||
{
|
{
|
||||||
struct samsung_pin_bank *bank = irq_data_get_irq_chip_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;
|
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);
|
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);
|
s3c64xx_irq_set_handler(irqd, type);
|
||||||
|
|
||||||
/* Set up interrupt trigger */
|
/* 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 = EINT_OFFS(bank->eint_offset) + irqd->hwirq;
|
||||||
shift = 4 * (shift / 4); /* 4 EINTs per trigger selector */
|
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 irq_chip *chip = irq_desc_get_chip(desc);
|
||||||
struct s3c64xx_eint_gpio_data *data = irq_desc_get_handler_data(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_pinctrl_drv_data *drvdata = data->drvdata;
|
||||||
struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd);
|
|
||||||
|
|
||||||
chained_irq_enter(chip, desc);
|
chained_irq_enter(chip, desc);
|
||||||
|
|
||||||
|
@ -420,7 +421,7 @@ static void s3c64xx_eint_gpio_irq(struct irq_desc *desc)
|
||||||
unsigned int pin;
|
unsigned int pin;
|
||||||
unsigned int virq;
|
unsigned int virq;
|
||||||
|
|
||||||
svc = readl(bank->eint_base + SERVICE_REG);
|
svc = readl(drvdata->virt_base + SERVICE_REG);
|
||||||
group = SVC_GROUP(svc);
|
group = SVC_GROUP(svc);
|
||||||
pin = svc & SVC_NUM_MASK;
|
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 =
|
struct s3c64xx_eint0_domain_data *ddata =
|
||||||
irq_data_get_irq_chip_data(irqd);
|
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;
|
u32 val;
|
||||||
|
|
||||||
val = readl(bank->eint_base + EINT0MASK_REG);
|
val = readl(d->virt_base + EINT0MASK_REG);
|
||||||
if (mask)
|
if (mask)
|
||||||
val |= 1 << ddata->eints[irqd->hwirq];
|
val |= 1 << ddata->eints[irqd->hwirq];
|
||||||
else
|
else
|
||||||
val &= ~(1 << ddata->eints[irqd->hwirq]);
|
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)
|
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 =
|
struct s3c64xx_eint0_domain_data *ddata =
|
||||||
irq_data_get_irq_chip_data(irqd);
|
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],
|
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)
|
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 =
|
struct s3c64xx_eint0_domain_data *ddata =
|
||||||
irq_data_get_irq_chip_data(irqd);
|
irq_data_get_irq_chip_data(irqd);
|
||||||
struct samsung_pin_bank *bank = ddata->bank;
|
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;
|
void __iomem *reg;
|
||||||
int trigger;
|
int trigger;
|
||||||
u8 shift;
|
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);
|
s3c64xx_irq_set_handler(irqd, type);
|
||||||
|
|
||||||
/* Set up interrupt trigger */
|
/* Set up interrupt trigger */
|
||||||
reg = bank->eint_base + EINT0CON0_REG;
|
reg = d->virt_base + EINT0CON0_REG;
|
||||||
shift = ddata->eints[irqd->hwirq];
|
shift = ddata->eints[irqd->hwirq];
|
||||||
if (shift >= EINT_MAX_PER_REG) {
|
if (shift >= EINT_MAX_PER_REG) {
|
||||||
reg += 4;
|
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)
|
static inline void s3c64xx_irq_demux_eint(struct irq_desc *desc, u32 range)
|
||||||
{
|
{
|
||||||
struct irq_chip *chip = irq_desc_get_chip(desc);
|
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 s3c64xx_eint0_data *data = irq_desc_get_handler_data(desc);
|
||||||
|
struct samsung_pinctrl_drv_data *drvdata = data->drvdata;
|
||||||
unsigned int pend, mask;
|
unsigned int pend, mask;
|
||||||
|
|
||||||
chained_irq_enter(chip, desc);
|
chained_irq_enter(chip, desc);
|
||||||
|
|
||||||
pend = readl(bank->eint_base + EINT0PEND_REG);
|
pend = readl(drvdata->virt_base + EINT0PEND_REG);
|
||||||
mask = readl(bank->eint_base + EINT0MASK_REG);
|
mask = readl(drvdata->virt_base + EINT0MASK_REG);
|
||||||
|
|
||||||
pend = pend & range & ~mask;
|
pend = pend & range & ~mask;
|
||||||
pend &= range;
|
pend &= range;
|
||||||
|
|
|
@ -1013,6 +1013,12 @@ samsung_pinctrl_get_soc_data(struct samsung_pinctrl_drv_data *d,
|
||||||
bank->eint_base = virt_base[0];
|
bank->eint_base = virt_base[0];
|
||||||
bank->pctl_base = virt_base[bdata->pctl_res_idx];
|
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) {
|
for_each_child_of_node(node, np) {
|
||||||
if (!of_find_property(np, "gpio-controller", NULL))
|
if (!of_find_property(np, "gpio-controller", NULL))
|
||||||
|
|
|
@ -247,6 +247,10 @@ struct samsung_pin_ctrl {
|
||||||
/**
|
/**
|
||||||
* struct samsung_pinctrl_drv_data: wrapper for holding driver data together.
|
* struct samsung_pinctrl_drv_data: wrapper for holding driver data together.
|
||||||
* @node: global list node
|
* @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.
|
* @dev: device instance representing the controller.
|
||||||
* @irq: interrpt number used by the controller to notify gpio interrupts.
|
* @irq: interrpt number used by the controller to notify gpio interrupts.
|
||||||
* @ctrl: pin controller instance managed by the driver.
|
* @ctrl: pin controller instance managed by the driver.
|
||||||
|
@ -262,6 +266,7 @@ struct samsung_pin_ctrl {
|
||||||
*/
|
*/
|
||||||
struct samsung_pinctrl_drv_data {
|
struct samsung_pinctrl_drv_data {
|
||||||
struct list_head node;
|
struct list_head node;
|
||||||
|
void __iomem *virt_base;
|
||||||
struct device *dev;
|
struct device *dev;
|
||||||
int irq;
|
int irq;
|
||||||
|
|
||||||
|
|
|
@ -77,6 +77,8 @@
|
||||||
#define CPCAP_BIT_VAUDIO_MODE0 BIT(1)
|
#define CPCAP_BIT_VAUDIO_MODE0 BIT(1)
|
||||||
#define CPCAP_BIT_V_AUDIO_EN BIT(0)
|
#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
|
* Off mode configuration bit. Used currently only by SW5 on omap4. There's
|
||||||
* the following comment in Motorola Linux kernel tree for it:
|
* 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);
|
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_STANDBY;
|
||||||
|
|
||||||
return REGULATOR_MODE_NORMAL;
|
return REGULATOR_MODE_NORMAL;
|
||||||
|
@ -230,10 +232,10 @@ static int cpcap_regulator_set_mode(struct regulator_dev *rdev,
|
||||||
|
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
case REGULATOR_MODE_NORMAL:
|
case REGULATOR_MODE_NORMAL:
|
||||||
value = CPCAP_BIT_AUDIO_LOW_PWR;
|
value = CPCAP_BIT_AUDIO_NORMAL_MODE;
|
||||||
break;
|
break;
|
||||||
case REGULATOR_MODE_STANDBY:
|
case REGULATOR_MODE_STANDBY:
|
||||||
value = 0;
|
value = CPCAP_BIT_AUDIO_LOW_PWR;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
*
|
*
|
||||||
* Debug traces for zfcp.
|
* Debug traces for zfcp.
|
||||||
*
|
*
|
||||||
* Copyright IBM Corp. 2002, 2016
|
* Copyright IBM Corp. 2002, 2017
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define KMSG_COMPONENT "zfcp"
|
#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_ct_hdr *reqh = sg_virt(ct_els->req);
|
||||||
struct fc_ns_gid_ft *reqn = (struct fc_ns_gid_ft *)(reqh + 1);
|
struct fc_ns_gid_ft *reqn = (struct fc_ns_gid_ft *)(reqh + 1);
|
||||||
struct scatterlist *resp_entry = ct_els->resp;
|
struct scatterlist *resp_entry = ct_els->resp;
|
||||||
|
struct fc_ct_hdr *resph;
|
||||||
struct fc_gpn_ft_resp *acc;
|
struct fc_gpn_ft_resp *acc;
|
||||||
int max_entries, x, last = 0;
|
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 */
|
return len; /* not GPN_FT response so do not cap */
|
||||||
|
|
||||||
acc = sg_virt(resp_entry);
|
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))
|
max_entries = (reqh->ct_mr_size * 4 / sizeof(struct fc_gpn_ft_resp))
|
||||||
+ 1 /* zfcp_fc_scan_ports: bytes correct, entries off-by-one
|
+ 1 /* zfcp_fc_scan_ports: bytes correct, entries off-by-one
|
||||||
* to account for header as 1st pseudo "entry" */;
|
* 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_retries = sc->retries;
|
||||||
rec->scsi_allowed = sc->allowed;
|
rec->scsi_allowed = sc->allowed;
|
||||||
rec->scsi_id = sc->device->id;
|
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 = (u32)sc->device->lun;
|
||||||
|
rec->scsi_lun_64_hi = (u32)(sc->device->lun >> 32);
|
||||||
rec->host_scribble = (unsigned long)sc->host_scribble;
|
rec->host_scribble = (unsigned long)sc->host_scribble;
|
||||||
|
|
||||||
memcpy(rec->scsi_opcode, sc->cmnd,
|
memcpy(rec->scsi_opcode, sc->cmnd,
|
||||||
|
@ -564,19 +572,32 @@ void zfcp_dbf_scsi(char *tag, int level, struct scsi_cmnd *sc,
|
||||||
|
|
||||||
if (fsf) {
|
if (fsf) {
|
||||||
rec->fsf_req_id = fsf->req_id;
|
rec->fsf_req_id = fsf->req_id;
|
||||||
|
rec->pl_len = FCP_RESP_WITH_EXT;
|
||||||
fcp_rsp = (struct fcp_resp_with_ext *)
|
fcp_rsp = (struct fcp_resp_with_ext *)
|
||||||
&(fsf->qtcb->bottom.io.fcp_rsp);
|
&(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);
|
memcpy(&rec->fcp_rsp, fcp_rsp, FCP_RESP_WITH_EXT);
|
||||||
if (fcp_rsp->resp.fr_flags & FCP_RSP_LEN_VAL) {
|
if (fcp_rsp->resp.fr_flags & FCP_RSP_LEN_VAL) {
|
||||||
fcp_rsp_info = (struct fcp_resp_rsp_info *) &fcp_rsp[1];
|
fcp_rsp_info = (struct fcp_resp_rsp_info *) &fcp_rsp[1];
|
||||||
rec->fcp_rsp_info = fcp_rsp_info->rsp_code;
|
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) {
|
if (fcp_rsp->resp.fr_flags & FCP_SNS_LEN_VAL) {
|
||||||
rec->pl_len = min((u16)SCSI_SENSE_BUFFERSIZE,
|
rec->pl_len += be32_to_cpu(fcp_rsp->ext.fr_sns_len);
|
||||||
(u16)ZFCP_DBF_PAY_MAX_REC);
|
|
||||||
zfcp_dbf_pl_write(dbf, sc->sense_buffer, rec->pl_len,
|
|
||||||
"fcp_sns", fsf->req_id);
|
|
||||||
}
|
}
|
||||||
|
/* 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));
|
debug_event(dbf->scsi, level, rec, sizeof(*rec));
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
* zfcp device driver
|
* zfcp device driver
|
||||||
* debug feature declarations
|
* debug feature declarations
|
||||||
*
|
*
|
||||||
* Copyright IBM Corp. 2008, 2016
|
* Copyright IBM Corp. 2008, 2017
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef ZFCP_DBF_H
|
#ifndef ZFCP_DBF_H
|
||||||
|
@ -204,7 +204,7 @@ enum zfcp_dbf_scsi_id {
|
||||||
* @id: unique number of recovery record type
|
* @id: unique number of recovery record type
|
||||||
* @tag: identifier string specifying the location of initiation
|
* @tag: identifier string specifying the location of initiation
|
||||||
* @scsi_id: scsi device id
|
* @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_result: scsi result
|
||||||
* @scsi_retries: current retry number of scsi request
|
* @scsi_retries: current retry number of scsi request
|
||||||
* @scsi_allowed: allowed retries
|
* @scsi_allowed: allowed retries
|
||||||
|
@ -214,6 +214,7 @@ enum zfcp_dbf_scsi_id {
|
||||||
* @host_scribble: LLD specific data attached to SCSI request
|
* @host_scribble: LLD specific data attached to SCSI request
|
||||||
* @pl_len: length of paload stored as zfcp_dbf_pay
|
* @pl_len: length of paload stored as zfcp_dbf_pay
|
||||||
* @fsf_rsp: response for fsf request
|
* @fsf_rsp: response for fsf request
|
||||||
|
* @scsi_lun_64_hi: scsi device logical unit number, high part of 64 bit
|
||||||
*/
|
*/
|
||||||
struct zfcp_dbf_scsi {
|
struct zfcp_dbf_scsi {
|
||||||
u8 id;
|
u8 id;
|
||||||
|
@ -230,6 +231,7 @@ struct zfcp_dbf_scsi {
|
||||||
u64 host_scribble;
|
u64 host_scribble;
|
||||||
u16 pl_len;
|
u16 pl_len;
|
||||||
struct fcp_resp_with_ext fcp_rsp;
|
struct fcp_resp_with_ext fcp_rsp;
|
||||||
|
u32 scsi_lun_64_hi;
|
||||||
} __packed;
|
} __packed;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -323,7 +325,11 @@ void zfcp_dbf_hba_fsf_response(struct zfcp_fsf_req *req)
|
||||||
{
|
{
|
||||||
struct fsf_qtcb *qtcb = req->qtcb;
|
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)) {
|
(qtcb->prefix.prot_status != FSF_PROT_FSF_STATUS_PRESENTED)) {
|
||||||
zfcp_dbf_hba_fsf_resp("fs_perr", 1, req);
|
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)
|
* @flag: indicates type of reset (Target Reset, Logical Unit Reset)
|
||||||
*/
|
*/
|
||||||
static inline
|
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];
|
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, "lr_", 3);
|
||||||
|
|
||||||
memcpy(&tmp_tag[3], tag, 4);
|
memcpy(&tmp_tag[3], tag, 4);
|
||||||
_zfcp_dbf_scsi(tmp_tag, 1, scmnd, NULL);
|
_zfcp_dbf_scsi(tmp_tag, 1, scmnd, fsf_req);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
* Fibre Channel related definitions and inline functions for the zfcp
|
* Fibre Channel related definitions and inline functions for the zfcp
|
||||||
* device driver
|
* device driver
|
||||||
*
|
*
|
||||||
* Copyright IBM Corp. 2009
|
* Copyright IBM Corp. 2009, 2017
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef ZFCP_FC_H
|
#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) &&
|
!(rsp_flags & FCP_SNS_LEN_VAL) &&
|
||||||
fcp_rsp->resp.fr_status == SAM_STAT_GOOD)
|
fcp_rsp->resp.fr_status == SAM_STAT_GOOD)
|
||||||
set_host_byte(scsi, DID_ERROR);
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -928,8 +928,8 @@ static void zfcp_fsf_send_ct_handler(struct zfcp_fsf_req *req)
|
||||||
|
|
||||||
switch (header->fsf_status) {
|
switch (header->fsf_status) {
|
||||||
case FSF_GOOD:
|
case FSF_GOOD:
|
||||||
zfcp_dbf_san_res("fsscth2", req);
|
|
||||||
ct->status = 0;
|
ct->status = 0;
|
||||||
|
zfcp_dbf_san_res("fsscth2", req);
|
||||||
break;
|
break;
|
||||||
case FSF_SERVICE_CLASS_NOT_SUPPORTED:
|
case FSF_SERVICE_CLASS_NOT_SUPPORTED:
|
||||||
zfcp_fsf_class_not_supp(req);
|
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) {
|
switch (header->fsf_status) {
|
||||||
case FSF_GOOD:
|
case FSF_GOOD:
|
||||||
zfcp_dbf_san_res("fsselh1", req);
|
|
||||||
send_els->status = 0;
|
send_els->status = 0;
|
||||||
|
zfcp_dbf_san_res("fsselh1", req);
|
||||||
break;
|
break;
|
||||||
case FSF_SERVICE_CLASS_NOT_SUPPORTED:
|
case FSF_SERVICE_CLASS_NOT_SUPPORTED:
|
||||||
zfcp_fsf_class_not_supp(req);
|
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;
|
fcp_cmnd = (struct fcp_cmnd *) &req->qtcb->bottom.io.fcp_cmnd;
|
||||||
zfcp_fc_scsi_to_fcp(fcp_cmnd, scsi_cmnd, 0);
|
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,
|
zfcp_qdio_set_data_div(qdio, &req->qdio_req,
|
||||||
scsi_prot_sg_count(scsi_cmnd));
|
scsi_prot_sg_count(scsi_cmnd));
|
||||||
retval = zfcp_qdio_sbals_from_sg(qdio, &req->qdio_req,
|
retval = zfcp_qdio_sbals_from_sg(qdio, &req->qdio_req,
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
*
|
*
|
||||||
* Interface to Linux SCSI midlayer.
|
* Interface to Linux SCSI midlayer.
|
||||||
*
|
*
|
||||||
* Copyright IBM Corp. 2002, 2016
|
* Copyright IBM Corp. 2002, 2017
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define KMSG_COMPONENT "zfcp"
|
#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);
|
zfcp_erp_wait(adapter);
|
||||||
ret = fc_block_scsi_eh(scpnt);
|
ret = fc_block_scsi_eh(scpnt);
|
||||||
if (ret)
|
if (ret) {
|
||||||
|
zfcp_dbf_scsi_devreset("fiof", scpnt, tm_flags, NULL);
|
||||||
return ret;
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
if (!(atomic_read(&adapter->status) &
|
if (!(atomic_read(&adapter->status) &
|
||||||
ZFCP_STATUS_COMMON_RUNNING)) {
|
ZFCP_STATUS_COMMON_RUNNING)) {
|
||||||
zfcp_dbf_scsi_devreset("nres", scpnt, tm_flags);
|
zfcp_dbf_scsi_devreset("nres", scpnt, tm_flags, NULL);
|
||||||
return SUCCESS;
|
return SUCCESS;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!fsf_req)
|
if (!fsf_req) {
|
||||||
|
zfcp_dbf_scsi_devreset("reqf", scpnt, tm_flags, NULL);
|
||||||
return FAILED;
|
return FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
wait_for_completion(&fsf_req->completion);
|
wait_for_completion(&fsf_req->completion);
|
||||||
|
|
||||||
if (fsf_req->status & ZFCP_STATUS_FSFREQ_TMFUNCFAILED) {
|
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;
|
retval = FAILED;
|
||||||
} else {
|
} 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);
|
zfcp_scsi_forget_cmnds(zfcp_sdev, tm_flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -594,6 +594,7 @@ static int aac_get_container_name(struct scsi_cmnd * scsicmd)
|
||||||
|
|
||||||
aac_fib_init(cmd_fibcontext);
|
aac_fib_init(cmd_fibcontext);
|
||||||
dinfo = (struct aac_get_name *) fib_data(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->command = cpu_to_le32(VM_ContainerConfig);
|
||||||
dinfo->type = cpu_to_le32(CT_READ_NAME);
|
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
|
* Check that the command queued to the controller
|
||||||
*/
|
*/
|
||||||
if (status == -EINPROGRESS) {
|
if (status == -EINPROGRESS)
|
||||||
scsicmd->SCp.phase = AAC_OWNER_FIRMWARE;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
|
||||||
|
|
||||||
printk(KERN_WARNING "aac_get_container_name: aac_fib_send failed with status: %d.\n", status);
|
printk(KERN_WARNING "aac_get_container_name: aac_fib_send failed with status: %d.\n", status);
|
||||||
aac_fib_complete(cmd_fibcontext);
|
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->count = cpu_to_le32(scmd_id(scsicmd));
|
||||||
dinfo->type = cpu_to_le32(FT_FILESYS);
|
dinfo->type = cpu_to_le32(FT_FILESYS);
|
||||||
|
scsicmd->SCp.phase = AAC_OWNER_FIRMWARE;
|
||||||
|
|
||||||
status = aac_fib_send(ContainerCommand,
|
status = aac_fib_send(ContainerCommand,
|
||||||
fibptr,
|
fibptr,
|
||||||
|
@ -736,9 +736,7 @@ static void _aac_probe_container1(void * context, struct fib * fibptr)
|
||||||
/*
|
/*
|
||||||
* Check that the command queued to the controller
|
* Check that the command queued to the controller
|
||||||
*/
|
*/
|
||||||
if (status == -EINPROGRESS)
|
if (status < 0 && status != -EINPROGRESS) {
|
||||||
scsicmd->SCp.phase = AAC_OWNER_FIRMWARE;
|
|
||||||
else if (status < 0) {
|
|
||||||
/* Inherit results from VM_NameServe, if any */
|
/* Inherit results from VM_NameServe, if any */
|
||||||
dresp->status = cpu_to_le32(ST_OK);
|
dresp->status = cpu_to_le32(ST_OK);
|
||||||
_aac_probe_container2(context, fibptr);
|
_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->count = cpu_to_le32(scmd_id(scsicmd));
|
||||||
dinfo->type = cpu_to_le32(FT_FILESYS);
|
dinfo->type = cpu_to_le32(FT_FILESYS);
|
||||||
scsicmd->SCp.ptr = (char *)callback;
|
scsicmd->SCp.ptr = (char *)callback;
|
||||||
|
scsicmd->SCp.phase = AAC_OWNER_FIRMWARE;
|
||||||
|
|
||||||
status = aac_fib_send(ContainerCommand,
|
status = aac_fib_send(ContainerCommand,
|
||||||
fibptr,
|
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
|
* Check that the command queued to the controller
|
||||||
*/
|
*/
|
||||||
if (status == -EINPROGRESS) {
|
if (status == -EINPROGRESS)
|
||||||
scsicmd->SCp.phase = AAC_OWNER_FIRMWARE;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
|
||||||
if (status < 0) {
|
if (status < 0) {
|
||||||
scsicmd->SCp.ptr = NULL;
|
scsicmd->SCp.ptr = NULL;
|
||||||
aac_fib_complete(fibptr);
|
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->command = cpu_to_le32(VM_ContainerConfig);
|
||||||
dinfo->type = cpu_to_le32(CT_CID_TO_32BITS_UID);
|
dinfo->type = cpu_to_le32(CT_CID_TO_32BITS_UID);
|
||||||
dinfo->cid = cpu_to_le32(scmd_id(scsicmd));
|
dinfo->cid = cpu_to_le32(scmd_id(scsicmd));
|
||||||
|
scsicmd->SCp.phase = AAC_OWNER_FIRMWARE;
|
||||||
|
|
||||||
status = aac_fib_send(ContainerCommand,
|
status = aac_fib_send(ContainerCommand,
|
||||||
cmd_fibcontext,
|
cmd_fibcontext,
|
||||||
|
@ -1138,10 +1137,8 @@ static int aac_get_container_serial(struct scsi_cmnd * scsicmd)
|
||||||
/*
|
/*
|
||||||
* Check that the command queued to the controller
|
* Check that the command queued to the controller
|
||||||
*/
|
*/
|
||||||
if (status == -EINPROGRESS) {
|
if (status == -EINPROGRESS)
|
||||||
scsicmd->SCp.phase = AAC_OWNER_FIRMWARE;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
|
||||||
|
|
||||||
printk(KERN_WARNING "aac_get_container_serial: aac_fib_send failed with status: %d.\n", status);
|
printk(KERN_WARNING "aac_get_container_serial: aac_fib_send failed with status: %d.\n", status);
|
||||||
aac_fib_complete(cmd_fibcontext);
|
aac_fib_complete(cmd_fibcontext);
|
||||||
|
@ -2335,16 +2332,14 @@ static int aac_read(struct scsi_cmnd * scsicmd)
|
||||||
* Alocate and initialize a Fib
|
* Alocate and initialize a Fib
|
||||||
*/
|
*/
|
||||||
cmd_fibcontext = aac_fib_alloc_tag(dev, scsicmd);
|
cmd_fibcontext = aac_fib_alloc_tag(dev, scsicmd);
|
||||||
|
scsicmd->SCp.phase = AAC_OWNER_FIRMWARE;
|
||||||
status = aac_adapter_read(cmd_fibcontext, scsicmd, lba, count);
|
status = aac_adapter_read(cmd_fibcontext, scsicmd, lba, count);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check that the command queued to the controller
|
* Check that the command queued to the controller
|
||||||
*/
|
*/
|
||||||
if (status == -EINPROGRESS) {
|
if (status == -EINPROGRESS)
|
||||||
scsicmd->SCp.phase = AAC_OWNER_FIRMWARE;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
|
||||||
|
|
||||||
printk(KERN_WARNING "aac_read: aac_fib_send failed with status: %d.\n", status);
|
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
|
* Allocate and initialize a Fib then setup a BlockWrite command
|
||||||
*/
|
*/
|
||||||
cmd_fibcontext = aac_fib_alloc_tag(dev, scsicmd);
|
cmd_fibcontext = aac_fib_alloc_tag(dev, scsicmd);
|
||||||
|
scsicmd->SCp.phase = AAC_OWNER_FIRMWARE;
|
||||||
status = aac_adapter_write(cmd_fibcontext, scsicmd, lba, count, fua);
|
status = aac_adapter_write(cmd_fibcontext, scsicmd, lba, count, fua);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check that the command queued to the controller
|
* Check that the command queued to the controller
|
||||||
*/
|
*/
|
||||||
if (status == -EINPROGRESS) {
|
if (status == -EINPROGRESS)
|
||||||
scsicmd->SCp.phase = AAC_OWNER_FIRMWARE;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
|
||||||
|
|
||||||
printk(KERN_WARNING "aac_write: aac_fib_send failed with status: %d\n", status);
|
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->cid = cpu_to_le32(scmd_id(scsicmd));
|
||||||
synchronizecmd->count =
|
synchronizecmd->count =
|
||||||
cpu_to_le32(sizeof(((struct aac_synchronize_reply *)NULL)->data));
|
cpu_to_le32(sizeof(((struct aac_synchronize_reply *)NULL)->data));
|
||||||
|
scsicmd->SCp.phase = AAC_OWNER_FIRMWARE;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Now send the Fib to the adapter
|
* 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
|
* Check that the command queued to the controller
|
||||||
*/
|
*/
|
||||||
if (status == -EINPROGRESS) {
|
if (status == -EINPROGRESS)
|
||||||
scsicmd->SCp.phase = AAC_OWNER_FIRMWARE;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
|
||||||
|
|
||||||
printk(KERN_WARNING
|
printk(KERN_WARNING
|
||||||
"aac_synchronize: aac_fib_send failed with status: %d.\n", status);
|
"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->cid = cpu_to_le32(sdev_id(sdev));
|
||||||
pmcmd->parm = (scsicmd->cmnd[1] & 1) ?
|
pmcmd->parm = (scsicmd->cmnd[1] & 1) ?
|
||||||
cpu_to_le32(CT_PM_UNIT_IMMEDIATE) : 0;
|
cpu_to_le32(CT_PM_UNIT_IMMEDIATE) : 0;
|
||||||
|
scsicmd->SCp.phase = AAC_OWNER_FIRMWARE;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Now send the Fib to the adapter
|
* 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
|
* Check that the command queued to the controller
|
||||||
*/
|
*/
|
||||||
if (status == -EINPROGRESS) {
|
if (status == -EINPROGRESS)
|
||||||
scsicmd->SCp.phase = AAC_OWNER_FIRMWARE;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
|
||||||
|
|
||||||
aac_fib_complete(cmd_fibcontext);
|
aac_fib_complete(cmd_fibcontext);
|
||||||
aac_fib_free(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
|
* Allocate and initialize a Fib then setup a BlockWrite command
|
||||||
*/
|
*/
|
||||||
cmd_fibcontext = aac_fib_alloc_tag(dev, scsicmd);
|
cmd_fibcontext = aac_fib_alloc_tag(dev, scsicmd);
|
||||||
|
scsicmd->SCp.phase = AAC_OWNER_FIRMWARE;
|
||||||
status = aac_adapter_scsi(cmd_fibcontext, scsicmd);
|
status = aac_adapter_scsi(cmd_fibcontext, scsicmd);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check that the command queued to the controller
|
* Check that the command queued to the controller
|
||||||
*/
|
*/
|
||||||
if (status == -EINPROGRESS) {
|
if (status == -EINPROGRESS)
|
||||||
scsicmd->SCp.phase = AAC_OWNER_FIRMWARE;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
|
||||||
|
|
||||||
printk(KERN_WARNING "aac_srb: aac_fib_send failed with status: %d\n", status);
|
printk(KERN_WARNING "aac_srb: aac_fib_send failed with status: %d\n", status);
|
||||||
aac_fib_complete(cmd_fibcontext);
|
aac_fib_complete(cmd_fibcontext);
|
||||||
|
@ -3739,15 +3728,14 @@ static int aac_send_hba_fib(struct scsi_cmnd *scsicmd)
|
||||||
if (!cmd_fibcontext)
|
if (!cmd_fibcontext)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
scsicmd->SCp.phase = AAC_OWNER_FIRMWARE;
|
||||||
status = aac_adapter_hba(cmd_fibcontext, scsicmd);
|
status = aac_adapter_hba(cmd_fibcontext, scsicmd);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check that the command queued to the controller
|
* Check that the command queued to the controller
|
||||||
*/
|
*/
|
||||||
if (status == -EINPROGRESS) {
|
if (status == -EINPROGRESS)
|
||||||
scsicmd->SCp.phase = AAC_OWNER_FIRMWARE;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
|
||||||
|
|
||||||
pr_warn("aac_hba_cmd_req: aac_fib_send failed with status: %d\n",
|
pr_warn("aac_hba_cmd_req: aac_fib_send failed with status: %d\n",
|
||||||
status);
|
status);
|
||||||
|
|
|
@ -1995,9 +1995,12 @@ static void megasas_complete_outstanding_ioctls(struct megasas_instance *instanc
|
||||||
if (cmd_fusion->sync_cmd_idx != (u32)ULONG_MAX) {
|
if (cmd_fusion->sync_cmd_idx != (u32)ULONG_MAX) {
|
||||||
cmd_mfi = instance->cmd_list[cmd_fusion->sync_cmd_idx];
|
cmd_mfi = instance->cmd_list[cmd_fusion->sync_cmd_idx];
|
||||||
if (cmd_mfi->sync_cmd &&
|
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,
|
megasas_complete_cmd(instance,
|
||||||
cmd_mfi, DID_OK);
|
cmd_mfi, DID_OK);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -5478,7 +5481,8 @@ static int megasas_init_fw(struct megasas_instance *instance)
|
||||||
instance->throttlequeuedepth =
|
instance->throttlequeuedepth =
|
||||||
MEGASAS_THROTTLE_QUEUE_DEPTH;
|
MEGASAS_THROTTLE_QUEUE_DEPTH;
|
||||||
|
|
||||||
if (resetwaittime > MEGASAS_RESET_WAIT_TIME)
|
if ((resetwaittime < 1) ||
|
||||||
|
(resetwaittime > MEGASAS_RESET_WAIT_TIME))
|
||||||
resetwaittime = MEGASAS_RESET_WAIT_TIME;
|
resetwaittime = MEGASAS_RESET_WAIT_TIME;
|
||||||
|
|
||||||
if ((scmd_timeout < 10) || (scmd_timeout > MEGASAS_DEFAULT_CMD_TIMEOUT))
|
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 =
|
prev_aen.word =
|
||||||
le32_to_cpu(instance->aen_cmd->frame->dcmd.mbox.w[1]);
|
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
|
* A class whose enum value is smaller is inclusive of all
|
||||||
* higher values. If a PROGRESS (= -1) was previously
|
* higher values. If a PROGRESS (= -1) was previously
|
||||||
|
|
|
@ -3287,7 +3287,7 @@ build_mpt_mfi_pass_thru(struct megasas_instance *instance,
|
||||||
mpi25_ieee_chain->Flags = IEEE_SGE_FLAGS_CHAIN_ELEMENT |
|
mpi25_ieee_chain->Flags = IEEE_SGE_FLAGS_CHAIN_ELEMENT |
|
||||||
MPI2_IEEE_SGE_FLAGS_IOCPLBNTA_ADDR;
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -1575,7 +1575,7 @@ struct qedi_cmd *qedi_get_cmd_from_tid(struct qedi_ctx *qedi, u32 tid)
|
||||||
{
|
{
|
||||||
struct qedi_cmd *cmd = NULL;
|
struct qedi_cmd *cmd = NULL;
|
||||||
|
|
||||||
if (tid > MAX_ISCSI_TASK_ENTRIES)
|
if (tid >= MAX_ISCSI_TASK_ENTRIES)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
cmd = qedi->itt_map[tid].p_cmd;
|
cmd = qedi->itt_map[tid].p_cmd;
|
||||||
|
|
|
@ -318,6 +318,8 @@ qla2x00_sysfs_write_optrom_ctl(struct file *filp, struct kobject *kobj,
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
if (start > ha->optrom_size)
|
if (start > ha->optrom_size)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
if (size > ha->optrom_size - start)
|
||||||
|
size = ha->optrom_size - start;
|
||||||
|
|
||||||
mutex_lock(&ha->optrom_mutex);
|
mutex_lock(&ha->optrom_mutex);
|
||||||
switch (val) {
|
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_start = start;
|
||||||
ha->optrom_region_size = start + size > ha->optrom_size ?
|
ha->optrom_region_size = start + size;
|
||||||
ha->optrom_size - start : size;
|
|
||||||
|
|
||||||
ha->optrom_state = QLA_SREADING;
|
ha->optrom_state = QLA_SREADING;
|
||||||
ha->optrom_buffer = vmalloc(ha->optrom_region_size);
|
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_start = start;
|
||||||
ha->optrom_region_size = start + size > ha->optrom_size ?
|
ha->optrom_region_size = start + size;
|
||||||
ha->optrom_size - start : size;
|
|
||||||
|
|
||||||
ha->optrom_state = QLA_SWRITING;
|
ha->optrom_state = QLA_SWRITING;
|
||||||
ha->optrom_buffer = vmalloc(ha->optrom_region_size);
|
ha->optrom_buffer = vmalloc(ha->optrom_region_size);
|
||||||
|
|
|
@ -3080,7 +3080,7 @@ int qla24xx_async_gpsc(scsi_qla_host_t *vha, fc_port_t *fcport)
|
||||||
GPSC_RSP_SIZE);
|
GPSC_RSP_SIZE);
|
||||||
|
|
||||||
/* GPSC req */
|
/* 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);
|
WWN_SIZE);
|
||||||
|
|
||||||
sp->u.iocb_cmd.u.ctarg.req = fcport->ct_desc.ct_sns;
|
sp->u.iocb_cmd.u.ctarg.req = fcport->ct_desc.ct_sns;
|
||||||
|
|
|
@ -7804,6 +7804,7 @@ struct qla_qpair *qla2xxx_create_qpair(struct scsi_qla_host *vha, int qos,
|
||||||
ha->queue_pair_map[qpair_id] = qpair;
|
ha->queue_pair_map[qpair_id] = qpair;
|
||||||
qpair->id = qpair_id;
|
qpair->id = qpair_id;
|
||||||
qpair->vp_idx = vp_idx;
|
qpair->vp_idx = vp_idx;
|
||||||
|
qpair->fw_started = ha->flags.fw_started;
|
||||||
INIT_LIST_HEAD(&qpair->hints_list);
|
INIT_LIST_HEAD(&qpair->hints_list);
|
||||||
qpair->chip_reset = ha->base_qpair->chip_reset;
|
qpair->chip_reset = ha->base_qpair->chip_reset;
|
||||||
qpair->enable_class_2 = ha->base_qpair->enable_class_2;
|
qpair->enable_class_2 = ha->base_qpair->enable_class_2;
|
||||||
|
|
|
@ -3429,7 +3429,7 @@ msix_register_fail:
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Enable MSI-X vector for response queue update for queue 0 */
|
/* 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 &&
|
if (ha->msixbase && ha->mqiobase &&
|
||||||
(ha->max_rsp_queues > 1 || ha->max_req_queues > 1 ||
|
(ha->max_rsp_queues > 1 || ha->max_req_queues > 1 ||
|
||||||
ql2xmqsupport))
|
ql2xmqsupport))
|
||||||
|
|
|
@ -54,6 +54,7 @@ static struct rom_cmd {
|
||||||
{ MBC_GET_MEM_OFFLOAD_CNTRL_STAT },
|
{ MBC_GET_MEM_OFFLOAD_CNTRL_STAT },
|
||||||
{ MBC_GET_RETRY_COUNT },
|
{ MBC_GET_RETRY_COUNT },
|
||||||
{ MBC_TRACE_CONTROL },
|
{ MBC_TRACE_CONTROL },
|
||||||
|
{ MBC_INITIALIZE_MULTIQ },
|
||||||
};
|
};
|
||||||
|
|
||||||
static int is_rom_cmd(uint16_t cmd)
|
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) &&
|
if (qla_ini_mode_enabled(vha) &&
|
||||||
ha->flags.fawwpn_enabled &&
|
ha->flags.fawwpn_enabled &&
|
||||||
(rptid_entry->u.f1.flags &
|
(rptid_entry->u.f1.flags &
|
||||||
VP_FLAGS_NAME_VALID)) {
|
BIT_6)) {
|
||||||
memcpy(vha->port_name,
|
memcpy(vha->port_name,
|
||||||
rptid_entry->u.f1.port_name,
|
rptid_entry->u.f1.port_name,
|
||||||
WWN_SIZE);
|
WWN_SIZE);
|
||||||
|
|
|
@ -74,7 +74,7 @@ qla24xx_deallocate_vp_id(scsi_qla_host_t *vha)
|
||||||
* ensures no active vp_list traversal while the vport is removed
|
* ensures no active vp_list traversal while the vport is removed
|
||||||
* from the queue)
|
* 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);
|
10*HZ);
|
||||||
|
|
||||||
spin_lock_irqsave(&ha->vport_slock, flags);
|
spin_lock_irqsave(&ha->vport_slock, flags);
|
||||||
|
|
|
@ -6796,7 +6796,7 @@ qlt_probe_one_stage1(struct scsi_qla_host *base_vha, struct qla_hw_data *ha)
|
||||||
if (!QLA_TGT_MODE_ENABLED())
|
if (!QLA_TGT_MODE_ENABLED())
|
||||||
return;
|
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_IN(base_vha) = &ha->mqiobase->isp25mq.atio_q_in;
|
||||||
ISP_ATIO_Q_OUT(base_vha) = &ha->mqiobase->isp25mq.atio_q_out;
|
ISP_ATIO_Q_OUT(base_vha) = &ha->mqiobase->isp25mq.atio_q_out;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -828,6 +828,39 @@ static int max_sectors_bytes(struct request_queue *q)
|
||||||
return max_sectors << 9;
|
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
|
static long
|
||||||
sg_ioctl(struct file *filp, unsigned int cmd_in, unsigned long arg)
|
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;
|
return -EFAULT;
|
||||||
else {
|
else {
|
||||||
sg_req_info_t *rinfo;
|
sg_req_info_t *rinfo;
|
||||||
unsigned int ms;
|
|
||||||
|
|
||||||
rinfo = kmalloc(SZ_SG_REQ_INFO * SG_MAX_QUEUE,
|
rinfo = kzalloc(SZ_SG_REQ_INFO * SG_MAX_QUEUE,
|
||||||
GFP_KERNEL);
|
GFP_KERNEL);
|
||||||
if (!rinfo)
|
if (!rinfo)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
read_lock_irqsave(&sfp->rq_list_lock, iflags);
|
read_lock_irqsave(&sfp->rq_list_lock, iflags);
|
||||||
val = 0;
|
sg_fill_request_table(sfp, rinfo);
|
||||||
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++;
|
|
||||||
}
|
|
||||||
read_unlock_irqrestore(&sfp->rq_list_lock, iflags);
|
read_unlock_irqrestore(&sfp->rq_list_lock, iflags);
|
||||||
result = __copy_to_user(p, rinfo,
|
result = __copy_to_user(p, rinfo,
|
||||||
SZ_SG_REQ_INFO * SG_MAX_QUEUE);
|
SZ_SG_REQ_INFO * SG_MAX_QUEUE);
|
||||||
|
|
|
@ -1640,6 +1640,8 @@ static int storvsc_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scmnd)
|
||||||
put_cpu();
|
put_cpu();
|
||||||
|
|
||||||
if (ret == -EAGAIN) {
|
if (ret == -EAGAIN) {
|
||||||
|
if (payload_sz > sizeof(cmd_request->mpb))
|
||||||
|
kfree(payload);
|
||||||
/* no more space */
|
/* no more space */
|
||||||
return SCSI_MLQUEUE_DEVICE_BUSY;
|
return SCSI_MLQUEUE_DEVICE_BUSY;
|
||||||
}
|
}
|
||||||
|
|
|
@ -361,6 +361,32 @@ int tty_insert_flip_string_flags(struct tty_port *port,
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(tty_insert_flip_string_flags);
|
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
|
* tty_schedule_flip - push characters to ldisc
|
||||||
* @port: tty port to push from
|
* @port: tty port to push from
|
||||||
|
|
|
@ -595,7 +595,7 @@ static loff_t ext4_seek_data(struct file *file, loff_t offset, loff_t maxsize)
|
||||||
inode_lock(inode);
|
inode_lock(inode);
|
||||||
|
|
||||||
isize = i_size_read(inode);
|
isize = i_size_read(inode);
|
||||||
if (offset >= isize) {
|
if (offset < 0 || offset >= isize) {
|
||||||
inode_unlock(inode);
|
inode_unlock(inode);
|
||||||
return -ENXIO;
|
return -ENXIO;
|
||||||
}
|
}
|
||||||
|
@ -658,7 +658,7 @@ static loff_t ext4_seek_hole(struct file *file, loff_t offset, loff_t maxsize)
|
||||||
inode_lock(inode);
|
inode_lock(inode);
|
||||||
|
|
||||||
isize = i_size_read(inode);
|
isize = i_size_read(inode);
|
||||||
if (offset >= isize) {
|
if (offset < 0 || offset >= isize) {
|
||||||
inode_unlock(inode);
|
inode_unlock(inode);
|
||||||
return -ENXIO;
|
return -ENXIO;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2404,6 +2404,7 @@ static void ext4_orphan_cleanup(struct super_block *sb,
|
||||||
unsigned int s_flags = sb->s_flags;
|
unsigned int s_flags = sb->s_flags;
|
||||||
int ret, nr_orphans = 0, nr_truncates = 0;
|
int ret, nr_orphans = 0, nr_truncates = 0;
|
||||||
#ifdef CONFIG_QUOTA
|
#ifdef CONFIG_QUOTA
|
||||||
|
int quota_update = 0;
|
||||||
int i;
|
int i;
|
||||||
#endif
|
#endif
|
||||||
if (!es->s_last_orphan) {
|
if (!es->s_last_orphan) {
|
||||||
|
@ -2442,14 +2443,32 @@ static void ext4_orphan_cleanup(struct super_block *sb,
|
||||||
#ifdef CONFIG_QUOTA
|
#ifdef CONFIG_QUOTA
|
||||||
/* Needed for iput() to work correctly and not trash data */
|
/* Needed for iput() to work correctly and not trash data */
|
||||||
sb->s_flags |= MS_ACTIVE;
|
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++) {
|
for (i = 0; i < EXT4_MAXQUOTAS; i++) {
|
||||||
if (EXT4_SB(sb)->s_qf_names[i]) {
|
if (EXT4_SB(sb)->s_qf_names[i]) {
|
||||||
int ret = ext4_quota_on_mount(sb, i);
|
int ret = ext4_quota_on_mount(sb, i);
|
||||||
if (ret < 0)
|
|
||||||
|
if (!ret)
|
||||||
|
quota_update = 1;
|
||||||
|
else
|
||||||
ext4_msg(sb, KERN_ERR,
|
ext4_msg(sb, KERN_ERR,
|
||||||
"Cannot turn on journaled "
|
"Cannot turn on journaled "
|
||||||
"quota: error %d", ret);
|
"quota: type %d: error %d", i, ret);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -2510,10 +2529,12 @@ static void ext4_orphan_cleanup(struct super_block *sb,
|
||||||
ext4_msg(sb, KERN_INFO, "%d truncate%s cleaned up",
|
ext4_msg(sb, KERN_INFO, "%d truncate%s cleaned up",
|
||||||
PLURAL(nr_truncates));
|
PLURAL(nr_truncates));
|
||||||
#ifdef CONFIG_QUOTA
|
#ifdef CONFIG_QUOTA
|
||||||
/* Turn quotas off */
|
/* Turn off quotas if they were enabled for orphan cleanup */
|
||||||
for (i = 0; i < EXT4_MAXQUOTAS; i++) {
|
if (quota_update) {
|
||||||
if (sb_dqopt(sb)->files[i])
|
for (i = 0; i < EXT4_MAXQUOTAS; i++) {
|
||||||
dquot_quota_off(sb, i);
|
if (sb_dqopt(sb)->files[i])
|
||||||
|
dquot_quota_off(sb, i);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
sb->s_flags = s_flags; /* Restore MS_RDONLY status */
|
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 |
|
DQUOT_USAGE_ENABLED |
|
||||||
(quota_mopt[type] ? DQUOT_LIMITS_ENABLED : 0));
|
(quota_mopt[type] ? DQUOT_LIMITS_ENABLED : 0));
|
||||||
if (err) {
|
if (err) {
|
||||||
|
for (type--; type >= 0; type--)
|
||||||
|
dquot_quota_off(sb, type);
|
||||||
|
|
||||||
ext4_warning(sb,
|
ext4_warning(sb,
|
||||||
"Failed to enable quota tracking "
|
"Failed to enable quota tracking "
|
||||||
"(type=%d, err=%d). Please run "
|
"(type=%d, err=%d). Please run "
|
||||||
|
|
|
@ -61,9 +61,9 @@ struct posix_acl *orangefs_get_acl(struct inode *inode, int type)
|
||||||
return acl;
|
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;
|
int error = 0;
|
||||||
void *value = NULL;
|
void *value = NULL;
|
||||||
size_t size = 0;
|
size_t size = 0;
|
||||||
|
@ -72,22 +72,6 @@ int orangefs_set_acl(struct inode *inode, struct posix_acl *acl, int type)
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case ACL_TYPE_ACCESS:
|
case ACL_TYPE_ACCESS:
|
||||||
name = XATTR_NAME_POSIX_ACL_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;
|
break;
|
||||||
case ACL_TYPE_DEFAULT:
|
case ACL_TYPE_DEFAULT:
|
||||||
name = XATTR_NAME_POSIX_ACL_DEFAULT;
|
name = XATTR_NAME_POSIX_ACL_DEFAULT;
|
||||||
|
@ -132,6 +116,29 @@ out:
|
||||||
return error;
|
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)
|
int orangefs_init_acl(struct inode *inode, struct inode *dir)
|
||||||
{
|
{
|
||||||
struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode);
|
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;
|
return error;
|
||||||
|
|
||||||
if (default_acl) {
|
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);
|
posix_acl_release(default_acl);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (acl) {
|
if (acl) {
|
||||||
if (!error)
|
if (!error)
|
||||||
error = orangefs_set_acl(inode, acl, ACL_TYPE_ACCESS);
|
error = __orangefs_set_acl(inode, acl, ACL_TYPE_ACCESS);
|
||||||
posix_acl_release(acl);
|
posix_acl_release(acl);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* AMD Cryptographic Coprocessor (CCP) driver
|
* 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: Tom Lendacky <thomas.lendacky@amd.com>
|
||||||
* Author: Gary R Hook <gary.hook@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.
|
* AES operation the new IV overwrites the old IV.
|
||||||
*/
|
*/
|
||||||
struct ccp_xts_aes_engine {
|
struct ccp_xts_aes_engine {
|
||||||
|
enum ccp_aes_type type;
|
||||||
enum ccp_aes_action action;
|
enum ccp_aes_action action;
|
||||||
enum ccp_xts_aes_unit_size unit_size;
|
enum ccp_xts_aes_unit_size unit_size;
|
||||||
|
|
||||||
|
|
|
@ -57,7 +57,9 @@ static inline void cpuset_dec(void)
|
||||||
|
|
||||||
extern int cpuset_init(void);
|
extern int cpuset_init(void);
|
||||||
extern void cpuset_init_smp(void);
|
extern void cpuset_init_smp(void);
|
||||||
|
extern void cpuset_force_rebuild(void);
|
||||||
extern void cpuset_update_active_cpus(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(struct task_struct *p, struct cpumask *mask);
|
||||||
extern void cpuset_cpus_allowed_fallback(struct task_struct *p);
|
extern void cpuset_cpus_allowed_fallback(struct task_struct *p);
|
||||||
extern nodemask_t cpuset_mems_allowed(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 int cpuset_init(void) { return 0; }
|
||||||
static inline void cpuset_init_smp(void) {}
|
static inline void cpuset_init_smp(void) {}
|
||||||
|
|
||||||
|
static inline void cpuset_force_rebuild(void) { }
|
||||||
|
|
||||||
static inline void cpuset_update_active_cpus(void)
|
static inline void cpuset_update_active_cpus(void)
|
||||||
{
|
{
|
||||||
partition_sched_domains(1, NULL, NULL);
|
partition_sched_domains(1, NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void cpuset_wait_for_hotplug(void) { }
|
||||||
|
|
||||||
static inline void cpuset_cpus_allowed(struct task_struct *p,
|
static inline void cpuset_cpus_allowed(struct task_struct *p,
|
||||||
struct cpumask *mask)
|
struct cpumask *mask)
|
||||||
{
|
{
|
||||||
|
|
|
@ -307,7 +307,7 @@ DECLARE_PER_CPU(int, disable_stack_tracer);
|
||||||
static inline void stack_tracer_disable(void)
|
static inline void stack_tracer_disable(void)
|
||||||
{
|
{
|
||||||
/* Preemption or interupts must be disabled */
|
/* 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());
|
WARN_ON_ONCE(!preempt_count() || !irqs_disabled());
|
||||||
this_cpu_inc(disable_stack_tracer);
|
this_cpu_inc(disable_stack_tracer);
|
||||||
}
|
}
|
||||||
|
@ -320,7 +320,7 @@ static inline void stack_tracer_disable(void)
|
||||||
*/
|
*/
|
||||||
static inline void stack_tracer_enable(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());
|
WARN_ON_ONCE(!preempt_count() || !irqs_disabled());
|
||||||
this_cpu_dec(disable_stack_tracer);
|
this_cpu_dec(disable_stack_tracer);
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,7 @@ extern int tty_prepare_flip_string(struct tty_port *port,
|
||||||
unsigned char **chars, size_t size);
|
unsigned char **chars, size_t size);
|
||||||
extern void tty_flip_buffer_push(struct tty_port *port);
|
extern void tty_flip_buffer_push(struct tty_port *port);
|
||||||
void tty_schedule_flip(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,
|
static inline int tty_insert_flip_char(struct tty_port *port,
|
||||||
unsigned char ch, char flag)
|
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;
|
*char_buf_ptr(tb, tb->used++) = ch;
|
||||||
return 1;
|
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,
|
static inline int tty_insert_flip_string(struct tty_port *port,
|
||||||
|
|
|
@ -156,7 +156,7 @@ copy_to_user(void __user *to, const void *from, unsigned long n)
|
||||||
}
|
}
|
||||||
#ifdef CONFIG_COMPAT
|
#ifdef CONFIG_COMPAT
|
||||||
static __always_inline unsigned long __must_check
|
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();
|
might_fault();
|
||||||
if (access_ok(VERIFY_WRITE, to, n) && access_ok(VERIFY_READ, from, n))
|
if (access_ok(VERIFY_WRITE, to, n) && access_ok(VERIFY_READ, from, n))
|
||||||
|
|
|
@ -2260,6 +2260,13 @@ retry:
|
||||||
mutex_unlock(&cpuset_mutex);
|
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
|
* 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 */
|
/* rebuild sched domains if cpus_allowed has changed */
|
||||||
if (cpus_updated)
|
if (cpus_updated || force_rebuild) {
|
||||||
|
force_rebuild = false;
|
||||||
rebuild_sched_domains();
|
rebuild_sched_domains();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void cpuset_update_active_cpus(void)
|
void cpuset_update_active_cpus(void)
|
||||||
|
@ -2354,6 +2363,11 @@ void cpuset_update_active_cpus(void)
|
||||||
schedule_work(&cpuset_hotplug_work);
|
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].
|
* Keep top_cpuset.mems_allowed tracking node_states[N_MEMORY].
|
||||||
* Call this routine anytime after node_states[N_MEMORY] changes.
|
* Call this routine anytime after node_states[N_MEMORY] changes.
|
||||||
|
|
|
@ -1252,7 +1252,17 @@ static int cpuhp_store_callbacks(enum cpuhp_state state, const char *name,
|
||||||
struct cpuhp_step *sp;
|
struct cpuhp_step *sp;
|
||||||
int ret = 0;
|
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);
|
ret = cpuhp_reserve_state(state);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
#include <linux/workqueue.h>
|
#include <linux/workqueue.h>
|
||||||
#include <linux/kmod.h>
|
#include <linux/kmod.h>
|
||||||
#include <trace/events/power.h>
|
#include <trace/events/power.h>
|
||||||
|
#include <linux/cpuset.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Timeout for stopping processes
|
* Timeout for stopping processes
|
||||||
|
@ -202,6 +203,8 @@ void thaw_processes(void)
|
||||||
__usermodehelper_set_disable_depth(UMH_FREEZING);
|
__usermodehelper_set_disable_depth(UMH_FREEZING);
|
||||||
thaw_workqueues();
|
thaw_workqueues();
|
||||||
|
|
||||||
|
cpuset_wait_for_hotplug();
|
||||||
|
|
||||||
read_lock(&tasklist_lock);
|
read_lock(&tasklist_lock);
|
||||||
for_each_process_thread(g, p) {
|
for_each_process_thread(g, p) {
|
||||||
/* No other threads should have PF_SUSPEND_TASK set */
|
/* No other threads should have PF_SUSPEND_TASK set */
|
||||||
|
|
|
@ -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);
|
__call_srcu(sp, &rcu.head, wakeme_after_rcu, do_norm);
|
||||||
wait_for_completion(&rcu.completion);
|
wait_for_completion(&rcu.completion);
|
||||||
destroy_rcu_head_on_stack(&rcu.head);
|
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
Loading…
Reference in a new issue