提交 27a03b1a 编写于 作者: L Linus Torvalds

Merge tag 's390-5.2-3' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux

Pull s390 fixes from Heiko Carstens:

 - Farewell Martin Schwidefsky: add Martin to CREDITS and remove him
   from MAINTAINERS

 - Vasily Gorbik and Christian Borntraeger join as maintainers for s390

 - Fix locking bug in ctr(aes) and ctr(des) s390 specific ciphers

 - A rather large patch which fixes gcm-aes-s390 scatter gather handling

 - Fix zcrypt wrong dispatching for control domain CPRBs

 - Fix assignment of bus resources in PCI code

 - Fix structure definition for set PCI function

 - Fix one compile error and one compile warning seen when
   CONFIG_OPTIMIZE_INLINING is enabled

* tag 's390-5.2-3' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux:
  MAINTAINERS: add Vasily Gorbik and Christian Borntraeger for s390
  MAINTAINERS: Farewell Martin Schwidefsky
  s390/crypto: fix possible sleep during spinlock aquired
  s390/crypto: fix gcm-aes-s390 selftest failures
  s390/zcrypt: Fix wrong dispatching for control domain CPRBs
  s390/pci: fix assignment of bus resources
  s390/pci: fix struct definition for set PCI function
  s390: mark __cpacf_check_opcode() and cpacf_query_func() as __always_inline
  s390: add unreachable() to dump_fault_info() to fix -Wmaybe-uninitialized
...@@ -3364,6 +3364,14 @@ S: Braunschweiger Strasse 79 ...@@ -3364,6 +3364,14 @@ S: Braunschweiger Strasse 79
S: 31134 Hildesheim S: 31134 Hildesheim
S: Germany S: Germany
N: Martin Schwidefsky
D: Martin was the most significant contributor to the initial s390
D: port of the Linux Kernel and later the maintainer of the s390
D: architecture backend for almost two decades.
D: He passed away in 2019, and will be greatly missed.
S: Germany
W: https://lwn.net/Articles/789028/
N: Marcel Selhorst N: Marcel Selhorst
E: tpmdd@selhorst.net E: tpmdd@selhorst.net
D: TPM driver D: TPM driver
......
...@@ -3049,8 +3049,9 @@ S: Maintained ...@@ -3049,8 +3049,9 @@ S: Maintained
F: arch/riscv/net/ F: arch/riscv/net/
BPF JIT for S390 BPF JIT for S390
M: Martin Schwidefsky <schwidefsky@de.ibm.com>
M: Heiko Carstens <heiko.carstens@de.ibm.com> M: Heiko Carstens <heiko.carstens@de.ibm.com>
M: Vasily Gorbik <gor@linux.ibm.com>
M: Christian Borntraeger <borntraeger@de.ibm.com>
L: netdev@vger.kernel.org L: netdev@vger.kernel.org
L: bpf@vger.kernel.org L: bpf@vger.kernel.org
S: Maintained S: Maintained
...@@ -13614,8 +13615,9 @@ S: Maintained ...@@ -13614,8 +13615,9 @@ S: Maintained
F: drivers/video/fbdev/savage/ F: drivers/video/fbdev/savage/
S390 S390
M: Martin Schwidefsky <schwidefsky@de.ibm.com>
M: Heiko Carstens <heiko.carstens@de.ibm.com> M: Heiko Carstens <heiko.carstens@de.ibm.com>
M: Vasily Gorbik <gor@linux.ibm.com>
M: Christian Borntraeger <borntraeger@de.ibm.com>
L: linux-s390@vger.kernel.org L: linux-s390@vger.kernel.org
W: http://www.ibm.com/developerworks/linux/linux390/ W: http://www.ibm.com/developerworks/linux/linux390/
T: git git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux.git T: git git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux.git
......
...@@ -27,14 +27,14 @@ ...@@ -27,14 +27,14 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/cpufeature.h> #include <linux/cpufeature.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/spinlock.h> #include <linux/mutex.h>
#include <linux/fips.h> #include <linux/fips.h>
#include <linux/string.h> #include <linux/string.h>
#include <crypto/xts.h> #include <crypto/xts.h>
#include <asm/cpacf.h> #include <asm/cpacf.h>
static u8 *ctrblk; static u8 *ctrblk;
static DEFINE_SPINLOCK(ctrblk_lock); static DEFINE_MUTEX(ctrblk_lock);
static cpacf_mask_t km_functions, kmc_functions, kmctr_functions, static cpacf_mask_t km_functions, kmc_functions, kmctr_functions,
kma_functions; kma_functions;
...@@ -698,7 +698,7 @@ static int ctr_aes_crypt(struct blkcipher_desc *desc, unsigned long modifier, ...@@ -698,7 +698,7 @@ static int ctr_aes_crypt(struct blkcipher_desc *desc, unsigned long modifier,
unsigned int n, nbytes; unsigned int n, nbytes;
int ret, locked; int ret, locked;
locked = spin_trylock(&ctrblk_lock); locked = mutex_trylock(&ctrblk_lock);
ret = blkcipher_walk_virt_block(desc, walk, AES_BLOCK_SIZE); ret = blkcipher_walk_virt_block(desc, walk, AES_BLOCK_SIZE);
while ((nbytes = walk->nbytes) >= AES_BLOCK_SIZE) { while ((nbytes = walk->nbytes) >= AES_BLOCK_SIZE) {
...@@ -716,7 +716,7 @@ static int ctr_aes_crypt(struct blkcipher_desc *desc, unsigned long modifier, ...@@ -716,7 +716,7 @@ static int ctr_aes_crypt(struct blkcipher_desc *desc, unsigned long modifier,
ret = blkcipher_walk_done(desc, walk, nbytes - n); ret = blkcipher_walk_done(desc, walk, nbytes - n);
} }
if (locked) if (locked)
spin_unlock(&ctrblk_lock); mutex_unlock(&ctrblk_lock);
/* /*
* final block may be < AES_BLOCK_SIZE, copy only nbytes * final block may be < AES_BLOCK_SIZE, copy only nbytes
*/ */
...@@ -826,19 +826,45 @@ static int gcm_aes_setauthsize(struct crypto_aead *tfm, unsigned int authsize) ...@@ -826,19 +826,45 @@ static int gcm_aes_setauthsize(struct crypto_aead *tfm, unsigned int authsize)
return 0; return 0;
} }
static void gcm_sg_walk_start(struct gcm_sg_walk *gw, struct scatterlist *sg, static void gcm_walk_start(struct gcm_sg_walk *gw, struct scatterlist *sg,
unsigned int len) unsigned int len)
{ {
memset(gw, 0, sizeof(*gw)); memset(gw, 0, sizeof(*gw));
gw->walk_bytes_remain = len; gw->walk_bytes_remain = len;
scatterwalk_start(&gw->walk, sg); scatterwalk_start(&gw->walk, sg);
} }
static int gcm_sg_walk_go(struct gcm_sg_walk *gw, unsigned int minbytesneeded) static inline unsigned int _gcm_sg_clamp_and_map(struct gcm_sg_walk *gw)
{
struct scatterlist *nextsg;
gw->walk_bytes = scatterwalk_clamp(&gw->walk, gw->walk_bytes_remain);
while (!gw->walk_bytes) {
nextsg = sg_next(gw->walk.sg);
if (!nextsg)
return 0;
scatterwalk_start(&gw->walk, nextsg);
gw->walk_bytes = scatterwalk_clamp(&gw->walk,
gw->walk_bytes_remain);
}
gw->walk_ptr = scatterwalk_map(&gw->walk);
return gw->walk_bytes;
}
static inline void _gcm_sg_unmap_and_advance(struct gcm_sg_walk *gw,
unsigned int nbytes)
{
gw->walk_bytes_remain -= nbytes;
scatterwalk_unmap(&gw->walk);
scatterwalk_advance(&gw->walk, nbytes);
scatterwalk_done(&gw->walk, 0, gw->walk_bytes_remain);
gw->walk_ptr = NULL;
}
static int gcm_in_walk_go(struct gcm_sg_walk *gw, unsigned int minbytesneeded)
{ {
int n; int n;
/* minbytesneeded <= AES_BLOCK_SIZE */
if (gw->buf_bytes && gw->buf_bytes >= minbytesneeded) { if (gw->buf_bytes && gw->buf_bytes >= minbytesneeded) {
gw->ptr = gw->buf; gw->ptr = gw->buf;
gw->nbytes = gw->buf_bytes; gw->nbytes = gw->buf_bytes;
...@@ -851,13 +877,11 @@ static int gcm_sg_walk_go(struct gcm_sg_walk *gw, unsigned int minbytesneeded) ...@@ -851,13 +877,11 @@ static int gcm_sg_walk_go(struct gcm_sg_walk *gw, unsigned int minbytesneeded)
goto out; goto out;
} }
gw->walk_bytes = scatterwalk_clamp(&gw->walk, gw->walk_bytes_remain); if (!_gcm_sg_clamp_and_map(gw)) {
if (!gw->walk_bytes) { gw->ptr = NULL;
scatterwalk_start(&gw->walk, sg_next(gw->walk.sg)); gw->nbytes = 0;
gw->walk_bytes = scatterwalk_clamp(&gw->walk, goto out;
gw->walk_bytes_remain);
} }
gw->walk_ptr = scatterwalk_map(&gw->walk);
if (!gw->buf_bytes && gw->walk_bytes >= minbytesneeded) { if (!gw->buf_bytes && gw->walk_bytes >= minbytesneeded) {
gw->ptr = gw->walk_ptr; gw->ptr = gw->walk_ptr;
...@@ -869,51 +893,90 @@ static int gcm_sg_walk_go(struct gcm_sg_walk *gw, unsigned int minbytesneeded) ...@@ -869,51 +893,90 @@ static int gcm_sg_walk_go(struct gcm_sg_walk *gw, unsigned int minbytesneeded)
n = min(gw->walk_bytes, AES_BLOCK_SIZE - gw->buf_bytes); n = min(gw->walk_bytes, AES_BLOCK_SIZE - gw->buf_bytes);
memcpy(gw->buf + gw->buf_bytes, gw->walk_ptr, n); memcpy(gw->buf + gw->buf_bytes, gw->walk_ptr, n);
gw->buf_bytes += n; gw->buf_bytes += n;
gw->walk_bytes_remain -= n; _gcm_sg_unmap_and_advance(gw, n);
scatterwalk_unmap(&gw->walk);
scatterwalk_advance(&gw->walk, n);
scatterwalk_done(&gw->walk, 0, gw->walk_bytes_remain);
if (gw->buf_bytes >= minbytesneeded) { if (gw->buf_bytes >= minbytesneeded) {
gw->ptr = gw->buf; gw->ptr = gw->buf;
gw->nbytes = gw->buf_bytes; gw->nbytes = gw->buf_bytes;
goto out; goto out;
} }
if (!_gcm_sg_clamp_and_map(gw)) {
gw->walk_bytes = scatterwalk_clamp(&gw->walk, gw->ptr = NULL;
gw->walk_bytes_remain); gw->nbytes = 0;
if (!gw->walk_bytes) { goto out;
scatterwalk_start(&gw->walk, sg_next(gw->walk.sg));
gw->walk_bytes = scatterwalk_clamp(&gw->walk,
gw->walk_bytes_remain);
} }
gw->walk_ptr = scatterwalk_map(&gw->walk);
} }
out: out:
return gw->nbytes; return gw->nbytes;
} }
static void gcm_sg_walk_done(struct gcm_sg_walk *gw, unsigned int bytesdone) static int gcm_out_walk_go(struct gcm_sg_walk *gw, unsigned int minbytesneeded)
{ {
int n; if (gw->walk_bytes_remain == 0) {
gw->ptr = NULL;
gw->nbytes = 0;
goto out;
}
if (!_gcm_sg_clamp_and_map(gw)) {
gw->ptr = NULL;
gw->nbytes = 0;
goto out;
}
if (gw->walk_bytes >= minbytesneeded) {
gw->ptr = gw->walk_ptr;
gw->nbytes = gw->walk_bytes;
goto out;
}
scatterwalk_unmap(&gw->walk);
gw->walk_ptr = NULL;
gw->ptr = gw->buf;
gw->nbytes = sizeof(gw->buf);
out:
return gw->nbytes;
}
static int gcm_in_walk_done(struct gcm_sg_walk *gw, unsigned int bytesdone)
{
if (gw->ptr == NULL) if (gw->ptr == NULL)
return; return 0;
if (gw->ptr == gw->buf) { if (gw->ptr == gw->buf) {
n = gw->buf_bytes - bytesdone; int n = gw->buf_bytes - bytesdone;
if (n > 0) { if (n > 0) {
memmove(gw->buf, gw->buf + bytesdone, n); memmove(gw->buf, gw->buf + bytesdone, n);
gw->buf_bytes -= n; gw->buf_bytes = n;
} else } else
gw->buf_bytes = 0; gw->buf_bytes = 0;
} else { } else
gw->walk_bytes_remain -= bytesdone; _gcm_sg_unmap_and_advance(gw, bytesdone);
scatterwalk_unmap(&gw->walk);
scatterwalk_advance(&gw->walk, bytesdone); return bytesdone;
scatterwalk_done(&gw->walk, 0, gw->walk_bytes_remain); }
}
static int gcm_out_walk_done(struct gcm_sg_walk *gw, unsigned int bytesdone)
{
int i, n;
if (gw->ptr == NULL)
return 0;
if (gw->ptr == gw->buf) {
for (i = 0; i < bytesdone; i += n) {
if (!_gcm_sg_clamp_and_map(gw))
return i;
n = min(gw->walk_bytes, bytesdone - i);
memcpy(gw->walk_ptr, gw->buf + i, n);
_gcm_sg_unmap_and_advance(gw, n);
}
} else
_gcm_sg_unmap_and_advance(gw, bytesdone);
return bytesdone;
} }
static int gcm_aes_crypt(struct aead_request *req, unsigned int flags) static int gcm_aes_crypt(struct aead_request *req, unsigned int flags)
...@@ -926,7 +989,7 @@ static int gcm_aes_crypt(struct aead_request *req, unsigned int flags) ...@@ -926,7 +989,7 @@ static int gcm_aes_crypt(struct aead_request *req, unsigned int flags)
unsigned int pclen = req->cryptlen; unsigned int pclen = req->cryptlen;
int ret = 0; int ret = 0;
unsigned int len, in_bytes, out_bytes, unsigned int n, len, in_bytes, out_bytes,
min_bytes, bytes, aad_bytes, pc_bytes; min_bytes, bytes, aad_bytes, pc_bytes;
struct gcm_sg_walk gw_in, gw_out; struct gcm_sg_walk gw_in, gw_out;
u8 tag[GHASH_DIGEST_SIZE]; u8 tag[GHASH_DIGEST_SIZE];
...@@ -963,14 +1026,14 @@ static int gcm_aes_crypt(struct aead_request *req, unsigned int flags) ...@@ -963,14 +1026,14 @@ static int gcm_aes_crypt(struct aead_request *req, unsigned int flags)
*(u32 *)(param.j0 + ivsize) = 1; *(u32 *)(param.j0 + ivsize) = 1;
memcpy(param.k, ctx->key, ctx->key_len); memcpy(param.k, ctx->key, ctx->key_len);
gcm_sg_walk_start(&gw_in, req->src, len); gcm_walk_start(&gw_in, req->src, len);
gcm_sg_walk_start(&gw_out, req->dst, len); gcm_walk_start(&gw_out, req->dst, len);
do { do {
min_bytes = min_t(unsigned int, min_bytes = min_t(unsigned int,
aadlen > 0 ? aadlen : pclen, AES_BLOCK_SIZE); aadlen > 0 ? aadlen : pclen, AES_BLOCK_SIZE);
in_bytes = gcm_sg_walk_go(&gw_in, min_bytes); in_bytes = gcm_in_walk_go(&gw_in, min_bytes);
out_bytes = gcm_sg_walk_go(&gw_out, min_bytes); out_bytes = gcm_out_walk_go(&gw_out, min_bytes);
bytes = min(in_bytes, out_bytes); bytes = min(in_bytes, out_bytes);
if (aadlen + pclen <= bytes) { if (aadlen + pclen <= bytes) {
...@@ -997,8 +1060,11 @@ static int gcm_aes_crypt(struct aead_request *req, unsigned int flags) ...@@ -997,8 +1060,11 @@ static int gcm_aes_crypt(struct aead_request *req, unsigned int flags)
gw_in.ptr + aad_bytes, pc_bytes, gw_in.ptr + aad_bytes, pc_bytes,
gw_in.ptr, aad_bytes); gw_in.ptr, aad_bytes);
gcm_sg_walk_done(&gw_in, aad_bytes + pc_bytes); n = aad_bytes + pc_bytes;
gcm_sg_walk_done(&gw_out, aad_bytes + pc_bytes); if (gcm_in_walk_done(&gw_in, n) != n)
return -ENOMEM;
if (gcm_out_walk_done(&gw_out, n) != n)
return -ENOMEM;
aadlen -= aad_bytes; aadlen -= aad_bytes;
pclen -= pc_bytes; pclen -= pc_bytes;
} while (aadlen + pclen > 0); } while (aadlen + pclen > 0);
......
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#include <linux/cpufeature.h> #include <linux/cpufeature.h>
#include <linux/crypto.h> #include <linux/crypto.h>
#include <linux/fips.h> #include <linux/fips.h>
#include <linux/mutex.h>
#include <crypto/algapi.h> #include <crypto/algapi.h>
#include <crypto/des.h> #include <crypto/des.h>
#include <asm/cpacf.h> #include <asm/cpacf.h>
...@@ -21,7 +22,7 @@ ...@@ -21,7 +22,7 @@
#define DES3_KEY_SIZE (3 * DES_KEY_SIZE) #define DES3_KEY_SIZE (3 * DES_KEY_SIZE)
static u8 *ctrblk; static u8 *ctrblk;
static DEFINE_SPINLOCK(ctrblk_lock); static DEFINE_MUTEX(ctrblk_lock);
static cpacf_mask_t km_functions, kmc_functions, kmctr_functions; static cpacf_mask_t km_functions, kmc_functions, kmctr_functions;
...@@ -374,7 +375,7 @@ static int ctr_desall_crypt(struct blkcipher_desc *desc, unsigned long fc, ...@@ -374,7 +375,7 @@ static int ctr_desall_crypt(struct blkcipher_desc *desc, unsigned long fc,
unsigned int n, nbytes; unsigned int n, nbytes;
int ret, locked; int ret, locked;
locked = spin_trylock(&ctrblk_lock); locked = mutex_trylock(&ctrblk_lock);
ret = blkcipher_walk_virt_block(desc, walk, DES_BLOCK_SIZE); ret = blkcipher_walk_virt_block(desc, walk, DES_BLOCK_SIZE);
while ((nbytes = walk->nbytes) >= DES_BLOCK_SIZE) { while ((nbytes = walk->nbytes) >= DES_BLOCK_SIZE) {
...@@ -391,7 +392,7 @@ static int ctr_desall_crypt(struct blkcipher_desc *desc, unsigned long fc, ...@@ -391,7 +392,7 @@ static int ctr_desall_crypt(struct blkcipher_desc *desc, unsigned long fc,
ret = blkcipher_walk_done(desc, walk, nbytes - n); ret = blkcipher_walk_done(desc, walk, nbytes - n);
} }
if (locked) if (locked)
spin_unlock(&ctrblk_lock); mutex_unlock(&ctrblk_lock);
/* final block may be < DES_BLOCK_SIZE, copy only nbytes */ /* final block may be < DES_BLOCK_SIZE, copy only nbytes */
if (nbytes) { if (nbytes) {
cpacf_kmctr(fc, ctx->key, buf, walk->src.virt.addr, cpacf_kmctr(fc, ctx->key, buf, walk->src.virt.addr,
......
...@@ -160,8 +160,8 @@ struct ap_config_info { ...@@ -160,8 +160,8 @@ struct ap_config_info {
unsigned char Nd; /* max # of Domains - 1 */ unsigned char Nd; /* max # of Domains - 1 */
unsigned char _reserved3[10]; unsigned char _reserved3[10];
unsigned int apm[8]; /* AP ID mask */ unsigned int apm[8]; /* AP ID mask */
unsigned int aqm[8]; /* AP queue mask */ unsigned int aqm[8]; /* AP (usage) queue mask */
unsigned int adm[8]; /* AP domain mask */ unsigned int adm[8]; /* AP (control) domain mask */
unsigned char _reserved4[16]; unsigned char _reserved4[16];
} __aligned(8); } __aligned(8);
......
...@@ -178,7 +178,7 @@ static inline void __cpacf_query(unsigned int opcode, cpacf_mask_t *mask) ...@@ -178,7 +178,7 @@ static inline void __cpacf_query(unsigned int opcode, cpacf_mask_t *mask)
: "cc"); : "cc");
} }
static inline int __cpacf_check_opcode(unsigned int opcode) static __always_inline int __cpacf_check_opcode(unsigned int opcode)
{ {
switch (opcode) { switch (opcode) {
case CPACF_KMAC: case CPACF_KMAC:
...@@ -218,7 +218,7 @@ static inline int cpacf_test_func(cpacf_mask_t *mask, unsigned int func) ...@@ -218,7 +218,7 @@ static inline int cpacf_test_func(cpacf_mask_t *mask, unsigned int func)
return (mask->bytes[func >> 3] & (0x80 >> (func & 7))) != 0; return (mask->bytes[func >> 3] & (0x80 >> (func & 7))) != 0;
} }
static inline int cpacf_query_func(unsigned int opcode, unsigned int func) static __always_inline int cpacf_query_func(unsigned int opcode, unsigned int func)
{ {
cpacf_mask_t mask; cpacf_mask_t mask;
......
...@@ -70,6 +70,17 @@ struct clp_rsp_list_pci { ...@@ -70,6 +70,17 @@ struct clp_rsp_list_pci {
struct clp_fh_list_entry fh_list[CLP_FH_LIST_NR_ENTRIES]; struct clp_fh_list_entry fh_list[CLP_FH_LIST_NR_ENTRIES];
} __packed; } __packed;
struct mio_info {
u32 valid : 6;
u32 : 26;
u32 : 32;
struct {
u64 wb;
u64 wt;
} addr[PCI_BAR_COUNT];
u32 reserved[6];
} __packed;
/* Query PCI function request */ /* Query PCI function request */
struct clp_req_query_pci { struct clp_req_query_pci {
struct clp_req_hdr hdr; struct clp_req_hdr hdr;
...@@ -100,14 +111,7 @@ struct clp_rsp_query_pci { ...@@ -100,14 +111,7 @@ struct clp_rsp_query_pci {
u32 uid; /* user defined id */ u32 uid; /* user defined id */
u8 util_str[CLP_UTIL_STR_LEN]; /* utility string */ u8 util_str[CLP_UTIL_STR_LEN]; /* utility string */
u32 reserved2[16]; u32 reserved2[16];
u32 mio_valid : 6; struct mio_info mio;
u32 : 26;
u32 : 32;
struct {
u64 wb;
u64 wt;
} addr[PCI_BAR_COUNT];
u32 reserved3[6];
} __packed; } __packed;
/* Query PCI function group request */ /* Query PCI function group request */
...@@ -155,8 +159,9 @@ struct clp_req_set_pci { ...@@ -155,8 +159,9 @@ struct clp_req_set_pci {
struct clp_rsp_set_pci { struct clp_rsp_set_pci {
struct clp_rsp_hdr hdr; struct clp_rsp_hdr hdr;
u32 fh; /* function handle */ u32 fh; /* function handle */
u32 reserved3; u32 reserved1;
u64 reserved4; u64 reserved2;
struct mio_info mio;
} __packed; } __packed;
/* Combined request/response block structures used by clp insn */ /* Combined request/response block structures used by clp insn */
......
...@@ -85,7 +85,7 @@ static inline int notify_page_fault(struct pt_regs *regs) ...@@ -85,7 +85,7 @@ static inline int notify_page_fault(struct pt_regs *regs)
* Find out which address space caused the exception. * Find out which address space caused the exception.
* Access register mode is impossible, ignore space == 3. * Access register mode is impossible, ignore space == 3.
*/ */
static inline enum fault_type get_fault_type(struct pt_regs *regs) static enum fault_type get_fault_type(struct pt_regs *regs)
{ {
unsigned long trans_exc_code; unsigned long trans_exc_code;
...@@ -211,6 +211,8 @@ static void dump_fault_info(struct pt_regs *regs) ...@@ -211,6 +211,8 @@ static void dump_fault_info(struct pt_regs *regs)
asce = S390_lowcore.kernel_asce; asce = S390_lowcore.kernel_asce;
pr_cont("kernel "); pr_cont("kernel ");
break; break;
default:
unreachable();
} }
pr_cont("ASCE.\n"); pr_cont("ASCE.\n");
dump_pagetable(asce, regs->int_parm_long & __FAIL_ADDR_MASK); dump_pagetable(asce, regs->int_parm_long & __FAIL_ADDR_MASK);
......
...@@ -528,7 +528,10 @@ static int zpci_setup_bus_resources(struct zpci_dev *zdev, ...@@ -528,7 +528,10 @@ static int zpci_setup_bus_resources(struct zpci_dev *zdev,
if (zdev->bars[i].val & 4) if (zdev->bars[i].val & 4)
flags |= IORESOURCE_MEM_64; flags |= IORESOURCE_MEM_64;
addr = ZPCI_ADDR(entry); if (static_branch_likely(&have_mio))
addr = (unsigned long) zdev->bars[i].mio_wb;
else
addr = ZPCI_ADDR(entry);
size = 1UL << zdev->bars[i].size; size = 1UL << zdev->bars[i].size;
res = __alloc_res(zdev, addr, size, flags); res = __alloc_res(zdev, addr, size, flags);
......
...@@ -165,11 +165,11 @@ static int clp_store_query_pci_fn(struct zpci_dev *zdev, ...@@ -165,11 +165,11 @@ static int clp_store_query_pci_fn(struct zpci_dev *zdev,
} }
zdev->mio_capable = response->mio_addr_avail; zdev->mio_capable = response->mio_addr_avail;
for (i = 0; i < PCI_BAR_COUNT; i++) { for (i = 0; i < PCI_BAR_COUNT; i++) {
if (!(response->mio_valid & (1 << (PCI_BAR_COUNT - i - 1)))) if (!(response->mio.valid & (1 << (PCI_BAR_COUNT - i - 1))))
continue; continue;
zdev->bars[i].mio_wb = (void __iomem *) response->addr[i].wb; zdev->bars[i].mio_wb = (void __iomem *) response->mio.addr[i].wb;
zdev->bars[i].mio_wt = (void __iomem *) response->addr[i].wt; zdev->bars[i].mio_wt = (void __iomem *) response->mio.addr[i].wt;
} }
return 0; return 0;
} }
......
...@@ -254,19 +254,37 @@ static inline int ap_test_config_card_id(unsigned int id) ...@@ -254,19 +254,37 @@ static inline int ap_test_config_card_id(unsigned int id)
} }
/* /*
* ap_test_config_domain(): Test, whether an AP usage domain is configured. * ap_test_config_usage_domain(): Test, whether an AP usage domain
* is configured.
* @domain AP usage domain ID * @domain AP usage domain ID
* *
* Returns 0 if the usage domain is not configured * Returns 0 if the usage domain is not configured
* 1 if the usage domain is configured or * 1 if the usage domain is configured or
* if the configuration information is not available * if the configuration information is not available
*/ */
static inline int ap_test_config_domain(unsigned int domain) int ap_test_config_usage_domain(unsigned int domain)
{ {
if (!ap_configuration) /* QCI not supported */ if (!ap_configuration) /* QCI not supported */
return domain < 16; return domain < 16;
return ap_test_config(ap_configuration->aqm, domain); return ap_test_config(ap_configuration->aqm, domain);
} }
EXPORT_SYMBOL(ap_test_config_usage_domain);
/*
* ap_test_config_ctrl_domain(): Test, whether an AP control domain
* is configured.
* @domain AP control domain ID
*
* Returns 1 if the control domain is configured
* 0 in all other cases
*/
int ap_test_config_ctrl_domain(unsigned int domain)
{
if (!ap_configuration) /* QCI not supported */
return 0;
return ap_test_config(ap_configuration->adm, domain);
}
EXPORT_SYMBOL(ap_test_config_ctrl_domain);
/** /**
* ap_query_queue(): Check if an AP queue is available. * ap_query_queue(): Check if an AP queue is available.
...@@ -1267,7 +1285,7 @@ static void ap_select_domain(void) ...@@ -1267,7 +1285,7 @@ static void ap_select_domain(void)
best_domain = -1; best_domain = -1;
max_count = 0; max_count = 0;
for (i = 0; i < AP_DOMAINS; i++) { for (i = 0; i < AP_DOMAINS; i++) {
if (!ap_test_config_domain(i) || if (!ap_test_config_usage_domain(i) ||
!test_bit_inv(i, ap_perms.aqm)) !test_bit_inv(i, ap_perms.aqm))
continue; continue;
count = 0; count = 0;
...@@ -1442,7 +1460,7 @@ static void _ap_scan_bus_adapter(int id) ...@@ -1442,7 +1460,7 @@ static void _ap_scan_bus_adapter(int id)
(void *)(long) qid, (void *)(long) qid,
__match_queue_device_with_qid); __match_queue_device_with_qid);
aq = dev ? to_ap_queue(dev) : NULL; aq = dev ? to_ap_queue(dev) : NULL;
if (!ap_test_config_domain(dom)) { if (!ap_test_config_usage_domain(dom)) {
if (dev) { if (dev) {
/* Queue device exists but has been /* Queue device exists but has been
* removed from configuration. * removed from configuration.
......
...@@ -251,6 +251,9 @@ void ap_wait(enum ap_wait wait); ...@@ -251,6 +251,9 @@ void ap_wait(enum ap_wait wait);
void ap_request_timeout(struct timer_list *t); void ap_request_timeout(struct timer_list *t);
void ap_bus_force_rescan(void); void ap_bus_force_rescan(void);
int ap_test_config_usage_domain(unsigned int domain);
int ap_test_config_ctrl_domain(unsigned int domain);
void ap_queue_init_reply(struct ap_queue *aq, struct ap_message *ap_msg); void ap_queue_init_reply(struct ap_queue *aq, struct ap_message *ap_msg);
struct ap_queue *ap_queue_create(ap_qid_t qid, int device_type); struct ap_queue *ap_queue_create(ap_qid_t qid, int device_type);
void ap_queue_prepare_remove(struct ap_queue *aq); void ap_queue_prepare_remove(struct ap_queue *aq);
......
...@@ -822,7 +822,7 @@ static long _zcrypt_send_cprb(struct ap_perms *perms, ...@@ -822,7 +822,7 @@ static long _zcrypt_send_cprb(struct ap_perms *perms,
struct ap_message ap_msg; struct ap_message ap_msg;
unsigned int weight, pref_weight; unsigned int weight, pref_weight;
unsigned int func_code; unsigned int func_code;
unsigned short *domain; unsigned short *domain, tdom;
int qid = 0, rc = -ENODEV; int qid = 0, rc = -ENODEV;
struct module *mod; struct module *mod;
...@@ -834,6 +834,17 @@ static long _zcrypt_send_cprb(struct ap_perms *perms, ...@@ -834,6 +834,17 @@ static long _zcrypt_send_cprb(struct ap_perms *perms,
if (rc) if (rc)
goto out; goto out;
/*
* If a valid target domain is set and this domain is NOT a usage
* domain but a control only domain, use the default domain as target.
*/
tdom = *domain;
if (tdom >= 0 && tdom < AP_DOMAINS &&
!ap_test_config_usage_domain(tdom) &&
ap_test_config_ctrl_domain(tdom) &&
ap_domain_index >= 0)
tdom = ap_domain_index;
pref_zc = NULL; pref_zc = NULL;
pref_zq = NULL; pref_zq = NULL;
spin_lock(&zcrypt_list_lock); spin_lock(&zcrypt_list_lock);
...@@ -856,8 +867,8 @@ static long _zcrypt_send_cprb(struct ap_perms *perms, ...@@ -856,8 +867,8 @@ static long _zcrypt_send_cprb(struct ap_perms *perms,
/* check if device is online and eligible */ /* check if device is online and eligible */
if (!zq->online || if (!zq->online ||
!zq->ops->send_cprb || !zq->ops->send_cprb ||
((*domain != (unsigned short) AUTOSELECT) && (tdom != (unsigned short) AUTOSELECT &&
(*domain != AP_QID_QUEUE(zq->queue->qid)))) tdom != AP_QID_QUEUE(zq->queue->qid)))
continue; continue;
/* check if device node has admission for this queue */ /* check if device node has admission for this queue */
if (!zcrypt_check_queue(perms, if (!zcrypt_check_queue(perms,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册