diff options
Diffstat (limited to 'drivers/s390')
26 files changed, 207 insertions, 113 deletions
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c index 5b11ee9234..833cfab7d8 100644 --- a/drivers/s390/block/dasd.c +++ b/drivers/s390/block/dasd.c @@ -412,7 +412,8 @@ dasd_state_ready_to_online(struct dasd_device * device) KOBJ_CHANGE); return 0; } - disk_uevent(device->block->bdev->bd_disk, KOBJ_CHANGE); + disk_uevent(device->block->bdev_handle->bdev->bd_disk, + KOBJ_CHANGE); } return 0; } @@ -432,7 +433,8 @@ static int dasd_state_online_to_ready(struct dasd_device *device) device->state = DASD_STATE_READY; if (device->block && !(device->features & DASD_FEATURE_USERAW)) - disk_uevent(device->block->bdev->bd_disk, KOBJ_CHANGE); + disk_uevent(device->block->bdev_handle->bdev->bd_disk, + KOBJ_CHANGE); return 0; } @@ -3592,7 +3594,7 @@ int dasd_generic_set_offline(struct ccw_device *cdev) * in the other openers. */ if (device->block) { - max_count = device->block->bdev ? 0 : -1; + max_count = device->block->bdev_handle ? 0 : -1; open_count = atomic_read(&device->block->open_count); if (open_count > max_count) { if (open_count > 0) @@ -3638,8 +3640,8 @@ int dasd_generic_set_offline(struct ccw_device *cdev) * so sync bdev first and then wait for our queues to become * empty */ - if (device->block) - bdev_mark_dead(device->block->bdev, false); + if (device->block && device->block->bdev_handle) + bdev_mark_dead(device->block->bdev_handle->bdev, false); dasd_schedule_device_bh(device); rc = wait_event_interruptible(shutdown_waitq, _wait_for_empty_queues(device)); diff --git a/drivers/s390/block/dasd_genhd.c b/drivers/s390/block/dasd_genhd.c index fe5108a1b3..55e3abe94c 100644 --- a/drivers/s390/block/dasd_genhd.c +++ b/drivers/s390/block/dasd_genhd.c @@ -127,15 +127,15 @@ void dasd_gendisk_free(struct dasd_block *block) */ int dasd_scan_partitions(struct dasd_block *block) { - struct block_device *bdev; + struct bdev_handle *bdev_handle; int rc; - bdev = blkdev_get_by_dev(disk_devt(block->gdp), BLK_OPEN_READ, NULL, - NULL); - if (IS_ERR(bdev)) { + bdev_handle = bdev_open_by_dev(disk_devt(block->gdp), BLK_OPEN_READ, + NULL, NULL); + if (IS_ERR(bdev_handle)) { DBF_DEV_EVENT(DBF_ERR, block->base, "scan partitions error, blkdev_get returned %ld", - PTR_ERR(bdev)); + PTR_ERR(bdev_handle)); return -ENODEV; } @@ -147,16 +147,15 @@ int dasd_scan_partitions(struct dasd_block *block) "scan partitions error, rc %d", rc); /* - * Since the matching blkdev_put call to the blkdev_get in - * this function is not called before dasd_destroy_partitions - * the offline open_count limit needs to be increased from - * 0 to 1. This is done by setting device->bdev (see - * dasd_generic_set_offline). As long as the partition - * detection is running no offline should be allowed. That - * is why the assignment to device->bdev is done AFTER - * the BLKRRPART ioctl. + * Since the matching bdev_release() call to the + * bdev_open_by_path() in this function is not called before + * dasd_destroy_partitions the offline open_count limit needs to be + * increased from 0 to 1. This is done by setting device->bdev_handle + * (see dasd_generic_set_offline). As long as the partition detection + * is running no offline should be allowed. That is why the assignment + * to block->bdev_handle is done AFTER the BLKRRPART ioctl. */ - block->bdev = bdev; + block->bdev_handle = bdev_handle; return 0; } @@ -166,21 +165,21 @@ int dasd_scan_partitions(struct dasd_block *block) */ void dasd_destroy_partitions(struct dasd_block *block) { - struct block_device *bdev; + struct bdev_handle *bdev_handle; /* - * Get the bdev pointer from the device structure and clear - * device->bdev to lower the offline open_count limit again. + * Get the bdev_handle pointer from the device structure and clear + * device->bdev_handle to lower the offline open_count limit again. */ - bdev = block->bdev; - block->bdev = NULL; + bdev_handle = block->bdev_handle; + block->bdev_handle = NULL; - mutex_lock(&bdev->bd_disk->open_mutex); - bdev_disk_changed(bdev->bd_disk, true); - mutex_unlock(&bdev->bd_disk->open_mutex); + mutex_lock(&bdev_handle->bdev->bd_disk->open_mutex); + bdev_disk_changed(bdev_handle->bdev->bd_disk, true); + mutex_unlock(&bdev_handle->bdev->bd_disk->open_mutex); /* Matching blkdev_put to the blkdev_get in dasd_scan_partitions. */ - blkdev_put(bdev, NULL); + bdev_release(bdev_handle); } int dasd_gendisk_init(void) diff --git a/drivers/s390/block/dasd_int.h b/drivers/s390/block/dasd_int.h index 8a4dbe9d77..1b1b8a41c4 100644 --- a/drivers/s390/block/dasd_int.h +++ b/drivers/s390/block/dasd_int.h @@ -283,7 +283,7 @@ struct dasd_pprc_dev_info { __u8 secondary; /* 7 Secondary device address */ __u16 pprc_id; /* 8-9 Peer-to-Peer Remote Copy ID */ __u8 reserved2[12]; /* 10-21 reserved */ - __u16 prim_cu_ssid; /* 22-23 Pimary Control Unit SSID */ + __u16 prim_cu_ssid; /* 22-23 Primary Control Unit SSID */ __u8 reserved3[12]; /* 24-35 reserved */ __u16 sec_cu_ssid; /* 36-37 Secondary Control Unit SSID */ __u8 reserved4[90]; /* 38-127 reserved */ @@ -650,7 +650,7 @@ struct dasd_block { struct gendisk *gdp; spinlock_t request_queue_lock; struct blk_mq_tag_set tag_set; - struct block_device *bdev; + struct bdev_handle *bdev_handle; atomic_t open_count; unsigned long blocks; /* size of volume in blocks */ diff --git a/drivers/s390/block/dasd_ioctl.c b/drivers/s390/block/dasd_ioctl.c index d55862605b..61b9675e2a 100644 --- a/drivers/s390/block/dasd_ioctl.c +++ b/drivers/s390/block/dasd_ioctl.c @@ -537,7 +537,7 @@ static int __dasd_ioctl_information(struct dasd_block *block, * This must be hidden from user-space. */ dasd_info->open_count = atomic_read(&block->open_count); - if (!block->bdev) + if (!block->bdev_handle) dasd_info->open_count++; /* diff --git a/drivers/s390/char/diag_ftp.c b/drivers/s390/char/diag_ftp.c index 65c7f2d565..9418a9270d 100644 --- a/drivers/s390/char/diag_ftp.c +++ b/drivers/s390/char/diag_ftp.c @@ -16,7 +16,7 @@ #include <linux/wait.h> #include <linux/string.h> #include <asm/asm-extable.h> -#include <asm/ctl_reg.h> +#include <asm/ctlreg.h> #include <asm/diag.h> #include "hmcdrv_ftp.h" diff --git a/drivers/s390/char/sclp.c b/drivers/s390/char/sclp.c index 8f74db689a..d53ee34d39 100644 --- a/drivers/s390/char/sclp.c +++ b/drivers/s390/char/sclp.c @@ -81,7 +81,7 @@ static inline void sclp_trace(int prio, char *id, u32 a, u64 b, bool err) struct sclp_trace_entry e; memset(&e, 0, sizeof(e)); - strncpy(e.id, id, sizeof(e.id)); + strtomem(e.id, id); e.a = a; e.b = b; debug_event(&sclp_debug, prio, &e, sizeof(e)); @@ -706,8 +706,8 @@ void sclp_sync_wait(void) { unsigned long long old_tick; + struct ctlreg cr0, cr0_sync; unsigned long flags; - unsigned long cr0, cr0_sync; static u64 sync_count; u64 timeout; int irq_context; @@ -732,10 +732,10 @@ sclp_sync_wait(void) /* Enable service-signal interruption, disable timer interrupts */ old_tick = local_tick_disable(); trace_hardirqs_on(); - __ctl_store(cr0, 0, 0); - cr0_sync = cr0 & ~CR0_IRQ_SUBCLASS_MASK; - cr0_sync |= 1UL << (63 - 54); - __ctl_load(cr0_sync, 0, 0); + local_ctl_store(0, &cr0); + cr0_sync.val = cr0.val & ~CR0_IRQ_SUBCLASS_MASK; + cr0_sync.val |= 1UL << (63 - 54); + local_ctl_load(0, &cr0_sync); __arch_local_irq_stosm(0x01); /* Loop until driver state indicates finished request */ while (sclp_running_state != sclp_running_state_idle) { @@ -745,7 +745,7 @@ sclp_sync_wait(void) cpu_relax(); } local_irq_disable(); - __ctl_load(cr0, 0, 0); + local_ctl_load(0, &cr0); if (!irq_context) _local_bh_enable(); local_tick_enable(old_tick); diff --git a/drivers/s390/char/sclp_cmd.c b/drivers/s390/char/sclp_cmd.c index 8b4575a0db..11c428f4c7 100644 --- a/drivers/s390/char/sclp_cmd.c +++ b/drivers/s390/char/sclp_cmd.c @@ -19,7 +19,7 @@ #include <linux/mmzone.h> #include <linux/memory.h> #include <linux/module.h> -#include <asm/ctl_reg.h> +#include <asm/ctlreg.h> #include <asm/chpid.h> #include <asm/setup.h> #include <asm/page.h> @@ -353,7 +353,6 @@ static int sclp_mem_notifier(struct notifier_block *nb, sclp_mem_change_state(start, size, 0); break; default: - rc = -EINVAL; break; } mutex_unlock(&sclp_mem_mutex); diff --git a/drivers/s390/char/sclp_early.c b/drivers/s390/char/sclp_early.c index fdc8668f3f..60a247fdb2 100644 --- a/drivers/s390/char/sclp_early.c +++ b/drivers/s390/char/sclp_early.c @@ -10,7 +10,7 @@ #include <linux/errno.h> #include <linux/memblock.h> -#include <asm/ctl_reg.h> +#include <asm/ctlreg.h> #include <asm/sclp.h> #include <asm/ipl.h> #include <asm/setup.h> diff --git a/drivers/s390/char/sclp_early_core.c b/drivers/s390/char/sclp_early_core.c index dbd5c53d8e..9f6165cafd 100644 --- a/drivers/s390/char/sclp_early_core.c +++ b/drivers/s390/char/sclp_early_core.c @@ -7,6 +7,7 @@ #include <linux/kernel.h> #include <asm/processor.h> #include <asm/lowcore.h> +#include <asm/ctlreg.h> #include <asm/ebcdic.h> #include <asm/irq.h> #include <asm/sections.h> @@ -31,11 +32,11 @@ void sclp_early_wait_irq(void) psw_t psw_ext_save, psw_wait; union ctlreg0 cr0, cr0_new; - __ctl_store(cr0.val, 0, 0); + local_ctl_store(0, &cr0.reg); cr0_new.val = cr0.val & ~CR0_IRQ_SUBCLASS_MASK; cr0_new.lap = 0; cr0_new.sssm = 1; - __ctl_load(cr0_new.val, 0, 0); + local_ctl_load(0, &cr0_new.reg); psw_ext_save = S390_lowcore.external_new_psw; psw_mask = __extract_psw(); @@ -58,7 +59,7 @@ void sclp_early_wait_irq(void) } while (S390_lowcore.ext_int_code != EXT_IRQ_SERVICE_SIG); S390_lowcore.external_new_psw = psw_ext_save; - __ctl_load(cr0.val, 0, 0); + local_ctl_load(0, &cr0.reg); } int sclp_early_cmd(sclp_cmdw_t cmd, void *sccb) diff --git a/drivers/s390/cio/chp.c b/drivers/s390/cio/chp.c index 5440f285f3..675d7ed823 100644 --- a/drivers/s390/cio/chp.c +++ b/drivers/s390/cio/chp.c @@ -334,7 +334,7 @@ static ssize_t chp_cmg_show(struct device *dev, struct device_attribute *attr, return 0; if (chp->cmg == -1) /* channel measurements not available */ return sprintf(buf, "unknown\n"); - return sprintf(buf, "%x\n", chp->cmg); + return sprintf(buf, "%d\n", chp->cmg); } static DEVICE_ATTR(cmg, 0444, chp_cmg_show, NULL); diff --git a/drivers/s390/cio/chsc.c b/drivers/s390/cio/chsc.c index 0abd77f4b6..f8b04ce615 100644 --- a/drivers/s390/cio/chsc.c +++ b/drivers/s390/cio/chsc.c @@ -393,8 +393,8 @@ static void format_node_data(char *params, char *id, struct node_descriptor *nd) memset(id, 0, NODEID_LEN); if (nd->validity != ND_VALIDITY_VALID) { - strncpy(params, "n/a", PARAMS_LEN - 1); - strncpy(id, "n/a", NODEID_LEN - 1); + strscpy(params, "n/a", PARAMS_LEN); + strscpy(id, "n/a", NODEID_LEN); return; } @@ -881,8 +881,8 @@ int __chsc_do_secm(struct channel_subsystem *css, int enable) secm_area->request.code = 0x0016; secm_area->key = PAGE_DEFAULT_KEY >> 4; - secm_area->cub_addr1 = (u64)(unsigned long)css->cub_addr1; - secm_area->cub_addr2 = (u64)(unsigned long)css->cub_addr2; + secm_area->cub_addr1 = virt_to_phys(css->cub_addr1); + secm_area->cub_addr2 = virt_to_phys(css->cub_addr2); secm_area->operation_code = enable ? 0 : 1; diff --git a/drivers/s390/cio/crw.c b/drivers/s390/cio/crw.c index 7b02a6349c..4916dd0a7e 100644 --- a/drivers/s390/cio/crw.c +++ b/drivers/s390/cio/crw.c @@ -12,8 +12,8 @@ #include <linux/kthread.h> #include <linux/init.h> #include <linux/wait.h> +#include <asm/ctlreg.h> #include <asm/crw.h> -#include <asm/ctl_reg.h> #include "ioasm.h" static DEFINE_MUTEX(crw_handler_mutex); @@ -156,7 +156,7 @@ static int __init crw_machine_check_init(void) task = kthread_run(crw_collect_info, NULL, "kmcheck"); if (IS_ERR(task)) return PTR_ERR(task); - ctl_set_bit(14, 28); /* enable channel report MCH */ + system_ctl_set_bit(14, CR14_CHANNEL_REPORT_SUBMASK_BIT); return 0; } device_initcall(crw_machine_check_init); diff --git a/drivers/s390/cio/device_ops.c b/drivers/s390/cio/device_ops.c index c533d1dadc..a5dba38297 100644 --- a/drivers/s390/cio/device_ops.c +++ b/drivers/s390/cio/device_ops.c @@ -202,7 +202,8 @@ int ccw_device_start_timeout_key(struct ccw_device *cdev, struct ccw1 *cpa, return -EINVAL; if (cdev->private->state == DEV_STATE_NOT_OPER) return -ENODEV; - if (cdev->private->state == DEV_STATE_VERIFY) { + if (cdev->private->state == DEV_STATE_VERIFY || + cdev->private->flags.doverify) { /* Remember to fake irb when finished. */ if (!cdev->private->flags.fake_irb) { cdev->private->flags.fake_irb = FAKE_CMD_IRB; @@ -214,8 +215,7 @@ int ccw_device_start_timeout_key(struct ccw_device *cdev, struct ccw1 *cpa, } if (cdev->private->state != DEV_STATE_ONLINE || ((sch->schib.scsw.cmd.stctl & SCSW_STCTL_PRIM_STATUS) && - !(sch->schib.scsw.cmd.stctl & SCSW_STCTL_SEC_STATUS)) || - cdev->private->flags.doverify) + !(sch->schib.scsw.cmd.stctl & SCSW_STCTL_SEC_STATUS))) return -EBUSY; ret = cio_set_options (sch, flags); if (ret) diff --git a/drivers/s390/cio/isc.c b/drivers/s390/cio/isc.c index 77fde9f5ea..dbc2ac7711 100644 --- a/drivers/s390/cio/isc.c +++ b/drivers/s390/cio/isc.c @@ -33,7 +33,7 @@ void isc_register(unsigned int isc) spin_lock(&isc_ref_lock); if (isc_refs[isc] == 0) - ctl_set_bit(6, 31 - isc); + system_ctl_set_bit(6, 31 - isc); isc_refs[isc]++; spin_unlock(&isc_ref_lock); } @@ -61,7 +61,7 @@ void isc_unregister(unsigned int isc) goto out_unlock; } if (isc_refs[isc] == 1) - ctl_clear_bit(6, 31 - isc); + system_ctl_clear_bit(6, 31 - isc); isc_refs[isc]--; out_unlock: spin_unlock(&isc_ref_lock); diff --git a/drivers/s390/crypto/ap_bus.c b/drivers/s390/crypto/ap_bus.c index d6ad437883..5dd33155d5 100644 --- a/drivers/s390/crypto/ap_bus.c +++ b/drivers/s390/crypto/ap_bus.c @@ -352,7 +352,7 @@ EXPORT_SYMBOL(ap_test_config_ctrl_domain); /* * ap_queue_info(): Check and get AP queue info. * Returns: 1 if APQN exists and info is filled, - * 0 if APQN seems to exit but there is no info + * 0 if APQN seems to exist but there is no info * available (eg. caused by an asynch pending error) * -1 invalid APQN, TAPQ error or AP queue status which * indicates there is no APQN. @@ -373,36 +373,33 @@ static int ap_queue_info(ap_qid_t qid, int *q_type, unsigned int *q_fac, /* call TAPQ on this APQN */ status = ap_test_queue(qid, ap_apft_available(), &tapq_info); - /* handle pending async error with return 'no info available' */ - if (status.async) - return 0; - switch (status.response_code) { case AP_RESPONSE_NORMAL: case AP_RESPONSE_RESET_IN_PROGRESS: case AP_RESPONSE_DECONFIGURED: case AP_RESPONSE_CHECKSTOPPED: case AP_RESPONSE_BUSY: - /* - * According to the architecture in all these cases the - * info should be filled. All bits 0 is not possible as - * there is at least one of the mode bits set. - */ - if (WARN_ON_ONCE(!tapq_info.value)) - return 0; - *q_type = tapq_info.at; - *q_fac = tapq_info.fac; - *q_depth = tapq_info.qd; - *q_ml = tapq_info.ml; - *q_decfg = status.response_code == AP_RESPONSE_DECONFIGURED; - *q_cstop = status.response_code == AP_RESPONSE_CHECKSTOPPED; - return 1; + /* For all these RCs the tapq info should be available */ + break; default: - /* - * A response code which indicates, there is no info available. - */ - return -1; + /* On a pending async error the info should be available */ + if (!status.async) + return -1; + break; } + + /* There should be at least one of the mode bits set */ + if (WARN_ON_ONCE(!tapq_info.value)) + return 0; + + *q_type = tapq_info.at; + *q_fac = tapq_info.fac; + *q_depth = tapq_info.qd; + *q_ml = tapq_info.ml; + *q_decfg = status.response_code == AP_RESPONSE_DECONFIGURED; + *q_cstop = status.response_code == AP_RESPONSE_CHECKSTOPPED; + + return 1; } void ap_wait(enum ap_sm_wait wait) diff --git a/drivers/s390/crypto/ap_bus.h b/drivers/s390/crypto/ap_bus.h index 3e34912a60..b0771ca084 100644 --- a/drivers/s390/crypto/ap_bus.h +++ b/drivers/s390/crypto/ap_bus.h @@ -206,7 +206,7 @@ struct ap_queue { bool config; /* configured state */ bool chkstop; /* checkstop state */ ap_qid_t qid; /* AP queue id. */ - bool interrupt; /* indicate if interrupts are enabled */ + bool se_bound; /* SE bound state */ unsigned int assoc_idx; /* SE association index */ int queue_count; /* # messages currently on AP queue. */ int pendingq_count; /* # requests on pendingq list. */ @@ -271,6 +271,7 @@ enum ap_sm_wait ap_sm_event_loop(struct ap_queue *aq, enum ap_sm_event event); int ap_queue_message(struct ap_queue *aq, struct ap_message *ap_msg); void ap_cancel_message(struct ap_queue *aq, struct ap_message *ap_msg); void ap_flush_queue(struct ap_queue *aq); +bool ap_queue_usable(struct ap_queue *aq); void *ap_airq_ptr(void); int ap_sb_available(void); diff --git a/drivers/s390/crypto/ap_queue.c b/drivers/s390/crypto/ap_queue.c index 2943b2529d..3934a0cc13 100644 --- a/drivers/s390/crypto/ap_queue.c +++ b/drivers/s390/crypto/ap_queue.c @@ -33,6 +33,11 @@ static inline bool ap_q_supports_assoc(struct ap_queue *aq) return ap_test_bit(&aq->card->functions, AP_FUNC_EP11); } +static inline bool ap_q_needs_bind(struct ap_queue *aq) +{ + return ap_q_supports_bind(aq) && ap_sb_available(); +} + /** * ap_queue_enable_irq(): Enable interrupt support on this AP queue. * @aq: The AP queue @@ -195,13 +200,13 @@ static enum ap_sm_wait ap_sm_read(struct ap_queue *aq) return AP_SM_WAIT_AGAIN; } aq->sm_state = AP_SM_STATE_IDLE; - return AP_SM_WAIT_NONE; + break; case AP_RESPONSE_NO_PENDING_REPLY: if (aq->queue_count > 0) - return aq->interrupt ? + return status.irq_enabled ? AP_SM_WAIT_INTERRUPT : AP_SM_WAIT_HIGH_TIMEOUT; aq->sm_state = AP_SM_STATE_IDLE; - return AP_SM_WAIT_NONE; + break; default: aq->dev_state = AP_DEV_STATE_ERROR; aq->last_err_rc = status.response_code; @@ -210,6 +215,16 @@ static enum ap_sm_wait ap_sm_read(struct ap_queue *aq) AP_QID_CARD(aq->qid), AP_QID_QUEUE(aq->qid)); return AP_SM_WAIT_NONE; } + /* Check and maybe enable irq support (again) on this queue */ + if (!status.irq_enabled && status.queue_empty) { + void *lsi_ptr = ap_airq_ptr(); + + if (lsi_ptr && ap_queue_enable_irq(aq, lsi_ptr) == 0) { + aq->sm_state = AP_SM_STATE_SETIRQ_WAIT; + return AP_SM_WAIT_AGAIN; + } + } + return AP_SM_WAIT_NONE; } /** @@ -249,7 +264,7 @@ static enum ap_sm_wait ap_sm_write(struct ap_queue *aq) fallthrough; case AP_RESPONSE_Q_FULL: aq->sm_state = AP_SM_STATE_QUEUE_FULL; - return aq->interrupt ? + return status.irq_enabled ? AP_SM_WAIT_INTERRUPT : AP_SM_WAIT_HIGH_TIMEOUT; case AP_RESPONSE_RESET_IN_PROGRESS: aq->sm_state = AP_SM_STATE_RESET_WAIT; @@ -302,8 +317,8 @@ static enum ap_sm_wait ap_sm_reset(struct ap_queue *aq) case AP_RESPONSE_NORMAL: case AP_RESPONSE_RESET_IN_PROGRESS: aq->sm_state = AP_SM_STATE_RESET_WAIT; - aq->interrupt = false; aq->rapq_fbit = 0; + aq->se_bound = false; return AP_SM_WAIT_LOW_TIMEOUT; default: aq->dev_state = AP_DEV_STATE_ERROR; @@ -377,7 +392,6 @@ static enum ap_sm_wait ap_sm_setirq_wait(struct ap_queue *aq) if (status.irq_enabled == 1) { /* Irqs are now enabled */ - aq->interrupt = true; aq->sm_state = (aq->queue_count > 0) ? AP_SM_STATE_WORKING : AP_SM_STATE_IDLE; } @@ -620,16 +634,21 @@ static ssize_t interrupt_show(struct device *dev, struct device_attribute *attr, char *buf) { struct ap_queue *aq = to_ap_queue(dev); + struct ap_queue_status status; int rc = 0; spin_lock_bh(&aq->lock); - if (aq->sm_state == AP_SM_STATE_SETIRQ_WAIT) + if (aq->sm_state == AP_SM_STATE_SETIRQ_WAIT) { rc = sysfs_emit(buf, "Enable Interrupt pending.\n"); - else if (aq->interrupt) - rc = sysfs_emit(buf, "Interrupts enabled.\n"); - else - rc = sysfs_emit(buf, "Interrupts disabled.\n"); + } else { + status = ap_tapq(aq->qid, NULL); + if (status.irq_enabled) + rc = sysfs_emit(buf, "Interrupts enabled.\n"); + else + rc = sysfs_emit(buf, "Interrupts disabled.\n"); + } spin_unlock_bh(&aq->lock); + return rc; } @@ -868,7 +887,12 @@ static ssize_t se_bind_store(struct device *dev, } status = ap_bapq(aq->qid); spin_unlock_bh(&aq->lock); - if (status.response_code) { + if (!status.response_code) { + aq->se_bound = true; + AP_DBF_INFO("%s bapq(0x%02x.%04x) success\n", __func__, + AP_QID_CARD(aq->qid), + AP_QID_QUEUE(aq->qid)); + } else { AP_DBF_WARN("%s RC 0x%02x on bapq(0x%02x.%04x)\n", __func__, status.response_code, AP_QID_CARD(aq->qid), @@ -1021,7 +1045,6 @@ struct ap_queue *ap_queue_create(ap_qid_t qid, int device_type) if (ap_sb_available() && is_prot_virt_guest()) aq->ap_dev.device.groups = ap_queue_dev_sb_attr_groups; aq->qid = qid; - aq->interrupt = false; spin_lock_init(&aq->lock); INIT_LIST_HEAD(&aq->pendingq); INIT_LIST_HEAD(&aq->requestq); @@ -1074,6 +1097,42 @@ int ap_queue_message(struct ap_queue *aq, struct ap_message *ap_msg) EXPORT_SYMBOL(ap_queue_message); /** + * ap_queue_usable(): Check if queue is usable just now. + * @aq: The AP queue device to test for usability. + * This function is intended for the scheduler to query if it makes + * sense to enqueue a message into this AP queue device by calling + * ap_queue_message(). The perspective is very short-term as the + * state machine and device state(s) may change at any time. + */ +bool ap_queue_usable(struct ap_queue *aq) +{ + bool rc = true; + + spin_lock_bh(&aq->lock); + + /* check for not configured or checkstopped */ + if (!aq->config || aq->chkstop) { + rc = false; + goto unlock_and_out; + } + + /* device state needs to be ok */ + if (aq->dev_state != AP_DEV_STATE_OPERATING) { + rc = false; + goto unlock_and_out; + } + + /* SE guest's queues additionally need to be bound */ + if (ap_q_needs_bind(aq) && !aq->se_bound) + rc = false; + +unlock_and_out: + spin_unlock_bh(&aq->lock); + return rc; +} +EXPORT_SYMBOL(ap_queue_usable); + +/** * ap_cancel_message(): Cancel a crypto request. * @aq: The AP device that has the message queued * @ap_msg: The message that is to be removed diff --git a/drivers/s390/crypto/vfio_ap_ops.c b/drivers/s390/crypto/vfio_ap_ops.c index 88f41f95cc..d6ea2fd4c2 100644 --- a/drivers/s390/crypto/vfio_ap_ops.c +++ b/drivers/s390/crypto/vfio_ap_ops.c @@ -2044,6 +2044,7 @@ static ssize_t status_show(struct device *dev, { ssize_t nchars = 0; struct vfio_ap_queue *q; + unsigned long apid, apqi; struct ap_matrix_mdev *matrix_mdev; struct ap_device *apdev = to_ap_dev(dev); @@ -2051,8 +2052,21 @@ static ssize_t status_show(struct device *dev, q = dev_get_drvdata(&apdev->device); matrix_mdev = vfio_ap_mdev_for_queue(q); + /* If the queue is assigned to the matrix mediated device, then + * determine whether it is passed through to a guest; otherwise, + * indicate that it is unassigned. + */ if (matrix_mdev) { - if (matrix_mdev->kvm) + apid = AP_QID_CARD(q->apqn); + apqi = AP_QID_QUEUE(q->apqn); + /* + * If the queue is passed through to the guest, then indicate + * that it is in use; otherwise, indicate that it is + * merely assigned to a matrix mediated device. + */ + if (matrix_mdev->kvm && + test_bit_inv(apid, matrix_mdev->shadow_apcb.apm) && + test_bit_inv(apqi, matrix_mdev->shadow_apcb.aqm)) nchars = scnprintf(buf, PAGE_SIZE, "%s\n", AP_QUEUE_IN_USE); else diff --git a/drivers/s390/crypto/zcrypt_api.c b/drivers/s390/crypto/zcrypt_api.c index ce04caa791..dcd6c7299f 100644 --- a/drivers/s390/crypto/zcrypt_api.c +++ b/drivers/s390/crypto/zcrypt_api.c @@ -693,7 +693,7 @@ static long zcrypt_rsa_modexpo(struct ap_perms *perms, for_each_zcrypt_queue(zq, zc) { /* check if device is usable and eligible */ if (!zq->online || !zq->ops->rsa_modexpo || - !zq->queue->config || zq->queue->chkstop) + !ap_queue_usable(zq->queue)) continue; /* check if device node has admission for this queue */ if (!zcrypt_check_queue(perms, @@ -798,7 +798,7 @@ static long zcrypt_rsa_crt(struct ap_perms *perms, for_each_zcrypt_queue(zq, zc) { /* check if device is usable and eligible */ if (!zq->online || !zq->ops->rsa_modexpo_crt || - !zq->queue->config || zq->queue->chkstop) + !ap_queue_usable(zq->queue)) continue; /* check if device node has admission for this queue */ if (!zcrypt_check_queue(perms, @@ -916,7 +916,7 @@ static long _zcrypt_send_cprb(bool userspace, struct ap_perms *perms, for_each_zcrypt_queue(zq, zc) { /* check for device usable and eligible */ if (!zq->online || !zq->ops->send_cprb || - !zq->queue->config || zq->queue->chkstop || + !ap_queue_usable(zq->queue) || (tdom != AUTOSEL_DOM && tdom != AP_QID_QUEUE(zq->queue->qid))) continue; @@ -1087,7 +1087,7 @@ static long _zcrypt_send_ep11_cprb(bool userspace, struct ap_perms *perms, for_each_zcrypt_queue(zq, zc) { /* check if device is usable and eligible */ if (!zq->online || !zq->ops->send_ep11_cprb || - !zq->queue->config || zq->queue->chkstop || + !ap_queue_usable(zq->queue) || (targets && !is_desired_ep11_queue(zq->queue->qid, target_num, targets))) @@ -1186,7 +1186,7 @@ static long zcrypt_rng(char *buffer) for_each_zcrypt_queue(zq, zc) { /* check if device is usable and eligible */ if (!zq->online || !zq->ops->rng || - !zq->queue->config || zq->queue->chkstop) + !ap_queue_usable(zq->queue)) continue; if (!zcrypt_queue_compare(zq, pref_zq, wgt, pref_wgt)) continue; diff --git a/drivers/s390/crypto/zcrypt_card.c b/drivers/s390/crypto/zcrypt_card.c index c815722d0a..050462d952 100644 --- a/drivers/s390/crypto/zcrypt_card.c +++ b/drivers/s390/crypto/zcrypt_card.c @@ -52,7 +52,7 @@ static ssize_t online_show(struct device *dev, { struct zcrypt_card *zc = dev_get_drvdata(dev); struct ap_card *ac = to_ap_card(dev); - int online = ac->config && zc->online ? 1 : 0; + int online = ac->config && !ac->chkstop && zc->online ? 1 : 0; return sysfs_emit(buf, "%d\n", online); } @@ -70,7 +70,7 @@ static ssize_t online_store(struct device *dev, if (sscanf(buf, "%d\n", &online) != 1 || online < 0 || online > 1) return -EINVAL; - if (online && !ac->config) + if (online && (!ac->config || ac->chkstop)) return -ENODEV; zc->online = online; diff --git a/drivers/s390/crypto/zcrypt_cex4.c b/drivers/s390/crypto/zcrypt_cex4.c index 9cfce9ff2e..5c4532ab00 100644 --- a/drivers/s390/crypto/zcrypt_cex4.c +++ b/drivers/s390/crypto/zcrypt_cex4.c @@ -279,7 +279,11 @@ static const struct { { 1, "BSI2009" }, { 2, "FIPS2011" }, { 3, "BSI2011" }, + { 4, "SIGG-IMPORT" }, + { 5, "SIGG" }, { 6, "BSICC2017" }, + { 7, "FIPS2021" }, + { 8, "FIPS2024" }, { 0, NULL } }; diff --git a/drivers/s390/crypto/zcrypt_error.h b/drivers/s390/crypto/zcrypt_error.h index d36177e65a..a44fcfcec9 100644 --- a/drivers/s390/crypto/zcrypt_error.h +++ b/drivers/s390/crypto/zcrypt_error.h @@ -98,8 +98,22 @@ static inline int convert_error(struct zcrypt_queue *zq, case REP88_ERROR_MESSAGE_MALFORMD: /* 0x22 */ case REP88_ERROR_KEY_TYPE: /* 0x34 */ /* RY indicates malformed request */ - ZCRYPT_DBF_WARN("%s dev=%02x.%04x RY=0x%02x => rc=EINVAL\n", - __func__, card, queue, ehdr->reply_code); + if (ehdr->reply_code == REP82_ERROR_FILTERED_BY_HYPERVISOR && + ehdr->type == TYPE86_RSP_CODE) { + struct { + struct type86_hdr hdr; + struct type86_fmt2_ext fmt2; + } __packed * head = reply->msg; + unsigned int apfs = *((u32 *)head->fmt2.apfs); + + ZCRYPT_DBF_WARN("%s dev=%02x.%04x RY=0x%02x apfs=0x%x => rc=EINVAL\n", + __func__, card, queue, + ehdr->reply_code, apfs); + } else { + ZCRYPT_DBF_WARN("%s dev=%02x.%04x RY=0x%02x => rc=EINVAL\n", + __func__, card, queue, + ehdr->reply_code); + } return -EINVAL; case REP82_ERROR_MACHINE_FAILURE: /* 0x10 */ case REP82_ERROR_MESSAGE_TYPE: /* 0x20 */ diff --git a/drivers/s390/crypto/zcrypt_queue.c b/drivers/s390/crypto/zcrypt_queue.c index 112a80e8e6..67d8e0ae0e 100644 --- a/drivers/s390/crypto/zcrypt_queue.c +++ b/drivers/s390/crypto/zcrypt_queue.c @@ -42,7 +42,7 @@ static ssize_t online_show(struct device *dev, { struct zcrypt_queue *zq = dev_get_drvdata(dev); struct ap_queue *aq = to_ap_queue(dev); - int online = aq->config && zq->online ? 1 : 0; + int online = aq->config && !aq->chkstop && zq->online ? 1 : 0; return sysfs_emit(buf, "%d\n", online); } @@ -59,7 +59,8 @@ static ssize_t online_store(struct device *dev, if (sscanf(buf, "%d\n", &online) != 1 || online < 0 || online > 1) return -EINVAL; - if (online && (!aq->config || !aq->card->config)) + if (online && (!aq->config || !aq->card->config || + aq->chkstop || aq->card->chkstop)) return -ENODEV; if (online && !zc->online) return -EINVAL; diff --git a/drivers/s390/net/ctcm_main.c b/drivers/s390/net/ctcm_main.c index 6faf271360..ac15d7c2b2 100644 --- a/drivers/s390/net/ctcm_main.c +++ b/drivers/s390/net/ctcm_main.c @@ -200,13 +200,13 @@ static void channel_free(struct channel *ch) static void channel_remove(struct channel *ch) { struct channel **c = &channels; - char chid[CTCM_ID_SIZE+1]; + char chid[CTCM_ID_SIZE]; int ok = 0; if (ch == NULL) return; else - strncpy(chid, ch->id, CTCM_ID_SIZE); + strscpy(chid, ch->id, sizeof(chid)); channel_free(ch); while (*c) { diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c index cd783290bd..cf8506d0f1 100644 --- a/drivers/s390/net/qeth_core_main.c +++ b/drivers/s390/net/qeth_core_main.c @@ -3675,7 +3675,7 @@ static void qeth_flush_queue(struct qeth_qdio_out_q *queue) static void qeth_check_outbound_queue(struct qeth_qdio_out_q *queue) { /* - * check if weed have to switch to non-packing mode or if + * check if we have to switch to non-packing mode or if * we have to get a pci flag out on the queue */ if ((atomic_read(&queue->used_buffers) <= QETH_LOW_WATERMARK_PACK) || @@ -6226,7 +6226,7 @@ static int qeth_add_dbf_entry(struct qeth_card *card, char *name) new_entry = kzalloc(sizeof(struct qeth_dbf_entry), GFP_KERNEL); if (!new_entry) goto err_dbg; - strncpy(new_entry->dbf_name, name, DBF_NAME_LEN); + strscpy(new_entry->dbf_name, name, sizeof(new_entry->dbf_name)); new_entry->dbf_info = card->debug; mutex_lock(&qeth_dbf_list_mutex); list_add(&new_entry->dbf_list, &qeth_dbf_list); diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c index b92a32b4b1..04c64ce0a1 100644 --- a/drivers/s390/net/qeth_l3_main.c +++ b/drivers/s390/net/qeth_l3_main.c @@ -255,9 +255,10 @@ static void qeth_l3_clear_ip_htable(struct qeth_card *card, int recover) if (!recover) { hash_del(&addr->hnode); kfree(addr); - continue; + } else { + /* prepare for recovery */ + addr->disp_flag = QETH_DISP_ADDR_ADD; } - addr->disp_flag = QETH_DISP_ADDR_ADD; } mutex_unlock(&card->ip_lock); @@ -278,9 +279,11 @@ static void qeth_l3_recover_ip(struct qeth_card *card) if (addr->disp_flag == QETH_DISP_ADDR_ADD) { rc = qeth_l3_register_addr_entry(card, addr); - if (!rc) { + if (!rc || rc == -EADDRINUSE || rc == -ENETDOWN) { + /* keep it in the records */ addr->disp_flag = QETH_DISP_ADDR_DO_NOTHING; } else { + /* bad address */ hash_del(&addr->hnode); kfree(addr); } |