Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
Merge net into net-next. Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
3715544750
|
@ -3787,6 +3787,8 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
|
|||
READ_CAPACITY_16 command);
|
||||
f = NO_REPORT_OPCODES (don't use report opcodes
|
||||
command, uas only);
|
||||
g = MAX_SECTORS_240 (don't transfer more than
|
||||
240 sectors at a time, uas only);
|
||||
h = CAPACITY_HEURISTICS (decrease the
|
||||
reported device capacity by one
|
||||
sector if the number is odd);
|
||||
|
|
|
@ -119,9 +119,9 @@ Most notably, in the x509.genkey file, the req_distinguished_name section
|
|||
should be altered from the default:
|
||||
|
||||
[ req_distinguished_name ]
|
||||
O = Magrathea
|
||||
CN = Glacier signing key
|
||||
emailAddress = slartibartfast@magrathea.h2g2
|
||||
#O = Unspecified company
|
||||
CN = Build time autogenerated kernel key
|
||||
#emailAddress = unspecified.user@unspecified.company
|
||||
|
||||
The generated RSA key size can also be set with:
|
||||
|
||||
|
|
|
@ -10523,7 +10523,6 @@ F: include/linux/virtio_console.h
|
|||
F: include/uapi/linux/virtio_console.h
|
||||
|
||||
VIRTIO CORE, NET AND BLOCK DRIVERS
|
||||
M: Rusty Russell <rusty@rustcorp.com.au>
|
||||
M: "Michael S. Tsirkin" <mst@redhat.com>
|
||||
L: virtualization@lists.linux-foundation.org
|
||||
S: Maintained
|
||||
|
|
|
@ -31,6 +31,7 @@ config ARM64
|
|||
select GENERIC_EARLY_IOREMAP
|
||||
select GENERIC_IRQ_PROBE
|
||||
select GENERIC_IRQ_SHOW
|
||||
select GENERIC_IRQ_SHOW_LEVEL
|
||||
select GENERIC_PCI_IOMAP
|
||||
select GENERIC_SCHED_CLOCK
|
||||
select GENERIC_SMP_IDLE_THREAD
|
||||
|
|
|
@ -65,6 +65,14 @@ do { \
|
|||
do { \
|
||||
compiletime_assert_atomic_type(*p); \
|
||||
switch (sizeof(*p)) { \
|
||||
case 1: \
|
||||
asm volatile ("stlrb %w1, %0" \
|
||||
: "=Q" (*p) : "r" (v) : "memory"); \
|
||||
break; \
|
||||
case 2: \
|
||||
asm volatile ("stlrh %w1, %0" \
|
||||
: "=Q" (*p) : "r" (v) : "memory"); \
|
||||
break; \
|
||||
case 4: \
|
||||
asm volatile ("stlr %w1, %0" \
|
||||
: "=Q" (*p) : "r" (v) : "memory"); \
|
||||
|
@ -81,6 +89,14 @@ do { \
|
|||
typeof(*p) ___p1; \
|
||||
compiletime_assert_atomic_type(*p); \
|
||||
switch (sizeof(*p)) { \
|
||||
case 1: \
|
||||
asm volatile ("ldarb %w0, %1" \
|
||||
: "=r" (___p1) : "Q" (*p) : "memory"); \
|
||||
break; \
|
||||
case 2: \
|
||||
asm volatile ("ldarh %w0, %1" \
|
||||
: "=r" (___p1) : "Q" (*p) : "memory"); \
|
||||
break; \
|
||||
case 4: \
|
||||
asm volatile ("ldar %w0, %1" \
|
||||
: "=r" (___p1) : "Q" (*p) : "memory"); \
|
||||
|
|
|
@ -1310,7 +1310,7 @@ static const struct of_device_id armpmu_of_device_ids[] = {
|
|||
|
||||
static int armpmu_device_probe(struct platform_device *pdev)
|
||||
{
|
||||
int i, *irqs;
|
||||
int i, irq, *irqs;
|
||||
|
||||
if (!cpu_pmu)
|
||||
return -ENODEV;
|
||||
|
@ -1319,6 +1319,11 @@ static int armpmu_device_probe(struct platform_device *pdev)
|
|||
if (!irqs)
|
||||
return -ENOMEM;
|
||||
|
||||
/* Don't bother with PPIs; they're already affine */
|
||||
irq = platform_get_irq(pdev, 0);
|
||||
if (irq >= 0 && irq_is_percpu(irq))
|
||||
return 0;
|
||||
|
||||
for (i = 0; i < pdev->num_resources; ++i) {
|
||||
struct device_node *dn;
|
||||
int cpu;
|
||||
|
@ -1327,7 +1332,7 @@ static int armpmu_device_probe(struct platform_device *pdev)
|
|||
i);
|
||||
if (!dn) {
|
||||
pr_warn("Failed to parse %s/interrupt-affinity[%d]\n",
|
||||
of_node_full_name(dn), i);
|
||||
of_node_full_name(pdev->dev.of_node), i);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -67,8 +67,7 @@ static void *__alloc_from_pool(size_t size, struct page **ret_page, gfp_t flags)
|
|||
|
||||
*ret_page = phys_to_page(phys);
|
||||
ptr = (void *)val;
|
||||
if (flags & __GFP_ZERO)
|
||||
memset(ptr, 0, size);
|
||||
memset(ptr, 0, size);
|
||||
}
|
||||
|
||||
return ptr;
|
||||
|
@ -105,7 +104,6 @@ static void *__dma_alloc_coherent(struct device *dev, size_t size,
|
|||
struct page *page;
|
||||
void *addr;
|
||||
|
||||
size = PAGE_ALIGN(size);
|
||||
page = dma_alloc_from_contiguous(dev, size >> PAGE_SHIFT,
|
||||
get_order(size));
|
||||
if (!page)
|
||||
|
@ -113,8 +111,7 @@ static void *__dma_alloc_coherent(struct device *dev, size_t size,
|
|||
|
||||
*dma_handle = phys_to_dma(dev, page_to_phys(page));
|
||||
addr = page_address(page);
|
||||
if (flags & __GFP_ZERO)
|
||||
memset(addr, 0, size);
|
||||
memset(addr, 0, size);
|
||||
return addr;
|
||||
} else {
|
||||
return swiotlb_alloc_coherent(dev, size, dma_handle, flags);
|
||||
|
@ -195,6 +192,8 @@ static void __dma_free(struct device *dev, size_t size,
|
|||
{
|
||||
void *swiotlb_addr = phys_to_virt(dma_to_phys(dev, dma_handle));
|
||||
|
||||
size = PAGE_ALIGN(size);
|
||||
|
||||
if (!is_device_dma_coherent(dev)) {
|
||||
if (__free_from_pool(vaddr, size))
|
||||
return;
|
||||
|
|
|
@ -115,7 +115,7 @@ config S390
|
|||
select HAVE_ARCH_SECCOMP_FILTER
|
||||
select HAVE_ARCH_TRACEHOOK
|
||||
select HAVE_ARCH_TRANSPARENT_HUGEPAGE
|
||||
select HAVE_BPF_JIT if PACK_STACK && HAVE_MARCH_Z9_109_FEATURES
|
||||
select HAVE_BPF_JIT if PACK_STACK && HAVE_MARCH_Z196_FEATURES
|
||||
select HAVE_CMPXCHG_DOUBLE
|
||||
select HAVE_CMPXCHG_LOCAL
|
||||
select HAVE_DEBUG_KMEMLEAK
|
||||
|
|
|
@ -3,9 +3,10 @@
|
|||
*
|
||||
* Support for s390 cryptographic instructions.
|
||||
*
|
||||
* Copyright IBM Corp. 2003, 2007
|
||||
* Copyright IBM Corp. 2003, 2015
|
||||
* Author(s): Thomas Spatzier
|
||||
* Jan Glauber (jan.glauber@de.ibm.com)
|
||||
* Harald Freudenberger (freude@de.ibm.com)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the Free
|
||||
|
@ -28,15 +29,17 @@
|
|||
#define CRYPT_S390_MSA 0x1
|
||||
#define CRYPT_S390_MSA3 0x2
|
||||
#define CRYPT_S390_MSA4 0x4
|
||||
#define CRYPT_S390_MSA5 0x8
|
||||
|
||||
/* s390 cryptographic operations */
|
||||
enum crypt_s390_operations {
|
||||
CRYPT_S390_KM = 0x0100,
|
||||
CRYPT_S390_KMC = 0x0200,
|
||||
CRYPT_S390_KIMD = 0x0300,
|
||||
CRYPT_S390_KLMD = 0x0400,
|
||||
CRYPT_S390_KMAC = 0x0500,
|
||||
CRYPT_S390_KMCTR = 0x0600
|
||||
CRYPT_S390_KM = 0x0100,
|
||||
CRYPT_S390_KMC = 0x0200,
|
||||
CRYPT_S390_KIMD = 0x0300,
|
||||
CRYPT_S390_KLMD = 0x0400,
|
||||
CRYPT_S390_KMAC = 0x0500,
|
||||
CRYPT_S390_KMCTR = 0x0600,
|
||||
CRYPT_S390_PPNO = 0x0700
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -138,6 +141,16 @@ enum crypt_s390_kmac_func {
|
|||
KMAC_TDEA_192 = CRYPT_S390_KMAC | 3
|
||||
};
|
||||
|
||||
/*
|
||||
* function codes for PPNO (PERFORM PSEUDORANDOM NUMBER
|
||||
* OPERATION) instruction
|
||||
*/
|
||||
enum crypt_s390_ppno_func {
|
||||
PPNO_QUERY = CRYPT_S390_PPNO | 0,
|
||||
PPNO_SHA512_DRNG_GEN = CRYPT_S390_PPNO | 3,
|
||||
PPNO_SHA512_DRNG_SEED = CRYPT_S390_PPNO | 0x83
|
||||
};
|
||||
|
||||
/**
|
||||
* crypt_s390_km:
|
||||
* @func: the function code passed to KM; see crypt_s390_km_func
|
||||
|
@ -162,11 +175,11 @@ static inline int crypt_s390_km(long func, void *param,
|
|||
int ret;
|
||||
|
||||
asm volatile(
|
||||
"0: .insn rre,0xb92e0000,%3,%1 \n" /* KM opcode */
|
||||
"1: brc 1,0b \n" /* handle partial completion */
|
||||
"0: .insn rre,0xb92e0000,%3,%1\n" /* KM opcode */
|
||||
"1: brc 1,0b\n" /* handle partial completion */
|
||||
" la %0,0\n"
|
||||
"2:\n"
|
||||
EX_TABLE(0b,2b) EX_TABLE(1b,2b)
|
||||
EX_TABLE(0b, 2b) EX_TABLE(1b, 2b)
|
||||
: "=d" (ret), "+a" (__src), "+d" (__src_len), "+a" (__dest)
|
||||
: "d" (__func), "a" (__param), "0" (-1) : "cc", "memory");
|
||||
if (ret < 0)
|
||||
|
@ -198,11 +211,11 @@ static inline int crypt_s390_kmc(long func, void *param,
|
|||
int ret;
|
||||
|
||||
asm volatile(
|
||||
"0: .insn rre,0xb92f0000,%3,%1 \n" /* KMC opcode */
|
||||
"1: brc 1,0b \n" /* handle partial completion */
|
||||
"0: .insn rre,0xb92f0000,%3,%1\n" /* KMC opcode */
|
||||
"1: brc 1,0b\n" /* handle partial completion */
|
||||
" la %0,0\n"
|
||||
"2:\n"
|
||||
EX_TABLE(0b,2b) EX_TABLE(1b,2b)
|
||||
EX_TABLE(0b, 2b) EX_TABLE(1b, 2b)
|
||||
: "=d" (ret), "+a" (__src), "+d" (__src_len), "+a" (__dest)
|
||||
: "d" (__func), "a" (__param), "0" (-1) : "cc", "memory");
|
||||
if (ret < 0)
|
||||
|
@ -233,11 +246,11 @@ static inline int crypt_s390_kimd(long func, void *param,
|
|||
int ret;
|
||||
|
||||
asm volatile(
|
||||
"0: .insn rre,0xb93e0000,%1,%1 \n" /* KIMD opcode */
|
||||
"1: brc 1,0b \n" /* handle partial completion */
|
||||
"0: .insn rre,0xb93e0000,%1,%1\n" /* KIMD opcode */
|
||||
"1: brc 1,0b\n" /* handle partial completion */
|
||||
" la %0,0\n"
|
||||
"2:\n"
|
||||
EX_TABLE(0b,2b) EX_TABLE(1b,2b)
|
||||
EX_TABLE(0b, 2b) EX_TABLE(1b, 2b)
|
||||
: "=d" (ret), "+a" (__src), "+d" (__src_len)
|
||||
: "d" (__func), "a" (__param), "0" (-1) : "cc", "memory");
|
||||
if (ret < 0)
|
||||
|
@ -267,11 +280,11 @@ static inline int crypt_s390_klmd(long func, void *param,
|
|||
int ret;
|
||||
|
||||
asm volatile(
|
||||
"0: .insn rre,0xb93f0000,%1,%1 \n" /* KLMD opcode */
|
||||
"1: brc 1,0b \n" /* handle partial completion */
|
||||
"0: .insn rre,0xb93f0000,%1,%1\n" /* KLMD opcode */
|
||||
"1: brc 1,0b\n" /* handle partial completion */
|
||||
" la %0,0\n"
|
||||
"2:\n"
|
||||
EX_TABLE(0b,2b) EX_TABLE(1b,2b)
|
||||
EX_TABLE(0b, 2b) EX_TABLE(1b, 2b)
|
||||
: "=d" (ret), "+a" (__src), "+d" (__src_len)
|
||||
: "d" (__func), "a" (__param), "0" (-1) : "cc", "memory");
|
||||
if (ret < 0)
|
||||
|
@ -302,11 +315,11 @@ static inline int crypt_s390_kmac(long func, void *param,
|
|||
int ret;
|
||||
|
||||
asm volatile(
|
||||
"0: .insn rre,0xb91e0000,%1,%1 \n" /* KLAC opcode */
|
||||
"1: brc 1,0b \n" /* handle partial completion */
|
||||
"0: .insn rre,0xb91e0000,%1,%1\n" /* KLAC opcode */
|
||||
"1: brc 1,0b\n" /* handle partial completion */
|
||||
" la %0,0\n"
|
||||
"2:\n"
|
||||
EX_TABLE(0b,2b) EX_TABLE(1b,2b)
|
||||
EX_TABLE(0b, 2b) EX_TABLE(1b, 2b)
|
||||
: "=d" (ret), "+a" (__src), "+d" (__src_len)
|
||||
: "d" (__func), "a" (__param), "0" (-1) : "cc", "memory");
|
||||
if (ret < 0)
|
||||
|
@ -340,11 +353,11 @@ static inline int crypt_s390_kmctr(long func, void *param, u8 *dest,
|
|||
int ret = -1;
|
||||
|
||||
asm volatile(
|
||||
"0: .insn rrf,0xb92d0000,%3,%1,%4,0 \n" /* KMCTR opcode */
|
||||
"1: brc 1,0b \n" /* handle partial completion */
|
||||
"0: .insn rrf,0xb92d0000,%3,%1,%4,0\n" /* KMCTR opcode */
|
||||
"1: brc 1,0b\n" /* handle partial completion */
|
||||
" la %0,0\n"
|
||||
"2:\n"
|
||||
EX_TABLE(0b,2b) EX_TABLE(1b,2b)
|
||||
EX_TABLE(0b, 2b) EX_TABLE(1b, 2b)
|
||||
: "+d" (ret), "+a" (__src), "+d" (__src_len), "+a" (__dest),
|
||||
"+a" (__ctr)
|
||||
: "d" (__func), "a" (__param) : "cc", "memory");
|
||||
|
@ -353,6 +366,47 @@ static inline int crypt_s390_kmctr(long func, void *param, u8 *dest,
|
|||
return (func & CRYPT_S390_FUNC_MASK) ? src_len - __src_len : __src_len;
|
||||
}
|
||||
|
||||
/**
|
||||
* crypt_s390_ppno:
|
||||
* @func: the function code passed to PPNO; see crypt_s390_ppno_func
|
||||
* @param: address of parameter block; see POP for details on each func
|
||||
* @dest: address of destination memory area
|
||||
* @dest_len: size of destination memory area in bytes
|
||||
* @seed: address of seed data
|
||||
* @seed_len: size of seed data in bytes
|
||||
*
|
||||
* Executes the PPNO (PERFORM PSEUDORANDOM NUMBER OPERATION)
|
||||
* operation of the CPU.
|
||||
*
|
||||
* Returns -1 for failure, 0 for the query func, number of random
|
||||
* bytes stored in dest buffer for generate function
|
||||
*/
|
||||
static inline int crypt_s390_ppno(long func, void *param,
|
||||
u8 *dest, long dest_len,
|
||||
const u8 *seed, long seed_len)
|
||||
{
|
||||
register long __func asm("0") = func & CRYPT_S390_FUNC_MASK;
|
||||
register void *__param asm("1") = param; /* param block (240 bytes) */
|
||||
register u8 *__dest asm("2") = dest; /* buf for recv random bytes */
|
||||
register long __dest_len asm("3") = dest_len; /* requested random bytes */
|
||||
register const u8 *__seed asm("4") = seed; /* buf with seed data */
|
||||
register long __seed_len asm("5") = seed_len; /* bytes in seed buf */
|
||||
int ret = -1;
|
||||
|
||||
asm volatile (
|
||||
"0: .insn rre,0xb93c0000,%1,%5\n" /* PPNO opcode */
|
||||
"1: brc 1,0b\n" /* handle partial completion */
|
||||
" la %0,0\n"
|
||||
"2:\n"
|
||||
EX_TABLE(0b, 2b) EX_TABLE(1b, 2b)
|
||||
: "+d" (ret), "+a"(__dest), "+d"(__dest_len)
|
||||
: "d"(__func), "a"(__param), "a"(__seed), "d"(__seed_len)
|
||||
: "cc", "memory");
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
return (func & CRYPT_S390_FUNC_MASK) ? dest_len - __dest_len : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* crypt_s390_func_available:
|
||||
* @func: the function code of the specific function; 0 if op in general
|
||||
|
@ -373,6 +427,9 @@ static inline int crypt_s390_func_available(int func,
|
|||
return 0;
|
||||
if (facility_mask & CRYPT_S390_MSA4 && !test_facility(77))
|
||||
return 0;
|
||||
if (facility_mask & CRYPT_S390_MSA5 && !test_facility(57))
|
||||
return 0;
|
||||
|
||||
switch (func & CRYPT_S390_OP_MASK) {
|
||||
case CRYPT_S390_KM:
|
||||
ret = crypt_s390_km(KM_QUERY, &status, NULL, NULL, 0);
|
||||
|
@ -390,8 +447,12 @@ static inline int crypt_s390_func_available(int func,
|
|||
ret = crypt_s390_kmac(KMAC_QUERY, &status, NULL, 0);
|
||||
break;
|
||||
case CRYPT_S390_KMCTR:
|
||||
ret = crypt_s390_kmctr(KMCTR_QUERY, &status, NULL, NULL, 0,
|
||||
NULL);
|
||||
ret = crypt_s390_kmctr(KMCTR_QUERY, &status,
|
||||
NULL, NULL, 0, NULL);
|
||||
break;
|
||||
case CRYPT_S390_PPNO:
|
||||
ret = crypt_s390_ppno(PPNO_QUERY, &status,
|
||||
NULL, 0, NULL, 0);
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
|
@ -419,15 +480,14 @@ static inline int crypt_s390_pcc(long func, void *param)
|
|||
int ret = -1;
|
||||
|
||||
asm volatile(
|
||||
"0: .insn rre,0xb92c0000,0,0 \n" /* PCC opcode */
|
||||
"1: brc 1,0b \n" /* handle partial completion */
|
||||
"0: .insn rre,0xb92c0000,0,0\n" /* PCC opcode */
|
||||
"1: brc 1,0b\n" /* handle partial completion */
|
||||
" la %0,0\n"
|
||||
"2:\n"
|
||||
EX_TABLE(0b,2b) EX_TABLE(1b,2b)
|
||||
EX_TABLE(0b, 2b) EX_TABLE(1b, 2b)
|
||||
: "+d" (ret)
|
||||
: "d" (__func), "a" (__param) : "cc", "memory");
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
#endif /* _CRYPTO_ARCH_S390_CRYPT_S390_H */
|
||||
|
|
|
@ -1,106 +1,529 @@
|
|||
/*
|
||||
* Copyright IBM Corp. 2006, 2007
|
||||
* Copyright IBM Corp. 2006, 2015
|
||||
* Author(s): Jan Glauber <jan.glauber@de.ibm.com>
|
||||
* Harald Freudenberger <freude@de.ibm.com>
|
||||
* Driver for the s390 pseudo random number generator
|
||||
*/
|
||||
|
||||
#define KMSG_COMPONENT "prng"
|
||||
#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
|
||||
|
||||
#include <linux/fs.h>
|
||||
#include <linux/fips.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/miscdevice.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/random.h>
|
||||
#include <linux/slab.h>
|
||||
#include <asm/debug.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/timex.h>
|
||||
|
||||
#include "crypt_s390.h"
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Jan Glauber <jan.glauber@de.ibm.com>");
|
||||
MODULE_AUTHOR("IBM Corporation");
|
||||
MODULE_DESCRIPTION("s390 PRNG interface");
|
||||
|
||||
static int prng_chunk_size = 256;
|
||||
module_param(prng_chunk_size, int, S_IRUSR | S_IRGRP | S_IROTH);
|
||||
|
||||
#define PRNG_MODE_AUTO 0
|
||||
#define PRNG_MODE_TDES 1
|
||||
#define PRNG_MODE_SHA512 2
|
||||
|
||||
static unsigned int prng_mode = PRNG_MODE_AUTO;
|
||||
module_param_named(mode, prng_mode, int, 0);
|
||||
MODULE_PARM_DESC(prng_mode, "PRNG mode: 0 - auto, 1 - TDES, 2 - SHA512");
|
||||
|
||||
|
||||
#define PRNG_CHUNKSIZE_TDES_MIN 8
|
||||
#define PRNG_CHUNKSIZE_TDES_MAX (64*1024)
|
||||
#define PRNG_CHUNKSIZE_SHA512_MIN 64
|
||||
#define PRNG_CHUNKSIZE_SHA512_MAX (64*1024)
|
||||
|
||||
static unsigned int prng_chunk_size = 256;
|
||||
module_param_named(chunksize, prng_chunk_size, int, 0);
|
||||
MODULE_PARM_DESC(prng_chunk_size, "PRNG read chunk size in bytes");
|
||||
|
||||
static int prng_entropy_limit = 4096;
|
||||
module_param(prng_entropy_limit, int, S_IRUSR | S_IRGRP | S_IROTH | S_IWUSR);
|
||||
MODULE_PARM_DESC(prng_entropy_limit,
|
||||
"PRNG add entropy after that much bytes were produced");
|
||||
|
||||
#define PRNG_RESEED_LIMIT_TDES 4096
|
||||
#define PRNG_RESEED_LIMIT_TDES_LOWER 4096
|
||||
#define PRNG_RESEED_LIMIT_SHA512 100000
|
||||
#define PRNG_RESEED_LIMIT_SHA512_LOWER 10000
|
||||
|
||||
static unsigned int prng_reseed_limit;
|
||||
module_param_named(reseed_limit, prng_reseed_limit, int, 0);
|
||||
MODULE_PARM_DESC(prng_reseed_limit, "PRNG reseed limit");
|
||||
|
||||
|
||||
/*
|
||||
* Any one who considers arithmetical methods of producing random digits is,
|
||||
* of course, in a state of sin. -- John von Neumann
|
||||
*/
|
||||
|
||||
struct s390_prng_data {
|
||||
unsigned long count; /* how many bytes were produced */
|
||||
char *buf;
|
||||
static int prng_errorflag;
|
||||
|
||||
#define PRNG_GEN_ENTROPY_FAILED 1
|
||||
#define PRNG_SELFTEST_FAILED 2
|
||||
#define PRNG_INSTANTIATE_FAILED 3
|
||||
#define PRNG_SEED_FAILED 4
|
||||
#define PRNG_RESEED_FAILED 5
|
||||
#define PRNG_GEN_FAILED 6
|
||||
|
||||
struct prng_ws_s {
|
||||
u8 parm_block[32];
|
||||
u32 reseed_counter;
|
||||
u64 byte_counter;
|
||||
};
|
||||
|
||||
static struct s390_prng_data *p;
|
||||
|
||||
/* copied from libica, use a non-zero initial parameter block */
|
||||
static unsigned char parm_block[32] = {
|
||||
0x0F,0x2B,0x8E,0x63,0x8C,0x8E,0xD2,0x52,0x64,0xB7,0xA0,0x7B,0x75,0x28,0xB8,0xF4,
|
||||
0x75,0x5F,0xD2,0xA6,0x8D,0x97,0x11,0xFF,0x49,0xD8,0x23,0xF3,0x7E,0x21,0xEC,0xA0,
|
||||
struct ppno_ws_s {
|
||||
u32 res;
|
||||
u32 reseed_counter;
|
||||
u64 stream_bytes;
|
||||
u8 V[112];
|
||||
u8 C[112];
|
||||
};
|
||||
|
||||
static int prng_open(struct inode *inode, struct file *file)
|
||||
struct prng_data_s {
|
||||
struct mutex mutex;
|
||||
union {
|
||||
struct prng_ws_s prngws;
|
||||
struct ppno_ws_s ppnows;
|
||||
};
|
||||
u8 *buf;
|
||||
u32 rest;
|
||||
u8 *prev;
|
||||
};
|
||||
|
||||
static struct prng_data_s *prng_data;
|
||||
|
||||
/* initial parameter block for tdes mode, copied from libica */
|
||||
static const u8 initial_parm_block[32] __initconst = {
|
||||
0x0F, 0x2B, 0x8E, 0x63, 0x8C, 0x8E, 0xD2, 0x52,
|
||||
0x64, 0xB7, 0xA0, 0x7B, 0x75, 0x28, 0xB8, 0xF4,
|
||||
0x75, 0x5F, 0xD2, 0xA6, 0x8D, 0x97, 0x11, 0xFF,
|
||||
0x49, 0xD8, 0x23, 0xF3, 0x7E, 0x21, 0xEC, 0xA0 };
|
||||
|
||||
|
||||
/*** helper functions ***/
|
||||
|
||||
static int generate_entropy(u8 *ebuf, size_t nbytes)
|
||||
{
|
||||
return nonseekable_open(inode, file);
|
||||
int n, ret = 0;
|
||||
u8 *pg, *h, hash[32];
|
||||
|
||||
pg = (u8 *) __get_free_page(GFP_KERNEL);
|
||||
if (!pg) {
|
||||
prng_errorflag = PRNG_GEN_ENTROPY_FAILED;
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
while (nbytes) {
|
||||
/* fill page with urandom bytes */
|
||||
get_random_bytes(pg, PAGE_SIZE);
|
||||
/* exor page with stckf values */
|
||||
for (n = 0; n < sizeof(PAGE_SIZE/sizeof(u64)); n++) {
|
||||
u64 *p = ((u64 *)pg) + n;
|
||||
*p ^= get_tod_clock_fast();
|
||||
}
|
||||
n = (nbytes < sizeof(hash)) ? nbytes : sizeof(hash);
|
||||
if (n < sizeof(hash))
|
||||
h = hash;
|
||||
else
|
||||
h = ebuf;
|
||||
/* generate sha256 from this page */
|
||||
if (crypt_s390_kimd(KIMD_SHA_256, h,
|
||||
pg, PAGE_SIZE) != PAGE_SIZE) {
|
||||
prng_errorflag = PRNG_GEN_ENTROPY_FAILED;
|
||||
ret = -EIO;
|
||||
goto out;
|
||||
}
|
||||
if (n < sizeof(hash))
|
||||
memcpy(ebuf, hash, n);
|
||||
ret += n;
|
||||
ebuf += n;
|
||||
nbytes -= n;
|
||||
}
|
||||
|
||||
out:
|
||||
free_page((unsigned long)pg);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void prng_add_entropy(void)
|
||||
|
||||
/*** tdes functions ***/
|
||||
|
||||
static void prng_tdes_add_entropy(void)
|
||||
{
|
||||
__u64 entropy[4];
|
||||
unsigned int i;
|
||||
int ret;
|
||||
|
||||
for (i = 0; i < 16; i++) {
|
||||
ret = crypt_s390_kmc(KMC_PRNG, parm_block, (char *)entropy,
|
||||
(char *)entropy, sizeof(entropy));
|
||||
ret = crypt_s390_kmc(KMC_PRNG, prng_data->prngws.parm_block,
|
||||
(char *)entropy, (char *)entropy,
|
||||
sizeof(entropy));
|
||||
BUG_ON(ret < 0 || ret != sizeof(entropy));
|
||||
memcpy(parm_block, entropy, sizeof(entropy));
|
||||
memcpy(prng_data->prngws.parm_block, entropy, sizeof(entropy));
|
||||
}
|
||||
}
|
||||
|
||||
static void prng_seed(int nbytes)
|
||||
|
||||
static void prng_tdes_seed(int nbytes)
|
||||
{
|
||||
char buf[16];
|
||||
int i = 0;
|
||||
|
||||
BUG_ON(nbytes > 16);
|
||||
BUG_ON(nbytes > sizeof(buf));
|
||||
|
||||
get_random_bytes(buf, nbytes);
|
||||
|
||||
/* Add the entropy */
|
||||
while (nbytes >= 8) {
|
||||
*((__u64 *)parm_block) ^= *((__u64 *)(buf+i));
|
||||
prng_add_entropy();
|
||||
*((__u64 *)prng_data->prngws.parm_block) ^= *((__u64 *)(buf+i));
|
||||
prng_tdes_add_entropy();
|
||||
i += 8;
|
||||
nbytes -= 8;
|
||||
}
|
||||
prng_add_entropy();
|
||||
prng_tdes_add_entropy();
|
||||
prng_data->prngws.reseed_counter = 0;
|
||||
}
|
||||
|
||||
static ssize_t prng_read(struct file *file, char __user *ubuf, size_t nbytes,
|
||||
loff_t *ppos)
|
||||
{
|
||||
int chunk, n;
|
||||
int ret = 0;
|
||||
int tmp;
|
||||
|
||||
/* nbytes can be arbitrary length, we split it into chunks */
|
||||
static int __init prng_tdes_instantiate(void)
|
||||
{
|
||||
int datalen;
|
||||
|
||||
pr_debug("prng runs in TDES mode with "
|
||||
"chunksize=%d and reseed_limit=%u\n",
|
||||
prng_chunk_size, prng_reseed_limit);
|
||||
|
||||
/* memory allocation, prng_data struct init, mutex init */
|
||||
datalen = sizeof(struct prng_data_s) + prng_chunk_size;
|
||||
prng_data = kzalloc(datalen, GFP_KERNEL);
|
||||
if (!prng_data) {
|
||||
prng_errorflag = PRNG_INSTANTIATE_FAILED;
|
||||
return -ENOMEM;
|
||||
}
|
||||
mutex_init(&prng_data->mutex);
|
||||
prng_data->buf = ((u8 *)prng_data) + sizeof(struct prng_data_s);
|
||||
memcpy(prng_data->prngws.parm_block, initial_parm_block, 32);
|
||||
|
||||
/* initialize the PRNG, add 128 bits of entropy */
|
||||
prng_tdes_seed(16);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void prng_tdes_deinstantiate(void)
|
||||
{
|
||||
pr_debug("The prng module stopped "
|
||||
"after running in triple DES mode\n");
|
||||
kzfree(prng_data);
|
||||
}
|
||||
|
||||
|
||||
/*** sha512 functions ***/
|
||||
|
||||
static int __init prng_sha512_selftest(void)
|
||||
{
|
||||
/* NIST DRBG testvector for Hash Drbg, Sha-512, Count #0 */
|
||||
static const u8 seed[] __initconst = {
|
||||
0x6b, 0x50, 0xa7, 0xd8, 0xf8, 0xa5, 0x5d, 0x7a,
|
||||
0x3d, 0xf8, 0xbb, 0x40, 0xbc, 0xc3, 0xb7, 0x22,
|
||||
0xd8, 0x70, 0x8d, 0xe6, 0x7f, 0xda, 0x01, 0x0b,
|
||||
0x03, 0xc4, 0xc8, 0x4d, 0x72, 0x09, 0x6f, 0x8c,
|
||||
0x3e, 0xc6, 0x49, 0xcc, 0x62, 0x56, 0xd9, 0xfa,
|
||||
0x31, 0xdb, 0x7a, 0x29, 0x04, 0xaa, 0xf0, 0x25 };
|
||||
static const u8 V0[] __initconst = {
|
||||
0x00, 0xad, 0xe3, 0x6f, 0x9a, 0x01, 0xc7, 0x76,
|
||||
0x61, 0x34, 0x35, 0xf5, 0x4e, 0x24, 0x74, 0x22,
|
||||
0x21, 0x9a, 0x29, 0x89, 0xc7, 0x93, 0x2e, 0x60,
|
||||
0x1e, 0xe8, 0x14, 0x24, 0x8d, 0xd5, 0x03, 0xf1,
|
||||
0x65, 0x5d, 0x08, 0x22, 0x72, 0xd5, 0xad, 0x95,
|
||||
0xe1, 0x23, 0x1e, 0x8a, 0xa7, 0x13, 0xd9, 0x2b,
|
||||
0x5e, 0xbc, 0xbb, 0x80, 0xab, 0x8d, 0xe5, 0x79,
|
||||
0xab, 0x5b, 0x47, 0x4e, 0xdd, 0xee, 0x6b, 0x03,
|
||||
0x8f, 0x0f, 0x5c, 0x5e, 0xa9, 0x1a, 0x83, 0xdd,
|
||||
0xd3, 0x88, 0xb2, 0x75, 0x4b, 0xce, 0x83, 0x36,
|
||||
0x57, 0x4b, 0xf1, 0x5c, 0xca, 0x7e, 0x09, 0xc0,
|
||||
0xd3, 0x89, 0xc6, 0xe0, 0xda, 0xc4, 0x81, 0x7e,
|
||||
0x5b, 0xf9, 0xe1, 0x01, 0xc1, 0x92, 0x05, 0xea,
|
||||
0xf5, 0x2f, 0xc6, 0xc6, 0xc7, 0x8f, 0xbc, 0xf4 };
|
||||
static const u8 C0[] __initconst = {
|
||||
0x00, 0xf4, 0xa3, 0xe5, 0xa0, 0x72, 0x63, 0x95,
|
||||
0xc6, 0x4f, 0x48, 0xd0, 0x8b, 0x5b, 0x5f, 0x8e,
|
||||
0x6b, 0x96, 0x1f, 0x16, 0xed, 0xbc, 0x66, 0x94,
|
||||
0x45, 0x31, 0xd7, 0x47, 0x73, 0x22, 0xa5, 0x86,
|
||||
0xce, 0xc0, 0x4c, 0xac, 0x63, 0xb8, 0x39, 0x50,
|
||||
0xbf, 0xe6, 0x59, 0x6c, 0x38, 0x58, 0x99, 0x1f,
|
||||
0x27, 0xa7, 0x9d, 0x71, 0x2a, 0xb3, 0x7b, 0xf9,
|
||||
0xfb, 0x17, 0x86, 0xaa, 0x99, 0x81, 0xaa, 0x43,
|
||||
0xe4, 0x37, 0xd3, 0x1e, 0x6e, 0xe5, 0xe6, 0xee,
|
||||
0xc2, 0xed, 0x95, 0x4f, 0x53, 0x0e, 0x46, 0x8a,
|
||||
0xcc, 0x45, 0xa5, 0xdb, 0x69, 0x0d, 0x81, 0xc9,
|
||||
0x32, 0x92, 0xbc, 0x8f, 0x33, 0xe6, 0xf6, 0x09,
|
||||
0x7c, 0x8e, 0x05, 0x19, 0x0d, 0xf1, 0xb6, 0xcc,
|
||||
0xf3, 0x02, 0x21, 0x90, 0x25, 0xec, 0xed, 0x0e };
|
||||
static const u8 random[] __initconst = {
|
||||
0x95, 0xb7, 0xf1, 0x7e, 0x98, 0x02, 0xd3, 0x57,
|
||||
0x73, 0x92, 0xc6, 0xa9, 0xc0, 0x80, 0x83, 0xb6,
|
||||
0x7d, 0xd1, 0x29, 0x22, 0x65, 0xb5, 0xf4, 0x2d,
|
||||
0x23, 0x7f, 0x1c, 0x55, 0xbb, 0x9b, 0x10, 0xbf,
|
||||
0xcf, 0xd8, 0x2c, 0x77, 0xa3, 0x78, 0xb8, 0x26,
|
||||
0x6a, 0x00, 0x99, 0x14, 0x3b, 0x3c, 0x2d, 0x64,
|
||||
0x61, 0x1e, 0xee, 0xb6, 0x9a, 0xcd, 0xc0, 0x55,
|
||||
0x95, 0x7c, 0x13, 0x9e, 0x8b, 0x19, 0x0c, 0x7a,
|
||||
0x06, 0x95, 0x5f, 0x2c, 0x79, 0x7c, 0x27, 0x78,
|
||||
0xde, 0x94, 0x03, 0x96, 0xa5, 0x01, 0xf4, 0x0e,
|
||||
0x91, 0x39, 0x6a, 0xcf, 0x8d, 0x7e, 0x45, 0xeb,
|
||||
0xdb, 0xb5, 0x3b, 0xbf, 0x8c, 0x97, 0x52, 0x30,
|
||||
0xd2, 0xf0, 0xff, 0x91, 0x06, 0xc7, 0x61, 0x19,
|
||||
0xae, 0x49, 0x8e, 0x7f, 0xbc, 0x03, 0xd9, 0x0f,
|
||||
0x8e, 0x4c, 0x51, 0x62, 0x7a, 0xed, 0x5c, 0x8d,
|
||||
0x42, 0x63, 0xd5, 0xd2, 0xb9, 0x78, 0x87, 0x3a,
|
||||
0x0d, 0xe5, 0x96, 0xee, 0x6d, 0xc7, 0xf7, 0xc2,
|
||||
0x9e, 0x37, 0xee, 0xe8, 0xb3, 0x4c, 0x90, 0xdd,
|
||||
0x1c, 0xf6, 0xa9, 0xdd, 0xb2, 0x2b, 0x4c, 0xbd,
|
||||
0x08, 0x6b, 0x14, 0xb3, 0x5d, 0xe9, 0x3d, 0xa2,
|
||||
0xd5, 0xcb, 0x18, 0x06, 0x69, 0x8c, 0xbd, 0x7b,
|
||||
0xbb, 0x67, 0xbf, 0xe3, 0xd3, 0x1f, 0xd2, 0xd1,
|
||||
0xdb, 0xd2, 0xa1, 0xe0, 0x58, 0xa3, 0xeb, 0x99,
|
||||
0xd7, 0xe5, 0x1f, 0x1a, 0x93, 0x8e, 0xed, 0x5e,
|
||||
0x1c, 0x1d, 0xe2, 0x3a, 0x6b, 0x43, 0x45, 0xd3,
|
||||
0x19, 0x14, 0x09, 0xf9, 0x2f, 0x39, 0xb3, 0x67,
|
||||
0x0d, 0x8d, 0xbf, 0xb6, 0x35, 0xd8, 0xe6, 0xa3,
|
||||
0x69, 0x32, 0xd8, 0x10, 0x33, 0xd1, 0x44, 0x8d,
|
||||
0x63, 0xb4, 0x03, 0xdd, 0xf8, 0x8e, 0x12, 0x1b,
|
||||
0x6e, 0x81, 0x9a, 0xc3, 0x81, 0x22, 0x6c, 0x13,
|
||||
0x21, 0xe4, 0xb0, 0x86, 0x44, 0xf6, 0x72, 0x7c,
|
||||
0x36, 0x8c, 0x5a, 0x9f, 0x7a, 0x4b, 0x3e, 0xe2 };
|
||||
|
||||
int ret = 0;
|
||||
u8 buf[sizeof(random)];
|
||||
struct ppno_ws_s ws;
|
||||
|
||||
memset(&ws, 0, sizeof(ws));
|
||||
|
||||
/* initial seed */
|
||||
ret = crypt_s390_ppno(PPNO_SHA512_DRNG_SEED,
|
||||
&ws, NULL, 0,
|
||||
seed, sizeof(seed));
|
||||
if (ret < 0) {
|
||||
pr_err("The prng self test seed operation for the "
|
||||
"SHA-512 mode failed with rc=%d\n", ret);
|
||||
prng_errorflag = PRNG_SELFTEST_FAILED;
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/* check working states V and C */
|
||||
if (memcmp(ws.V, V0, sizeof(V0)) != 0
|
||||
|| memcmp(ws.C, C0, sizeof(C0)) != 0) {
|
||||
pr_err("The prng self test state test "
|
||||
"for the SHA-512 mode failed\n");
|
||||
prng_errorflag = PRNG_SELFTEST_FAILED;
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/* generate random bytes */
|
||||
ret = crypt_s390_ppno(PPNO_SHA512_DRNG_GEN,
|
||||
&ws, buf, sizeof(buf),
|
||||
NULL, 0);
|
||||
if (ret < 0) {
|
||||
pr_err("The prng self test generate operation for "
|
||||
"the SHA-512 mode failed with rc=%d\n", ret);
|
||||
prng_errorflag = PRNG_SELFTEST_FAILED;
|
||||
return -EIO;
|
||||
}
|
||||
ret = crypt_s390_ppno(PPNO_SHA512_DRNG_GEN,
|
||||
&ws, buf, sizeof(buf),
|
||||
NULL, 0);
|
||||
if (ret < 0) {
|
||||
pr_err("The prng self test generate operation for "
|
||||
"the SHA-512 mode failed with rc=%d\n", ret);
|
||||
prng_errorflag = PRNG_SELFTEST_FAILED;
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/* check against expected data */
|
||||
if (memcmp(buf, random, sizeof(random)) != 0) {
|
||||
pr_err("The prng self test data test "
|
||||
"for the SHA-512 mode failed\n");
|
||||
prng_errorflag = PRNG_SELFTEST_FAILED;
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int __init prng_sha512_instantiate(void)
|
||||
{
|
||||
int ret, datalen;
|
||||
u8 seed[64];
|
||||
|
||||
pr_debug("prng runs in SHA-512 mode "
|
||||
"with chunksize=%d and reseed_limit=%u\n",
|
||||
prng_chunk_size, prng_reseed_limit);
|
||||
|
||||
/* memory allocation, prng_data struct init, mutex init */
|
||||
datalen = sizeof(struct prng_data_s) + prng_chunk_size;
|
||||
if (fips_enabled)
|
||||
datalen += prng_chunk_size;
|
||||
prng_data = kzalloc(datalen, GFP_KERNEL);
|
||||
if (!prng_data) {
|
||||
prng_errorflag = PRNG_INSTANTIATE_FAILED;
|
||||
return -ENOMEM;
|
||||
}
|
||||
mutex_init(&prng_data->mutex);
|
||||
prng_data->buf = ((u8 *)prng_data) + sizeof(struct prng_data_s);
|
||||
|
||||
/* selftest */
|
||||
ret = prng_sha512_selftest();
|
||||
if (ret)
|
||||
goto outfree;
|
||||
|
||||
/* generate initial seed bytestring, first 48 bytes of entropy */
|
||||
ret = generate_entropy(seed, 48);
|
||||
if (ret != 48)
|
||||
goto outfree;
|
||||
/* followed by 16 bytes of unique nonce */
|
||||
get_tod_clock_ext(seed + 48);
|
||||
|
||||
/* initial seed of the ppno drng */
|
||||
ret = crypt_s390_ppno(PPNO_SHA512_DRNG_SEED,
|
||||
&prng_data->ppnows, NULL, 0,
|
||||
seed, sizeof(seed));
|
||||
if (ret < 0) {
|
||||
prng_errorflag = PRNG_SEED_FAILED;
|
||||
ret = -EIO;
|
||||
goto outfree;
|
||||
}
|
||||
|
||||
/* if fips mode is enabled, generate a first block of random
|
||||
bytes for the FIPS 140-2 Conditional Self Test */
|
||||
if (fips_enabled) {
|
||||
prng_data->prev = prng_data->buf + prng_chunk_size;
|
||||
ret = crypt_s390_ppno(PPNO_SHA512_DRNG_GEN,
|
||||
&prng_data->ppnows,
|
||||
prng_data->prev,
|
||||
prng_chunk_size,
|
||||
NULL, 0);
|
||||
if (ret < 0 || ret != prng_chunk_size) {
|
||||
prng_errorflag = PRNG_GEN_FAILED;
|
||||
ret = -EIO;
|
||||
goto outfree;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
outfree:
|
||||
kfree(prng_data);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static void prng_sha512_deinstantiate(void)
|
||||
{
|
||||
pr_debug("The prng module stopped after running in SHA-512 mode\n");
|
||||
kzfree(prng_data);
|
||||
}
|
||||
|
||||
|
||||
static int prng_sha512_reseed(void)
|
||||
{
|
||||
int ret;
|
||||
u8 seed[32];
|
||||
|
||||
/* generate 32 bytes of fresh entropy */
|
||||
ret = generate_entropy(seed, sizeof(seed));
|
||||
if (ret != sizeof(seed))
|
||||
return ret;
|
||||
|
||||
/* do a reseed of the ppno drng with this bytestring */
|
||||
ret = crypt_s390_ppno(PPNO_SHA512_DRNG_SEED,
|
||||
&prng_data->ppnows, NULL, 0,
|
||||
seed, sizeof(seed));
|
||||
if (ret) {
|
||||
prng_errorflag = PRNG_RESEED_FAILED;
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int prng_sha512_generate(u8 *buf, size_t nbytes)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* reseed needed ? */
|
||||
if (prng_data->ppnows.reseed_counter > prng_reseed_limit) {
|
||||
ret = prng_sha512_reseed();
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* PPNO generate */
|
||||
ret = crypt_s390_ppno(PPNO_SHA512_DRNG_GEN,
|
||||
&prng_data->ppnows, buf, nbytes,
|
||||
NULL, 0);
|
||||
if (ret < 0 || ret != nbytes) {
|
||||
prng_errorflag = PRNG_GEN_FAILED;
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/* FIPS 140-2 Conditional Self Test */
|
||||
if (fips_enabled) {
|
||||
if (!memcmp(prng_data->prev, buf, nbytes)) {
|
||||
prng_errorflag = PRNG_GEN_FAILED;
|
||||
return -EILSEQ;
|
||||
}
|
||||
memcpy(prng_data->prev, buf, nbytes);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/*** file io functions ***/
|
||||
|
||||
static int prng_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return nonseekable_open(inode, file);
|
||||
}
|
||||
|
||||
|
||||
static ssize_t prng_tdes_read(struct file *file, char __user *ubuf,
|
||||
size_t nbytes, loff_t *ppos)
|
||||
{
|
||||
int chunk, n, tmp, ret = 0;
|
||||
|
||||
/* lock prng_data struct */
|
||||
if (mutex_lock_interruptible(&prng_data->mutex))
|
||||
return -ERESTARTSYS;
|
||||
|
||||
while (nbytes) {
|
||||
/* same as in extract_entropy_user in random.c */
|
||||
if (need_resched()) {
|
||||
if (signal_pending(current)) {
|
||||
if (ret == 0)
|
||||
ret = -ERESTARTSYS;
|
||||
break;
|
||||
}
|
||||
/* give mutex free before calling schedule() */
|
||||
mutex_unlock(&prng_data->mutex);
|
||||
schedule();
|
||||
/* occopy mutex again */
|
||||
if (mutex_lock_interruptible(&prng_data->mutex)) {
|
||||
if (ret == 0)
|
||||
ret = -ERESTARTSYS;
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -112,12 +535,11 @@ static ssize_t prng_read(struct file *file, char __user *ubuf, size_t nbytes,
|
|||
/* PRNG only likes multiples of 8 bytes */
|
||||
n = (chunk + 7) & -8;
|
||||
|
||||
if (p->count > prng_entropy_limit)
|
||||
prng_seed(8);
|
||||
if (prng_data->prngws.reseed_counter > prng_reseed_limit)
|
||||
prng_tdes_seed(8);
|
||||
|
||||
/* if the CPU supports PRNG stckf is present too */
|
||||
asm volatile(".insn s,0xb27c0000,%0"
|
||||
: "=m" (*((unsigned long long *)p->buf)) : : "cc");
|
||||
*((unsigned long long *)prng_data->buf) = get_tod_clock_fast();
|
||||
|
||||
/*
|
||||
* Beside the STCKF the input for the TDES-EDE is the output
|
||||
|
@ -132,34 +554,258 @@ static ssize_t prng_read(struct file *file, char __user *ubuf, size_t nbytes,
|
|||
* Note: you can still get strict X9.17 conformity by setting
|
||||
* prng_chunk_size to 8 bytes.
|
||||
*/
|
||||
tmp = crypt_s390_kmc(KMC_PRNG, parm_block, p->buf, p->buf, n);
|
||||
BUG_ON((tmp < 0) || (tmp != n));
|
||||
tmp = crypt_s390_kmc(KMC_PRNG, prng_data->prngws.parm_block,
|
||||
prng_data->buf, prng_data->buf, n);
|
||||
if (tmp < 0 || tmp != n) {
|
||||
ret = -EIO;
|
||||
break;
|
||||
}
|
||||
|
||||
p->count += n;
|
||||
prng_data->prngws.byte_counter += n;
|
||||
prng_data->prngws.reseed_counter += n;
|
||||
|
||||
if (copy_to_user(ubuf, p->buf, chunk))
|
||||
if (copy_to_user(ubuf, prng_data->buf, chunk))
|
||||
return -EFAULT;
|
||||
|
||||
nbytes -= chunk;
|
||||
ret += chunk;
|
||||
ubuf += chunk;
|
||||
}
|
||||
|
||||
/* unlock prng_data struct */
|
||||
mutex_unlock(&prng_data->mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct file_operations prng_fops = {
|
||||
|
||||
static ssize_t prng_sha512_read(struct file *file, char __user *ubuf,
|
||||
size_t nbytes, loff_t *ppos)
|
||||
{
|
||||
int n, ret = 0;
|
||||
u8 *p;
|
||||
|
||||
/* if errorflag is set do nothing and return 'broken pipe' */
|
||||
if (prng_errorflag)
|
||||
return -EPIPE;
|
||||
|
||||
/* lock prng_data struct */
|
||||
if (mutex_lock_interruptible(&prng_data->mutex))
|
||||
return -ERESTARTSYS;
|
||||
|
||||
while (nbytes) {
|
||||
if (need_resched()) {
|
||||
if (signal_pending(current)) {
|
||||
if (ret == 0)
|
||||
ret = -ERESTARTSYS;
|
||||
break;
|
||||
}
|
||||
/* give mutex free before calling schedule() */
|
||||
mutex_unlock(&prng_data->mutex);
|
||||
schedule();
|
||||
/* occopy mutex again */
|
||||
if (mutex_lock_interruptible(&prng_data->mutex)) {
|
||||
if (ret == 0)
|
||||
ret = -ERESTARTSYS;
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
if (prng_data->rest) {
|
||||
/* push left over random bytes from the previous read */
|
||||
p = prng_data->buf + prng_chunk_size - prng_data->rest;
|
||||
n = (nbytes < prng_data->rest) ?
|
||||
nbytes : prng_data->rest;
|
||||
prng_data->rest -= n;
|
||||
} else {
|
||||
/* generate one chunk of random bytes into read buf */
|
||||
p = prng_data->buf;
|
||||
n = prng_sha512_generate(p, prng_chunk_size);
|
||||
if (n < 0) {
|
||||
ret = n;
|
||||
break;
|
||||
}
|
||||
if (nbytes < prng_chunk_size) {
|
||||
n = nbytes;
|
||||
prng_data->rest = prng_chunk_size - n;
|
||||
} else {
|
||||
n = prng_chunk_size;
|
||||
prng_data->rest = 0;
|
||||
}
|
||||
}
|
||||
if (copy_to_user(ubuf, p, n)) {
|
||||
ret = -EFAULT;
|
||||
break;
|
||||
}
|
||||
ubuf += n;
|
||||
nbytes -= n;
|
||||
ret += n;
|
||||
}
|
||||
|
||||
/* unlock prng_data struct */
|
||||
mutex_unlock(&prng_data->mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/*** sysfs stuff ***/
|
||||
|
||||
static const struct file_operations prng_sha512_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = &prng_open,
|
||||
.release = NULL,
|
||||
.read = &prng_read,
|
||||
.read = &prng_sha512_read,
|
||||
.llseek = noop_llseek,
|
||||
};
|
||||
static const struct file_operations prng_tdes_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = &prng_open,
|
||||
.release = NULL,
|
||||
.read = &prng_tdes_read,
|
||||
.llseek = noop_llseek,
|
||||
};
|
||||
|
||||
static struct miscdevice prng_dev = {
|
||||
static struct miscdevice prng_sha512_dev = {
|
||||
.name = "prandom",
|
||||
.minor = MISC_DYNAMIC_MINOR,
|
||||
.fops = &prng_fops,
|
||||
.fops = &prng_sha512_fops,
|
||||
};
|
||||
static struct miscdevice prng_tdes_dev = {
|
||||
.name = "prandom",
|
||||
.minor = MISC_DYNAMIC_MINOR,
|
||||
.fops = &prng_tdes_fops,
|
||||
};
|
||||
|
||||
|
||||
/* chunksize attribute (ro) */
|
||||
static ssize_t prng_chunksize_show(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
return snprintf(buf, PAGE_SIZE, "%u\n", prng_chunk_size);
|
||||
}
|
||||
static DEVICE_ATTR(chunksize, 0444, prng_chunksize_show, NULL);
|
||||
|
||||
/* counter attribute (ro) */
|
||||
static ssize_t prng_counter_show(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
u64 counter;
|
||||
|
||||
if (mutex_lock_interruptible(&prng_data->mutex))
|
||||
return -ERESTARTSYS;
|
||||
if (prng_mode == PRNG_MODE_SHA512)
|
||||
counter = prng_data->ppnows.stream_bytes;
|
||||
else
|
||||
counter = prng_data->prngws.byte_counter;
|
||||
mutex_unlock(&prng_data->mutex);
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%llu\n", counter);
|
||||
}
|
||||
static DEVICE_ATTR(byte_counter, 0444, prng_counter_show, NULL);
|
||||
|
||||
/* errorflag attribute (ro) */
|
||||
static ssize_t prng_errorflag_show(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", prng_errorflag);
|
||||
}
|
||||
static DEVICE_ATTR(errorflag, 0444, prng_errorflag_show, NULL);
|
||||
|
||||
/* mode attribute (ro) */
|
||||
static ssize_t prng_mode_show(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
if (prng_mode == PRNG_MODE_TDES)
|
||||
return snprintf(buf, PAGE_SIZE, "TDES\n");
|
||||
else
|
||||
return snprintf(buf, PAGE_SIZE, "SHA512\n");
|
||||
}
|
||||
static DEVICE_ATTR(mode, 0444, prng_mode_show, NULL);
|
||||
|
||||
/* reseed attribute (w) */
|
||||
static ssize_t prng_reseed_store(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
if (mutex_lock_interruptible(&prng_data->mutex))
|
||||
return -ERESTARTSYS;
|
||||
prng_sha512_reseed();
|
||||
mutex_unlock(&prng_data->mutex);
|
||||
|
||||
return count;
|
||||
}
|
||||
static DEVICE_ATTR(reseed, 0200, NULL, prng_reseed_store);
|
||||
|
||||
/* reseed limit attribute (rw) */
|
||||
static ssize_t prng_reseed_limit_show(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
return snprintf(buf, PAGE_SIZE, "%u\n", prng_reseed_limit);
|
||||
}
|
||||
static ssize_t prng_reseed_limit_store(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
unsigned limit;
|
||||
|
||||
if (sscanf(buf, "%u\n", &limit) != 1)
|
||||
return -EINVAL;
|
||||
|
||||
if (prng_mode == PRNG_MODE_SHA512) {
|
||||
if (limit < PRNG_RESEED_LIMIT_SHA512_LOWER)
|
||||
return -EINVAL;
|
||||
} else {
|
||||
if (limit < PRNG_RESEED_LIMIT_TDES_LOWER)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
prng_reseed_limit = limit;
|
||||
|
||||
return count;
|
||||
}
|
||||
static DEVICE_ATTR(reseed_limit, 0644,
|
||||
prng_reseed_limit_show, prng_reseed_limit_store);
|
||||
|
||||
/* strength attribute (ro) */
|
||||
static ssize_t prng_strength_show(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
return snprintf(buf, PAGE_SIZE, "256\n");
|
||||
}
|
||||
static DEVICE_ATTR(strength, 0444, prng_strength_show, NULL);
|
||||
|
||||
static struct attribute *prng_sha512_dev_attrs[] = {
|
||||
&dev_attr_errorflag.attr,
|
||||
&dev_attr_chunksize.attr,
|
||||
&dev_attr_byte_counter.attr,
|
||||
&dev_attr_mode.attr,
|
||||
&dev_attr_reseed.attr,
|
||||
&dev_attr_reseed_limit.attr,
|
||||
&dev_attr_strength.attr,
|
||||
NULL
|
||||
};
|
||||
static struct attribute *prng_tdes_dev_attrs[] = {
|
||||
&dev_attr_chunksize.attr,
|
||||
&dev_attr_byte_counter.attr,
|
||||
&dev_attr_mode.attr,
|
||||
NULL
|
||||
};
|
||||
|
||||
static struct attribute_group prng_sha512_dev_attr_group = {
|
||||
.attrs = prng_sha512_dev_attrs
|
||||
};
|
||||
static struct attribute_group prng_tdes_dev_attr_group = {
|
||||
.attrs = prng_tdes_dev_attrs
|
||||
};
|
||||
|
||||
|
||||
/*** module init and exit ***/
|
||||
|
||||
static int __init prng_init(void)
|
||||
{
|
||||
|
@ -169,43 +815,105 @@ static int __init prng_init(void)
|
|||
if (!crypt_s390_func_available(KMC_PRNG, CRYPT_S390_MSA))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (prng_chunk_size < 8)
|
||||
return -EINVAL;
|
||||
|
||||
p = kmalloc(sizeof(struct s390_prng_data), GFP_KERNEL);
|
||||
if (!p)
|
||||
return -ENOMEM;
|
||||
p->count = 0;
|
||||
|
||||
p->buf = kmalloc(prng_chunk_size, GFP_KERNEL);
|
||||
if (!p->buf) {
|
||||
ret = -ENOMEM;
|
||||
goto out_free;
|
||||
/* choose prng mode */
|
||||
if (prng_mode != PRNG_MODE_TDES) {
|
||||
/* check for MSA5 support for PPNO operations */
|
||||
if (!crypt_s390_func_available(PPNO_SHA512_DRNG_GEN,
|
||||
CRYPT_S390_MSA5)) {
|
||||
if (prng_mode == PRNG_MODE_SHA512) {
|
||||
pr_err("The prng module cannot "
|
||||
"start in SHA-512 mode\n");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
prng_mode = PRNG_MODE_TDES;
|
||||
} else
|
||||
prng_mode = PRNG_MODE_SHA512;
|
||||
}
|
||||
|
||||
/* initialize the PRNG, add 128 bits of entropy */
|
||||
prng_seed(16);
|
||||
if (prng_mode == PRNG_MODE_SHA512) {
|
||||
|
||||
ret = misc_register(&prng_dev);
|
||||
if (ret)
|
||||
goto out_buf;
|
||||
return 0;
|
||||
/* SHA512 mode */
|
||||
|
||||
out_buf:
|
||||
kfree(p->buf);
|
||||
out_free:
|
||||
kfree(p);
|
||||
if (prng_chunk_size < PRNG_CHUNKSIZE_SHA512_MIN
|
||||
|| prng_chunk_size > PRNG_CHUNKSIZE_SHA512_MAX)
|
||||
return -EINVAL;
|
||||
prng_chunk_size = (prng_chunk_size + 0x3f) & ~0x3f;
|
||||
|
||||
if (prng_reseed_limit == 0)
|
||||
prng_reseed_limit = PRNG_RESEED_LIMIT_SHA512;
|
||||
else if (prng_reseed_limit < PRNG_RESEED_LIMIT_SHA512_LOWER)
|
||||
return -EINVAL;
|
||||
|
||||
ret = prng_sha512_instantiate();
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
ret = misc_register(&prng_sha512_dev);
|
||||
if (ret) {
|
||||
prng_sha512_deinstantiate();
|
||||
goto out;
|
||||
}
|
||||
ret = sysfs_create_group(&prng_sha512_dev.this_device->kobj,
|
||||
&prng_sha512_dev_attr_group);
|
||||
if (ret) {
|
||||
misc_deregister(&prng_sha512_dev);
|
||||
prng_sha512_deinstantiate();
|
||||
goto out;
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
/* TDES mode */
|
||||
|
||||
if (prng_chunk_size < PRNG_CHUNKSIZE_TDES_MIN
|
||||
|| prng_chunk_size > PRNG_CHUNKSIZE_TDES_MAX)
|
||||
return -EINVAL;
|
||||
prng_chunk_size = (prng_chunk_size + 0x07) & ~0x07;
|
||||
|
||||
if (prng_reseed_limit == 0)
|
||||
prng_reseed_limit = PRNG_RESEED_LIMIT_TDES;
|
||||
else if (prng_reseed_limit < PRNG_RESEED_LIMIT_TDES_LOWER)
|
||||
return -EINVAL;
|
||||
|
||||
ret = prng_tdes_instantiate();
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
ret = misc_register(&prng_tdes_dev);
|
||||
if (ret) {
|
||||
prng_tdes_deinstantiate();
|
||||
goto out;
|
||||
}
|
||||
ret = sysfs_create_group(&prng_tdes_dev.this_device->kobj,
|
||||
&prng_tdes_dev_attr_group);
|
||||
if (ret) {
|
||||
misc_deregister(&prng_tdes_dev);
|
||||
prng_tdes_deinstantiate();
|
||||
goto out;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static void __exit prng_exit(void)
|
||||
{
|
||||
/* wipe me */
|
||||
kzfree(p->buf);
|
||||
kfree(p);
|
||||
|
||||
misc_deregister(&prng_dev);
|
||||
if (prng_mode == PRNG_MODE_SHA512) {
|
||||
sysfs_remove_group(&prng_sha512_dev.this_device->kobj,
|
||||
&prng_sha512_dev_attr_group);
|
||||
misc_deregister(&prng_sha512_dev);
|
||||
prng_sha512_deinstantiate();
|
||||
} else {
|
||||
sysfs_remove_group(&prng_tdes_dev.this_device->kobj,
|
||||
&prng_tdes_dev_attr_group);
|
||||
misc_deregister(&prng_tdes_dev);
|
||||
prng_tdes_deinstantiate();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
module_init(prng_init);
|
||||
module_exit(prng_exit);
|
||||
|
|
|
@ -26,6 +26,9 @@
|
|||
/* Not more than 2GB */
|
||||
#define KEXEC_CONTROL_MEMORY_LIMIT (1UL<<31)
|
||||
|
||||
/* Allocate control page with GFP_DMA */
|
||||
#define KEXEC_CONTROL_MEMORY_GFP GFP_DMA
|
||||
|
||||
/* Maximum address we can use for the crash control pages */
|
||||
#define KEXEC_CRASH_CONTROL_MEMORY_LIMIT (-1UL)
|
||||
|
||||
|
|
|
@ -14,7 +14,9 @@ typedef struct {
|
|||
unsigned long asce_bits;
|
||||
unsigned long asce_limit;
|
||||
unsigned long vdso_base;
|
||||
/* The mmu context has extended page tables. */
|
||||
/* The mmu context allocates 4K page tables. */
|
||||
unsigned int alloc_pgste:1;
|
||||
/* The mmu context uses extended page tables. */
|
||||
unsigned int has_pgste:1;
|
||||
/* The mmu context uses storage keys. */
|
||||
unsigned int use_skey:1;
|
||||
|
|
|
@ -20,8 +20,11 @@ static inline int init_new_context(struct task_struct *tsk,
|
|||
mm->context.flush_mm = 0;
|
||||
mm->context.asce_bits = _ASCE_TABLE_LENGTH | _ASCE_USER_BITS;
|
||||
mm->context.asce_bits |= _ASCE_TYPE_REGION3;
|
||||
#ifdef CONFIG_PGSTE
|
||||
mm->context.alloc_pgste = page_table_allocate_pgste;
|
||||
mm->context.has_pgste = 0;
|
||||
mm->context.use_skey = 0;
|
||||
#endif
|
||||
mm->context.asce_limit = STACK_TOP_MAX;
|
||||
crst_table_init((unsigned long *) mm->pgd, pgd_entry_type(mm));
|
||||
return 0;
|
||||
|
|
|
@ -21,6 +21,7 @@ void crst_table_free(struct mm_struct *, unsigned long *);
|
|||
unsigned long *page_table_alloc(struct mm_struct *);
|
||||
void page_table_free(struct mm_struct *, unsigned long *);
|
||||
void page_table_free_rcu(struct mmu_gather *, unsigned long *, unsigned long);
|
||||
extern int page_table_allocate_pgste;
|
||||
|
||||
int set_guest_storage_key(struct mm_struct *mm, unsigned long addr,
|
||||
unsigned long key, bool nq);
|
||||
|
|
|
@ -12,12 +12,9 @@
|
|||
#define _ASM_S390_PGTABLE_H
|
||||
|
||||
/*
|
||||
* The Linux memory management assumes a three-level page table setup. For
|
||||
* s390 31 bit we "fold" the mid level into the top-level page table, so
|
||||
* that we physically have the same two-level page table as the s390 mmu
|
||||
* expects in 31 bit mode. For s390 64 bit we use three of the five levels
|
||||
* the hardware provides (region first and region second tables are not
|
||||
* used).
|
||||
* The Linux memory management assumes a three-level page table setup.
|
||||
* For s390 64 bit we use up to four of the five levels the hardware
|
||||
* provides (region first tables are not used).
|
||||
*
|
||||
* The "pgd_xxx()" functions are trivial for a folded two-level
|
||||
* setup: the pgd is never bad, and a pmd always exists (as it's folded
|
||||
|
@ -101,8 +98,8 @@ extern unsigned long zero_page_mask;
|
|||
|
||||
#ifndef __ASSEMBLY__
|
||||
/*
|
||||
* The vmalloc and module area will always be on the topmost area of the kernel
|
||||
* mapping. We reserve 96MB (31bit) / 128GB (64bit) for vmalloc and modules.
|
||||
* The vmalloc and module area will always be on the topmost area of the
|
||||
* kernel mapping. We reserve 128GB (64bit) for vmalloc and modules.
|
||||
* On 64 bit kernels we have a 2GB area at the top of the vmalloc area where
|
||||
* modules will reside. That makes sure that inter module branches always
|
||||
* happen without trampolines and in addition the placement within a 2GB frame
|
||||
|
@ -131,38 +128,6 @@ static inline int is_module_addr(void *addr)
|
|||
}
|
||||
|
||||
/*
|
||||
* A 31 bit pagetable entry of S390 has following format:
|
||||
* | PFRA | | OS |
|
||||
* 0 0IP0
|
||||
* 00000000001111111111222222222233
|
||||
* 01234567890123456789012345678901
|
||||
*
|
||||
* I Page-Invalid Bit: Page is not available for address-translation
|
||||
* P Page-Protection Bit: Store access not possible for page
|
||||
*
|
||||
* A 31 bit segmenttable entry of S390 has following format:
|
||||
* | P-table origin | |PTL
|
||||
* 0 IC
|
||||
* 00000000001111111111222222222233
|
||||
* 01234567890123456789012345678901
|
||||
*
|
||||
* I Segment-Invalid Bit: Segment is not available for address-translation
|
||||
* C Common-Segment Bit: Segment is not private (PoP 3-30)
|
||||
* PTL Page-Table-Length: Page-table length (PTL+1*16 entries -> up to 256)
|
||||
*
|
||||
* The 31 bit segmenttable origin of S390 has following format:
|
||||
*
|
||||
* |S-table origin | | STL |
|
||||
* X **GPS
|
||||
* 00000000001111111111222222222233
|
||||
* 01234567890123456789012345678901
|
||||
*
|
||||
* X Space-Switch event:
|
||||
* G Segment-Invalid Bit: *
|
||||
* P Private-Space Bit: Segment is not private (PoP 3-30)
|
||||
* S Storage-Alteration:
|
||||
* STL Segment-Table-Length: Segment-table length (STL+1*16 entries -> up to 2048)
|
||||
*
|
||||
* A 64 bit pagetable entry of S390 has following format:
|
||||
* | PFRA |0IPC| OS |
|
||||
* 0000000000111111111122222222223333333333444444444455555555556666
|
||||
|
@ -220,7 +185,6 @@ static inline int is_module_addr(void *addr)
|
|||
|
||||
/* Software bits in the page table entry */
|
||||
#define _PAGE_PRESENT 0x001 /* SW pte present bit */
|
||||
#define _PAGE_TYPE 0x002 /* SW pte type bit */
|
||||
#define _PAGE_YOUNG 0x004 /* SW pte young bit */
|
||||
#define _PAGE_DIRTY 0x008 /* SW pte dirty bit */
|
||||
#define _PAGE_READ 0x010 /* SW pte read bit */
|
||||
|
@ -240,31 +204,34 @@ static inline int is_module_addr(void *addr)
|
|||
* table lock held.
|
||||
*
|
||||
* The following table gives the different possible bit combinations for
|
||||
* the pte hardware and software bits in the last 12 bits of a pte:
|
||||
* the pte hardware and software bits in the last 12 bits of a pte
|
||||
* (. unassigned bit, x don't care, t swap type):
|
||||
*
|
||||
* 842100000000
|
||||
* 000084210000
|
||||
* 000000008421
|
||||
* .IR...wrdytp
|
||||
* empty .10...000000
|
||||
* swap .10...xxxx10
|
||||
* file .11...xxxxx0
|
||||
* prot-none, clean, old .11...000001
|
||||
* prot-none, clean, young .11...000101
|
||||
* prot-none, dirty, old .10...001001
|
||||
* prot-none, dirty, young .10...001101
|
||||
* read-only, clean, old .11...010001
|
||||
* read-only, clean, young .01...010101
|
||||
* read-only, dirty, old .11...011001
|
||||
* read-only, dirty, young .01...011101
|
||||
* read-write, clean, old .11...110001
|
||||
* read-write, clean, young .01...110101
|
||||
* read-write, dirty, old .10...111001
|
||||
* read-write, dirty, young .00...111101
|
||||
* .IR.uswrdy.p
|
||||
* empty .10.00000000
|
||||
* swap .11..ttttt.0
|
||||
* prot-none, clean, old .11.xx0000.1
|
||||
* prot-none, clean, young .11.xx0001.1
|
||||
* prot-none, dirty, old .10.xx0010.1
|
||||
* prot-none, dirty, young .10.xx0011.1
|
||||
* read-only, clean, old .11.xx0100.1
|
||||
* read-only, clean, young .01.xx0101.1
|
||||
* read-only, dirty, old .11.xx0110.1
|
||||
* read-only, dirty, young .01.xx0111.1
|
||||
* read-write, clean, old .11.xx1100.1
|
||||
* read-write, clean, young .01.xx1101.1
|
||||
* read-write, dirty, old .10.xx1110.1
|
||||
* read-write, dirty, young .00.xx1111.1
|
||||
* HW-bits: R read-only, I invalid
|
||||
* SW-bits: p present, y young, d dirty, r read, w write, s special,
|
||||
* u unused, l large
|
||||
*
|
||||
* pte_present is true for the bit pattern .xx...xxxxx1, (pte & 0x001) == 0x001
|
||||
* pte_none is true for the bit pattern .10...xxxx00, (pte & 0x603) == 0x400
|
||||
* pte_swap is true for the bit pattern .10...xxxx10, (pte & 0x603) == 0x402
|
||||
* pte_none is true for the bit pattern .10.00000000, pte == 0x400
|
||||
* pte_swap is true for the bit pattern .11..ooooo.0, (pte & 0x201) == 0x200
|
||||
* pte_present is true for the bit pattern .xx.xxxxxx.1, (pte & 0x001) == 0x001
|
||||
*/
|
||||
|
||||
/* Bits in the segment/region table address-space-control-element */
|
||||
|
@ -335,6 +302,8 @@ static inline int is_module_addr(void *addr)
|
|||
* read-write, dirty, young 11..0...0...11
|
||||
* The segment table origin is used to distinguish empty (origin==0) from
|
||||
* read-write, old segment table entries (origin!=0)
|
||||
* HW-bits: R read-only, I invalid
|
||||
* SW-bits: y young, d dirty, r read, w write
|
||||
*/
|
||||
|
||||
#define _SEGMENT_ENTRY_SPLIT_BIT 11 /* THP splitting bit number */
|
||||
|
@ -423,6 +392,15 @@ static inline int mm_has_pgste(struct mm_struct *mm)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static inline int mm_alloc_pgste(struct mm_struct *mm)
|
||||
{
|
||||
#ifdef CONFIG_PGSTE
|
||||
if (unlikely(mm->context.alloc_pgste))
|
||||
return 1;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* In the case that a guest uses storage keys
|
||||
* faults should no longer be backed by zero pages
|
||||
|
@ -582,10 +560,9 @@ static inline int pte_none(pte_t pte)
|
|||
|
||||
static inline int pte_swap(pte_t pte)
|
||||
{
|
||||
/* Bit pattern: (pte & 0x603) == 0x402 */
|
||||
return (pte_val(pte) & (_PAGE_INVALID | _PAGE_PROTECT |
|
||||
_PAGE_TYPE | _PAGE_PRESENT))
|
||||
== (_PAGE_INVALID | _PAGE_TYPE);
|
||||
/* Bit pattern: (pte & 0x201) == 0x200 */
|
||||
return (pte_val(pte) & (_PAGE_PROTECT | _PAGE_PRESENT))
|
||||
== _PAGE_PROTECT;
|
||||
}
|
||||
|
||||
static inline int pte_special(pte_t pte)
|
||||
|
@ -1586,51 +1563,51 @@ static inline int has_transparent_hugepage(void)
|
|||
#endif /* CONFIG_TRANSPARENT_HUGEPAGE */
|
||||
|
||||
/*
|
||||
* 31 bit swap entry format:
|
||||
* A page-table entry has some bits we have to treat in a special way.
|
||||
* Bits 0, 20 and bit 23 have to be zero, otherwise an specification
|
||||
* exception will occur instead of a page translation exception. The
|
||||
* specifiation exception has the bad habit not to store necessary
|
||||
* information in the lowcore.
|
||||
* Bits 21, 22, 30 and 31 are used to indicate the page type.
|
||||
* A swap pte is indicated by bit pattern (pte & 0x603) == 0x402
|
||||
* This leaves the bits 1-19 and bits 24-29 to store type and offset.
|
||||
* We use the 5 bits from 25-29 for the type and the 20 bits from 1-19
|
||||
* plus 24 for the offset.
|
||||
* 0| offset |0110|o|type |00|
|
||||
* 0 0000000001111111111 2222 2 22222 33
|
||||
* 0 1234567890123456789 0123 4 56789 01
|
||||
*
|
||||
* 64 bit swap entry format:
|
||||
* A page-table entry has some bits we have to treat in a special way.
|
||||
* Bits 52 and bit 55 have to be zero, otherwise an specification
|
||||
* exception will occur instead of a page translation exception. The
|
||||
* specifiation exception has the bad habit not to store necessary
|
||||
* information in the lowcore.
|
||||
* Bits 53, 54, 62 and 63 are used to indicate the page type.
|
||||
* A swap pte is indicated by bit pattern (pte & 0x603) == 0x402
|
||||
* This leaves the bits 0-51 and bits 56-61 to store type and offset.
|
||||
* We use the 5 bits from 57-61 for the type and the 53 bits from 0-51
|
||||
* plus 56 for the offset.
|
||||
* | offset |0110|o|type |00|
|
||||
* 0000000000111111111122222222223333333333444444444455 5555 5 55566 66
|
||||
* 0123456789012345678901234567890123456789012345678901 2345 6 78901 23
|
||||
* Bits 54 and 63 are used to indicate the page type.
|
||||
* A swap pte is indicated by bit pattern (pte & 0x201) == 0x200
|
||||
* This leaves the bits 0-51 and bits 56-62 to store type and offset.
|
||||
* We use the 5 bits from 57-61 for the type and the 52 bits from 0-51
|
||||
* for the offset.
|
||||
* | offset |01100|type |00|
|
||||
* |0000000000111111111122222222223333333333444444444455|55555|55566|66|
|
||||
* |0123456789012345678901234567890123456789012345678901|23456|78901|23|
|
||||
*/
|
||||
|
||||
#define __SWP_OFFSET_MASK (~0UL >> 11)
|
||||
#define __SWP_OFFSET_MASK ((1UL << 52) - 1)
|
||||
#define __SWP_OFFSET_SHIFT 12
|
||||
#define __SWP_TYPE_MASK ((1UL << 5) - 1)
|
||||
#define __SWP_TYPE_SHIFT 2
|
||||
|
||||
static inline pte_t mk_swap_pte(unsigned long type, unsigned long offset)
|
||||
{
|
||||
pte_t pte;
|
||||
offset &= __SWP_OFFSET_MASK;
|
||||
pte_val(pte) = _PAGE_INVALID | _PAGE_TYPE | ((type & 0x1f) << 2) |
|
||||
((offset & 1UL) << 7) | ((offset & ~1UL) << 11);
|
||||
|
||||
pte_val(pte) = _PAGE_INVALID | _PAGE_PROTECT;
|
||||
pte_val(pte) |= (offset & __SWP_OFFSET_MASK) << __SWP_OFFSET_SHIFT;
|
||||
pte_val(pte) |= (type & __SWP_TYPE_MASK) << __SWP_TYPE_SHIFT;
|
||||
return pte;
|
||||
}
|
||||
|
||||
#define __swp_type(entry) (((entry).val >> 2) & 0x1f)
|
||||
#define __swp_offset(entry) (((entry).val >> 11) | (((entry).val >> 7) & 1))
|
||||
#define __swp_entry(type,offset) ((swp_entry_t) { pte_val(mk_swap_pte((type),(offset))) })
|
||||
static inline unsigned long __swp_type(swp_entry_t entry)
|
||||
{
|
||||
return (entry.val >> __SWP_TYPE_SHIFT) & __SWP_TYPE_MASK;
|
||||
}
|
||||
|
||||
static inline unsigned long __swp_offset(swp_entry_t entry)
|
||||
{
|
||||
return (entry.val >> __SWP_OFFSET_SHIFT) & __SWP_OFFSET_MASK;
|
||||
}
|
||||
|
||||
static inline swp_entry_t __swp_entry(unsigned long type, unsigned long offset)
|
||||
{
|
||||
return (swp_entry_t) { pte_val(mk_swap_pte(type, offset)) };
|
||||
}
|
||||
|
||||
#define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) })
|
||||
#define __swp_entry_to_pte(x) ((pte_t) { (x).val })
|
||||
|
|
|
@ -14,20 +14,23 @@ static inline pmd_t __pte_to_pmd(pte_t pte)
|
|||
|
||||
/*
|
||||
* Convert encoding pte bits pmd bits
|
||||
* .IR...wrdytp dy..R...I...wr
|
||||
* empty .10...000000 -> 00..0...1...00
|
||||
* prot-none, clean, old .11...000001 -> 00..1...1...00
|
||||
* prot-none, clean, young .11...000101 -> 01..1...1...00
|
||||
* prot-none, dirty, old .10...001001 -> 10..1...1...00
|
||||
* prot-none, dirty, young .10...001101 -> 11..1...1...00
|
||||
* read-only, clean, old .11...010001 -> 00..1...1...01
|
||||
* read-only, clean, young .01...010101 -> 01..1...0...01
|
||||
* read-only, dirty, old .11...011001 -> 10..1...1...01
|
||||
* read-only, dirty, young .01...011101 -> 11..1...0...01
|
||||
* read-write, clean, old .11...110001 -> 00..0...1...11
|
||||
* read-write, clean, young .01...110101 -> 01..0...0...11
|
||||
* read-write, dirty, old .10...111001 -> 10..0...1...11
|
||||
* read-write, dirty, young .00...111101 -> 11..0...0...11
|
||||
* lIR.uswrdy.p dy..R...I...wr
|
||||
* empty 010.000000.0 -> 00..0...1...00
|
||||
* prot-none, clean, old 111.000000.1 -> 00..1...1...00
|
||||
* prot-none, clean, young 111.000001.1 -> 01..1...1...00
|
||||
* prot-none, dirty, old 111.000010.1 -> 10..1...1...00
|
||||
* prot-none, dirty, young 111.000011.1 -> 11..1...1...00
|
||||
* read-only, clean, old 111.000100.1 -> 00..1...1...01
|
||||
* read-only, clean, young 101.000101.1 -> 01..1...0...01
|
||||
* read-only, dirty, old 111.000110.1 -> 10..1...1...01
|
||||
* read-only, dirty, young 101.000111.1 -> 11..1...0...01
|
||||
* read-write, clean, old 111.001100.1 -> 00..1...1...11
|
||||
* read-write, clean, young 101.001101.1 -> 01..1...0...11
|
||||
* read-write, dirty, old 110.001110.1 -> 10..0...1...11
|
||||
* read-write, dirty, young 100.001111.1 -> 11..0...0...11
|
||||
* HW-bits: R read-only, I invalid
|
||||
* SW-bits: p present, y young, d dirty, r read, w write, s special,
|
||||
* u unused, l large
|
||||
*/
|
||||
if (pte_present(pte)) {
|
||||
pmd_val(pmd) = pte_val(pte) & PAGE_MASK;
|
||||
|
@ -48,20 +51,23 @@ static inline pte_t __pmd_to_pte(pmd_t pmd)
|
|||
|
||||
/*
|
||||
* Convert encoding pmd bits pte bits
|
||||
* dy..R...I...wr .IR...wrdytp
|
||||
* empty 00..0...1...00 -> .10...001100
|
||||
* prot-none, clean, old 00..0...1...00 -> .10...000001
|
||||
* prot-none, clean, young 01..0...1...00 -> .10...000101
|
||||
* prot-none, dirty, old 10..0...1...00 -> .10...001001
|
||||
* prot-none, dirty, young 11..0...1...00 -> .10...001101
|
||||
* read-only, clean, old 00..1...1...01 -> .11...010001
|
||||
* read-only, clean, young 01..1...1...01 -> .11...010101
|
||||
* read-only, dirty, old 10..1...1...01 -> .11...011001
|
||||
* read-only, dirty, young 11..1...1...01 -> .11...011101
|
||||
* read-write, clean, old 00..0...1...11 -> .10...110001
|
||||
* read-write, clean, young 01..0...1...11 -> .10...110101
|
||||
* read-write, dirty, old 10..0...1...11 -> .10...111001
|
||||
* read-write, dirty, young 11..0...1...11 -> .10...111101
|
||||
* dy..R...I...wr lIR.uswrdy.p
|
||||
* empty 00..0...1...00 -> 010.000000.0
|
||||
* prot-none, clean, old 00..1...1...00 -> 111.000000.1
|
||||
* prot-none, clean, young 01..1...1...00 -> 111.000001.1
|
||||
* prot-none, dirty, old 10..1...1...00 -> 111.000010.1
|
||||
* prot-none, dirty, young 11..1...1...00 -> 111.000011.1
|
||||
* read-only, clean, old 00..1...1...01 -> 111.000100.1
|
||||
* read-only, clean, young 01..1...0...01 -> 101.000101.1
|
||||
* read-only, dirty, old 10..1...1...01 -> 111.000110.1
|
||||
* read-only, dirty, young 11..1...0...01 -> 101.000111.1
|
||||
* read-write, clean, old 00..1...1...11 -> 111.001100.1
|
||||
* read-write, clean, young 01..1...0...11 -> 101.001101.1
|
||||
* read-write, dirty, old 10..0...1...11 -> 110.001110.1
|
||||
* read-write, dirty, young 11..0...0...11 -> 100.001111.1
|
||||
* HW-bits: R read-only, I invalid
|
||||
* SW-bits: p present, y young, d dirty, r read, w write, s special,
|
||||
* u unused, l large
|
||||
*/
|
||||
if (pmd_present(pmd)) {
|
||||
pte_val(pte) = pmd_val(pmd) & _SEGMENT_ENTRY_ORIGIN_LARGE;
|
||||
|
@ -70,8 +76,8 @@ static inline pte_t __pmd_to_pte(pmd_t pmd)
|
|||
pte_val(pte) |= (pmd_val(pmd) & _SEGMENT_ENTRY_WRITE) << 4;
|
||||
pte_val(pte) |= (pmd_val(pmd) & _SEGMENT_ENTRY_INVALID) << 5;
|
||||
pte_val(pte) |= (pmd_val(pmd) & _SEGMENT_ENTRY_PROTECT);
|
||||
pmd_val(pmd) |= (pte_val(pte) & _PAGE_DIRTY) << 10;
|
||||
pmd_val(pmd) |= (pte_val(pte) & _PAGE_YOUNG) << 10;
|
||||
pte_val(pte) |= (pmd_val(pmd) & _SEGMENT_ENTRY_DIRTY) >> 10;
|
||||
pte_val(pte) |= (pmd_val(pmd) & _SEGMENT_ENTRY_YOUNG) >> 10;
|
||||
} else
|
||||
pte_val(pte) = _PAGE_INVALID;
|
||||
return pte;
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include <linux/rcupdate.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/swapops.h>
|
||||
#include <linux/sysctl.h>
|
||||
#include <linux/ksm.h>
|
||||
#include <linux/mman.h>
|
||||
|
||||
|
@ -920,6 +921,40 @@ unsigned long get_guest_storage_key(struct mm_struct *mm, unsigned long addr)
|
|||
}
|
||||
EXPORT_SYMBOL(get_guest_storage_key);
|
||||
|
||||
static int page_table_allocate_pgste_min = 0;
|
||||
static int page_table_allocate_pgste_max = 1;
|
||||
int page_table_allocate_pgste = 0;
|
||||
EXPORT_SYMBOL(page_table_allocate_pgste);
|
||||
|
||||
static struct ctl_table page_table_sysctl[] = {
|
||||
{
|
||||
.procname = "allocate_pgste",
|
||||
.data = &page_table_allocate_pgste,
|
||||
.maxlen = sizeof(int),
|
||||
.mode = S_IRUGO | S_IWUSR,
|
||||
.proc_handler = proc_dointvec,
|
||||
.extra1 = &page_table_allocate_pgste_min,
|
||||
.extra2 = &page_table_allocate_pgste_max,
|
||||
},
|
||||
{ }
|
||||
};
|
||||
|
||||
static struct ctl_table page_table_sysctl_dir[] = {
|
||||
{
|
||||
.procname = "vm",
|
||||
.maxlen = 0,
|
||||
.mode = 0555,
|
||||
.child = page_table_sysctl,
|
||||
},
|
||||
{ }
|
||||
};
|
||||
|
||||
static int __init page_table_register_sysctl(void)
|
||||
{
|
||||
return register_sysctl_table(page_table_sysctl_dir) ? 0 : -ENOMEM;
|
||||
}
|
||||
__initcall(page_table_register_sysctl);
|
||||
|
||||
#else /* CONFIG_PGSTE */
|
||||
|
||||
static inline int page_table_with_pgste(struct page *page)
|
||||
|
@ -963,7 +998,7 @@ unsigned long *page_table_alloc(struct mm_struct *mm)
|
|||
struct page *uninitialized_var(page);
|
||||
unsigned int mask, bit;
|
||||
|
||||
if (mm_has_pgste(mm))
|
||||
if (mm_alloc_pgste(mm))
|
||||
return page_table_alloc_pgste(mm);
|
||||
/* Allocate fragments of a 4K page as 1K/2K page table */
|
||||
spin_lock_bh(&mm->context.list_lock);
|
||||
|
@ -1165,116 +1200,25 @@ static inline void thp_split_mm(struct mm_struct *mm)
|
|||
}
|
||||
#endif /* CONFIG_TRANSPARENT_HUGEPAGE */
|
||||
|
||||
static unsigned long page_table_realloc_pmd(struct mmu_gather *tlb,
|
||||
struct mm_struct *mm, pud_t *pud,
|
||||
unsigned long addr, unsigned long end)
|
||||
{
|
||||
unsigned long next, *table, *new;
|
||||
struct page *page;
|
||||
spinlock_t *ptl;
|
||||
pmd_t *pmd;
|
||||
|
||||
pmd = pmd_offset(pud, addr);
|
||||
do {
|
||||
next = pmd_addr_end(addr, end);
|
||||
again:
|
||||
if (pmd_none_or_clear_bad(pmd))
|
||||
continue;
|
||||
table = (unsigned long *) pmd_deref(*pmd);
|
||||
page = pfn_to_page(__pa(table) >> PAGE_SHIFT);
|
||||
if (page_table_with_pgste(page))
|
||||
continue;
|
||||
/* Allocate new page table with pgstes */
|
||||
new = page_table_alloc_pgste(mm);
|
||||
if (!new)
|
||||
return -ENOMEM;
|
||||
|
||||
ptl = pmd_lock(mm, pmd);
|
||||
if (likely((unsigned long *) pmd_deref(*pmd) == table)) {
|
||||
/* Nuke pmd entry pointing to the "short" page table */
|
||||
pmdp_flush_lazy(mm, addr, pmd);
|
||||
pmd_clear(pmd);
|
||||
/* Copy ptes from old table to new table */
|
||||
memcpy(new, table, PAGE_SIZE/2);
|
||||
clear_table(table, _PAGE_INVALID, PAGE_SIZE/2);
|
||||
/* Establish new table */
|
||||
pmd_populate(mm, pmd, (pte_t *) new);
|
||||
/* Free old table with rcu, there might be a walker! */
|
||||
page_table_free_rcu(tlb, table, addr);
|
||||
new = NULL;
|
||||
}
|
||||
spin_unlock(ptl);
|
||||
if (new) {
|
||||
page_table_free_pgste(new);
|
||||
goto again;
|
||||
}
|
||||
} while (pmd++, addr = next, addr != end);
|
||||
|
||||
return addr;
|
||||
}
|
||||
|
||||
static unsigned long page_table_realloc_pud(struct mmu_gather *tlb,
|
||||
struct mm_struct *mm, pgd_t *pgd,
|
||||
unsigned long addr, unsigned long end)
|
||||
{
|
||||
unsigned long next;
|
||||
pud_t *pud;
|
||||
|
||||
pud = pud_offset(pgd, addr);
|
||||
do {
|
||||
next = pud_addr_end(addr, end);
|
||||
if (pud_none_or_clear_bad(pud))
|
||||
continue;
|
||||
next = page_table_realloc_pmd(tlb, mm, pud, addr, next);
|
||||
if (unlikely(IS_ERR_VALUE(next)))
|
||||
return next;
|
||||
} while (pud++, addr = next, addr != end);
|
||||
|
||||
return addr;
|
||||
}
|
||||
|
||||
static unsigned long page_table_realloc(struct mmu_gather *tlb, struct mm_struct *mm,
|
||||
unsigned long addr, unsigned long end)
|
||||
{
|
||||
unsigned long next;
|
||||
pgd_t *pgd;
|
||||
|
||||
pgd = pgd_offset(mm, addr);
|
||||
do {
|
||||
next = pgd_addr_end(addr, end);
|
||||
if (pgd_none_or_clear_bad(pgd))
|
||||
continue;
|
||||
next = page_table_realloc_pud(tlb, mm, pgd, addr, next);
|
||||
if (unlikely(IS_ERR_VALUE(next)))
|
||||
return next;
|
||||
} while (pgd++, addr = next, addr != end);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* switch on pgstes for its userspace process (for kvm)
|
||||
*/
|
||||
int s390_enable_sie(void)
|
||||
{
|
||||
struct task_struct *tsk = current;
|
||||
struct mm_struct *mm = tsk->mm;
|
||||
struct mmu_gather tlb;
|
||||
struct mm_struct *mm = current->mm;
|
||||
|
||||
/* Do we have pgstes? if yes, we are done */
|
||||
if (mm_has_pgste(tsk->mm))
|
||||
if (mm_has_pgste(mm))
|
||||
return 0;
|
||||
|
||||
/* Fail if the page tables are 2K */
|
||||
if (!mm_alloc_pgste(mm))
|
||||
return -EINVAL;
|
||||
down_write(&mm->mmap_sem);
|
||||
mm->context.has_pgste = 1;
|
||||
/* split thp mappings and disable thp for future mappings */
|
||||
thp_split_mm(mm);
|
||||
/* Reallocate the page tables with pgstes */
|
||||
tlb_gather_mmu(&tlb, mm, 0, TASK_SIZE);
|
||||
if (!page_table_realloc(&tlb, mm, 0, TASK_SIZE))
|
||||
mm->context.has_pgste = 1;
|
||||
tlb_finish_mmu(&tlb, 0, TASK_SIZE);
|
||||
up_write(&mm->mmap_sem);
|
||||
return mm->context.has_pgste ? 0 : -ENOMEM;
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(s390_enable_sie);
|
||||
|
||||
|
|
|
@ -774,7 +774,7 @@ static void __init zone_sizes_init(void)
|
|||
* though, there'll be no lowmem, so we just alloc_bootmem
|
||||
* the memmap. There will be no percpu memory either.
|
||||
*/
|
||||
if (i != 0 && cpumask_test_cpu(i, &isolnodes)) {
|
||||
if (i != 0 && node_isset(i, isolnodes)) {
|
||||
node_memmap_pfn[i] =
|
||||
alloc_bootmem_pfn(0, memmap_size, 0);
|
||||
BUG_ON(node_percpu[i] != 0);
|
||||
|
|
|
@ -95,7 +95,6 @@ unsigned __pvclock_read_cycles(const struct pvclock_vcpu_time_info *src,
|
|||
|
||||
struct pvclock_vsyscall_time_info {
|
||||
struct pvclock_vcpu_time_info pvti;
|
||||
u32 migrate_count;
|
||||
} __attribute__((__aligned__(SMP_CACHE_BYTES)));
|
||||
|
||||
#define PVTI_SIZE sizeof(struct pvclock_vsyscall_time_info)
|
||||
|
|
|
@ -141,46 +141,7 @@ void pvclock_read_wallclock(struct pvclock_wall_clock *wall_clock,
|
|||
set_normalized_timespec(ts, now.tv_sec, now.tv_nsec);
|
||||
}
|
||||
|
||||
static struct pvclock_vsyscall_time_info *pvclock_vdso_info;
|
||||
|
||||
static struct pvclock_vsyscall_time_info *
|
||||
pvclock_get_vsyscall_user_time_info(int cpu)
|
||||
{
|
||||
if (!pvclock_vdso_info) {
|
||||
BUG();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return &pvclock_vdso_info[cpu];
|
||||
}
|
||||
|
||||
struct pvclock_vcpu_time_info *pvclock_get_vsyscall_time_info(int cpu)
|
||||
{
|
||||
return &pvclock_get_vsyscall_user_time_info(cpu)->pvti;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_X86_64
|
||||
static int pvclock_task_migrate(struct notifier_block *nb, unsigned long l,
|
||||
void *v)
|
||||
{
|
||||
struct task_migration_notifier *mn = v;
|
||||
struct pvclock_vsyscall_time_info *pvti;
|
||||
|
||||
pvti = pvclock_get_vsyscall_user_time_info(mn->from_cpu);
|
||||
|
||||
/* this is NULL when pvclock vsyscall is not initialized */
|
||||
if (unlikely(pvti == NULL))
|
||||
return NOTIFY_DONE;
|
||||
|
||||
pvti->migrate_count++;
|
||||
|
||||
return NOTIFY_DONE;
|
||||
}
|
||||
|
||||
static struct notifier_block pvclock_migrate = {
|
||||
.notifier_call = pvclock_task_migrate,
|
||||
};
|
||||
|
||||
/*
|
||||
* Initialize the generic pvclock vsyscall state. This will allocate
|
||||
* a/some page(s) for the per-vcpu pvclock information, set up a
|
||||
|
@ -194,17 +155,12 @@ int __init pvclock_init_vsyscall(struct pvclock_vsyscall_time_info *i,
|
|||
|
||||
WARN_ON (size != PVCLOCK_VSYSCALL_NR_PAGES*PAGE_SIZE);
|
||||
|
||||
pvclock_vdso_info = i;
|
||||
|
||||
for (idx = 0; idx <= (PVCLOCK_FIXMAP_END-PVCLOCK_FIXMAP_BEGIN); idx++) {
|
||||
__set_fixmap(PVCLOCK_FIXMAP_BEGIN + idx,
|
||||
__pa(i) + (idx*PAGE_SIZE),
|
||||
PAGE_KERNEL_VVAR);
|
||||
}
|
||||
|
||||
|
||||
register_task_migration_notifier(&pvclock_migrate);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -1669,12 +1669,28 @@ static int kvm_guest_time_update(struct kvm_vcpu *v)
|
|||
&guest_hv_clock, sizeof(guest_hv_clock))))
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* The interface expects us to write an even number signaling that the
|
||||
* update is finished. Since the guest won't see the intermediate
|
||||
* state, we just increase by 2 at the end.
|
||||
/* This VCPU is paused, but it's legal for a guest to read another
|
||||
* VCPU's kvmclock, so we really have to follow the specification where
|
||||
* it says that version is odd if data is being modified, and even after
|
||||
* it is consistent.
|
||||
*
|
||||
* Version field updates must be kept separate. This is because
|
||||
* kvm_write_guest_cached might use a "rep movs" instruction, and
|
||||
* writes within a string instruction are weakly ordered. So there
|
||||
* are three writes overall.
|
||||
*
|
||||
* As a small optimization, only write the version field in the first
|
||||
* and third write. The vcpu->pv_time cache is still valid, because the
|
||||
* version field is the first in the struct.
|
||||
*/
|
||||
vcpu->hv_clock.version = guest_hv_clock.version + 2;
|
||||
BUILD_BUG_ON(offsetof(struct pvclock_vcpu_time_info, version) != 0);
|
||||
|
||||
vcpu->hv_clock.version = guest_hv_clock.version + 1;
|
||||
kvm_write_guest_cached(v->kvm, &vcpu->pv_time,
|
||||
&vcpu->hv_clock,
|
||||
sizeof(vcpu->hv_clock.version));
|
||||
|
||||
smp_wmb();
|
||||
|
||||
/* retain PVCLOCK_GUEST_STOPPED if set in guest copy */
|
||||
pvclock_flags = (guest_hv_clock.flags & PVCLOCK_GUEST_STOPPED);
|
||||
|
@ -1695,6 +1711,13 @@ static int kvm_guest_time_update(struct kvm_vcpu *v)
|
|||
kvm_write_guest_cached(v->kvm, &vcpu->pv_time,
|
||||
&vcpu->hv_clock,
|
||||
sizeof(vcpu->hv_clock));
|
||||
|
||||
smp_wmb();
|
||||
|
||||
vcpu->hv_clock.version++;
|
||||
kvm_write_guest_cached(v->kvm, &vcpu->pv_time,
|
||||
&vcpu->hv_clock,
|
||||
sizeof(vcpu->hv_clock.version));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -82,15 +82,18 @@ static notrace cycle_t vread_pvclock(int *mode)
|
|||
cycle_t ret;
|
||||
u64 last;
|
||||
u32 version;
|
||||
u32 migrate_count;
|
||||
u8 flags;
|
||||
unsigned cpu, cpu1;
|
||||
|
||||
|
||||
/*
|
||||
* When looping to get a consistent (time-info, tsc) pair, we
|
||||
* also need to deal with the possibility we can switch vcpus,
|
||||
* so make sure we always re-fetch time-info for the current vcpu.
|
||||
* Note: hypervisor must guarantee that:
|
||||
* 1. cpu ID number maps 1:1 to per-CPU pvclock time info.
|
||||
* 2. that per-CPU pvclock time info is updated if the
|
||||
* underlying CPU changes.
|
||||
* 3. that version is increased whenever underlying CPU
|
||||
* changes.
|
||||
*
|
||||
*/
|
||||
do {
|
||||
cpu = __getcpu() & VGETCPU_CPU_MASK;
|
||||
|
@ -99,27 +102,20 @@ static notrace cycle_t vread_pvclock(int *mode)
|
|||
* __getcpu() calls (Gleb).
|
||||
*/
|
||||
|
||||
/* Make sure migrate_count will change if we leave the VCPU. */
|
||||
do {
|
||||
pvti = get_pvti(cpu);
|
||||
migrate_count = pvti->migrate_count;
|
||||
|
||||
cpu1 = cpu;
|
||||
cpu = __getcpu() & VGETCPU_CPU_MASK;
|
||||
} while (unlikely(cpu != cpu1));
|
||||
pvti = get_pvti(cpu);
|
||||
|
||||
version = __pvclock_read_cycles(&pvti->pvti, &ret, &flags);
|
||||
|
||||
/*
|
||||
* Test we're still on the cpu as well as the version.
|
||||
* - We must read TSC of pvti's VCPU.
|
||||
* - KVM doesn't follow the versioning protocol, so data could
|
||||
* change before version if we left the VCPU.
|
||||
* We could have been migrated just after the first
|
||||
* vgetcpu but before fetching the version, so we
|
||||
* wouldn't notice a version change.
|
||||
*/
|
||||
smp_rmb();
|
||||
} while (unlikely((pvti->pvti.version & 1) ||
|
||||
pvti->pvti.version != version ||
|
||||
pvti->migrate_count != migrate_count));
|
||||
cpu1 = __getcpu() & VGETCPU_CPU_MASK;
|
||||
} while (unlikely(cpu != cpu1 ||
|
||||
(pvti->pvti.version & 1) ||
|
||||
pvti->pvti.version != version));
|
||||
|
||||
if (unlikely(!(flags & PVCLOCK_TSC_STABLE_BIT)))
|
||||
*mode = VCLOCK_NONE;
|
||||
|
|
|
@ -684,7 +684,7 @@ static int acpi_sbs_add(struct acpi_device *device)
|
|||
if (!sbs_manager_broken) {
|
||||
result = acpi_manager_get_info(sbs);
|
||||
if (!result) {
|
||||
sbs->manager_present = 0;
|
||||
sbs->manager_present = 1;
|
||||
for (id = 0; id < MAX_SBS_BAT; ++id)
|
||||
if ((sbs->batteries_supported & (1 << id)))
|
||||
acpi_battery_add(sbs, id);
|
||||
|
|
|
@ -2264,6 +2264,11 @@ static bool rbd_img_obj_end_request(struct rbd_obj_request *obj_request)
|
|||
result, xferred);
|
||||
if (!img_request->result)
|
||||
img_request->result = result;
|
||||
/*
|
||||
* Need to end I/O on the entire obj_request worth of
|
||||
* bytes in case of error.
|
||||
*/
|
||||
xferred = obj_request->length;
|
||||
}
|
||||
|
||||
/* Image object requests don't own their page array */
|
||||
|
|
|
@ -158,9 +158,18 @@ int cpuidle_enter_state(struct cpuidle_device *dev, struct cpuidle_driver *drv,
|
|||
int entered_state;
|
||||
|
||||
struct cpuidle_state *target_state = &drv->states[index];
|
||||
bool broadcast = !!(target_state->flags & CPUIDLE_FLAG_TIMER_STOP);
|
||||
ktime_t time_start, time_end;
|
||||
s64 diff;
|
||||
|
||||
/*
|
||||
* Tell the time framework to switch to a broadcast timer because our
|
||||
* local timer will be shut down. If a local timer is used from another
|
||||
* CPU as a broadcast timer, this call may fail if it is not available.
|
||||
*/
|
||||
if (broadcast && tick_broadcast_enter())
|
||||
return -EBUSY;
|
||||
|
||||
trace_cpu_idle_rcuidle(index, dev->cpu);
|
||||
time_start = ktime_get();
|
||||
|
||||
|
@ -169,6 +178,13 @@ int cpuidle_enter_state(struct cpuidle_device *dev, struct cpuidle_driver *drv,
|
|||
time_end = ktime_get();
|
||||
trace_cpu_idle_rcuidle(PWR_EVENT_EXIT, dev->cpu);
|
||||
|
||||
if (broadcast) {
|
||||
if (WARN_ON_ONCE(!irqs_disabled()))
|
||||
local_irq_disable();
|
||||
|
||||
tick_broadcast_exit();
|
||||
}
|
||||
|
||||
if (!cpuidle_state_is_coupled(dev, drv, entered_state))
|
||||
local_irq_enable();
|
||||
|
||||
|
|
|
@ -1298,21 +1298,22 @@ static int table_load(struct dm_ioctl *param, size_t param_size)
|
|||
goto err_unlock_md_type;
|
||||
}
|
||||
|
||||
if (dm_get_md_type(md) == DM_TYPE_NONE)
|
||||
if (dm_get_md_type(md) == DM_TYPE_NONE) {
|
||||
/* Initial table load: acquire type of table. */
|
||||
dm_set_md_type(md, dm_table_get_type(t));
|
||||
else if (dm_get_md_type(md) != dm_table_get_type(t)) {
|
||||
|
||||
/* setup md->queue to reflect md's type (may block) */
|
||||
r = dm_setup_md_queue(md);
|
||||
if (r) {
|
||||
DMWARN("unable to set up device queue for new table.");
|
||||
goto err_unlock_md_type;
|
||||
}
|
||||
} else if (dm_get_md_type(md) != dm_table_get_type(t)) {
|
||||
DMWARN("can't change device type after initial table load.");
|
||||
r = -EINVAL;
|
||||
goto err_unlock_md_type;
|
||||
}
|
||||
|
||||
/* setup md->queue to reflect md's type (may block) */
|
||||
r = dm_setup_md_queue(md);
|
||||
if (r) {
|
||||
DMWARN("unable to set up device queue for new table.");
|
||||
goto err_unlock_md_type;
|
||||
}
|
||||
dm_unlock_md_type(md);
|
||||
|
||||
/* stage inactive table */
|
||||
|
|
|
@ -1082,18 +1082,26 @@ static void rq_completed(struct mapped_device *md, int rw, bool run_queue)
|
|||
dm_put(md);
|
||||
}
|
||||
|
||||
static void free_rq_clone(struct request *clone)
|
||||
static void free_rq_clone(struct request *clone, bool must_be_mapped)
|
||||
{
|
||||
struct dm_rq_target_io *tio = clone->end_io_data;
|
||||
struct mapped_device *md = tio->md;
|
||||
|
||||
WARN_ON_ONCE(must_be_mapped && !clone->q);
|
||||
|
||||
blk_rq_unprep_clone(clone);
|
||||
|
||||
if (clone->q->mq_ops)
|
||||
if (md->type == DM_TYPE_MQ_REQUEST_BASED)
|
||||
/* stacked on blk-mq queue(s) */
|
||||
tio->ti->type->release_clone_rq(clone);
|
||||
else if (!md->queue->mq_ops)
|
||||
/* request_fn queue stacked on request_fn queue(s) */
|
||||
free_clone_request(md, clone);
|
||||
/*
|
||||
* NOTE: for the blk-mq queue stacked on request_fn queue(s) case:
|
||||
* no need to call free_clone_request() because we leverage blk-mq by
|
||||
* allocating the clone at the end of the blk-mq pdu (see: clone_rq)
|
||||
*/
|
||||
|
||||
if (!md->queue->mq_ops)
|
||||
free_rq_tio(tio);
|
||||
|
@ -1124,7 +1132,7 @@ static void dm_end_request(struct request *clone, int error)
|
|||
rq->sense_len = clone->sense_len;
|
||||
}
|
||||
|
||||
free_rq_clone(clone);
|
||||
free_rq_clone(clone, true);
|
||||
if (!rq->q->mq_ops)
|
||||
blk_end_request_all(rq, error);
|
||||
else
|
||||
|
@ -1143,7 +1151,7 @@ static void dm_unprep_request(struct request *rq)
|
|||
}
|
||||
|
||||
if (clone)
|
||||
free_rq_clone(clone);
|
||||
free_rq_clone(clone, false);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -2662,9 +2670,6 @@ static int dm_init_request_based_queue(struct mapped_device *md)
|
|||
{
|
||||
struct request_queue *q = NULL;
|
||||
|
||||
if (md->queue->elevator)
|
||||
return 0;
|
||||
|
||||
/* Fully initialize the queue */
|
||||
q = blk_init_allocated_queue(md->queue, dm_request_fn, NULL);
|
||||
if (!q)
|
||||
|
|
|
@ -4544,6 +4544,8 @@ unsigned int bond_get_num_tx_queues(void)
|
|||
int bond_create(struct net *net, const char *name)
|
||||
{
|
||||
struct net_device *bond_dev;
|
||||
struct bonding *bond;
|
||||
struct alb_bond_info *bond_info;
|
||||
int res;
|
||||
|
||||
rtnl_lock();
|
||||
|
@ -4557,6 +4559,14 @@ int bond_create(struct net *net, const char *name)
|
|||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize rx_hashtbl_used_head to RLB_NULL_INDEX.
|
||||
* It is set to 0 by default which is wrong.
|
||||
*/
|
||||
bond = netdev_priv(bond_dev);
|
||||
bond_info = &(BOND_ALB_INFO(bond));
|
||||
bond_info->rx_hashtbl_used_head = RLB_NULL_INDEX;
|
||||
|
||||
dev_net_set(bond_dev, net);
|
||||
bond_dev->rtnl_link_ops = &bond_link_ops;
|
||||
|
||||
|
|
|
@ -391,6 +391,12 @@ static int tse_rx(struct altera_tse_private *priv, int limit)
|
|||
"RCV pktstatus %08X pktlength %08X\n",
|
||||
pktstatus, pktlength);
|
||||
|
||||
/* DMA trasfer from TSE starts with 2 aditional bytes for
|
||||
* IP payload alignment. Status returned by get_rx_status()
|
||||
* contains DMA transfer length. Packet is 2 bytes shorter.
|
||||
*/
|
||||
pktlength -= 2;
|
||||
|
||||
count++;
|
||||
next_entry = (++priv->rx_cons) % priv->rx_ring_size;
|
||||
|
||||
|
|
|
@ -129,7 +129,7 @@ s32 atl1e_restart_autoneg(struct atl1e_hw *hw);
|
|||
#define TWSI_CTRL_LD_SLV_ADDR_SHIFT 8
|
||||
#define TWSI_CTRL_SW_LDSTART 0x800
|
||||
#define TWSI_CTRL_HW_LDSTART 0x1000
|
||||
#define TWSI_CTRL_SMB_SLV_ADDR_MASK 0x0x7F
|
||||
#define TWSI_CTRL_SMB_SLV_ADDR_MASK 0x7F
|
||||
#define TWSI_CTRL_SMB_SLV_ADDR_SHIFT 15
|
||||
#define TWSI_CTRL_LD_EXIST 0x400000
|
||||
#define TWSI_CTRL_READ_FREQ_SEL_MASK 0x3
|
||||
|
|
|
@ -543,7 +543,7 @@ struct bcm_sysport_tx_counters {
|
|||
u32 jbr; /* RO # of xmited jabber count*/
|
||||
u32 bytes; /* RO # of xmited byte count */
|
||||
u32 pok; /* RO # of xmited good pkt */
|
||||
u32 uc; /* RO (0x0x4f0)# of xmited unitcast pkt */
|
||||
u32 uc; /* RO (0x4f0) # of xmited unicast pkt */
|
||||
};
|
||||
|
||||
struct bcm_sysport_mib {
|
||||
|
|
|
@ -521,6 +521,7 @@ struct bnx2x_fp_txdata {
|
|||
};
|
||||
|
||||
enum bnx2x_tpa_mode_t {
|
||||
TPA_MODE_DISABLED,
|
||||
TPA_MODE_LRO,
|
||||
TPA_MODE_GRO
|
||||
};
|
||||
|
@ -589,7 +590,6 @@ struct bnx2x_fastpath {
|
|||
|
||||
/* TPA related */
|
||||
struct bnx2x_agg_info *tpa_info;
|
||||
u8 disable_tpa;
|
||||
#ifdef BNX2X_STOP_ON_ERROR
|
||||
u64 tpa_queue_used;
|
||||
#endif
|
||||
|
@ -1545,9 +1545,7 @@ struct bnx2x {
|
|||
#define USING_MSIX_FLAG (1 << 5)
|
||||
#define USING_MSI_FLAG (1 << 6)
|
||||
#define DISABLE_MSI_FLAG (1 << 7)
|
||||
#define TPA_ENABLE_FLAG (1 << 8)
|
||||
#define NO_MCP_FLAG (1 << 9)
|
||||
#define GRO_ENABLE_FLAG (1 << 10)
|
||||
#define MF_FUNC_DIS (1 << 11)
|
||||
#define OWN_CNIC_IRQ (1 << 12)
|
||||
#define NO_ISCSI_OOO_FLAG (1 << 13)
|
||||
|
|
|
@ -947,10 +947,10 @@ static int bnx2x_rx_int(struct bnx2x_fastpath *fp, int budget)
|
|||
u16 frag_size, pages;
|
||||
#ifdef BNX2X_STOP_ON_ERROR
|
||||
/* sanity check */
|
||||
if (fp->disable_tpa &&
|
||||
if (fp->mode == TPA_MODE_DISABLED &&
|
||||
(CQE_TYPE_START(cqe_fp_type) ||
|
||||
CQE_TYPE_STOP(cqe_fp_type)))
|
||||
BNX2X_ERR("START/STOP packet while disable_tpa type %x\n",
|
||||
BNX2X_ERR("START/STOP packet while TPA disabled, type %x\n",
|
||||
CQE_TYPE(cqe_fp_type));
|
||||
#endif
|
||||
|
||||
|
@ -1396,7 +1396,7 @@ void bnx2x_init_rx_rings(struct bnx2x *bp)
|
|||
DP(NETIF_MSG_IFUP,
|
||||
"mtu %d rx_buf_size %d\n", bp->dev->mtu, fp->rx_buf_size);
|
||||
|
||||
if (!fp->disable_tpa) {
|
||||
if (fp->mode != TPA_MODE_DISABLED) {
|
||||
/* Fill the per-aggregation pool */
|
||||
for (i = 0; i < MAX_AGG_QS(bp); i++) {
|
||||
struct bnx2x_agg_info *tpa_info =
|
||||
|
@ -1410,7 +1410,7 @@ void bnx2x_init_rx_rings(struct bnx2x *bp)
|
|||
BNX2X_ERR("Failed to allocate TPA skb pool for queue[%d] - disabling TPA on this queue!\n",
|
||||
j);
|
||||
bnx2x_free_tpa_pool(bp, fp, i);
|
||||
fp->disable_tpa = 1;
|
||||
fp->mode = TPA_MODE_DISABLED;
|
||||
break;
|
||||
}
|
||||
dma_unmap_addr_set(first_buf, mapping, 0);
|
||||
|
@ -1438,7 +1438,7 @@ void bnx2x_init_rx_rings(struct bnx2x *bp)
|
|||
ring_prod);
|
||||
bnx2x_free_tpa_pool(bp, fp,
|
||||
MAX_AGG_QS(bp));
|
||||
fp->disable_tpa = 1;
|
||||
fp->mode = TPA_MODE_DISABLED;
|
||||
ring_prod = 0;
|
||||
break;
|
||||
}
|
||||
|
@ -1560,7 +1560,7 @@ static void bnx2x_free_rx_skbs(struct bnx2x *bp)
|
|||
|
||||
bnx2x_free_rx_bds(fp);
|
||||
|
||||
if (!fp->disable_tpa)
|
||||
if (fp->mode != TPA_MODE_DISABLED)
|
||||
bnx2x_free_tpa_pool(bp, fp, MAX_AGG_QS(bp));
|
||||
}
|
||||
}
|
||||
|
@ -2477,19 +2477,19 @@ static void bnx2x_bz_fp(struct bnx2x *bp, int index)
|
|||
/* set the tpa flag for each queue. The tpa flag determines the queue
|
||||
* minimal size so it must be set prior to queue memory allocation
|
||||
*/
|
||||
fp->disable_tpa = !(bp->flags & TPA_ENABLE_FLAG ||
|
||||
(bp->flags & GRO_ENABLE_FLAG &&
|
||||
bnx2x_mtu_allows_gro(bp->dev->mtu)));
|
||||
if (bp->flags & TPA_ENABLE_FLAG)
|
||||
if (bp->dev->features & NETIF_F_LRO)
|
||||
fp->mode = TPA_MODE_LRO;
|
||||
else if (bp->flags & GRO_ENABLE_FLAG)
|
||||
else if (bp->dev->features & NETIF_F_GRO &&
|
||||
bnx2x_mtu_allows_gro(bp->dev->mtu))
|
||||
fp->mode = TPA_MODE_GRO;
|
||||
else
|
||||
fp->mode = TPA_MODE_DISABLED;
|
||||
|
||||
/* We don't want TPA if it's disabled in bp
|
||||
* or if this is an FCoE L2 ring.
|
||||
*/
|
||||
if (bp->disable_tpa || IS_FCOE_FP(fp))
|
||||
fp->disable_tpa = 1;
|
||||
fp->mode = TPA_MODE_DISABLED;
|
||||
}
|
||||
|
||||
int bnx2x_load_cnic(struct bnx2x *bp)
|
||||
|
@ -2610,7 +2610,7 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
|
|||
/*
|
||||
* Zero fastpath structures preserving invariants like napi, which are
|
||||
* allocated only once, fp index, max_cos, bp pointer.
|
||||
* Also set fp->disable_tpa and txdata_ptr.
|
||||
* Also set fp->mode and txdata_ptr.
|
||||
*/
|
||||
DP(NETIF_MSG_IFUP, "num queues: %d", bp->num_queues);
|
||||
for_each_queue(bp, i)
|
||||
|
@ -3249,7 +3249,7 @@ int bnx2x_low_latency_recv(struct napi_struct *napi)
|
|||
|
||||
if ((bp->state == BNX2X_STATE_CLOSED) ||
|
||||
(bp->state == BNX2X_STATE_ERROR) ||
|
||||
(bp->flags & (TPA_ENABLE_FLAG | GRO_ENABLE_FLAG)))
|
||||
(bp->dev->features & (NETIF_F_LRO | NETIF_F_GRO)))
|
||||
return LL_FLUSH_FAILED;
|
||||
|
||||
if (!bnx2x_fp_lock_poll(fp))
|
||||
|
@ -4545,7 +4545,7 @@ alloc_mem_err:
|
|||
* In these cases we disable the queue
|
||||
* Min size is different for OOO, TPA and non-TPA queues
|
||||
*/
|
||||
if (ring_size < (fp->disable_tpa ?
|
||||
if (ring_size < (fp->mode == TPA_MODE_DISABLED ?
|
||||
MIN_RX_SIZE_NONTPA : MIN_RX_SIZE_TPA)) {
|
||||
/* release memory allocated for this queue */
|
||||
bnx2x_free_fp_mem_at(bp, index);
|
||||
|
@ -4834,29 +4834,15 @@ netdev_features_t bnx2x_fix_features(struct net_device *dev,
|
|||
features &= ~NETIF_F_GRO;
|
||||
}
|
||||
|
||||
/* Note: do not disable SW GRO in kernel when HW GRO is off */
|
||||
if (bp->disable_tpa)
|
||||
features &= ~NETIF_F_LRO;
|
||||
|
||||
return features;
|
||||
}
|
||||
|
||||
int bnx2x_set_features(struct net_device *dev, netdev_features_t features)
|
||||
{
|
||||
struct bnx2x *bp = netdev_priv(dev);
|
||||
u32 flags = bp->flags;
|
||||
u32 changes;
|
||||
netdev_features_t changes = features ^ dev->features;
|
||||
bool bnx2x_reload = false;
|
||||
|
||||
if (features & NETIF_F_LRO)
|
||||
flags |= TPA_ENABLE_FLAG;
|
||||
else
|
||||
flags &= ~TPA_ENABLE_FLAG;
|
||||
|
||||
if (features & NETIF_F_GRO)
|
||||
flags |= GRO_ENABLE_FLAG;
|
||||
else
|
||||
flags &= ~GRO_ENABLE_FLAG;
|
||||
int rc;
|
||||
|
||||
/* VFs or non SRIOV PFs should be able to change loopback feature */
|
||||
if (!pci_num_vf(bp->pdev)) {
|
||||
|
@ -4873,24 +4859,23 @@ int bnx2x_set_features(struct net_device *dev, netdev_features_t features)
|
|||
}
|
||||
}
|
||||
|
||||
changes = flags ^ bp->flags;
|
||||
|
||||
/* if GRO is changed while LRO is enabled, don't force a reload */
|
||||
if ((changes & GRO_ENABLE_FLAG) && (flags & TPA_ENABLE_FLAG))
|
||||
changes &= ~GRO_ENABLE_FLAG;
|
||||
if ((changes & NETIF_F_GRO) && (features & NETIF_F_LRO))
|
||||
changes &= ~NETIF_F_GRO;
|
||||
|
||||
/* if GRO is changed while HW TPA is off, don't force a reload */
|
||||
if ((changes & GRO_ENABLE_FLAG) && bp->disable_tpa)
|
||||
changes &= ~GRO_ENABLE_FLAG;
|
||||
if ((changes & NETIF_F_GRO) && bp->disable_tpa)
|
||||
changes &= ~NETIF_F_GRO;
|
||||
|
||||
if (changes)
|
||||
bnx2x_reload = true;
|
||||
|
||||
bp->flags = flags;
|
||||
|
||||
if (bnx2x_reload) {
|
||||
if (bp->recovery_state == BNX2X_RECOVERY_DONE)
|
||||
return bnx2x_reload_if_running(dev);
|
||||
if (bp->recovery_state == BNX2X_RECOVERY_DONE) {
|
||||
dev->features = features;
|
||||
rc = bnx2x_reload_if_running(dev);
|
||||
return rc ? rc : 1;
|
||||
}
|
||||
/* else: bnx2x_nic_load() will be called at end of recovery */
|
||||
}
|
||||
|
||||
|
|
|
@ -969,7 +969,7 @@ static inline void bnx2x_free_rx_sge_range(struct bnx2x *bp,
|
|||
{
|
||||
int i;
|
||||
|
||||
if (fp->disable_tpa)
|
||||
if (fp->mode == TPA_MODE_DISABLED)
|
||||
return;
|
||||
|
||||
for (i = 0; i < last; i++)
|
||||
|
|
|
@ -3128,7 +3128,7 @@ static unsigned long bnx2x_get_q_flags(struct bnx2x *bp,
|
|||
__set_bit(BNX2X_Q_FLG_FORCE_DEFAULT_PRI, &flags);
|
||||
}
|
||||
|
||||
if (!fp->disable_tpa) {
|
||||
if (fp->mode != TPA_MODE_DISABLED) {
|
||||
__set_bit(BNX2X_Q_FLG_TPA, &flags);
|
||||
__set_bit(BNX2X_Q_FLG_TPA_IPV6, &flags);
|
||||
if (fp->mode == TPA_MODE_GRO)
|
||||
|
@ -3176,7 +3176,7 @@ static void bnx2x_pf_rx_q_prep(struct bnx2x *bp,
|
|||
u16 sge_sz = 0;
|
||||
u16 tpa_agg_size = 0;
|
||||
|
||||
if (!fp->disable_tpa) {
|
||||
if (fp->mode != TPA_MODE_DISABLED) {
|
||||
pause->sge_th_lo = SGE_TH_LO(bp);
|
||||
pause->sge_th_hi = SGE_TH_HI(bp);
|
||||
|
||||
|
@ -3304,7 +3304,7 @@ static void bnx2x_pf_init(struct bnx2x *bp)
|
|||
/* This flag is relevant for E1x only.
|
||||
* E2 doesn't have a TPA configuration in a function level.
|
||||
*/
|
||||
flags |= (bp->flags & TPA_ENABLE_FLAG) ? FUNC_FLG_TPA : 0;
|
||||
flags |= (bp->dev->features & NETIF_F_LRO) ? FUNC_FLG_TPA : 0;
|
||||
|
||||
func_init.func_flgs = flags;
|
||||
func_init.pf_id = BP_FUNC(bp);
|
||||
|
@ -12107,11 +12107,8 @@ static int bnx2x_init_bp(struct bnx2x *bp)
|
|||
|
||||
/* Set TPA flags */
|
||||
if (bp->disable_tpa) {
|
||||
bp->flags &= ~(TPA_ENABLE_FLAG | GRO_ENABLE_FLAG);
|
||||
bp->dev->hw_features &= ~NETIF_F_LRO;
|
||||
bp->dev->features &= ~NETIF_F_LRO;
|
||||
} else {
|
||||
bp->flags |= (TPA_ENABLE_FLAG | GRO_ENABLE_FLAG);
|
||||
bp->dev->features |= NETIF_F_LRO;
|
||||
}
|
||||
|
||||
if (CHIP_IS_E1(bp))
|
||||
|
@ -13371,6 +13368,12 @@ static int bnx2x_init_one(struct pci_dev *pdev,
|
|||
bool is_vf;
|
||||
int cnic_cnt;
|
||||
|
||||
/* Management FW 'remembers' living interfaces. Allow it some time
|
||||
* to forget previously living interfaces, allowing a proper re-load.
|
||||
*/
|
||||
if (is_kdump_kernel())
|
||||
msleep(5000);
|
||||
|
||||
/* An estimated maximum supported CoS number according to the chip
|
||||
* version.
|
||||
* We will try to roughly estimate the maximum number of CoSes this chip
|
||||
|
|
|
@ -594,7 +594,7 @@ int bnx2x_vfpf_setup_q(struct bnx2x *bp, struct bnx2x_fastpath *fp,
|
|||
bnx2x_vfpf_prep(bp, &req->first_tlv, CHANNEL_TLV_SETUP_Q, sizeof(*req));
|
||||
|
||||
/* select tpa mode to request */
|
||||
if (!fp->disable_tpa) {
|
||||
if (fp->mode != TPA_MODE_DISABLED) {
|
||||
flags |= VFPF_QUEUE_FLG_TPA;
|
||||
flags |= VFPF_QUEUE_FLG_TPA_IPV6;
|
||||
if (fp->mode == TPA_MODE_GRO)
|
||||
|
|
|
@ -707,6 +707,9 @@ static void gem_rx_refill(struct macb *bp)
|
|||
|
||||
/* properly align Ethernet header */
|
||||
skb_reserve(skb, NET_IP_ALIGN);
|
||||
} else {
|
||||
bp->rx_ring[entry].addr &= ~MACB_BIT(RX_USED);
|
||||
bp->rx_ring[entry].ctrl = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -492,7 +492,7 @@ int t4_memory_rw(struct adapter *adap, int win, int mtype, u32 addr,
|
|||
memoffset = (mtype * (edc_size * 1024 * 1024));
|
||||
else {
|
||||
mc_size = EXT_MEM0_SIZE_G(t4_read_reg(adap,
|
||||
MA_EXT_MEMORY1_BAR_A));
|
||||
MA_EXT_MEMORY0_BAR_A));
|
||||
memoffset = (MEM_MC0 * edc_size + mc_size) * 1024 * 1024;
|
||||
}
|
||||
|
||||
|
|
|
@ -4848,7 +4848,8 @@ err:
|
|||
}
|
||||
|
||||
static int be_ndo_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq,
|
||||
struct net_device *dev, u32 filter_mask)
|
||||
struct net_device *dev, u32 filter_mask,
|
||||
int nlflags)
|
||||
{
|
||||
struct be_adapter *adapter = netdev_priv(dev);
|
||||
int status = 0;
|
||||
|
@ -4870,7 +4871,7 @@ static int be_ndo_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq,
|
|||
return ndo_dflt_bridge_getlink(skb, pid, seq, dev,
|
||||
hsw_mode == PORT_FWD_TYPE_VEPA ?
|
||||
BRIDGE_MODE_VEPA : BRIDGE_MODE_VEB,
|
||||
0, 0);
|
||||
0, 0, nlflags);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_BE2NET_VXLAN
|
||||
|
|
|
@ -988,7 +988,10 @@ fec_restart(struct net_device *ndev)
|
|||
rcntl |= 0x40000000 | 0x00000020;
|
||||
|
||||
/* RGMII, RMII or MII */
|
||||
if (fep->phy_interface == PHY_INTERFACE_MODE_RGMII)
|
||||
if (fep->phy_interface == PHY_INTERFACE_MODE_RGMII ||
|
||||
fep->phy_interface == PHY_INTERFACE_MODE_RGMII_ID ||
|
||||
fep->phy_interface == PHY_INTERFACE_MODE_RGMII_RXID ||
|
||||
fep->phy_interface == PHY_INTERFACE_MODE_RGMII_TXID)
|
||||
rcntl |= (1 << 6);
|
||||
else if (fep->phy_interface == PHY_INTERFACE_MODE_RMII)
|
||||
rcntl |= (1 << 8);
|
||||
|
|
|
@ -8053,10 +8053,10 @@ static int i40e_ndo_bridge_setlink(struct net_device *dev,
|
|||
#ifdef HAVE_BRIDGE_FILTER
|
||||
static int i40e_ndo_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq,
|
||||
struct net_device *dev,
|
||||
u32 __always_unused filter_mask)
|
||||
u32 __always_unused filter_mask, int nlflags)
|
||||
#else
|
||||
static int i40e_ndo_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq,
|
||||
struct net_device *dev)
|
||||
struct net_device *dev, int nlflags)
|
||||
#endif /* HAVE_BRIDGE_FILTER */
|
||||
{
|
||||
struct i40e_netdev_priv *np = netdev_priv(dev);
|
||||
|
@ -8078,7 +8078,8 @@ static int i40e_ndo_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq,
|
|||
if (!veb)
|
||||
return 0;
|
||||
|
||||
return ndo_dflt_bridge_getlink(skb, pid, seq, dev, veb->bridge_mode);
|
||||
return ndo_dflt_bridge_getlink(skb, pid, seq, dev, veb->bridge_mode,
|
||||
nlflags);
|
||||
}
|
||||
#endif /* HAVE_BRIDGE_ATTRIBS */
|
||||
|
||||
|
|
|
@ -8044,7 +8044,7 @@ static int ixgbe_ndo_bridge_setlink(struct net_device *dev,
|
|||
|
||||
static int ixgbe_ndo_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq,
|
||||
struct net_device *dev,
|
||||
u32 filter_mask)
|
||||
u32 filter_mask, int nlflags)
|
||||
{
|
||||
struct ixgbe_adapter *adapter = netdev_priv(dev);
|
||||
|
||||
|
@ -8052,7 +8052,7 @@ static int ixgbe_ndo_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq,
|
|||
return 0;
|
||||
|
||||
return ndo_dflt_bridge_getlink(skb, pid, seq, dev,
|
||||
adapter->bridge_mode, 0, 0);
|
||||
adapter->bridge_mode, 0, 0, nlflags);
|
||||
}
|
||||
|
||||
static void *ixgbe_fwd_add(struct net_device *pdev, struct net_device *vdev)
|
||||
|
|
|
@ -1467,6 +1467,7 @@ static void mlx4_en_service_task(struct work_struct *work)
|
|||
if (mdev->dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_TS)
|
||||
mlx4_en_ptp_overflow_check(mdev);
|
||||
|
||||
mlx4_en_recover_from_oom(priv);
|
||||
queue_delayed_work(mdev->workqueue, &priv->service_task,
|
||||
SERVICE_TASK_DELAY);
|
||||
}
|
||||
|
@ -1721,7 +1722,7 @@ mac_err:
|
|||
cq_err:
|
||||
while (rx_index--) {
|
||||
mlx4_en_deactivate_cq(priv, priv->rx_cq[rx_index]);
|
||||
mlx4_en_free_affinity_hint(priv, i);
|
||||
mlx4_en_free_affinity_hint(priv, rx_index);
|
||||
}
|
||||
for (i = 0; i < priv->rx_ring_num; i++)
|
||||
mlx4_en_deactivate_rx_ring(priv, priv->rx_ring[i]);
|
||||
|
|
|
@ -244,6 +244,12 @@ static int mlx4_en_prepare_rx_desc(struct mlx4_en_priv *priv,
|
|||
return mlx4_en_alloc_frags(priv, rx_desc, frags, ring->page_alloc, gfp);
|
||||
}
|
||||
|
||||
static inline bool mlx4_en_is_ring_empty(struct mlx4_en_rx_ring *ring)
|
||||
{
|
||||
BUG_ON((u32)(ring->prod - ring->cons) > ring->actual_size);
|
||||
return ring->prod == ring->cons;
|
||||
}
|
||||
|
||||
static inline void mlx4_en_update_rx_prod_db(struct mlx4_en_rx_ring *ring)
|
||||
{
|
||||
*ring->wqres.db.db = cpu_to_be32(ring->prod & 0xffff);
|
||||
|
@ -315,8 +321,7 @@ static void mlx4_en_free_rx_buf(struct mlx4_en_priv *priv,
|
|||
ring->cons, ring->prod);
|
||||
|
||||
/* Unmap and free Rx buffers */
|
||||
BUG_ON((u32) (ring->prod - ring->cons) > ring->actual_size);
|
||||
while (ring->cons != ring->prod) {
|
||||
while (!mlx4_en_is_ring_empty(ring)) {
|
||||
index = ring->cons & ring->size_mask;
|
||||
en_dbg(DRV, priv, "Processing descriptor:%d\n", index);
|
||||
mlx4_en_free_rx_desc(priv, ring, index);
|
||||
|
@ -491,6 +496,23 @@ err_allocator:
|
|||
return err;
|
||||
}
|
||||
|
||||
/* We recover from out of memory by scheduling our napi poll
|
||||
* function (mlx4_en_process_cq), which tries to allocate
|
||||
* all missing RX buffers (call to mlx4_en_refill_rx_buffers).
|
||||
*/
|
||||
void mlx4_en_recover_from_oom(struct mlx4_en_priv *priv)
|
||||
{
|
||||
int ring;
|
||||
|
||||
if (!priv->port_up)
|
||||
return;
|
||||
|
||||
for (ring = 0; ring < priv->rx_ring_num; ring++) {
|
||||
if (mlx4_en_is_ring_empty(priv->rx_ring[ring]))
|
||||
napi_reschedule(&priv->rx_cq[ring]->napi);
|
||||
}
|
||||
}
|
||||
|
||||
void mlx4_en_destroy_rx_ring(struct mlx4_en_priv *priv,
|
||||
struct mlx4_en_rx_ring **pring,
|
||||
u32 size, u16 stride)
|
||||
|
|
|
@ -143,8 +143,10 @@ int mlx4_en_create_tx_ring(struct mlx4_en_priv *priv,
|
|||
ring->hwtstamp_tx_type = priv->hwtstamp_config.tx_type;
|
||||
ring->queue_index = queue_index;
|
||||
|
||||
if (queue_index < priv->num_tx_rings_p_up && cpu_online(queue_index))
|
||||
cpumask_set_cpu(queue_index, &ring->affinity_mask);
|
||||
if (queue_index < priv->num_tx_rings_p_up)
|
||||
cpumask_set_cpu_local_first(queue_index,
|
||||
priv->mdev->dev->numa_node,
|
||||
&ring->affinity_mask);
|
||||
|
||||
*pring = ring;
|
||||
return 0;
|
||||
|
@ -213,7 +215,7 @@ int mlx4_en_activate_tx_ring(struct mlx4_en_priv *priv,
|
|||
|
||||
err = mlx4_qp_to_ready(mdev->dev, &ring->wqres.mtt, &ring->context,
|
||||
&ring->qp, &ring->qp_state);
|
||||
if (!user_prio && cpu_online(ring->queue_index))
|
||||
if (!cpumask_empty(&ring->affinity_mask))
|
||||
netif_set_xps_queue(priv->dev, &ring->affinity_mask,
|
||||
ring->queue_index);
|
||||
|
||||
|
|
|
@ -56,11 +56,13 @@ MODULE_PARM_DESC(enable_qos, "Enable Enhanced QoS support (default: on)");
|
|||
#define MLX4_GET(dest, source, offset) \
|
||||
do { \
|
||||
void *__p = (char *) (source) + (offset); \
|
||||
u64 val; \
|
||||
switch (sizeof (dest)) { \
|
||||
case 1: (dest) = *(u8 *) __p; break; \
|
||||
case 2: (dest) = be16_to_cpup(__p); break; \
|
||||
case 4: (dest) = be32_to_cpup(__p); break; \
|
||||
case 8: (dest) = be64_to_cpup(__p); break; \
|
||||
case 8: val = get_unaligned((u64 *)__p); \
|
||||
(dest) = be64_to_cpu(val); break; \
|
||||
default: __buggy_use_of_MLX4_GET(); \
|
||||
} \
|
||||
} while (0)
|
||||
|
@ -1605,9 +1607,17 @@ static void get_board_id(void *vsd, char *board_id)
|
|||
* swaps each 4-byte word before passing it back to
|
||||
* us. Therefore we need to swab it before printing.
|
||||
*/
|
||||
for (i = 0; i < 4; ++i)
|
||||
((u32 *) board_id)[i] =
|
||||
swab32(*(u32 *) (vsd + VSD_OFFSET_MLX_BOARD_ID + i * 4));
|
||||
u32 *bid_u32 = (u32 *)board_id;
|
||||
|
||||
for (i = 0; i < 4; ++i) {
|
||||
u32 *addr;
|
||||
u32 val;
|
||||
|
||||
addr = (u32 *) (vsd + VSD_OFFSET_MLX_BOARD_ID + i * 4);
|
||||
val = get_unaligned(addr);
|
||||
val = swab32(val);
|
||||
put_unaligned(val, &bid_u32[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -774,6 +774,7 @@ int mlx4_en_activate_tx_ring(struct mlx4_en_priv *priv,
|
|||
void mlx4_en_deactivate_tx_ring(struct mlx4_en_priv *priv,
|
||||
struct mlx4_en_tx_ring *ring);
|
||||
void mlx4_en_set_num_rx_rings(struct mlx4_en_dev *mdev);
|
||||
void mlx4_en_recover_from_oom(struct mlx4_en_priv *priv);
|
||||
int mlx4_en_create_rx_ring(struct mlx4_en_priv *priv,
|
||||
struct mlx4_en_rx_ring **pring,
|
||||
u32 size, u16 stride, int node);
|
||||
|
|
|
@ -135,7 +135,7 @@ void netxen_release_tx_buffers(struct netxen_adapter *adapter)
|
|||
int i, j;
|
||||
struct nx_host_tx_ring *tx_ring = adapter->tx_ring;
|
||||
|
||||
spin_lock(&adapter->tx_clean_lock);
|
||||
spin_lock_bh(&adapter->tx_clean_lock);
|
||||
cmd_buf = tx_ring->cmd_buf_arr;
|
||||
for (i = 0; i < tx_ring->num_desc; i++) {
|
||||
buffrag = cmd_buf->frag_array;
|
||||
|
@ -159,7 +159,7 @@ void netxen_release_tx_buffers(struct netxen_adapter *adapter)
|
|||
}
|
||||
cmd_buf++;
|
||||
}
|
||||
spin_unlock(&adapter->tx_clean_lock);
|
||||
spin_unlock_bh(&adapter->tx_clean_lock);
|
||||
}
|
||||
|
||||
void netxen_free_sw_resources(struct netxen_adapter *adapter)
|
||||
|
|
|
@ -4176,14 +4176,15 @@ static int rocker_port_bridge_setlink(struct net_device *dev,
|
|||
|
||||
static int rocker_port_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq,
|
||||
struct net_device *dev,
|
||||
u32 filter_mask)
|
||||
u32 filter_mask, int nlflags)
|
||||
{
|
||||
struct rocker_port *rocker_port = netdev_priv(dev);
|
||||
u16 mode = BRIDGE_MODE_UNDEF;
|
||||
u32 mask = BR_LEARNING | BR_LEARNING_SYNC;
|
||||
|
||||
return ndo_dflt_bridge_getlink(skb, pid, seq, dev, mode,
|
||||
rocker_port->brport_flags, mask);
|
||||
rocker_port->brport_flags, mask,
|
||||
nlflags);
|
||||
}
|
||||
|
||||
static int rocker_port_get_phys_port_name(struct net_device *dev,
|
||||
|
|
|
@ -1765,7 +1765,9 @@ static void netcp_ethss_link_state_action(struct gbe_priv *gbe_dev,
|
|||
ALE_PORT_STATE,
|
||||
ALE_PORT_STATE_FORWARD);
|
||||
|
||||
if (ndev && slave->open)
|
||||
if (ndev && slave->open &&
|
||||
slave->link_interface != SGMII_LINK_MAC_PHY &&
|
||||
slave->link_interface != XGMII_LINK_MAC_PHY)
|
||||
netif_carrier_on(ndev);
|
||||
} else {
|
||||
writel(mac_control, GBE_REG_ADDR(slave, emac_regs,
|
||||
|
@ -1773,7 +1775,9 @@ static void netcp_ethss_link_state_action(struct gbe_priv *gbe_dev,
|
|||
cpsw_ale_control_set(gbe_dev->ale, slave->port_num,
|
||||
ALE_PORT_STATE,
|
||||
ALE_PORT_STATE_DISABLE);
|
||||
if (ndev)
|
||||
if (ndev &&
|
||||
slave->link_interface != SGMII_LINK_MAC_PHY &&
|
||||
slave->link_interface != XGMII_LINK_MAC_PHY)
|
||||
netif_carrier_off(ndev);
|
||||
}
|
||||
|
||||
|
|
|
@ -128,7 +128,6 @@ struct ndis_tcp_ip_checksum_info;
|
|||
struct hv_netvsc_packet {
|
||||
/* Bookkeeping stuff */
|
||||
u32 status;
|
||||
bool part_of_skb;
|
||||
|
||||
bool is_data_pkt;
|
||||
bool xmit_more; /* from skb */
|
||||
|
@ -612,6 +611,15 @@ struct multi_send_data {
|
|||
u32 count; /* counter of batched packets */
|
||||
};
|
||||
|
||||
/* The context of the netvsc device */
|
||||
struct net_device_context {
|
||||
/* point back to our device context */
|
||||
struct hv_device *device_ctx;
|
||||
struct delayed_work dwork;
|
||||
struct work_struct work;
|
||||
u32 msg_enable; /* debug level */
|
||||
};
|
||||
|
||||
/* Per netvsc device */
|
||||
struct netvsc_device {
|
||||
struct hv_device *dev;
|
||||
|
@ -667,6 +675,9 @@ struct netvsc_device {
|
|||
struct multi_send_data msd[NR_CPUS];
|
||||
u32 max_pkt; /* max number of pkt in one send, e.g. 8 */
|
||||
u32 pkt_align; /* alignment bytes, e.g. 8 */
|
||||
|
||||
/* The net device context */
|
||||
struct net_device_context *nd_ctx;
|
||||
};
|
||||
|
||||
/* NdisInitialize message */
|
||||
|
|
|
@ -889,11 +889,6 @@ int netvsc_send(struct hv_device *device,
|
|||
} else {
|
||||
packet->page_buf_cnt = 0;
|
||||
packet->total_data_buflen += msd_len;
|
||||
if (!packet->part_of_skb) {
|
||||
skb = (struct sk_buff *)(unsigned long)packet->
|
||||
send_completion_tid;
|
||||
packet->send_completion_tid = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (msdp->pkt)
|
||||
|
@ -1197,6 +1192,9 @@ int netvsc_device_add(struct hv_device *device, void *additional_info)
|
|||
*/
|
||||
ndev = net_device->ndev;
|
||||
|
||||
/* Add netvsc_device context to netvsc_device */
|
||||
net_device->nd_ctx = netdev_priv(ndev);
|
||||
|
||||
/* Initialize the NetVSC channel extension */
|
||||
init_completion(&net_device->channel_init_wait);
|
||||
|
||||
|
|
|
@ -40,18 +40,21 @@
|
|||
|
||||
#include "hyperv_net.h"
|
||||
|
||||
struct net_device_context {
|
||||
/* point back to our device context */
|
||||
struct hv_device *device_ctx;
|
||||
struct delayed_work dwork;
|
||||
struct work_struct work;
|
||||
};
|
||||
|
||||
#define RING_SIZE_MIN 64
|
||||
static int ring_size = 128;
|
||||
module_param(ring_size, int, S_IRUGO);
|
||||
MODULE_PARM_DESC(ring_size, "Ring buffer size (# of pages)");
|
||||
|
||||
static const u32 default_msg = NETIF_MSG_DRV | NETIF_MSG_PROBE |
|
||||
NETIF_MSG_LINK | NETIF_MSG_IFUP |
|
||||
NETIF_MSG_IFDOWN | NETIF_MSG_RX_ERR |
|
||||
NETIF_MSG_TX_ERR;
|
||||
|
||||
static int debug = -1;
|
||||
module_param(debug, int, S_IRUGO);
|
||||
MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)");
|
||||
|
||||
static void do_set_multicast(struct work_struct *w)
|
||||
{
|
||||
struct net_device_context *ndevctx =
|
||||
|
@ -235,9 +238,6 @@ void netvsc_xmit_completion(void *context)
|
|||
struct sk_buff *skb = (struct sk_buff *)
|
||||
(unsigned long)packet->send_completion_tid;
|
||||
|
||||
if (!packet->part_of_skb)
|
||||
kfree(packet);
|
||||
|
||||
if (skb)
|
||||
dev_kfree_skb_any(skb);
|
||||
}
|
||||
|
@ -389,7 +389,6 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net)
|
|||
u32 net_trans_info;
|
||||
u32 hash;
|
||||
u32 skb_length;
|
||||
u32 head_room;
|
||||
u32 pkt_sz;
|
||||
struct hv_page_buffer page_buf[MAX_PAGE_BUFFER_COUNT];
|
||||
|
||||
|
@ -402,7 +401,6 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net)
|
|||
|
||||
check_size:
|
||||
skb_length = skb->len;
|
||||
head_room = skb_headroom(skb);
|
||||
num_data_pgs = netvsc_get_slots(skb) + 2;
|
||||
if (num_data_pgs > MAX_PAGE_BUFFER_COUNT && linear) {
|
||||
net_alert_ratelimited("packet too big: %u pages (%u bytes)\n",
|
||||
|
@ -421,20 +419,14 @@ check_size:
|
|||
|
||||
pkt_sz = sizeof(struct hv_netvsc_packet) + RNDIS_AND_PPI_SIZE;
|
||||
|
||||
if (head_room < pkt_sz) {
|
||||
packet = kmalloc(pkt_sz, GFP_ATOMIC);
|
||||
if (!packet) {
|
||||
/* out of memory, drop packet */
|
||||
netdev_err(net, "unable to alloc hv_netvsc_packet\n");
|
||||
ret = -ENOMEM;
|
||||
goto drop;
|
||||
}
|
||||
packet->part_of_skb = false;
|
||||
} else {
|
||||
/* Use the headroom for building up the packet */
|
||||
packet = (struct hv_netvsc_packet *)skb->head;
|
||||
packet->part_of_skb = true;
|
||||
ret = skb_cow_head(skb, pkt_sz);
|
||||
if (ret) {
|
||||
netdev_err(net, "unable to alloc hv_netvsc_packet\n");
|
||||
ret = -ENOMEM;
|
||||
goto drop;
|
||||
}
|
||||
/* Use the headroom for building up the packet */
|
||||
packet = (struct hv_netvsc_packet *)skb->head;
|
||||
|
||||
packet->status = 0;
|
||||
packet->xmit_more = skb->xmit_more;
|
||||
|
@ -591,8 +583,6 @@ drop:
|
|||
net->stats.tx_bytes += skb_length;
|
||||
net->stats.tx_packets++;
|
||||
} else {
|
||||
if (packet && !packet->part_of_skb)
|
||||
kfree(packet);
|
||||
if (ret != -EAGAIN) {
|
||||
dev_kfree_skb_any(skb);
|
||||
net->stats.tx_dropped++;
|
||||
|
@ -888,6 +878,11 @@ static int netvsc_probe(struct hv_device *dev,
|
|||
|
||||
net_device_ctx = netdev_priv(net);
|
||||
net_device_ctx->device_ctx = dev;
|
||||
net_device_ctx->msg_enable = netif_msg_init(debug, default_msg);
|
||||
if (netif_msg_probe(net_device_ctx))
|
||||
netdev_dbg(net, "netvsc msg_enable: %d\n",
|
||||
net_device_ctx->msg_enable);
|
||||
|
||||
hv_set_drvdata(dev, net);
|
||||
INIT_DELAYED_WORK(&net_device_ctx->dwork, netvsc_link_change);
|
||||
INIT_WORK(&net_device_ctx->work, do_set_multicast);
|
||||
|
|
|
@ -429,7 +429,8 @@ int rndis_filter_receive(struct hv_device *dev,
|
|||
|
||||
rndis_msg = pkt->data;
|
||||
|
||||
dump_rndis_message(dev, rndis_msg);
|
||||
if (netif_msg_rx_err(net_dev->nd_ctx))
|
||||
dump_rndis_message(dev, rndis_msg);
|
||||
|
||||
switch (rndis_msg->ndis_msg_type) {
|
||||
case RNDIS_MSG_PACKET:
|
||||
|
|
|
@ -667,6 +667,8 @@ static struct raw3215_info *raw3215_alloc_info(void)
|
|||
info->buffer = kzalloc(RAW3215_BUFFER_SIZE, GFP_KERNEL | GFP_DMA);
|
||||
info->inbuf = kzalloc(RAW3215_INBUF_SIZE, GFP_KERNEL | GFP_DMA);
|
||||
if (!info->buffer || !info->inbuf) {
|
||||
kfree(info->inbuf);
|
||||
kfree(info->buffer);
|
||||
kfree(info);
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
@ -80,9 +80,10 @@ static int __init sh_pm_runtime_init(void)
|
|||
if (IS_ENABLED(CONFIG_ARCH_SHMOBILE_MULTI)) {
|
||||
if (!of_machine_is_compatible("renesas,emev2") &&
|
||||
!of_machine_is_compatible("renesas,r7s72100") &&
|
||||
!of_machine_is_compatible("renesas,r8a73a4") &&
|
||||
#ifndef CONFIG_PM_GENERIC_DOMAINS_OF
|
||||
!of_machine_is_compatible("renesas,r8a73a4") &&
|
||||
!of_machine_is_compatible("renesas,r8a7740") &&
|
||||
!of_machine_is_compatible("renesas,sh73a0") &&
|
||||
#endif
|
||||
!of_machine_is_compatible("renesas,r8a7778") &&
|
||||
!of_machine_is_compatible("renesas,r8a7779") &&
|
||||
|
@ -90,9 +91,7 @@ static int __init sh_pm_runtime_init(void)
|
|||
!of_machine_is_compatible("renesas,r8a7791") &&
|
||||
!of_machine_is_compatible("renesas,r8a7792") &&
|
||||
!of_machine_is_compatible("renesas,r8a7793") &&
|
||||
!of_machine_is_compatible("renesas,r8a7794") &&
|
||||
!of_machine_is_compatible("renesas,sh7372") &&
|
||||
!of_machine_is_compatible("renesas,sh73a0"))
|
||||
!of_machine_is_compatible("renesas,r8a7794"))
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -1998,6 +1998,8 @@ pci_wch_ch38x_setup(struct serial_private *priv,
|
|||
#define PCIE_DEVICE_ID_WCH_CH382_2S1P 0x3250
|
||||
#define PCIE_DEVICE_ID_WCH_CH384_4S 0x3470
|
||||
|
||||
#define PCI_DEVICE_ID_EXAR_XR17V8358 0x8358
|
||||
|
||||
/* Unknown vendors/cards - this should not be in linux/pci_ids.h */
|
||||
#define PCI_SUBDEVICE_ID_UNKNOWN_0x1584 0x1584
|
||||
#define PCI_SUBDEVICE_ID_UNKNOWN_0x1588 0x1588
|
||||
|
@ -2520,6 +2522,13 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
|
|||
.subdevice = PCI_ANY_ID,
|
||||
.setup = pci_xr17v35x_setup,
|
||||
},
|
||||
{
|
||||
.vendor = PCI_VENDOR_ID_EXAR,
|
||||
.device = PCI_DEVICE_ID_EXAR_XR17V8358,
|
||||
.subvendor = PCI_ANY_ID,
|
||||
.subdevice = PCI_ANY_ID,
|
||||
.setup = pci_xr17v35x_setup,
|
||||
},
|
||||
/*
|
||||
* Xircom cards
|
||||
*/
|
||||
|
@ -2999,6 +3008,7 @@ enum pci_board_num_t {
|
|||
pbn_exar_XR17V352,
|
||||
pbn_exar_XR17V354,
|
||||
pbn_exar_XR17V358,
|
||||
pbn_exar_XR17V8358,
|
||||
pbn_exar_ibm_saturn,
|
||||
pbn_pasemi_1682M,
|
||||
pbn_ni8430_2,
|
||||
|
@ -3685,6 +3695,14 @@ static struct pciserial_board pci_boards[] = {
|
|||
.reg_shift = 0,
|
||||
.first_offset = 0,
|
||||
},
|
||||
[pbn_exar_XR17V8358] = {
|
||||
.flags = FL_BASE0,
|
||||
.num_ports = 16,
|
||||
.base_baud = 7812500,
|
||||
.uart_offset = 0x400,
|
||||
.reg_shift = 0,
|
||||
.first_offset = 0,
|
||||
},
|
||||
[pbn_exar_ibm_saturn] = {
|
||||
.flags = FL_BASE0,
|
||||
.num_ports = 1,
|
||||
|
@ -5080,7 +5098,7 @@ static struct pci_device_id serial_pci_tbl[] = {
|
|||
0,
|
||||
0, pbn_exar_XR17C158 },
|
||||
/*
|
||||
* Exar Corp. XR17V35[248] Dual/Quad/Octal PCIe UARTs
|
||||
* Exar Corp. XR17V[48]35[248] Dual/Quad/Octal/Hexa PCIe UARTs
|
||||
*/
|
||||
{ PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17V352,
|
||||
PCI_ANY_ID, PCI_ANY_ID,
|
||||
|
@ -5094,7 +5112,10 @@ static struct pci_device_id serial_pci_tbl[] = {
|
|||
PCI_ANY_ID, PCI_ANY_ID,
|
||||
0,
|
||||
0, pbn_exar_XR17V358 },
|
||||
|
||||
{ PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17V8358,
|
||||
PCI_ANY_ID, PCI_ANY_ID,
|
||||
0,
|
||||
0, pbn_exar_XR17V8358 },
|
||||
/*
|
||||
* Topic TP560 Data/Fax/Voice 56k modem (reported by Evan Clarke)
|
||||
*/
|
||||
|
|
|
@ -880,6 +880,7 @@ static int atmel_prepare_tx_dma(struct uart_port *port)
|
|||
config.direction = DMA_MEM_TO_DEV;
|
||||
config.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
|
||||
config.dst_addr = port->mapbase + ATMEL_US_THR;
|
||||
config.dst_maxburst = 1;
|
||||
|
||||
ret = dmaengine_slave_config(atmel_port->chan_tx,
|
||||
&config);
|
||||
|
@ -1059,6 +1060,7 @@ static int atmel_prepare_rx_dma(struct uart_port *port)
|
|||
config.direction = DMA_DEV_TO_MEM;
|
||||
config.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
|
||||
config.src_addr = port->mapbase + ATMEL_US_RHR;
|
||||
config.src_maxburst = 1;
|
||||
|
||||
ret = dmaengine_slave_config(atmel_port->chan_rx,
|
||||
&config);
|
||||
|
|
|
@ -346,7 +346,6 @@ static const struct of_device_id of_platform_serial_table[] = {
|
|||
{ .compatible = "ibm,qpace-nwp-serial",
|
||||
.data = (void *)PORT_NWPSERIAL, },
|
||||
#endif
|
||||
{ .type = "serial", .data = (void *)PORT_UNKNOWN, },
|
||||
{ /* end of list */ },
|
||||
};
|
||||
|
||||
|
|
|
@ -1068,8 +1068,9 @@ static int s3c64xx_serial_startup(struct uart_port *port)
|
|||
spin_lock_irqsave(&port->lock, flags);
|
||||
|
||||
ufcon = rd_regl(port, S3C2410_UFCON);
|
||||
ufcon |= S3C2410_UFCON_RESETRX | S3C2410_UFCON_RESETTX |
|
||||
S5PV210_UFCON_RXTRIG8;
|
||||
ufcon |= S3C2410_UFCON_RESETRX | S5PV210_UFCON_RXTRIG8;
|
||||
if (!uart_console(port))
|
||||
ufcon |= S3C2410_UFCON_RESETTX;
|
||||
wr_regl(port, S3C2410_UFCON, ufcon);
|
||||
|
||||
enable_rx_pio(ourport);
|
||||
|
|
|
@ -1770,7 +1770,7 @@ static const struct file_operations uart_proc_fops = {
|
|||
* @port: the port to write the message
|
||||
* @s: array of characters
|
||||
* @count: number of characters in string to write
|
||||
* @write: function to write character to port
|
||||
* @putchar: function to write character to port
|
||||
*/
|
||||
void uart_console_write(struct uart_port *port, const char *s,
|
||||
unsigned int count,
|
||||
|
|
|
@ -632,7 +632,8 @@ MODULE_DEVICE_TABLE(of, ulite_of_match);
|
|||
|
||||
static int ulite_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct resource *res, *res2;
|
||||
struct resource *res;
|
||||
int irq;
|
||||
int id = pdev->id;
|
||||
#ifdef CONFIG_OF
|
||||
const __be32 *prop;
|
||||
|
@ -646,11 +647,11 @@ static int ulite_probe(struct platform_device *pdev)
|
|||
if (!res)
|
||||
return -ENODEV;
|
||||
|
||||
res2 = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
|
||||
if (!res2)
|
||||
return -ENODEV;
|
||||
irq = platform_get_irq(pdev, 0);
|
||||
if (irq <= 0)
|
||||
return -ENXIO;
|
||||
|
||||
return ulite_assign(&pdev->dev, id, res->start, res2->start);
|
||||
return ulite_assign(&pdev->dev, id, res->start, irq);
|
||||
}
|
||||
|
||||
static int ulite_remove(struct platform_device *pdev)
|
||||
|
|
|
@ -1331,9 +1331,9 @@ static SIMPLE_DEV_PM_OPS(cdns_uart_dev_pm_ops, cdns_uart_suspend,
|
|||
*/
|
||||
static int cdns_uart_probe(struct platform_device *pdev)
|
||||
{
|
||||
int rc, id;
|
||||
int rc, id, irq;
|
||||
struct uart_port *port;
|
||||
struct resource *res, *res2;
|
||||
struct resource *res;
|
||||
struct cdns_uart *cdns_uart_data;
|
||||
|
||||
cdns_uart_data = devm_kzalloc(&pdev->dev, sizeof(*cdns_uart_data),
|
||||
|
@ -1380,9 +1380,9 @@ static int cdns_uart_probe(struct platform_device *pdev)
|
|||
goto err_out_clk_disable;
|
||||
}
|
||||
|
||||
res2 = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
|
||||
if (!res2) {
|
||||
rc = -ENODEV;
|
||||
irq = platform_get_irq(pdev, 0);
|
||||
if (irq <= 0) {
|
||||
rc = -ENXIO;
|
||||
goto err_out_clk_disable;
|
||||
}
|
||||
|
||||
|
@ -1411,7 +1411,7 @@ static int cdns_uart_probe(struct platform_device *pdev)
|
|||
* and triggers invocation of the config_port() entry point.
|
||||
*/
|
||||
port->mapbase = res->start;
|
||||
port->irq = res2->start;
|
||||
port->irq = irq;
|
||||
port->dev = &pdev->dev;
|
||||
port->uartclk = clk_get_rate(cdns_uart_data->uartclk);
|
||||
port->private_data = cdns_uart_data;
|
||||
|
|
|
@ -536,7 +536,7 @@ EXPORT_SYMBOL(tty_termios_hw_change);
|
|||
* Locking: termios_rwsem
|
||||
*/
|
||||
|
||||
static int tty_set_termios(struct tty_struct *tty, struct ktermios *new_termios)
|
||||
int tty_set_termios(struct tty_struct *tty, struct ktermios *new_termios)
|
||||
{
|
||||
struct ktermios old_termios;
|
||||
struct tty_ldisc *ld;
|
||||
|
@ -569,6 +569,7 @@ static int tty_set_termios(struct tty_struct *tty, struct ktermios *new_termios)
|
|||
up_write(&tty->termios_rwsem);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(tty_set_termios);
|
||||
|
||||
/**
|
||||
* set_termios - set termios values for a tty
|
||||
|
|
|
@ -520,7 +520,6 @@ static int ci_otg_start_host(struct otg_fsm *fsm, int on)
|
|||
{
|
||||
struct ci_hdrc *ci = container_of(fsm, struct ci_hdrc, fsm);
|
||||
|
||||
mutex_unlock(&fsm->lock);
|
||||
if (on) {
|
||||
ci_role_stop(ci);
|
||||
ci_role_start(ci, CI_ROLE_HOST);
|
||||
|
@ -529,7 +528,6 @@ static int ci_otg_start_host(struct otg_fsm *fsm, int on)
|
|||
hw_device_reset(ci);
|
||||
ci_role_start(ci, CI_ROLE_GADGET);
|
||||
}
|
||||
mutex_lock(&fsm->lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -537,12 +535,10 @@ static int ci_otg_start_gadget(struct otg_fsm *fsm, int on)
|
|||
{
|
||||
struct ci_hdrc *ci = container_of(fsm, struct ci_hdrc, fsm);
|
||||
|
||||
mutex_unlock(&fsm->lock);
|
||||
if (on)
|
||||
usb_gadget_vbus_connect(&ci->gadget);
|
||||
else
|
||||
usb_gadget_vbus_disconnect(&ci->gadget);
|
||||
mutex_lock(&fsm->lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -1142,11 +1142,16 @@ static int acm_probe(struct usb_interface *intf,
|
|||
}
|
||||
|
||||
while (buflen > 0) {
|
||||
elength = buffer[0];
|
||||
if (!elength) {
|
||||
dev_err(&intf->dev, "skipping garbage byte\n");
|
||||
elength = 1;
|
||||
goto next_desc;
|
||||
}
|
||||
if (buffer[1] != USB_DT_CS_INTERFACE) {
|
||||
dev_err(&intf->dev, "skipping garbage\n");
|
||||
goto next_desc;
|
||||
}
|
||||
elength = buffer[0];
|
||||
|
||||
switch (buffer[2]) {
|
||||
case USB_CDC_UNION_TYPE: /* we've found it */
|
||||
|
|
|
@ -88,13 +88,20 @@ static int ehci_msm_probe(struct platform_device *pdev)
|
|||
}
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
hcd->regs = devm_ioremap_resource(&pdev->dev, res);
|
||||
if (IS_ERR(hcd->regs)) {
|
||||
ret = PTR_ERR(hcd->regs);
|
||||
if (!res) {
|
||||
dev_err(&pdev->dev, "Unable to get memory resource\n");
|
||||
ret = -ENODEV;
|
||||
goto put_hcd;
|
||||
}
|
||||
|
||||
hcd->rsrc_start = res->start;
|
||||
hcd->rsrc_len = resource_size(res);
|
||||
hcd->regs = devm_ioremap(&pdev->dev, hcd->rsrc_start, hcd->rsrc_len);
|
||||
if (!hcd->regs) {
|
||||
dev_err(&pdev->dev, "ioremap failed\n");
|
||||
ret = -ENOMEM;
|
||||
goto put_hcd;
|
||||
}
|
||||
|
||||
/*
|
||||
* OTG driver takes care of PHY initialization, clock management,
|
||||
|
|
|
@ -51,7 +51,8 @@ static int uas_find_endpoints(struct usb_host_interface *alt,
|
|||
}
|
||||
|
||||
static int uas_use_uas_driver(struct usb_interface *intf,
|
||||
const struct usb_device_id *id)
|
||||
const struct usb_device_id *id,
|
||||
unsigned long *flags_ret)
|
||||
{
|
||||
struct usb_host_endpoint *eps[4] = { };
|
||||
struct usb_device *udev = interface_to_usbdev(intf);
|
||||
|
@ -73,7 +74,7 @@ static int uas_use_uas_driver(struct usb_interface *intf,
|
|||
* this writing the following versions exist:
|
||||
* ASM1051 - no uas support version
|
||||
* ASM1051 - with broken (*) uas support
|
||||
* ASM1053 - with working uas support
|
||||
* ASM1053 - with working uas support, but problems with large xfers
|
||||
* ASM1153 - with working uas support
|
||||
*
|
||||
* Devices with these chips re-use a number of device-ids over the
|
||||
|
@ -103,6 +104,9 @@ static int uas_use_uas_driver(struct usb_interface *intf,
|
|||
} else if (usb_ss_max_streams(&eps[1]->ss_ep_comp) == 32) {
|
||||
/* Possibly an ASM1051, disable uas */
|
||||
flags |= US_FL_IGNORE_UAS;
|
||||
} else {
|
||||
/* ASM1053, these have issues with large transfers */
|
||||
flags |= US_FL_MAX_SECTORS_240;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -132,5 +136,8 @@ static int uas_use_uas_driver(struct usb_interface *intf,
|
|||
return 0;
|
||||
}
|
||||
|
||||
if (flags_ret)
|
||||
*flags_ret = flags;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
|
|
@ -759,7 +759,10 @@ static int uas_eh_bus_reset_handler(struct scsi_cmnd *cmnd)
|
|||
|
||||
static int uas_slave_alloc(struct scsi_device *sdev)
|
||||
{
|
||||
sdev->hostdata = (void *)sdev->host->hostdata;
|
||||
struct uas_dev_info *devinfo =
|
||||
(struct uas_dev_info *)sdev->host->hostdata;
|
||||
|
||||
sdev->hostdata = devinfo;
|
||||
|
||||
/* USB has unusual DMA-alignment requirements: Although the
|
||||
* starting address of each scatter-gather element doesn't matter,
|
||||
|
@ -778,6 +781,11 @@ static int uas_slave_alloc(struct scsi_device *sdev)
|
|||
*/
|
||||
blk_queue_update_dma_alignment(sdev->request_queue, (512 - 1));
|
||||
|
||||
if (devinfo->flags & US_FL_MAX_SECTORS_64)
|
||||
blk_queue_max_hw_sectors(sdev->request_queue, 64);
|
||||
else if (devinfo->flags & US_FL_MAX_SECTORS_240)
|
||||
blk_queue_max_hw_sectors(sdev->request_queue, 240);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -887,8 +895,9 @@ static int uas_probe(struct usb_interface *intf, const struct usb_device_id *id)
|
|||
struct Scsi_Host *shost = NULL;
|
||||
struct uas_dev_info *devinfo;
|
||||
struct usb_device *udev = interface_to_usbdev(intf);
|
||||
unsigned long dev_flags;
|
||||
|
||||
if (!uas_use_uas_driver(intf, id))
|
||||
if (!uas_use_uas_driver(intf, id, &dev_flags))
|
||||
return -ENODEV;
|
||||
|
||||
if (uas_switch_interface(udev, intf))
|
||||
|
@ -910,8 +919,7 @@ static int uas_probe(struct usb_interface *intf, const struct usb_device_id *id)
|
|||
devinfo->udev = udev;
|
||||
devinfo->resetting = 0;
|
||||
devinfo->shutdown = 0;
|
||||
devinfo->flags = id->driver_info;
|
||||
usb_stor_adjust_quirks(udev, &devinfo->flags);
|
||||
devinfo->flags = dev_flags;
|
||||
init_usb_anchor(&devinfo->cmd_urbs);
|
||||
init_usb_anchor(&devinfo->sense_urbs);
|
||||
init_usb_anchor(&devinfo->data_urbs);
|
||||
|
|
|
@ -479,7 +479,8 @@ void usb_stor_adjust_quirks(struct usb_device *udev, unsigned long *fflags)
|
|||
US_FL_SINGLE_LUN | US_FL_NO_WP_DETECT |
|
||||
US_FL_NO_READ_DISC_INFO | US_FL_NO_READ_CAPACITY_16 |
|
||||
US_FL_INITIAL_READ10 | US_FL_WRITE_CACHE |
|
||||
US_FL_NO_ATA_1X | US_FL_NO_REPORT_OPCODES);
|
||||
US_FL_NO_ATA_1X | US_FL_NO_REPORT_OPCODES |
|
||||
US_FL_MAX_SECTORS_240);
|
||||
|
||||
p = quirks;
|
||||
while (*p) {
|
||||
|
@ -520,6 +521,9 @@ void usb_stor_adjust_quirks(struct usb_device *udev, unsigned long *fflags)
|
|||
case 'f':
|
||||
f |= US_FL_NO_REPORT_OPCODES;
|
||||
break;
|
||||
case 'g':
|
||||
f |= US_FL_MAX_SECTORS_240;
|
||||
break;
|
||||
case 'h':
|
||||
f |= US_FL_CAPACITY_HEURISTICS;
|
||||
break;
|
||||
|
@ -1080,7 +1084,7 @@ static int storage_probe(struct usb_interface *intf,
|
|||
|
||||
/* If uas is enabled and this device can do uas then ignore it. */
|
||||
#if IS_ENABLED(CONFIG_USB_UAS)
|
||||
if (uas_use_uas_driver(intf, id))
|
||||
if (uas_use_uas_driver(intf, id, NULL))
|
||||
return -ENXIO;
|
||||
#endif
|
||||
|
||||
|
|
|
@ -1802,6 +1802,8 @@ int btrfs_fill_inode(struct inode *inode, u32 *rdev)
|
|||
set_nlink(inode, btrfs_stack_inode_nlink(inode_item));
|
||||
inode_set_bytes(inode, btrfs_stack_inode_nbytes(inode_item));
|
||||
BTRFS_I(inode)->generation = btrfs_stack_inode_generation(inode_item);
|
||||
BTRFS_I(inode)->last_trans = btrfs_stack_inode_transid(inode_item);
|
||||
|
||||
inode->i_version = btrfs_stack_inode_sequence(inode_item);
|
||||
inode->i_rdev = 0;
|
||||
*rdev = btrfs_stack_inode_rdev(inode_item);
|
||||
|
|
|
@ -3178,8 +3178,8 @@ static int write_one_cache_group(struct btrfs_trans_handle *trans,
|
|||
bi = btrfs_item_ptr_offset(leaf, path->slots[0]);
|
||||
write_extent_buffer(leaf, &cache->item, bi, sizeof(cache->item));
|
||||
btrfs_mark_buffer_dirty(leaf);
|
||||
btrfs_release_path(path);
|
||||
fail:
|
||||
btrfs_release_path(path);
|
||||
if (ret)
|
||||
btrfs_abort_transaction(trans, root, ret);
|
||||
return ret;
|
||||
|
@ -3305,8 +3305,7 @@ again:
|
|||
|
||||
spin_lock(&block_group->lock);
|
||||
if (block_group->cached != BTRFS_CACHE_FINISHED ||
|
||||
!btrfs_test_opt(root, SPACE_CACHE) ||
|
||||
block_group->delalloc_bytes) {
|
||||
!btrfs_test_opt(root, SPACE_CACHE)) {
|
||||
/*
|
||||
* don't bother trying to write stuff out _if_
|
||||
* a) we're not cached,
|
||||
|
@ -3408,17 +3407,14 @@ int btrfs_start_dirty_block_groups(struct btrfs_trans_handle *trans,
|
|||
int loops = 0;
|
||||
|
||||
spin_lock(&cur_trans->dirty_bgs_lock);
|
||||
if (!list_empty(&cur_trans->dirty_bgs)) {
|
||||
list_splice_init(&cur_trans->dirty_bgs, &dirty);
|
||||
if (list_empty(&cur_trans->dirty_bgs)) {
|
||||
spin_unlock(&cur_trans->dirty_bgs_lock);
|
||||
return 0;
|
||||
}
|
||||
list_splice_init(&cur_trans->dirty_bgs, &dirty);
|
||||
spin_unlock(&cur_trans->dirty_bgs_lock);
|
||||
|
||||
again:
|
||||
if (list_empty(&dirty)) {
|
||||
btrfs_free_path(path);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* make sure all the block groups on our dirty list actually
|
||||
* exist
|
||||
|
@ -3431,18 +3427,16 @@ again:
|
|||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/*
|
||||
* cache_write_mutex is here only to save us from balance or automatic
|
||||
* removal of empty block groups deleting this block group while we are
|
||||
* writing out the cache
|
||||
*/
|
||||
mutex_lock(&trans->transaction->cache_write_mutex);
|
||||
while (!list_empty(&dirty)) {
|
||||
cache = list_first_entry(&dirty,
|
||||
struct btrfs_block_group_cache,
|
||||
dirty_list);
|
||||
|
||||
/*
|
||||
* cache_write_mutex is here only to save us from balance
|
||||
* deleting this block group while we are writing out the
|
||||
* cache
|
||||
*/
|
||||
mutex_lock(&trans->transaction->cache_write_mutex);
|
||||
|
||||
/*
|
||||
* this can happen if something re-dirties a block
|
||||
* group that is already under IO. Just wait for it to
|
||||
|
@ -3495,7 +3489,6 @@ again:
|
|||
}
|
||||
if (!ret)
|
||||
ret = write_one_cache_group(trans, root, path, cache);
|
||||
mutex_unlock(&trans->transaction->cache_write_mutex);
|
||||
|
||||
/* if its not on the io list, we need to put the block group */
|
||||
if (should_put)
|
||||
|
@ -3503,7 +3496,16 @@ again:
|
|||
|
||||
if (ret)
|
||||
break;
|
||||
|
||||
/*
|
||||
* Avoid blocking other tasks for too long. It might even save
|
||||
* us from writing caches for block groups that are going to be
|
||||
* removed.
|
||||
*/
|
||||
mutex_unlock(&trans->transaction->cache_write_mutex);
|
||||
mutex_lock(&trans->transaction->cache_write_mutex);
|
||||
}
|
||||
mutex_unlock(&trans->transaction->cache_write_mutex);
|
||||
|
||||
/*
|
||||
* go through delayed refs for all the stuff we've just kicked off
|
||||
|
@ -3514,8 +3516,15 @@ again:
|
|||
loops++;
|
||||
spin_lock(&cur_trans->dirty_bgs_lock);
|
||||
list_splice_init(&cur_trans->dirty_bgs, &dirty);
|
||||
/*
|
||||
* dirty_bgs_lock protects us from concurrent block group
|
||||
* deletes too (not just cache_write_mutex).
|
||||
*/
|
||||
if (!list_empty(&dirty)) {
|
||||
spin_unlock(&cur_trans->dirty_bgs_lock);
|
||||
goto again;
|
||||
}
|
||||
spin_unlock(&cur_trans->dirty_bgs_lock);
|
||||
goto again;
|
||||
}
|
||||
|
||||
btrfs_free_path(path);
|
||||
|
@ -7537,7 +7546,7 @@ static void unuse_block_rsv(struct btrfs_fs_info *fs_info,
|
|||
* returns the key for the extent through ins, and a tree buffer for
|
||||
* the first block of the extent through buf.
|
||||
*
|
||||
* returns the tree buffer or NULL.
|
||||
* returns the tree buffer or an ERR_PTR on error.
|
||||
*/
|
||||
struct extent_buffer *btrfs_alloc_tree_block(struct btrfs_trans_handle *trans,
|
||||
struct btrfs_root *root,
|
||||
|
@ -7548,6 +7557,7 @@ struct extent_buffer *btrfs_alloc_tree_block(struct btrfs_trans_handle *trans,
|
|||
struct btrfs_key ins;
|
||||
struct btrfs_block_rsv *block_rsv;
|
||||
struct extent_buffer *buf;
|
||||
struct btrfs_delayed_extent_op *extent_op;
|
||||
u64 flags = 0;
|
||||
int ret;
|
||||
u32 blocksize = root->nodesize;
|
||||
|
@ -7568,13 +7578,14 @@ struct extent_buffer *btrfs_alloc_tree_block(struct btrfs_trans_handle *trans,
|
|||
|
||||
ret = btrfs_reserve_extent(root, blocksize, blocksize,
|
||||
empty_size, hint, &ins, 0, 0);
|
||||
if (ret) {
|
||||
unuse_block_rsv(root->fs_info, block_rsv, blocksize);
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
if (ret)
|
||||
goto out_unuse;
|
||||
|
||||
buf = btrfs_init_new_buffer(trans, root, ins.objectid, level);
|
||||
BUG_ON(IS_ERR(buf)); /* -ENOMEM */
|
||||
if (IS_ERR(buf)) {
|
||||
ret = PTR_ERR(buf);
|
||||
goto out_free_reserved;
|
||||
}
|
||||
|
||||
if (root_objectid == BTRFS_TREE_RELOC_OBJECTID) {
|
||||
if (parent == 0)
|
||||
|
@ -7584,9 +7595,11 @@ struct extent_buffer *btrfs_alloc_tree_block(struct btrfs_trans_handle *trans,
|
|||
BUG_ON(parent > 0);
|
||||
|
||||
if (root_objectid != BTRFS_TREE_LOG_OBJECTID) {
|
||||
struct btrfs_delayed_extent_op *extent_op;
|
||||
extent_op = btrfs_alloc_delayed_extent_op();
|
||||
BUG_ON(!extent_op); /* -ENOMEM */
|
||||
if (!extent_op) {
|
||||
ret = -ENOMEM;
|
||||
goto out_free_buf;
|
||||
}
|
||||
if (key)
|
||||
memcpy(&extent_op->key, key, sizeof(extent_op->key));
|
||||
else
|
||||
|
@ -7601,13 +7614,24 @@ struct extent_buffer *btrfs_alloc_tree_block(struct btrfs_trans_handle *trans,
|
|||
extent_op->level = level;
|
||||
|
||||
ret = btrfs_add_delayed_tree_ref(root->fs_info, trans,
|
||||
ins.objectid,
|
||||
ins.offset, parent, root_objectid,
|
||||
level, BTRFS_ADD_DELAYED_EXTENT,
|
||||
extent_op, 0);
|
||||
BUG_ON(ret); /* -ENOMEM */
|
||||
ins.objectid, ins.offset,
|
||||
parent, root_objectid, level,
|
||||
BTRFS_ADD_DELAYED_EXTENT,
|
||||
extent_op, 0);
|
||||
if (ret)
|
||||
goto out_free_delayed;
|
||||
}
|
||||
return buf;
|
||||
|
||||
out_free_delayed:
|
||||
btrfs_free_delayed_extent_op(extent_op);
|
||||
out_free_buf:
|
||||
free_extent_buffer(buf);
|
||||
out_free_reserved:
|
||||
btrfs_free_reserved_extent(root, ins.objectid, ins.offset, 0);
|
||||
out_unuse:
|
||||
unuse_block_rsv(root->fs_info, block_rsv, blocksize);
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
|
||||
struct walk_control {
|
||||
|
|
|
@ -4560,36 +4560,37 @@ static void btrfs_release_extent_buffer_page(struct extent_buffer *eb)
|
|||
do {
|
||||
index--;
|
||||
page = eb->pages[index];
|
||||
if (page && mapped) {
|
||||
if (!page)
|
||||
continue;
|
||||
if (mapped)
|
||||
spin_lock(&page->mapping->private_lock);
|
||||
/*
|
||||
* We do this since we'll remove the pages after we've
|
||||
* removed the eb from the radix tree, so we could race
|
||||
* and have this page now attached to the new eb. So
|
||||
* only clear page_private if it's still connected to
|
||||
* this eb.
|
||||
*/
|
||||
if (PagePrivate(page) &&
|
||||
page->private == (unsigned long)eb) {
|
||||
BUG_ON(test_bit(EXTENT_BUFFER_DIRTY, &eb->bflags));
|
||||
BUG_ON(PageDirty(page));
|
||||
BUG_ON(PageWriteback(page));
|
||||
/*
|
||||
* We do this since we'll remove the pages after we've
|
||||
* removed the eb from the radix tree, so we could race
|
||||
* and have this page now attached to the new eb. So
|
||||
* only clear page_private if it's still connected to
|
||||
* this eb.
|
||||
* We need to make sure we haven't be attached
|
||||
* to a new eb.
|
||||
*/
|
||||
if (PagePrivate(page) &&
|
||||
page->private == (unsigned long)eb) {
|
||||
BUG_ON(test_bit(EXTENT_BUFFER_DIRTY, &eb->bflags));
|
||||
BUG_ON(PageDirty(page));
|
||||
BUG_ON(PageWriteback(page));
|
||||
/*
|
||||
* We need to make sure we haven't be attached
|
||||
* to a new eb.
|
||||
*/
|
||||
ClearPagePrivate(page);
|
||||
set_page_private(page, 0);
|
||||
/* One for the page private */
|
||||
page_cache_release(page);
|
||||
}
|
||||
spin_unlock(&page->mapping->private_lock);
|
||||
|
||||
}
|
||||
if (page) {
|
||||
/* One for when we alloced the page */
|
||||
ClearPagePrivate(page);
|
||||
set_page_private(page, 0);
|
||||
/* One for the page private */
|
||||
page_cache_release(page);
|
||||
}
|
||||
|
||||
if (mapped)
|
||||
spin_unlock(&page->mapping->private_lock);
|
||||
|
||||
/* One for when we alloced the page */
|
||||
page_cache_release(page);
|
||||
} while (index != 0);
|
||||
}
|
||||
|
||||
|
@ -4870,6 +4871,7 @@ struct extent_buffer *alloc_extent_buffer(struct btrfs_fs_info *fs_info,
|
|||
mark_extent_buffer_accessed(exists, p);
|
||||
goto free_eb;
|
||||
}
|
||||
exists = NULL;
|
||||
|
||||
/*
|
||||
* Do this so attach doesn't complain and we need to
|
||||
|
@ -4933,12 +4935,12 @@ again:
|
|||
return eb;
|
||||
|
||||
free_eb:
|
||||
WARN_ON(!atomic_dec_and_test(&eb->refs));
|
||||
for (i = 0; i < num_pages; i++) {
|
||||
if (eb->pages[i])
|
||||
unlock_page(eb->pages[i]);
|
||||
}
|
||||
|
||||
WARN_ON(!atomic_dec_and_test(&eb->refs));
|
||||
btrfs_release_extent_buffer(eb);
|
||||
return exists;
|
||||
}
|
||||
|
|
|
@ -1218,7 +1218,7 @@ out:
|
|||
*
|
||||
* This function writes out a free space cache struct to disk for quick recovery
|
||||
* on mount. This will return 0 if it was successfull in writing the cache out,
|
||||
* and -1 if it was not.
|
||||
* or an errno if it was not.
|
||||
*/
|
||||
static int __btrfs_write_out_cache(struct btrfs_root *root, struct inode *inode,
|
||||
struct btrfs_free_space_ctl *ctl,
|
||||
|
@ -1235,12 +1235,12 @@ static int __btrfs_write_out_cache(struct btrfs_root *root, struct inode *inode,
|
|||
int must_iput = 0;
|
||||
|
||||
if (!i_size_read(inode))
|
||||
return -1;
|
||||
return -EIO;
|
||||
|
||||
WARN_ON(io_ctl->pages);
|
||||
ret = io_ctl_init(io_ctl, inode, root, 1);
|
||||
if (ret)
|
||||
return -1;
|
||||
return ret;
|
||||
|
||||
if (block_group && (block_group->flags & BTRFS_BLOCK_GROUP_DATA)) {
|
||||
down_write(&block_group->data_rwsem);
|
||||
|
@ -1258,7 +1258,9 @@ static int __btrfs_write_out_cache(struct btrfs_root *root, struct inode *inode,
|
|||
}
|
||||
|
||||
/* Lock all pages first so we can lock the extent safely. */
|
||||
io_ctl_prepare_pages(io_ctl, inode, 0);
|
||||
ret = io_ctl_prepare_pages(io_ctl, inode, 0);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
lock_extent_bits(&BTRFS_I(inode)->io_tree, 0, i_size_read(inode) - 1,
|
||||
0, &cached_state);
|
||||
|
|
|
@ -3632,16 +3632,6 @@ static void btrfs_read_locked_inode(struct inode *inode)
|
|||
BTRFS_I(inode)->generation = btrfs_inode_generation(leaf, inode_item);
|
||||
BTRFS_I(inode)->last_trans = btrfs_inode_transid(leaf, inode_item);
|
||||
|
||||
/*
|
||||
* If we were modified in the current generation and evicted from memory
|
||||
* and then re-read we need to do a full sync since we don't have any
|
||||
* idea about which extents were modified before we were evicted from
|
||||
* cache.
|
||||
*/
|
||||
if (BTRFS_I(inode)->last_trans == root->fs_info->generation)
|
||||
set_bit(BTRFS_INODE_NEEDS_FULL_SYNC,
|
||||
&BTRFS_I(inode)->runtime_flags);
|
||||
|
||||
inode->i_version = btrfs_inode_sequence(leaf, inode_item);
|
||||
inode->i_generation = BTRFS_I(inode)->generation;
|
||||
inode->i_rdev = 0;
|
||||
|
@ -3651,6 +3641,19 @@ static void btrfs_read_locked_inode(struct inode *inode)
|
|||
BTRFS_I(inode)->flags = btrfs_inode_flags(leaf, inode_item);
|
||||
|
||||
cache_index:
|
||||
/*
|
||||
* If we were modified in the current generation and evicted from memory
|
||||
* and then re-read we need to do a full sync since we don't have any
|
||||
* idea about which extents were modified before we were evicted from
|
||||
* cache.
|
||||
*
|
||||
* This is required for both inode re-read from disk and delayed inode
|
||||
* in delayed_nodes_tree.
|
||||
*/
|
||||
if (BTRFS_I(inode)->last_trans == root->fs_info->generation)
|
||||
set_bit(BTRFS_INODE_NEEDS_FULL_SYNC,
|
||||
&BTRFS_I(inode)->runtime_flags);
|
||||
|
||||
path->slots[0]++;
|
||||
if (inode->i_nlink != 1 ||
|
||||
path->slots[0] >= btrfs_header_nritems(leaf))
|
||||
|
|
|
@ -2410,7 +2410,7 @@ static noinline int btrfs_ioctl_snap_destroy(struct file *file,
|
|||
"Attempt to delete subvolume %llu during send",
|
||||
dest->root_key.objectid);
|
||||
err = -EPERM;
|
||||
goto out_dput;
|
||||
goto out_unlock_inode;
|
||||
}
|
||||
|
||||
d_invalidate(dentry);
|
||||
|
@ -2505,6 +2505,7 @@ out_up_write:
|
|||
root_flags & ~BTRFS_ROOT_SUBVOL_DEAD);
|
||||
spin_unlock(&dest->root_item_lock);
|
||||
}
|
||||
out_unlock_inode:
|
||||
mutex_unlock(&inode->i_mutex);
|
||||
if (!err) {
|
||||
shrink_dcache_sb(root->fs_info->sb);
|
||||
|
|
|
@ -1058,6 +1058,7 @@ static int contains_pending_extent(struct btrfs_trans_handle *trans,
|
|||
struct extent_map *em;
|
||||
struct list_head *search_list = &trans->transaction->pending_chunks;
|
||||
int ret = 0;
|
||||
u64 physical_start = *start;
|
||||
|
||||
again:
|
||||
list_for_each_entry(em, search_list, list) {
|
||||
|
@ -1068,9 +1069,9 @@ again:
|
|||
for (i = 0; i < map->num_stripes; i++) {
|
||||
if (map->stripes[i].dev != device)
|
||||
continue;
|
||||
if (map->stripes[i].physical >= *start + len ||
|
||||
if (map->stripes[i].physical >= physical_start + len ||
|
||||
map->stripes[i].physical + em->orig_block_len <=
|
||||
*start)
|
||||
physical_start)
|
||||
continue;
|
||||
*start = map->stripes[i].physical +
|
||||
em->orig_block_len;
|
||||
|
@ -1193,8 +1194,14 @@ again:
|
|||
*/
|
||||
if (contains_pending_extent(trans, device,
|
||||
&search_start,
|
||||
hole_size))
|
||||
hole_size = 0;
|
||||
hole_size)) {
|
||||
if (key.offset >= search_start) {
|
||||
hole_size = key.offset - search_start;
|
||||
} else {
|
||||
WARN_ON_ONCE(1);
|
||||
hole_size = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (hole_size > max_hole_size) {
|
||||
max_hole_start = search_start;
|
||||
|
|
|
@ -123,7 +123,6 @@
|
|||
|
||||
#ifndef ACPI_USE_SYSTEM_INTTYPES
|
||||
|
||||
typedef unsigned char u8;
|
||||
typedef unsigned char u8;
|
||||
typedef unsigned short u16;
|
||||
typedef short s16;
|
||||
|
|
|
@ -40,6 +40,10 @@
|
|||
#error KEXEC_CONTROL_MEMORY_LIMIT not defined
|
||||
#endif
|
||||
|
||||
#ifndef KEXEC_CONTROL_MEMORY_GFP
|
||||
#define KEXEC_CONTROL_MEMORY_GFP GFP_KERNEL
|
||||
#endif
|
||||
|
||||
#ifndef KEXEC_CONTROL_PAGE_SIZE
|
||||
#error KEXEC_CONTROL_PAGE_SIZE not defined
|
||||
#endif
|
||||
|
|
|
@ -977,7 +977,8 @@ typedef u16 (*select_queue_fallback_t)(struct net_device *dev,
|
|||
* int (*ndo_bridge_setlink)(struct net_device *dev, struct nlmsghdr *nlh,
|
||||
* u16 flags)
|
||||
* int (*ndo_bridge_getlink)(struct sk_buff *skb, u32 pid, u32 seq,
|
||||
* struct net_device *dev, u32 filter_mask)
|
||||
* struct net_device *dev, u32 filter_mask,
|
||||
* int nlflags)
|
||||
* int (*ndo_bridge_dellink)(struct net_device *dev, struct nlmsghdr *nlh,
|
||||
* u16 flags);
|
||||
*
|
||||
|
@ -1173,7 +1174,8 @@ struct net_device_ops {
|
|||
int (*ndo_bridge_getlink)(struct sk_buff *skb,
|
||||
u32 pid, u32 seq,
|
||||
struct net_device *dev,
|
||||
u32 filter_mask);
|
||||
u32 filter_mask,
|
||||
int nlflags);
|
||||
int (*ndo_bridge_dellink)(struct net_device *dev,
|
||||
struct nlmsghdr *nlh,
|
||||
u16 flags);
|
||||
|
|
|
@ -39,12 +39,24 @@ static inline void br_drop_fake_rtable(struct sk_buff *skb)
|
|||
|
||||
static inline int nf_bridge_get_physinif(const struct sk_buff *skb)
|
||||
{
|
||||
return skb->nf_bridge ? skb->nf_bridge->physindev->ifindex : 0;
|
||||
struct nf_bridge_info *nf_bridge;
|
||||
|
||||
if (skb->nf_bridge == NULL)
|
||||
return 0;
|
||||
|
||||
nf_bridge = skb->nf_bridge;
|
||||
return nf_bridge->physindev ? nf_bridge->physindev->ifindex : 0;
|
||||
}
|
||||
|
||||
static inline int nf_bridge_get_physoutif(const struct sk_buff *skb)
|
||||
{
|
||||
return skb->nf_bridge ? skb->nf_bridge->physoutdev->ifindex : 0;
|
||||
struct nf_bridge_info *nf_bridge;
|
||||
|
||||
if (skb->nf_bridge == NULL)
|
||||
return 0;
|
||||
|
||||
nf_bridge = skb->nf_bridge;
|
||||
return nf_bridge->physoutdev ? nf_bridge->physoutdev->ifindex : 0;
|
||||
}
|
||||
|
||||
static inline struct net_device *
|
||||
|
|
|
@ -122,5 +122,5 @@ extern int ndo_dflt_fdb_del(struct ndmsg *ndm,
|
|||
|
||||
extern int ndo_dflt_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq,
|
||||
struct net_device *dev, u16 mode,
|
||||
u32 flags, u32 mask);
|
||||
u32 flags, u32 mask, int nlflags);
|
||||
#endif /* __LINUX_RTNETLINK_H */
|
||||
|
|
|
@ -175,14 +175,6 @@ extern void get_iowait_load(unsigned long *nr_waiters, unsigned long *load);
|
|||
extern void calc_global_load(unsigned long ticks);
|
||||
extern void update_cpu_load_nohz(void);
|
||||
|
||||
/* Notifier for when a task gets migrated to a new CPU */
|
||||
struct task_migration_notifier {
|
||||
struct task_struct *task;
|
||||
int from_cpu;
|
||||
int to_cpu;
|
||||
};
|
||||
extern void register_task_migration_notifier(struct notifier_block *n);
|
||||
|
||||
extern unsigned long get_parent_ip(unsigned long addr);
|
||||
|
||||
extern void dump_cpu_task(int cpu);
|
||||
|
|
|
@ -491,6 +491,7 @@ static inline speed_t tty_get_baud_rate(struct tty_struct *tty)
|
|||
|
||||
extern void tty_termios_copy_hw(struct ktermios *new, struct ktermios *old);
|
||||
extern int tty_termios_hw_change(struct ktermios *a, struct ktermios *b);
|
||||
extern int tty_set_termios(struct tty_struct *tty, struct ktermios *kt);
|
||||
|
||||
extern struct tty_ldisc *tty_ldisc_ref(struct tty_struct *);
|
||||
extern void tty_ldisc_deref(struct tty_ldisc *);
|
||||
|
|
|
@ -77,6 +77,8 @@
|
|||
/* Cannot handle ATA_12 or ATA_16 CDBs */ \
|
||||
US_FLAG(NO_REPORT_OPCODES, 0x04000000) \
|
||||
/* Cannot handle MI_REPORT_SUPPORTED_OPERATION_CODES */ \
|
||||
US_FLAG(MAX_SECTORS_240, 0x08000000) \
|
||||
/* Sets max_sectors to 240 */ \
|
||||
|
||||
#define US_FLAG(name, value) US_FL_##name = value ,
|
||||
enum { US_DO_ALL_FLAGS };
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (ST) 2012 Rajeev Kumar (rajeev-dlh.kumar@st.com)
|
||||
* Copyright (ST) 2012 Rajeev Kumar (rajeevkumar.linux@gmail.com)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
|
|
@ -41,7 +41,8 @@
|
|||
|
||||
#define EMUPAGESIZE 4096
|
||||
#define MAXREQVOICES 8
|
||||
#define MAXPAGES 8192
|
||||
#define MAXPAGES0 4096 /* 32 bit mode */
|
||||
#define MAXPAGES1 8192 /* 31 bit mode */
|
||||
#define RESERVED 0
|
||||
#define NUM_MIDI 16
|
||||
#define NUM_G 64 /* use all channels */
|
||||
|
@ -50,8 +51,7 @@
|
|||
|
||||
/* FIXME? - according to the OSS driver the EMU10K1 needs a 29 bit DMA mask */
|
||||
#define EMU10K1_DMA_MASK 0x7fffffffUL /* 31bit */
|
||||
#define AUDIGY_DMA_MASK 0x7fffffffUL /* 31bit FIXME - 32 should work? */
|
||||
/* See ALSA bug #1276 - rlrevell */
|
||||
#define AUDIGY_DMA_MASK 0xffffffffUL /* 32bit mode */
|
||||
|
||||
#define TMEMSIZE 256*1024
|
||||
#define TMEMSIZEREG 4
|
||||
|
@ -466,8 +466,11 @@
|
|||
|
||||
#define MAPB 0x0d /* Cache map B */
|
||||
|
||||
#define MAP_PTE_MASK 0xffffe000 /* The 19 MSBs of the PTE indexed by the PTI */
|
||||
#define MAP_PTI_MASK 0x00001fff /* The 13 bit index to one of the 8192 PTE dwords */
|
||||
#define MAP_PTE_MASK0 0xfffff000 /* The 20 MSBs of the PTE indexed by the PTI */
|
||||
#define MAP_PTI_MASK0 0x00000fff /* The 12 bit index to one of the 4096 PTE dwords */
|
||||
|
||||
#define MAP_PTE_MASK1 0xffffe000 /* The 19 MSBs of the PTE indexed by the PTI */
|
||||
#define MAP_PTI_MASK1 0x00001fff /* The 13 bit index to one of the 8192 PTE dwords */
|
||||
|
||||
/* 0x0e, 0x0f: Not used */
|
||||
|
||||
|
@ -1704,6 +1707,7 @@ struct snd_emu10k1 {
|
|||
unsigned short model; /* subsystem id */
|
||||
unsigned int card_type; /* EMU10K1_CARD_* */
|
||||
unsigned int ecard_ctrl; /* ecard control bits */
|
||||
unsigned int address_mode; /* address mode */
|
||||
unsigned long dma_mask; /* PCI DMA mask */
|
||||
unsigned int delay_pcm_irq; /* in samples */
|
||||
int max_cache_pages; /* max memory size / PAGE_SIZE */
|
||||
|
|
|
@ -287,7 +287,7 @@ struct device;
|
|||
.access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | SNDRV_CTL_ELEM_ACCESS_READWRITE,\
|
||||
.tlv.p = (tlv_array), \
|
||||
.get = snd_soc_dapm_get_volsw, .put = snd_soc_dapm_put_volsw, \
|
||||
.private_value = SOC_SINGLE_VALUE(reg, shift, max, invert, 0) }
|
||||
.private_value = SOC_SINGLE_VALUE(reg, shift, max, invert, 1) }
|
||||
#define SOC_DAPM_SINGLE_TLV_VIRT(xname, max, tlv_array) \
|
||||
SOC_DAPM_SINGLE(xname, SND_SOC_NOPM, 0, max, 0, tlv_array)
|
||||
#define SOC_DAPM_ENUM(xname, xenum) \
|
||||
|
|
|
@ -387,8 +387,20 @@ int snd_soc_codec_set_pll(struct snd_soc_codec *codec, int pll_id, int source,
|
|||
int snd_soc_register_card(struct snd_soc_card *card);
|
||||
int snd_soc_unregister_card(struct snd_soc_card *card);
|
||||
int devm_snd_soc_register_card(struct device *dev, struct snd_soc_card *card);
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
int snd_soc_suspend(struct device *dev);
|
||||
int snd_soc_resume(struct device *dev);
|
||||
#else
|
||||
static inline int snd_soc_suspend(struct device *dev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int snd_soc_resume(struct device *dev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
int snd_soc_poweroff(struct device *dev);
|
||||
int snd_soc_register_platform(struct device *dev,
|
||||
const struct snd_soc_platform_driver *platform_drv);
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* linux/spear_dma.h
|
||||
*
|
||||
* Copyright (ST) 2012 Rajeev Kumar (rajeev-dlh.kumar@st.com)
|
||||
* Copyright (ST) 2012 Rajeev Kumar (rajeevkumar.linux@gmail.com)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
|
|
@ -155,7 +155,7 @@ static inline unsigned vring_size(unsigned int num, unsigned long align)
|
|||
}
|
||||
|
||||
/* The following is used with USED_EVENT_IDX and AVAIL_EVENT_IDX */
|
||||
/* Assuming a given event_idx value from the other size, if
|
||||
/* Assuming a given event_idx value from the other side, if
|
||||
* we have just incremented index from old to new_idx,
|
||||
* should we trigger an event? */
|
||||
static inline int vring_need_event(__u16 event_idx, __u16 new_idx, __u16 old)
|
||||
|
|
|
@ -197,9 +197,9 @@ x509.genkey:
|
|||
@echo >>x509.genkey "x509_extensions = myexts"
|
||||
@echo >>x509.genkey
|
||||
@echo >>x509.genkey "[ req_distinguished_name ]"
|
||||
@echo >>x509.genkey "O = Magrathea"
|
||||
@echo >>x509.genkey "CN = Glacier signing key"
|
||||
@echo >>x509.genkey "emailAddress = slartibartfast@magrathea.h2g2"
|
||||
@echo >>x509.genkey "#O = Unspecified company"
|
||||
@echo >>x509.genkey "CN = Build time autogenerated kernel key"
|
||||
@echo >>x509.genkey "#emailAddress = unspecified.user@unspecified.company"
|
||||
@echo >>x509.genkey
|
||||
@echo >>x509.genkey "[ myexts ]"
|
||||
@echo >>x509.genkey "basicConstraints=critical,CA:FALSE"
|
||||
|
|
|
@ -357,8 +357,8 @@ select_insn:
|
|||
ALU64_MOD_X:
|
||||
if (unlikely(SRC == 0))
|
||||
return 0;
|
||||
tmp = DST;
|
||||
DST = do_div(tmp, SRC);
|
||||
div64_u64_rem(DST, SRC, &tmp);
|
||||
DST = tmp;
|
||||
CONT;
|
||||
ALU_MOD_X:
|
||||
if (unlikely(SRC == 0))
|
||||
|
@ -367,8 +367,8 @@ select_insn:
|
|||
DST = do_div(tmp, (u32) SRC);
|
||||
CONT;
|
||||
ALU64_MOD_K:
|
||||
tmp = DST;
|
||||
DST = do_div(tmp, IMM);
|
||||
div64_u64_rem(DST, IMM, &tmp);
|
||||
DST = tmp;
|
||||
CONT;
|
||||
ALU_MOD_K:
|
||||
tmp = (u32) DST;
|
||||
|
@ -377,7 +377,7 @@ select_insn:
|
|||
ALU64_DIV_X:
|
||||
if (unlikely(SRC == 0))
|
||||
return 0;
|
||||
do_div(DST, SRC);
|
||||
DST = div64_u64(DST, SRC);
|
||||
CONT;
|
||||
ALU_DIV_X:
|
||||
if (unlikely(SRC == 0))
|
||||
|
@ -387,7 +387,7 @@ select_insn:
|
|||
DST = (u32) tmp;
|
||||
CONT;
|
||||
ALU64_DIV_K:
|
||||
do_div(DST, IMM);
|
||||
DST = div64_u64(DST, IMM);
|
||||
CONT;
|
||||
ALU_DIV_K:
|
||||
tmp = (u32) DST;
|
||||
|
|
|
@ -707,7 +707,7 @@ static struct page *kimage_alloc_normal_control_pages(struct kimage *image,
|
|||
do {
|
||||
unsigned long pfn, epfn, addr, eaddr;
|
||||
|
||||
pages = kimage_alloc_pages(GFP_KERNEL, order);
|
||||
pages = kimage_alloc_pages(KEXEC_CONTROL_MEMORY_GFP, order);
|
||||
if (!pages)
|
||||
break;
|
||||
pfn = page_to_pfn(pages);
|
||||
|
|
|
@ -1016,13 +1016,6 @@ void check_preempt_curr(struct rq *rq, struct task_struct *p, int flags)
|
|||
rq_clock_skip_update(rq, true);
|
||||
}
|
||||
|
||||
static ATOMIC_NOTIFIER_HEAD(task_migration_notifier);
|
||||
|
||||
void register_task_migration_notifier(struct notifier_block *n)
|
||||
{
|
||||
atomic_notifier_chain_register(&task_migration_notifier, n);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
void set_task_cpu(struct task_struct *p, unsigned int new_cpu)
|
||||
{
|
||||
|
@ -1053,18 +1046,10 @@ void set_task_cpu(struct task_struct *p, unsigned int new_cpu)
|
|||
trace_sched_migrate_task(p, new_cpu);
|
||||
|
||||
if (task_cpu(p) != new_cpu) {
|
||||
struct task_migration_notifier tmn;
|
||||
|
||||
if (p->sched_class->migrate_task_rq)
|
||||
p->sched_class->migrate_task_rq(p, new_cpu);
|
||||
p->se.nr_migrations++;
|
||||
perf_sw_event_sched(PERF_COUNT_SW_CPU_MIGRATIONS, 1, 0);
|
||||
|
||||
tmn.task = p;
|
||||
tmn.from_cpu = task_cpu(p);
|
||||
tmn.to_cpu = new_cpu;
|
||||
|
||||
atomic_notifier_call_chain(&task_migration_notifier, 0, &tmn);
|
||||
}
|
||||
|
||||
__set_task_cpu(p, new_cpu);
|
||||
|
|
|
@ -81,7 +81,6 @@ static void cpuidle_idle_call(void)
|
|||
struct cpuidle_device *dev = __this_cpu_read(cpuidle_devices);
|
||||
struct cpuidle_driver *drv = cpuidle_get_cpu_driver(dev);
|
||||
int next_state, entered_state;
|
||||
unsigned int broadcast;
|
||||
bool reflect;
|
||||
|
||||
/*
|
||||
|
@ -150,17 +149,6 @@ static void cpuidle_idle_call(void)
|
|||
goto exit_idle;
|
||||
}
|
||||
|
||||
broadcast = drv->states[next_state].flags & CPUIDLE_FLAG_TIMER_STOP;
|
||||
|
||||
/*
|
||||
* Tell the time framework to switch to a broadcast timer
|
||||
* because our local timer will be shutdown. If a local timer
|
||||
* is used from another cpu as a broadcast timer, this call may
|
||||
* fail if it is not available
|
||||
*/
|
||||
if (broadcast && tick_broadcast_enter())
|
||||
goto use_default;
|
||||
|
||||
/* Take note of the planned idle state. */
|
||||
idle_set_state(this_rq(), &drv->states[next_state]);
|
||||
|
||||
|
@ -174,8 +162,8 @@ static void cpuidle_idle_call(void)
|
|||
/* The cpu is no longer idle or about to enter idle. */
|
||||
idle_set_state(this_rq(), NULL);
|
||||
|
||||
if (broadcast)
|
||||
tick_broadcast_exit();
|
||||
if (entered_state == -EBUSY)
|
||||
goto use_default;
|
||||
|
||||
/*
|
||||
* Give the governor an opportunity to reflect on the outcome
|
||||
|
|
|
@ -170,7 +170,7 @@ static int nlmsg_populate_mdb_fill(struct sk_buff *skb,
|
|||
struct br_port_msg *bpm;
|
||||
struct nlattr *nest, *nest2;
|
||||
|
||||
nlh = nlmsg_put(skb, pid, seq, type, sizeof(*bpm), NLM_F_MULTI);
|
||||
nlh = nlmsg_put(skb, pid, seq, type, sizeof(*bpm), 0);
|
||||
if (!nlh)
|
||||
return -EMSGSIZE;
|
||||
|
||||
|
|
|
@ -394,7 +394,7 @@ errout:
|
|||
* Dump information about all ports, in response to GETLINK
|
||||
*/
|
||||
int br_getlink(struct sk_buff *skb, u32 pid, u32 seq,
|
||||
struct net_device *dev, u32 filter_mask)
|
||||
struct net_device *dev, u32 filter_mask, int nlflags)
|
||||
{
|
||||
struct net_bridge_port *port = br_port_get_rtnl(dev);
|
||||
|
||||
|
@ -402,7 +402,7 @@ int br_getlink(struct sk_buff *skb, u32 pid, u32 seq,
|
|||
!(filter_mask & RTEXT_FILTER_BRVLAN_COMPRESSED))
|
||||
return 0;
|
||||
|
||||
return br_fill_ifinfo(skb, port, pid, seq, RTM_NEWLINK, NLM_F_MULTI,
|
||||
return br_fill_ifinfo(skb, port, pid, seq, RTM_NEWLINK, nlflags,
|
||||
filter_mask, dev);
|
||||
}
|
||||
|
||||
|
|
|
@ -828,7 +828,7 @@ void br_ifinfo_notify(int event, struct net_bridge_port *port);
|
|||
int br_setlink(struct net_device *dev, struct nlmsghdr *nlmsg, u16 flags);
|
||||
int br_dellink(struct net_device *dev, struct nlmsghdr *nlmsg, u16 flags);
|
||||
int br_getlink(struct sk_buff *skb, u32 pid, u32 seq, struct net_device *dev,
|
||||
u32 filter_mask);
|
||||
u32 filter_mask, int nlflags);
|
||||
|
||||
#ifdef CONFIG_SYSFS
|
||||
/* br_sysfs_if.c */
|
||||
|
|
|
@ -2854,7 +2854,7 @@ static int brport_nla_put_flag(struct sk_buff *skb, u32 flags, u32 mask,
|
|||
|
||||
int ndo_dflt_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq,
|
||||
struct net_device *dev, u16 mode,
|
||||
u32 flags, u32 mask)
|
||||
u32 flags, u32 mask, int nlflags)
|
||||
{
|
||||
struct nlmsghdr *nlh;
|
||||
struct ifinfomsg *ifm;
|
||||
|
@ -2863,7 +2863,7 @@ int ndo_dflt_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq,
|
|||
u8 operstate = netif_running(dev) ? dev->operstate : IF_OPER_DOWN;
|
||||
struct net_device *br_dev = netdev_master_upper_dev_get(dev);
|
||||
|
||||
nlh = nlmsg_put(skb, pid, seq, RTM_NEWLINK, sizeof(*ifm), NLM_F_MULTI);
|
||||
nlh = nlmsg_put(skb, pid, seq, RTM_NEWLINK, sizeof(*ifm), nlflags);
|
||||
if (nlh == NULL)
|
||||
return -EMSGSIZE;
|
||||
|
||||
|
@ -2969,7 +2969,8 @@ static int rtnl_bridge_getlink(struct sk_buff *skb, struct netlink_callback *cb)
|
|||
if (br_dev && br_dev->netdev_ops->ndo_bridge_getlink) {
|
||||
if (idx >= cb->args[0] &&
|
||||
br_dev->netdev_ops->ndo_bridge_getlink(
|
||||
skb, portid, seq, dev, filter_mask) < 0)
|
||||
skb, portid, seq, dev, filter_mask,
|
||||
NLM_F_MULTI) < 0)
|
||||
break;
|
||||
idx++;
|
||||
}
|
||||
|
@ -2977,7 +2978,8 @@ static int rtnl_bridge_getlink(struct sk_buff *skb, struct netlink_callback *cb)
|
|||
if (ops->ndo_bridge_getlink) {
|
||||
if (idx >= cb->args[0] &&
|
||||
ops->ndo_bridge_getlink(skb, portid, seq, dev,
|
||||
filter_mask) < 0)
|
||||
filter_mask,
|
||||
NLM_F_MULTI) < 0)
|
||||
break;
|
||||
idx++;
|
||||
}
|
||||
|
@ -3018,7 +3020,7 @@ static int rtnl_bridge_notify(struct net_device *dev)
|
|||
goto errout;
|
||||
}
|
||||
|
||||
err = dev->netdev_ops->ndo_bridge_getlink(skb, 0, 0, dev, 0);
|
||||
err = dev->netdev_ops->ndo_bridge_getlink(skb, 0, 0, dev, 0, 0);
|
||||
if (err < 0)
|
||||
goto errout;
|
||||
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue