diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2018-06-05 11:13:17 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2018-06-05 11:13:17 -0700 |
commit | 5037be168f0e4ee910602935b1180291082d3aac (patch) | |
tree | 57274da3467dccd7650d4107d3a352c9d3b892dd /drivers/s390 | |
parent | eab733afcb85f4a218540890f25dfb497d44a979 (diff) | |
parent | 89a0c0ec0d2e3ce0ee9caa00f60c0c26ccf11c21 (diff) | |
download | blackbird-op-linux-5037be168f0e4ee910602935b1180291082d3aac.tar.gz blackbird-op-linux-5037be168f0e4ee910602935b1180291082d3aac.zip |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux
Pull s390 updates from Martin Schwidefsky:
- A rework for the s390 arch random code, the TRNG instruction is
rather slow and should not be used on the interrupt path
- A fix for a memory leak in the zcrypt driver
- Changes to the early boot code to add a compile time check for code
that may not use the .bss section, with the goal to avoid initrd
corruptions
- Add an interface to get the physical network ID (pnetid), this is
useful to group network devices that are attached to the same network
- Some cleanup for the linker script
- Some code improvement for the dasd driver
- Two fixes for the perf sampling support
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux:
s390/zcrypt: Fix CCA and EP11 CPRB processing failure memory leak.
s390/archrandom: Rework arch random implementation.
s390/net: add pnetid support
s390/dasd: simplify locking in dasd_times_out
s390/cio: add test for ccwgroup device
s390/cio: add helper to query utility strings per given ccw device
s390: remove no-op macro VMLINUX_SYMBOL()
s390: remove closung punctuation from spectre messages
s390: introduce compile time check for empty .bss section
s390/early: move functions which may not access bss section to extra file
s390/early: get rid of #ifdef CONFIG_BLK_DEV_INITRD
s390/early: get rid of memmove_early
s390/cpum_sf: Add data entry sizes to sampling trailer entry
perf: fix invalid bit in diagnostic entry
Diffstat (limited to 'drivers/s390')
-rw-r--r-- | drivers/s390/block/dasd.c | 31 | ||||
-rw-r--r-- | drivers/s390/char/Makefile | 3 | ||||
-rw-r--r-- | drivers/s390/cio/ccwgroup.c | 6 | ||||
-rw-r--r-- | drivers/s390/cio/device_ops.c | 31 | ||||
-rw-r--r-- | drivers/s390/crypto/ap_bus.h | 17 | ||||
-rw-r--r-- | drivers/s390/crypto/zcrypt_api.c | 15 | ||||
-rw-r--r-- | drivers/s390/crypto/zcrypt_msgtype6.c | 51 |
7 files changed, 100 insertions, 54 deletions
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c index cb9b685118da..73cce3ecb97f 100644 --- a/drivers/s390/block/dasd.c +++ b/drivers/s390/block/dasd.c @@ -2569,14 +2569,11 @@ EXPORT_SYMBOL(dasd_sleep_on_immediatly); * Cancellation of a request is an asynchronous operation! The calling * function has to wait until the request is properly returned via callback. */ -int dasd_cancel_req(struct dasd_ccw_req *cqr) +static int __dasd_cancel_req(struct dasd_ccw_req *cqr) { struct dasd_device *device = cqr->startdev; - unsigned long flags; - int rc; + int rc = 0; - rc = 0; - spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags); switch (cqr->status) { case DASD_CQR_QUEUED: /* request was not started - just set to cleared */ @@ -2596,11 +2593,21 @@ int dasd_cancel_req(struct dasd_ccw_req *cqr) default: /* already finished or clear pending - do nothing */ break; } - spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags); dasd_schedule_device_bh(device); return rc; } -EXPORT_SYMBOL(dasd_cancel_req); + +int dasd_cancel_req(struct dasd_ccw_req *cqr) +{ + struct dasd_device *device = cqr->startdev; + unsigned long flags; + int rc; + + spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags); + rc = __dasd_cancel_req(cqr); + spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags); + return rc; +} /* * SECTION: Operations of the dasd_block layer. @@ -3084,12 +3091,10 @@ enum blk_eh_timer_return dasd_times_out(struct request *req, bool reserved) cqr->retries = -1; cqr->intrc = -ETIMEDOUT; if (cqr->status >= DASD_CQR_QUEUED) { - spin_unlock(get_ccwdev_lock(device->cdev)); - rc = dasd_cancel_req(cqr); + rc = __dasd_cancel_req(cqr); } else if (cqr->status == DASD_CQR_FILLED || cqr->status == DASD_CQR_NEED_ERP) { cqr->status = DASD_CQR_TERMINATED; - spin_unlock(get_ccwdev_lock(device->cdev)); } else if (cqr->status == DASD_CQR_IN_ERP) { struct dasd_ccw_req *searchcqr, *nextcqr, *tmpcqr; @@ -3104,9 +3109,7 @@ enum blk_eh_timer_return dasd_times_out(struct request *req, bool reserved) searchcqr->retries = -1; searchcqr->intrc = -ETIMEDOUT; if (searchcqr->status >= DASD_CQR_QUEUED) { - spin_unlock(get_ccwdev_lock(device->cdev)); - rc = dasd_cancel_req(searchcqr); - spin_lock(get_ccwdev_lock(device->cdev)); + rc = __dasd_cancel_req(searchcqr); } else if ((searchcqr->status == DASD_CQR_FILLED) || (searchcqr->status == DASD_CQR_NEED_ERP)) { searchcqr->status = DASD_CQR_TERMINATED; @@ -3120,8 +3123,8 @@ enum blk_eh_timer_return dasd_times_out(struct request *req, bool reserved) } break; } - spin_unlock(get_ccwdev_lock(device->cdev)); } + spin_unlock(get_ccwdev_lock(device->cdev)); dasd_schedule_block_bh(block); spin_unlock(&block->queue_lock); spin_unlock_irqrestore(&cqr->dq->lock, flags); diff --git a/drivers/s390/char/Makefile b/drivers/s390/char/Makefile index d049e2d74484..0a4c13e1e76e 100644 --- a/drivers/s390/char/Makefile +++ b/drivers/s390/char/Makefile @@ -54,3 +54,6 @@ obj-$(CONFIG_CRASH_DUMP) += sclp_sdias.o zcore.o hmcdrv-objs := hmcdrv_mod.o hmcdrv_dev.o hmcdrv_ftp.o hmcdrv_cache.o diag_ftp.o sclp_ftp.o obj-$(CONFIG_HMC_DRV) += hmcdrv.o + +chkbss := sclp_early_core.o +include $(srctree)/arch/s390/scripts/Makefile.chkbss diff --git a/drivers/s390/cio/ccwgroup.c b/drivers/s390/cio/ccwgroup.c index 5535312602af..db9c854088bc 100644 --- a/drivers/s390/cio/ccwgroup.c +++ b/drivers/s390/cio/ccwgroup.c @@ -561,6 +561,12 @@ static struct bus_type ccwgroup_bus_type = { .pm = &ccwgroup_pm_ops, }; +bool dev_is_ccwgroup(struct device *dev) +{ + return dev->bus == &ccwgroup_bus_type; +} +EXPORT_SYMBOL(dev_is_ccwgroup); + /** * ccwgroup_driver_register() - register a ccw group driver * @cdriver: driver to be registered diff --git a/drivers/s390/cio/device_ops.c b/drivers/s390/cio/device_ops.c index aecfebb74157..4435ae0b3027 100644 --- a/drivers/s390/cio/device_ops.c +++ b/drivers/s390/cio/device_ops.c @@ -473,6 +473,36 @@ struct channel_path_desc_fmt0 *ccw_device_get_chp_desc(struct ccw_device *cdev, } /** + * ccw_device_get_util_str() - return newly allocated utility strings + * @cdev: device to obtain the utility strings for + * @chp_idx: index of the channel path + * + * On success return a newly allocated copy of the utility strings + * associated with the given channel path. Return %NULL on error. + */ +u8 *ccw_device_get_util_str(struct ccw_device *cdev, int chp_idx) +{ + struct subchannel *sch = to_subchannel(cdev->dev.parent); + struct channel_path *chp; + struct chp_id chpid; + u8 *util_str; + + chp_id_init(&chpid); + chpid.id = sch->schib.pmcw.chpid[chp_idx]; + chp = chpid_to_chp(chpid); + + util_str = kmalloc(sizeof(chp->desc_fmt3.util_str), GFP_KERNEL); + if (!util_str) + return NULL; + + mutex_lock(&chp->lock); + memcpy(util_str, chp->desc_fmt3.util_str, sizeof(chp->desc_fmt3.util_str)); + mutex_unlock(&chp->lock); + + return util_str; +} + +/** * ccw_device_get_id() - obtain a ccw device id * @cdev: device to obtain the id for * @dev_id: where to fill in the values @@ -682,3 +712,4 @@ EXPORT_SYMBOL(ccw_device_start_key); EXPORT_SYMBOL(ccw_device_get_ciw); EXPORT_SYMBOL(ccw_device_get_path_mask); EXPORT_SYMBOL_GPL(ccw_device_get_chp_desc); +EXPORT_SYMBOL_GPL(ccw_device_get_util_str); diff --git a/drivers/s390/crypto/ap_bus.h b/drivers/s390/crypto/ap_bus.h index 02184cf35834..6a273c5ebca5 100644 --- a/drivers/s390/crypto/ap_bus.h +++ b/drivers/s390/crypto/ap_bus.h @@ -198,11 +198,18 @@ struct ap_message { */ static inline void ap_init_message(struct ap_message *ap_msg) { - ap_msg->psmid = 0; - ap_msg->length = 0; - ap_msg->rc = 0; - ap_msg->special = 0; - ap_msg->receive = NULL; + memset(ap_msg, 0, sizeof(*ap_msg)); +} + +/** + * ap_release_message() - Release ap_message. + * Releases all memory used internal within the ap_message struct + * Currently this is the message and private field. + */ +static inline void ap_release_message(struct ap_message *ap_msg) +{ + kzfree(ap_msg->message); + kzfree(ap_msg->private); } #define for_each_ap_card(_ac) \ diff --git a/drivers/s390/crypto/zcrypt_api.c b/drivers/s390/crypto/zcrypt_api.c index 5efd84862ccb..febcdb5135bf 100644 --- a/drivers/s390/crypto/zcrypt_api.c +++ b/drivers/s390/crypto/zcrypt_api.c @@ -371,6 +371,7 @@ long zcrypt_send_cprb(struct ica_xcRB *xcRB) trace_s390_zcrypt_req(xcRB, TB_ZSECSENDCPRB); + ap_init_message(&ap_msg); rc = get_cprb_fc(xcRB, &ap_msg, &func_code, &domain); if (rc) goto out; @@ -425,6 +426,7 @@ long zcrypt_send_cprb(struct ica_xcRB *xcRB) spin_unlock(&zcrypt_list_lock); out: + ap_release_message(&ap_msg); trace_s390_zcrypt_rep(xcRB, func_code, rc, AP_QID_CARD(qid), AP_QID_QUEUE(qid)); return rc; @@ -468,6 +470,8 @@ static long zcrypt_send_ep11_cprb(struct ep11_urb *xcrb) trace_s390_zcrypt_req(xcrb, TP_ZSENDEP11CPRB); + ap_init_message(&ap_msg); + target_num = (unsigned short) xcrb->targets_num; /* empty list indicates autoselect (all available targets) */ @@ -485,7 +489,7 @@ static long zcrypt_send_ep11_cprb(struct ep11_urb *xcrb) if (copy_from_user(targets, uptr, target_num * sizeof(*targets))) { rc = -EFAULT; - goto out; + goto out_free; } } @@ -542,6 +546,7 @@ static long zcrypt_send_ep11_cprb(struct ep11_urb *xcrb) out_free: kfree(targets); out: + ap_release_message(&ap_msg); trace_s390_zcrypt_rep(xcrb, func_code, rc, AP_QID_CARD(qid), AP_QID_QUEUE(qid)); return rc; @@ -559,6 +564,7 @@ static long zcrypt_rng(char *buffer) trace_s390_zcrypt_req(buffer, TP_HWRNGCPRB); + ap_init_message(&ap_msg); rc = get_rng_fc(&ap_msg, &func_code, &domain); if (rc) goto out; @@ -589,8 +595,10 @@ static long zcrypt_rng(char *buffer) pref_zq = zcrypt_pick_queue(pref_zc, pref_zq, weight); spin_unlock(&zcrypt_list_lock); - if (!pref_zq) - return -ENODEV; + if (!pref_zq) { + rc = -ENODEV; + goto out; + } qid = pref_zq->queue->qid; rc = pref_zq->ops->rng(pref_zq, buffer, &ap_msg); @@ -600,6 +608,7 @@ static long zcrypt_rng(char *buffer) spin_unlock(&zcrypt_list_lock); out: + ap_release_message(&ap_msg); trace_s390_zcrypt_rep(buffer, func_code, rc, AP_QID_CARD(qid), AP_QID_QUEUE(qid)); return rc; diff --git a/drivers/s390/crypto/zcrypt_msgtype6.c b/drivers/s390/crypto/zcrypt_msgtype6.c index f54bef4a928e..97d4bacbc442 100644 --- a/drivers/s390/crypto/zcrypt_msgtype6.c +++ b/drivers/s390/crypto/zcrypt_msgtype6.c @@ -1084,6 +1084,13 @@ out_free: return rc; } +/** + * Fetch function code from cprb. + * Extracting the fc requires to copy the cprb from userspace. + * So this function allocates memory and needs an ap_msg prepared + * by the caller with ap_init_message(). Also the caller has to + * make sure ap_release_message() is always called even on failure. + */ unsigned int get_cprb_fc(struct ica_xcRB *xcRB, struct ap_message *ap_msg, unsigned int *func_code, unsigned short **dom) @@ -1091,9 +1098,7 @@ unsigned int get_cprb_fc(struct ica_xcRB *xcRB, struct response_type resp_type = { .type = PCIXCC_RESPONSE_TYPE_XCRB, }; - int rc; - ap_init_message(ap_msg); ap_msg->message = kmalloc(MSGTYPE06_MAX_MSG_SIZE, GFP_KERNEL); if (!ap_msg->message) return -ENOMEM; @@ -1101,17 +1106,10 @@ unsigned int get_cprb_fc(struct ica_xcRB *xcRB, ap_msg->psmid = (((unsigned long long) current->pid) << 32) + atomic_inc_return(&zcrypt_step); ap_msg->private = kmalloc(sizeof(resp_type), GFP_KERNEL); - if (!ap_msg->private) { - kzfree(ap_msg->message); + if (!ap_msg->private) return -ENOMEM; - } memcpy(ap_msg->private, &resp_type, sizeof(resp_type)); - rc = XCRB_msg_to_type6CPRB_msgX(ap_msg, xcRB, func_code, dom); - if (rc) { - kzfree(ap_msg->message); - kzfree(ap_msg->private); - } - return rc; + return XCRB_msg_to_type6CPRB_msgX(ap_msg, xcRB, func_code, dom); } /** @@ -1139,11 +1137,16 @@ static long zcrypt_msgtype6_send_cprb(struct zcrypt_queue *zq, /* Signal pending. */ ap_cancel_message(zq->queue, ap_msg); - kzfree(ap_msg->message); - kzfree(ap_msg->private); return rc; } +/** + * Fetch function code from ep11 cprb. + * Extracting the fc requires to copy the ep11 cprb from userspace. + * So this function allocates memory and needs an ap_msg prepared + * by the caller with ap_init_message(). Also the caller has to + * make sure ap_release_message() is always called even on failure. + */ unsigned int get_ep11cprb_fc(struct ep11_urb *xcrb, struct ap_message *ap_msg, unsigned int *func_code) @@ -1151,9 +1154,7 @@ unsigned int get_ep11cprb_fc(struct ep11_urb *xcrb, struct response_type resp_type = { .type = PCIXCC_RESPONSE_TYPE_EP11, }; - int rc; - ap_init_message(ap_msg); ap_msg->message = kmalloc(MSGTYPE06_MAX_MSG_SIZE, GFP_KERNEL); if (!ap_msg->message) return -ENOMEM; @@ -1161,17 +1162,10 @@ unsigned int get_ep11cprb_fc(struct ep11_urb *xcrb, ap_msg->psmid = (((unsigned long long) current->pid) << 32) + atomic_inc_return(&zcrypt_step); ap_msg->private = kmalloc(sizeof(resp_type), GFP_KERNEL); - if (!ap_msg->private) { - kzfree(ap_msg->message); + if (!ap_msg->private) return -ENOMEM; - } memcpy(ap_msg->private, &resp_type, sizeof(resp_type)); - rc = xcrb_msg_to_type6_ep11cprb_msgx(ap_msg, xcrb, func_code); - if (rc) { - kzfree(ap_msg->message); - kzfree(ap_msg->private); - } - return rc; + return xcrb_msg_to_type6_ep11cprb_msgx(ap_msg, xcrb, func_code); } /** @@ -1246,8 +1240,6 @@ static long zcrypt_msgtype6_send_ep11_cprb(struct zcrypt_queue *zq, /* Signal pending. */ ap_cancel_message(zq->queue, ap_msg); - kzfree(ap_msg->message); - kzfree(ap_msg->private); return rc; } @@ -1258,7 +1250,6 @@ unsigned int get_rng_fc(struct ap_message *ap_msg, int *func_code, .type = PCIXCC_RESPONSE_TYPE_XCRB, }; - ap_init_message(ap_msg); ap_msg->message = kmalloc(MSGTYPE06_MAX_MSG_SIZE, GFP_KERNEL); if (!ap_msg->message) return -ENOMEM; @@ -1266,10 +1257,8 @@ unsigned int get_rng_fc(struct ap_message *ap_msg, int *func_code, ap_msg->psmid = (((unsigned long long) current->pid) << 32) + atomic_inc_return(&zcrypt_step); ap_msg->private = kmalloc(sizeof(resp_type), GFP_KERNEL); - if (!ap_msg->private) { - kzfree(ap_msg->message); + if (!ap_msg->private) return -ENOMEM; - } memcpy(ap_msg->private, &resp_type, sizeof(resp_type)); rng_type6CPRB_msgX(ap_msg, ZCRYPT_RNG_BUFFER_SIZE, domain); @@ -1313,8 +1302,6 @@ static long zcrypt_msgtype6_rng(struct zcrypt_queue *zq, /* Signal pending. */ ap_cancel_message(zq->queue, ap_msg); - kzfree(ap_msg->message); - kzfree(ap_msg->private); return rc; } |