diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2019-01-03 03:37:01 +0100 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2019-01-03 03:37:01 +0100 |
commit | 04a17edeca524b71dbb5be41a7002d247fbf34c0 (patch) | |
tree | ad2809ab91000a6fb5a831c26ff78bba6a52bb0d /drivers/s390 | |
parent | Merge tag 'nfs-for-4.21-1' of git://git.linux-nfs.org/projects/anna/linux-nfs (diff) | |
parent | Merge tag 'vfio-ccw-20181213' of git://git.kernel.org/pub/scm/linux/kernel/gi... (diff) | |
download | linux-04a17edeca524b71dbb5be41a7002d247fbf34c0.tar.xz linux-04a17edeca524b71dbb5be41a7002d247fbf34c0.zip |
Merge tag 's390-4.21-1' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux
Pull s390 updates from Martin Schwidefsky:
- A larger update for the zcrypt / AP bus code:
+ Update two inline assemblies in the zcrypt driver to make gcc happy
+ Add a missing reply code for invalid special commands for zcrypt
+ Allow AP device reset to be triggered from user space
+ Split the AP scan function into smaller, more readable functions
- Updates for vfio-ccw and vfio-ap
+ Add maintainers and reviewer for vfio-ccw
+ Include facility.h in vfio_ap_drv.c to avoid fragile include chain
+ Simplicy vfio-ccw state machine
- Use the common code version of bust_spinlocks
- Make use of the DEFINE_SHOW_ATTRIBUTE
- Fix three incorrect file permissions in the DASD driver
- Remove bit spin-lock from the PCI interrupt handler
- Fix GFP_ATOMIC vs GFP_KERNEL in the PCI code
* tag 's390-4.21-1' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux:
s390/zcrypt: rework ap scan bus code
s390/zcrypt: make sysfs reset attribute trigger queue reset
s390/pci: fix sleeping in atomic during hotplug
s390/pci: remove bit_lock usage in interrupt handler
s390/drivers: fix proc/debugfs file permissions
s390: convert to DEFINE_SHOW_ATTRIBUTE
MAINTAINERS/vfio-ccw: add Farhan and Eric, make Halil Reviewer
vfio: ccw: Merge BUSY and BOXED states
s390: use common bust_spinlocks()
s390/zcrypt: improve special ap message cmd handling
s390/ap: rework assembler functions to use unions for in/out register variables
s390: vfio-ap: include <asm/facility> for test_facility()
Diffstat (limited to 'drivers/s390')
-rw-r--r-- | drivers/s390/block/dasd.c | 15 | ||||
-rw-r--r-- | drivers/s390/block/dasd_proc.c | 3 | ||||
-rw-r--r-- | drivers/s390/char/tape_proc.c | 7 | ||||
-rw-r--r-- | drivers/s390/cio/qdio_debug.c | 18 | ||||
-rw-r--r-- | drivers/s390/cio/vfio_ccw_fsm.c | 7 | ||||
-rw-r--r-- | drivers/s390/cio/vfio_ccw_private.h | 1 | ||||
-rw-r--r-- | drivers/s390/crypto/ap_bus.c | 277 | ||||
-rw-r--r-- | drivers/s390/crypto/ap_queue.c | 23 | ||||
-rw-r--r-- | drivers/s390/crypto/vfio_ap_drv.c | 1 | ||||
-rw-r--r-- | drivers/s390/crypto/zcrypt_error.h | 2 |
10 files changed, 193 insertions, 161 deletions
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c index 5e9ebdb0594c..397af07e4d88 100644 --- a/drivers/s390/block/dasd.c +++ b/drivers/s390/block/dasd.c @@ -1192,20 +1192,7 @@ static int dasd_hosts_show(struct seq_file *m, void *v) return rc; } -static int dasd_hosts_open(struct inode *inode, struct file *file) -{ - struct dasd_device *device = inode->i_private; - - return single_open(file, dasd_hosts_show, device); -} - -static const struct file_operations dasd_hosts_fops = { - .owner = THIS_MODULE, - .open = dasd_hosts_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; +DEFINE_SHOW_ATTRIBUTE(dasd_hosts); static void dasd_hosts_exit(struct dasd_device *device) { diff --git a/drivers/s390/block/dasd_proc.c b/drivers/s390/block/dasd_proc.c index 5cb80c645489..1770b99f607e 100644 --- a/drivers/s390/block/dasd_proc.c +++ b/drivers/s390/block/dasd_proc.c @@ -339,8 +339,7 @@ dasd_proc_init(void) dasd_proc_root_entry = proc_mkdir("dasd", NULL); if (!dasd_proc_root_entry) goto out_nodasd; - dasd_devices_entry = proc_create_seq("devices", - S_IFREG | S_IRUGO | S_IWUSR, + dasd_devices_entry = proc_create_seq("devices", 0444, dasd_proc_root_entry, &dasd_devices_seq_ops); if (!dasd_devices_entry) diff --git a/drivers/s390/char/tape_proc.c b/drivers/s390/char/tape_proc.c index 32a14ee31c6b..2238d9df6c47 100644 --- a/drivers/s390/char/tape_proc.c +++ b/drivers/s390/char/tape_proc.c @@ -111,11 +111,8 @@ static const struct seq_operations tape_proc_seq = { void tape_proc_init(void) { - tape_proc_devices = proc_create_seq("tapedevices", - S_IFREG | S_IRUGO | S_IWUSR, NULL, &tape_proc_seq); - if (tape_proc_devices == NULL) { - return; - } + tape_proc_devices = proc_create_seq("tapedevices", 0444, NULL, + &tape_proc_seq); } /* diff --git a/drivers/s390/cio/qdio_debug.c b/drivers/s390/cio/qdio_debug.c index 68a82f3e2e92..d2f98e5829d4 100644 --- a/drivers/s390/cio/qdio_debug.c +++ b/drivers/s390/cio/qdio_debug.c @@ -190,19 +190,7 @@ static int qstat_show(struct seq_file *m, void *v) return 0; } -static int qstat_seq_open(struct inode *inode, struct file *filp) -{ - return single_open(filp, qstat_show, - file_inode(filp)->i_private); -} - -static const struct file_operations debugfs_fops = { - .owner = THIS_MODULE, - .open = qstat_seq_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; +DEFINE_SHOW_ATTRIBUTE(qstat); static char *qperf_names[] = { "Assumed adapter interrupts", @@ -305,8 +293,8 @@ static void setup_debugfs_entry(struct qdio_q *q) snprintf(name, QDIO_DEBUGFS_NAME_LEN, "%s_%d", q->is_input_q ? "input" : "output", q->nr); - q->debugfs_q = debugfs_create_file(name, S_IFREG | S_IRUGO | S_IWUSR, - q->irq_ptr->debugfs_dev, q, &debugfs_fops); + q->debugfs_q = debugfs_create_file(name, 0444, + q->irq_ptr->debugfs_dev, q, &qstat_fops); if (IS_ERR(q->debugfs_q)) q->debugfs_q = NULL; } diff --git a/drivers/s390/cio/vfio_ccw_fsm.c b/drivers/s390/cio/vfio_ccw_fsm.c index f94aa01f9c36..cab17865aafe 100644 --- a/drivers/s390/cio/vfio_ccw_fsm.c +++ b/drivers/s390/cio/vfio_ccw_fsm.c @@ -130,7 +130,7 @@ static void fsm_io_request(struct vfio_ccw_private *private, struct mdev_device *mdev = private->mdev; char *errstr = "request"; - private->state = VFIO_CCW_STATE_BOXED; + private->state = VFIO_CCW_STATE_BUSY; memcpy(scsw, io_region->scsw_area, sizeof(*scsw)); @@ -216,11 +216,6 @@ fsm_func_t *vfio_ccw_jumptable[NR_VFIO_CCW_STATES][NR_VFIO_CCW_EVENTS] = { [VFIO_CCW_EVENT_IO_REQ] = fsm_io_request, [VFIO_CCW_EVENT_INTERRUPT] = fsm_irq, }, - [VFIO_CCW_STATE_BOXED] = { - [VFIO_CCW_EVENT_NOT_OPER] = fsm_notoper, - [VFIO_CCW_EVENT_IO_REQ] = fsm_io_busy, - [VFIO_CCW_EVENT_INTERRUPT] = fsm_irq, - }, [VFIO_CCW_STATE_BUSY] = { [VFIO_CCW_EVENT_NOT_OPER] = fsm_notoper, [VFIO_CCW_EVENT_IO_REQ] = fsm_io_busy, diff --git a/drivers/s390/cio/vfio_ccw_private.h b/drivers/s390/cio/vfio_ccw_private.h index 078e46f9623d..08e9a7dc9176 100644 --- a/drivers/s390/cio/vfio_ccw_private.h +++ b/drivers/s390/cio/vfio_ccw_private.h @@ -63,7 +63,6 @@ enum vfio_ccw_state { VFIO_CCW_STATE_NOT_OPER, VFIO_CCW_STATE_STANDBY, VFIO_CCW_STATE_IDLE, - VFIO_CCW_STATE_BOXED, VFIO_CCW_STATE_BUSY, /* last element! */ NR_VFIO_CCW_STATES diff --git a/drivers/s390/crypto/ap_bus.c b/drivers/s390/crypto/ap_bus.c index 9f5a201c4c87..48ea0004a56d 100644 --- a/drivers/s390/crypto/ap_bus.c +++ b/drivers/s390/crypto/ap_bus.c @@ -299,7 +299,7 @@ static int ap_query_queue(ap_qid_t qid, int *queue_depth, int *device_type, ap_max_domain_id = 15; switch (*device_type) { /* For CEX2 and CEX3 the available functions - * are not refrected by the facilities bits. + * are not reflected by the facilities bits. * Instead it is coded into the type. So here * modify the function bits based on the type. */ @@ -1317,7 +1317,7 @@ static int ap_get_compatible_type(ap_qid_t qid, int rawtype, unsigned int func) } /* - * helper function to be used with bus_find_dev + * Helper function to be used with bus_find_dev * matches for the card device with the given id */ static int __match_card_device_with_id(struct device *dev, void *data) @@ -1325,7 +1325,8 @@ static int __match_card_device_with_id(struct device *dev, void *data) return is_card_dev(dev) && to_ap_card(dev)->id == (int)(long) data; } -/* helper function to be used with bus_find_dev +/* + * Helper function to be used with bus_find_dev * matches for the queue device with a given qid */ static int __match_queue_device_with_qid(struct device *dev, void *data) @@ -1333,143 +1334,185 @@ static int __match_queue_device_with_qid(struct device *dev, void *data) return is_queue_dev(dev) && to_ap_queue(dev)->qid == (int)(long) data; } -/** - * ap_scan_bus(): Scan the AP bus for new devices - * Runs periodically, workqueue timer (ap_config_time) +/* + * Helper function for ap_scan_bus(). + * Does the scan bus job for the given adapter id. */ -static void ap_scan_bus(struct work_struct *unused) +static void _ap_scan_bus_adapter(int id) { - struct ap_queue *aq; + ap_qid_t qid; + unsigned int func; struct ap_card *ac; struct device *dev; - ap_qid_t qid; - int comp_type, depth = 0, type = 0; - unsigned int func = 0; - int rc, id, dom, borked, domains, defdomdevs = 0; - - AP_DBF(DBF_DEBUG, "%s running\n", __func__); + struct ap_queue *aq; + int rc, dom, depth, type, comp_type, borked; + + /* check if there is a card device registered with this id */ + dev = bus_find_device(&ap_bus_type, NULL, + (void *)(long) id, + __match_card_device_with_id); + ac = dev ? to_ap_card(dev) : NULL; + if (!ap_test_config_card_id(id)) { + if (dev) { + /* Card device has been removed from configuration */ + bus_for_each_dev(&ap_bus_type, NULL, + (void *)(long) id, + __ap_queue_devices_with_id_unregister); + device_unregister(dev); + put_device(dev); + } + return; + } - ap_query_configuration(ap_configuration); - ap_select_domain(); + /* + * This card id is enabled in the configuration. If we already have + * a card device with this id, check if type and functions are still + * the very same. Also verify that at least one queue is available. + */ + if (ac) { + /* find the first valid queue */ + for (dom = 0; dom < AP_DOMAINS; dom++) { + qid = AP_MKQID(id, dom); + if (ap_query_queue(qid, &depth, &type, &func) == 0) + break; + } + borked = 0; + if (dom >= AP_DOMAINS) { + /* no accessible queue on this card */ + borked = 1; + } else if (ac->raw_hwtype != type) { + /* card type has changed */ + AP_DBF(DBF_INFO, "card=%02x type changed.\n", id); + borked = 1; + } else if (ac->functions != func) { + /* card functions have changed */ + AP_DBF(DBF_INFO, "card=%02x functions changed.\n", id); + borked = 1; + } + if (borked) { + /* unregister card device and associated queues */ + bus_for_each_dev(&ap_bus_type, NULL, + (void *)(long) id, + __ap_queue_devices_with_id_unregister); + device_unregister(dev); + put_device(dev); + /* go back if there is no valid queue on this card */ + if (dom >= AP_DOMAINS) + return; + ac = NULL; + } + } - for (id = 0; id < AP_DEVICES; id++) { - /* check if device is registered */ + /* + * Go through all possible queue ids. Check and maybe create or release + * queue devices for this card. If there exists no card device yet, + * create a card device also. + */ + for (dom = 0; dom < AP_DOMAINS; dom++) { + qid = AP_MKQID(id, dom); dev = bus_find_device(&ap_bus_type, NULL, - (void *)(long) id, - __match_card_device_with_id); - ac = dev ? to_ap_card(dev) : NULL; - if (!ap_test_config_card_id(id)) { + (void *)(long) qid, + __match_queue_device_with_qid); + aq = dev ? to_ap_queue(dev) : NULL; + if (!ap_test_config_domain(dom)) { if (dev) { - /* Card device has been removed from - * configuration, remove the belonging - * queue devices. + /* Queue device exists but has been + * removed from configuration. */ - bus_for_each_dev(&ap_bus_type, NULL, - (void *)(long) id, - __ap_queue_devices_with_id_unregister); - /* now remove the card device */ device_unregister(dev); put_device(dev); } continue; } - /* According to the configuration there should be a card - * device, so check if there is at least one valid queue - * and maybe create queue devices and the card device. - */ - domains = 0; - for (dom = 0; dom < AP_DOMAINS; dom++) { - qid = AP_MKQID(id, dom); - dev = bus_find_device(&ap_bus_type, NULL, - (void *)(long) qid, - __match_queue_device_with_qid); - aq = dev ? to_ap_queue(dev) : NULL; - if (!ap_test_config_domain(dom)) { - if (dev) { - /* Queue device exists but has been - * removed from configuration. - */ - device_unregister(dev); - put_device(dev); - } - continue; - } - rc = ap_query_queue(qid, &depth, &type, &func); - if (dev) { + /* try to fetch infos about this queue */ + rc = ap_query_queue(qid, &depth, &type, &func); + if (dev) { + if (rc == -ENODEV) + borked = 1; + else { spin_lock_bh(&aq->lock); - if (rc == -ENODEV || - /* adapter reconfiguration */ - (ac && ac->functions != func)) - aq->state = AP_STATE_BORKED; borked = aq->state == AP_STATE_BORKED; spin_unlock_bh(&aq->lock); - if (borked) /* Remove broken device */ - device_unregister(dev); - put_device(dev); - if (!borked) { - domains++; - if (dom == ap_domain_index) - defdomdevs++; - continue; - } - } - if (rc) - continue; - /* a new queue device is needed, check out comp type */ - comp_type = ap_get_compatible_type(qid, type, func); - if (!comp_type) - continue; - /* maybe a card device needs to be created first */ - if (!ac) { - ac = ap_card_create(id, depth, type, - comp_type, func); - if (!ac) - continue; - ac->ap_dev.device.bus = &ap_bus_type; - ac->ap_dev.device.parent = ap_root_device; - dev_set_name(&ac->ap_dev.device, - "card%02x", id); - /* Register card with AP bus */ - rc = device_register(&ac->ap_dev.device); - if (rc) { - put_device(&ac->ap_dev.device); - ac = NULL; - break; - } - /* get it and thus adjust reference counter */ - get_device(&ac->ap_dev.device); } - /* now create the new queue device */ - aq = ap_queue_create(qid, comp_type); - if (!aq) + if (borked) /* Remove broken device */ + device_unregister(dev); + put_device(dev); + continue; + } + if (rc) + continue; + /* a new queue device is needed, check out comp type */ + comp_type = ap_get_compatible_type(qid, type, func); + if (!comp_type) + continue; + /* maybe a card device needs to be created first */ + if (!ac) { + ac = ap_card_create(id, depth, type, comp_type, func); + if (!ac) continue; - aq->card = ac; - aq->ap_dev.device.bus = &ap_bus_type; - aq->ap_dev.device.parent = &ac->ap_dev.device; - dev_set_name(&aq->ap_dev.device, - "%02x.%04x", id, dom); - /* Register device */ - rc = device_register(&aq->ap_dev.device); + ac->ap_dev.device.bus = &ap_bus_type; + ac->ap_dev.device.parent = ap_root_device; + dev_set_name(&ac->ap_dev.device, "card%02x", id); + /* Register card device with AP bus */ + rc = device_register(&ac->ap_dev.device); if (rc) { - put_device(&aq->ap_dev.device); - continue; + put_device(&ac->ap_dev.device); + ac = NULL; + break; } - domains++; - if (dom == ap_domain_index) - defdomdevs++; - } /* end domain loop */ - if (ac) { - /* remove card dev if there are no queue devices */ - if (!domains) - device_unregister(&ac->ap_dev.device); - put_device(&ac->ap_dev.device); + /* get it and thus adjust reference counter */ + get_device(&ac->ap_dev.device); + } + /* now create the new queue device */ + aq = ap_queue_create(qid, comp_type); + if (!aq) + continue; + aq->card = ac; + aq->ap_dev.device.bus = &ap_bus_type; + aq->ap_dev.device.parent = &ac->ap_dev.device; + dev_set_name(&aq->ap_dev.device, "%02x.%04x", id, dom); + /* Register queue device */ + rc = device_register(&aq->ap_dev.device); + if (rc) { + put_device(&aq->ap_dev.device); + continue; } - } /* end device loop */ + } /* end domain loop */ + + if (ac) + put_device(&ac->ap_dev.device); +} - if (ap_domain_index >= 0 && defdomdevs < 1) - AP_DBF(DBF_INFO, - "no queue device with default domain %d available\n", - ap_domain_index); +/** + * ap_scan_bus(): Scan the AP bus for new devices + * Runs periodically, workqueue timer (ap_config_time) + */ +static void ap_scan_bus(struct work_struct *unused) +{ + int id; + + AP_DBF(DBF_DEBUG, "%s running\n", __func__); + + ap_query_configuration(ap_configuration); + ap_select_domain(); + + /* loop over all possible adapters */ + for (id = 0; id < AP_DEVICES; id++) + _ap_scan_bus_adapter(id); + + /* check if there is at least one queue available with default domain */ + if (ap_domain_index >= 0) { + struct device *dev = + bus_find_device(&ap_bus_type, NULL, + (void *)(long) ap_domain_index, + __match_queue_device_with_qid); + if (dev) + put_device(dev); + else + AP_DBF(DBF_INFO, + "no queue device with default domain %d available\n", + ap_domain_index); + } mod_timer(&ap_config_timer, jiffies + ap_config_time * HZ); } diff --git a/drivers/s390/crypto/ap_queue.c b/drivers/s390/crypto/ap_queue.c index 0aa4b3ccc948..576ac08777c5 100644 --- a/drivers/s390/crypto/ap_queue.c +++ b/drivers/s390/crypto/ap_queue.c @@ -14,6 +14,9 @@ #include <asm/facility.h> #include "ap_bus.h" +#include "ap_debug.h" + +static void __ap_flush_queue(struct ap_queue *aq); /** * ap_queue_enable_interruption(): Enable interruption on an AP queue. @@ -541,7 +544,25 @@ static ssize_t reset_show(struct device *dev, return rc; } -static DEVICE_ATTR_RO(reset); +static ssize_t reset_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct ap_queue *aq = to_ap_queue(dev); + + spin_lock_bh(&aq->lock); + __ap_flush_queue(aq); + aq->state = AP_STATE_RESET_START; + ap_wait(ap_sm_event(aq, AP_EVENT_POLL)); + spin_unlock_bh(&aq->lock); + + AP_DBF(DBF_INFO, "reset queue=%02x.%04x triggered by user\n", + AP_QID_CARD(aq->qid), AP_QID_QUEUE(aq->qid)); + + return count; +} + +static DEVICE_ATTR_RW(reset); static ssize_t interrupt_show(struct device *dev, struct device_attribute *attr, char *buf) diff --git a/drivers/s390/crypto/vfio_ap_drv.c b/drivers/s390/crypto/vfio_ap_drv.c index 7667b38728f0..31c6c847eaca 100644 --- a/drivers/s390/crypto/vfio_ap_drv.c +++ b/drivers/s390/crypto/vfio_ap_drv.c @@ -11,6 +11,7 @@ #include <linux/mod_devicetable.h> #include <linux/slab.h> #include <linux/string.h> +#include <asm/facility.h> #include "vfio_ap_private.h" #define VFIO_AP_ROOT_NAME "vfio_ap" diff --git a/drivers/s390/crypto/zcrypt_error.h b/drivers/s390/crypto/zcrypt_error.h index 240b27f3f5f6..f34ee41cbed8 100644 --- a/drivers/s390/crypto/zcrypt_error.h +++ b/drivers/s390/crypto/zcrypt_error.h @@ -51,6 +51,7 @@ struct error_hdr { #define REP82_ERROR_FORMAT_FIELD 0x29 #define REP82_ERROR_INVALID_COMMAND 0x30 #define REP82_ERROR_MALFORMED_MSG 0x40 +#define REP82_ERROR_INVALID_SPECIAL_CMD 0x41 #define REP82_ERROR_INVALID_DOMAIN_PRECHECK 0x42 #define REP82_ERROR_RESERVED_FIELDO 0x50 /* old value */ #define REP82_ERROR_WORD_ALIGNMENT 0x60 @@ -89,6 +90,7 @@ static inline int convert_error(struct zcrypt_queue *zq, case REP88_ERROR_MESSAGE_MALFORMD: case REP82_ERROR_INVALID_DOMAIN_PRECHECK: case REP82_ERROR_INVALID_DOMAIN_PENDING: + case REP82_ERROR_INVALID_SPECIAL_CMD: // REP88_ERROR_INVALID_KEY // '82' CEX2A // REP88_ERROR_OPERAND // '84' CEX2A // REP88_ERROR_OPERAND_EVEN_MOD // '85' CEX2A |