aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/s390')
-rw-r--r--drivers/s390/block/dasd.c6
-rw-r--r--drivers/s390/char/con3215.c25
-rw-r--r--drivers/s390/char/con3270.c12
-rw-r--r--drivers/s390/char/uvdevice.c3
-rw-r--r--drivers/s390/cio/chsc.c18
-rw-r--r--drivers/s390/cio/chsc_sch.c6
-rw-r--r--drivers/s390/cio/cio.c6
-rw-r--r--drivers/s390/cio/cio.h2
-rw-r--r--drivers/s390/cio/css.c36
-rw-r--r--drivers/s390/cio/device.c66
-rw-r--r--drivers/s390/cio/device_ops.c6
-rw-r--r--drivers/s390/cio/device_pgid.c12
-rw-r--r--drivers/s390/cio/eadm_sch.c36
-rw-r--r--drivers/s390/cio/vfio_ccw_chp.c2
-rw-r--r--drivers/s390/cio/vfio_ccw_drv.c12
-rw-r--r--drivers/s390/cio/vfio_ccw_fsm.c24
-rw-r--r--drivers/s390/cio/vfio_ccw_ops.c6
-rw-r--r--drivers/s390/crypto/ap_bus.c72
-rw-r--r--drivers/s390/crypto/ap_bus.h22
-rw-r--r--drivers/s390/crypto/ap_card.c18
-rw-r--r--drivers/s390/crypto/ap_queue.c200
-rw-r--r--drivers/s390/crypto/vfio_ap_ops.c300
-rw-r--r--drivers/s390/crypto/vfio_ap_private.h3
-rw-r--r--drivers/s390/crypto/zcrypt_api.c16
-rw-r--r--drivers/s390/crypto/zcrypt_cex4.c31
-rw-r--r--drivers/s390/net/ism.h7
-rw-r--r--drivers/s390/net/ism_drv.c57
-rw-r--r--drivers/s390/net/qeth_l3_main.c9
-rw-r--r--drivers/s390/scsi/zfcp_fc.c15
29 files changed, 574 insertions, 454 deletions
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c
index 833cfab7d877..7327e81352e9 100644
--- a/drivers/s390/block/dasd.c
+++ b/drivers/s390/block/dasd.c
@@ -1106,12 +1106,6 @@ static void dasd_statistics_removeroot(void)
return;
}
-int dasd_stats_generic_show(struct seq_file *m, void *v)
-{
- seq_puts(m, "Statistics are not activated in this kernel\n");
- return 0;
-}
-
static void dasd_profile_init(struct dasd_profile *profile,
struct dentry *base_dentry)
{
diff --git a/drivers/s390/char/con3215.c b/drivers/s390/char/con3215.c
index 99361618c31f..0b0324fe4aff 100644
--- a/drivers/s390/char/con3215.c
+++ b/drivers/s390/char/con3215.c
@@ -79,8 +79,8 @@ struct raw3215_info {
struct ccw_device *cdev; /* device for tty driver */
spinlock_t *lock; /* pointer to irq lock */
int flags; /* state flags */
- char *buffer; /* pointer to output buffer */
- char *inbuf; /* pointer to input buffer */
+ u8 *buffer; /* pointer to output buffer */
+ u8 *inbuf; /* pointer to input buffer */
int head; /* first free byte in output buffer */
int count; /* number of bytes in output buffer */
int written; /* number of bytes in write requests */
@@ -89,7 +89,6 @@ struct raw3215_info {
wait_queue_head_t empty_wait; /* wait queue for flushing */
struct timer_list timer; /* timer for delayed output */
int line_pos; /* position on the line (for tabs) */
- char ubuffer[80]; /* copy_from_user buffer */
};
/* array of 3215 devices structures */
@@ -523,12 +522,14 @@ static unsigned int raw3215_make_room(struct raw3215_info *raw,
* string without blocking.
* Return value is the number of bytes copied.
*/
-static unsigned int raw3215_addtext(const char *str, unsigned int length,
+static unsigned int raw3215_addtext(const u8 *str, size_t length,
struct raw3215_info *raw, int opmode,
unsigned int todrop)
{
- unsigned int c, ch, i, blanks, expanded_size = 0;
+ unsigned int i, blanks, expanded_size = 0;
unsigned int column = raw->line_pos;
+ size_t c;
+ u8 ch;
if (opmode == RAW3215_COUNT)
todrop = 0;
@@ -559,7 +560,7 @@ static unsigned int raw3215_addtext(const char *str, unsigned int length,
if (todrop && expanded_size < todrop) /* Drop head data */
continue;
for (i = 0; i < blanks; i++) {
- raw->buffer[raw->head] = (char)_ascebc[(int)ch];
+ raw->buffer[raw->head] = _ascebc[ch];
raw->head = (raw->head + 1) & (RAW3215_BUFFER_SIZE - 1);
raw->count++;
}
@@ -571,8 +572,8 @@ static unsigned int raw3215_addtext(const char *str, unsigned int length,
/*
* String write routine for 3215 devices
*/
-static void raw3215_write(struct raw3215_info *raw, const char *str,
- unsigned int length)
+static void raw3215_write(struct raw3215_info *raw, const u8 *str,
+ size_t length)
{
unsigned int count, avail;
unsigned long flags;
@@ -597,7 +598,7 @@ static void raw3215_write(struct raw3215_info *raw, const char *str,
/*
* Put character routine for 3215 devices
*/
-static void raw3215_putchar(struct raw3215_info *raw, unsigned char ch)
+static void raw3215_putchar(struct raw3215_info *raw, u8 ch)
{
raw3215_write(raw, &ch, 1);
}
@@ -824,12 +825,10 @@ static struct ccw_driver raw3215_ccw_driver = {
.int_class = IRQIO_C15,
};
-static void handle_write(struct raw3215_info *raw, const char *str, int count)
+static void handle_write(struct raw3215_info *raw, const u8 *str, size_t count)
{
- int i;
-
while (count > 0) {
- i = min_t(int, count, RAW3215_BUFFER_SIZE - 1);
+ size_t i = min_t(size_t, count, RAW3215_BUFFER_SIZE - 1);
raw3215_write(raw, str, i);
count -= i;
str += i;
diff --git a/drivers/s390/char/con3270.c b/drivers/s390/char/con3270.c
index 363315fa1666..251d2a1c3eef 100644
--- a/drivers/s390/char/con3270.c
+++ b/drivers/s390/char/con3270.c
@@ -54,7 +54,7 @@ struct tty3270_attribute {
};
struct tty3270_cell {
- unsigned char character;
+ u8 character;
struct tty3270_attribute attributes;
};
@@ -123,7 +123,7 @@ struct tty3270 {
/* Character array for put_char/flush_chars. */
unsigned int char_count;
- char char_buf[TTY3270_CHAR_BUF_SIZE];
+ u8 char_buf[TTY3270_CHAR_BUF_SIZE];
};
/* tty3270->update_flags. See tty3270_update for details. */
@@ -1255,7 +1255,7 @@ static unsigned int tty3270_write_room(struct tty_struct *tty)
* Insert character into the screen at the current position with the
* current color and highlight. This function does NOT do cursor movement.
*/
-static void tty3270_put_character(struct tty3270 *tp, char ch)
+static void tty3270_put_character(struct tty3270 *tp, u8 ch)
{
struct tty3270_line *line;
struct tty3270_cell *cell;
@@ -1561,7 +1561,7 @@ static void tty3270_goto_xy(struct tty3270 *tp, int cx, int cy)
* Pn is a numeric parameter, a string of zero or more decimal digits.
* Ps is a selective parameter.
*/
-static void tty3270_escape_sequence(struct tty3270 *tp, char ch)
+static void tty3270_escape_sequence(struct tty3270 *tp, u8 ch)
{
enum { ES_NORMAL, ES_ESC, ES_SQUARE, ES_PAREN, ES_GETPARS };
@@ -1726,7 +1726,7 @@ static void tty3270_escape_sequence(struct tty3270 *tp, char ch)
* String write routine for 3270 ttys
*/
static void tty3270_do_write(struct tty3270 *tp, struct tty_struct *tty,
- const unsigned char *buf, int count)
+ const u8 *buf, size_t count)
{
int i_msg, i;
@@ -2052,7 +2052,7 @@ con3270_write(struct console *co, const char *str, unsigned int count)
{
struct tty3270 *tp = co->data;
unsigned long flags;
- char c;
+ u8 c;
spin_lock_irqsave(&tp->view.lock, flags);
while (count--) {
diff --git a/drivers/s390/char/uvdevice.c b/drivers/s390/char/uvdevice.c
index 144cd2e03590..42c9f77f8da0 100644
--- a/drivers/s390/char/uvdevice.c
+++ b/drivers/s390/char/uvdevice.c
@@ -109,6 +109,7 @@ static int uvio_copy_attest_result_to_user(struct uv_cb_attest *uvcb_attest,
struct uvio_attest *uvio_attest)
{
struct uvio_attest __user *user_uvio_attest = (void __user *)uv_ioctl->argument_addr;
+ u32 __user *user_buf_add_len = (u32 __user *)&user_uvio_attest->add_data_len;
void __user *user_buf_add = (void __user *)uvio_attest->add_data_addr;
void __user *user_buf_meas = (void __user *)uvio_attest->meas_addr;
void __user *user_buf_uid = &user_uvio_attest->config_uid;
@@ -117,6 +118,8 @@ static int uvio_copy_attest_result_to_user(struct uv_cb_attest *uvcb_attest,
return -EFAULT;
if (add_data && copy_to_user(user_buf_add, add_data, uvio_attest->add_data_len))
return -EFAULT;
+ if (put_user(uvio_attest->add_data_len, user_buf_add_len))
+ return -EFAULT;
if (copy_to_user(user_buf_uid, uvcb_attest->config_uid, sizeof(uvcb_attest->config_uid)))
return -EFAULT;
return 0;
diff --git a/drivers/s390/cio/chsc.c b/drivers/s390/cio/chsc.c
index f8b04ce61556..64ed55c3aed6 100644
--- a/drivers/s390/cio/chsc.c
+++ b/drivers/s390/cio/chsc.c
@@ -219,16 +219,16 @@ EXPORT_SYMBOL_GPL(chsc_sadc);
static int s390_subchannel_remove_chpid(struct subchannel *sch, void *data)
{
- spin_lock_irq(sch->lock);
+ spin_lock_irq(&sch->lock);
if (sch->driver && sch->driver->chp_event)
if (sch->driver->chp_event(sch, data, CHP_OFFLINE) != 0)
goto out_unreg;
- spin_unlock_irq(sch->lock);
+ spin_unlock_irq(&sch->lock);
return 0;
out_unreg:
sch->lpm = 0;
- spin_unlock_irq(sch->lock);
+ spin_unlock_irq(&sch->lock);
css_schedule_eval(sch->schid);
return 0;
}
@@ -258,10 +258,10 @@ void chsc_chp_offline(struct chp_id chpid)
static int __s390_process_res_acc(struct subchannel *sch, void *data)
{
- spin_lock_irq(sch->lock);
+ spin_lock_irq(&sch->lock);
if (sch->driver && sch->driver->chp_event)
sch->driver->chp_event(sch, data, CHP_ONLINE);
- spin_unlock_irq(sch->lock);
+ spin_unlock_irq(&sch->lock);
return 0;
}
@@ -292,10 +292,10 @@ static void s390_process_res_acc(struct chp_link *link)
static int process_fces_event(struct subchannel *sch, void *data)
{
- spin_lock_irq(sch->lock);
+ spin_lock_irq(&sch->lock);
if (sch->driver && sch->driver->chp_event)
sch->driver->chp_event(sch, data, CHP_FCES_EVENT);
- spin_unlock_irq(sch->lock);
+ spin_unlock_irq(&sch->lock);
return 0;
}
@@ -769,11 +769,11 @@ static void __s390_subchannel_vary_chpid(struct subchannel *sch,
memset(&link, 0, sizeof(struct chp_link));
link.chpid = chpid;
- spin_lock_irqsave(sch->lock, flags);
+ spin_lock_irqsave(&sch->lock, flags);
if (sch->driver && sch->driver->chp_event)
sch->driver->chp_event(sch, &link,
on ? CHP_VARY_ON : CHP_VARY_OFF);
- spin_unlock_irqrestore(sch->lock, flags);
+ spin_unlock_irqrestore(&sch->lock, flags);
}
static int s390_subchannel_vary_chpid_off(struct subchannel *sch, void *data)
diff --git a/drivers/s390/cio/chsc_sch.c b/drivers/s390/cio/chsc_sch.c
index 180ab899289c..902237d0baef 100644
--- a/drivers/s390/cio/chsc_sch.c
+++ b/drivers/s390/cio/chsc_sch.c
@@ -211,10 +211,10 @@ static int chsc_async(struct chsc_async_area *chsc_area,
chsc_area->header.key = PAGE_DEFAULT_KEY >> 4;
while ((sch = chsc_get_next_subchannel(sch))) {
- spin_lock(sch->lock);
+ spin_lock(&sch->lock);
private = dev_get_drvdata(&sch->dev);
if (private->request) {
- spin_unlock(sch->lock);
+ spin_unlock(&sch->lock);
ret = -EBUSY;
continue;
}
@@ -239,7 +239,7 @@ static int chsc_async(struct chsc_async_area *chsc_area,
default:
ret = -ENODEV;
}
- spin_unlock(sch->lock);
+ spin_unlock(&sch->lock);
CHSC_MSG(2, "chsc on 0.%x.%04x returned cc=%d\n",
sch->schid.ssid, sch->schid.sch_no, cc);
if (ret == -EINPROGRESS)
diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c
index 6127add746d1..a5736b7357b2 100644
--- a/drivers/s390/cio/cio.c
+++ b/drivers/s390/cio/cio.c
@@ -546,7 +546,7 @@ static irqreturn_t do_cio_interrupt(int irq, void *dummy)
return IRQ_HANDLED;
}
sch = phys_to_virt(tpi_info->intparm);
- spin_lock(sch->lock);
+ spin_lock(&sch->lock);
/* Store interrupt response block to lowcore. */
if (tsch(tpi_info->schid, irb) == 0) {
/* Keep subchannel information word up to date. */
@@ -558,7 +558,7 @@ static irqreturn_t do_cio_interrupt(int irq, void *dummy)
inc_irq_stat(IRQIO_CIO);
} else
inc_irq_stat(IRQIO_CIO);
- spin_unlock(sch->lock);
+ spin_unlock(&sch->lock);
return IRQ_HANDLED;
}
@@ -663,7 +663,7 @@ struct subchannel *cio_probe_console(void)
if (IS_ERR(sch))
return sch;
- lockdep_set_class(sch->lock, &console_sch_key);
+ lockdep_set_class(&sch->lock, &console_sch_key);
isc_register(CONSOLE_ISC);
sch->config.isc = CONSOLE_ISC;
sch->config.intparm = (u32)virt_to_phys(sch);
diff --git a/drivers/s390/cio/cio.h b/drivers/s390/cio/cio.h
index fa8df50bb49e..a9057a5b670a 100644
--- a/drivers/s390/cio/cio.h
+++ b/drivers/s390/cio/cio.h
@@ -83,7 +83,7 @@ enum sch_todo {
/* subchannel data structure used by I/O subroutines */
struct subchannel {
struct subchannel_id schid;
- spinlock_t *lock; /* subchannel lock */
+ spinlock_t lock; /* subchannel lock */
struct mutex reg_mutex;
enum {
SUBCHANNEL_TYPE_IO = 0,
diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c
index 3ff46fc694f8..28a88ed2c3aa 100644
--- a/drivers/s390/cio/css.c
+++ b/drivers/s390/cio/css.c
@@ -148,16 +148,10 @@ out:
static void css_sch_todo(struct work_struct *work);
-static int css_sch_create_locks(struct subchannel *sch)
+static void css_sch_create_locks(struct subchannel *sch)
{
- sch->lock = kmalloc(sizeof(*sch->lock), GFP_KERNEL);
- if (!sch->lock)
- return -ENOMEM;
-
- spin_lock_init(sch->lock);
+ spin_lock_init(&sch->lock);
mutex_init(&sch->reg_mutex);
-
- return 0;
}
static void css_subchannel_release(struct device *dev)
@@ -167,7 +161,6 @@ static void css_subchannel_release(struct device *dev)
sch->config.intparm = 0;
cio_commit_config(sch);
kfree(sch->driver_override);
- kfree(sch->lock);
kfree(sch);
}
@@ -219,9 +212,7 @@ struct subchannel *css_alloc_subchannel(struct subchannel_id schid,
sch->schib = *schib;
sch->st = schib->pmcw.st;
- ret = css_sch_create_locks(sch);
- if (ret)
- goto err;
+ css_sch_create_locks(sch);
INIT_WORK(&sch->todo_work, css_sch_todo);
sch->dev.release = &css_subchannel_release;
@@ -233,19 +224,17 @@ struct subchannel *css_alloc_subchannel(struct subchannel_id schid,
*/
ret = dma_set_coherent_mask(&sch->dev, DMA_BIT_MASK(31));
if (ret)
- goto err_lock;
+ goto err;
/*
* But we don't have such restrictions imposed on the stuff that
* is handled by the streaming API.
*/
ret = dma_set_mask(&sch->dev, DMA_BIT_MASK(64));
if (ret)
- goto err_lock;
+ goto err;
return sch;
-err_lock:
- kfree(sch->lock);
err:
kfree(sch);
return ERR_PTR(ret);
@@ -604,12 +593,12 @@ static void css_sch_todo(struct work_struct *work)
sch = container_of(work, struct subchannel, todo_work);
/* Find out todo. */
- spin_lock_irq(sch->lock);
+ spin_lock_irq(&sch->lock);
todo = sch->todo;
CIO_MSG_EVENT(4, "sch_todo: sch=0.%x.%04x, todo=%d\n", sch->schid.ssid,
sch->schid.sch_no, todo);
sch->todo = SCH_TODO_NOTHING;
- spin_unlock_irq(sch->lock);
+ spin_unlock_irq(&sch->lock);
/* Perform todo. */
switch (todo) {
case SCH_TODO_NOTHING:
@@ -617,9 +606,9 @@ static void css_sch_todo(struct work_struct *work)
case SCH_TODO_EVAL:
ret = css_evaluate_known_subchannel(sch, 1);
if (ret == -EAGAIN) {
- spin_lock_irq(sch->lock);
+ spin_lock_irq(&sch->lock);
css_sched_sch_todo(sch, todo);
- spin_unlock_irq(sch->lock);
+ spin_unlock_irq(&sch->lock);
}
break;
case SCH_TODO_UNREG:
@@ -1028,12 +1017,7 @@ static int __init setup_css(int nr)
css->pseudo_subchannel->dev.parent = &css->device;
css->pseudo_subchannel->dev.release = css_subchannel_release;
mutex_init(&css->pseudo_subchannel->reg_mutex);
- ret = css_sch_create_locks(css->pseudo_subchannel);
- if (ret) {
- kfree(css->pseudo_subchannel);
- device_unregister(&css->device);
- goto out_err;
- }
+ css_sch_create_locks(css->pseudo_subchannel);
dev_set_name(&css->pseudo_subchannel->dev, "defunct");
ret = device_register(&css->pseudo_subchannel->dev);
diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c
index 4ca5adce9107..0cfb179e1bcb 100644
--- a/drivers/s390/cio/device.c
+++ b/drivers/s390/cio/device.c
@@ -748,7 +748,7 @@ static int io_subchannel_initialize_dev(struct subchannel *sch,
mutex_init(&cdev->reg_mutex);
atomic_set(&priv->onoff, 0);
- cdev->ccwlock = sch->lock;
+ cdev->ccwlock = &sch->lock;
cdev->dev.parent = &sch->dev;
cdev->dev.release = ccw_device_release;
cdev->dev.bus = &ccw_bus_type;
@@ -764,9 +764,9 @@ static int io_subchannel_initialize_dev(struct subchannel *sch,
goto out_put;
}
priv->flags.initialized = 1;
- spin_lock_irq(sch->lock);
+ spin_lock_irq(&sch->lock);
sch_set_cdev(sch, cdev);
- spin_unlock_irq(sch->lock);
+ spin_unlock_irq(&sch->lock);
return 0;
out_put:
@@ -851,9 +851,9 @@ static void io_subchannel_register(struct ccw_device *cdev)
CIO_MSG_EVENT(0, "Could not register ccw dev 0.%x.%04x: %d\n",
cdev->private->dev_id.ssid,
cdev->private->dev_id.devno, ret);
- spin_lock_irqsave(sch->lock, flags);
+ spin_lock_irqsave(&sch->lock, flags);
sch_set_cdev(sch, NULL);
- spin_unlock_irqrestore(sch->lock, flags);
+ spin_unlock_irqrestore(&sch->lock, flags);
mutex_unlock(&cdev->reg_mutex);
/* Release initial device reference. */
put_device(&cdev->dev);
@@ -904,9 +904,9 @@ static void io_subchannel_recog(struct ccw_device *cdev, struct subchannel *sch)
atomic_inc(&ccw_device_init_count);
/* Start async. device sensing. */
- spin_lock_irq(sch->lock);
+ spin_lock_irq(&sch->lock);
ccw_device_recognition(cdev);
- spin_unlock_irq(sch->lock);
+ spin_unlock_irq(&sch->lock);
}
static int ccw_device_move_to_sch(struct ccw_device *cdev,
@@ -921,12 +921,12 @@ static int ccw_device_move_to_sch(struct ccw_device *cdev,
return -ENODEV;
if (!sch_is_pseudo_sch(old_sch)) {
- spin_lock_irq(old_sch->lock);
+ spin_lock_irq(&old_sch->lock);
old_enabled = old_sch->schib.pmcw.ena;
rc = 0;
if (old_enabled)
rc = cio_disable_subchannel(old_sch);
- spin_unlock_irq(old_sch->lock);
+ spin_unlock_irq(&old_sch->lock);
if (rc == -EBUSY) {
/* Release child reference for new parent. */
put_device(&sch->dev);
@@ -944,9 +944,9 @@ static int ccw_device_move_to_sch(struct ccw_device *cdev,
sch->schib.pmcw.dev, rc);
if (old_enabled) {
/* Try to re-enable the old subchannel. */
- spin_lock_irq(old_sch->lock);
+ spin_lock_irq(&old_sch->lock);
cio_enable_subchannel(old_sch, (u32)virt_to_phys(old_sch));
- spin_unlock_irq(old_sch->lock);
+ spin_unlock_irq(&old_sch->lock);
}
/* Release child reference for new parent. */
put_device(&sch->dev);
@@ -954,19 +954,19 @@ static int ccw_device_move_to_sch(struct ccw_device *cdev,
}
/* Clean up old subchannel. */
if (!sch_is_pseudo_sch(old_sch)) {
- spin_lock_irq(old_sch->lock);
+ spin_lock_irq(&old_sch->lock);
sch_set_cdev(old_sch, NULL);
- spin_unlock_irq(old_sch->lock);
+ spin_unlock_irq(&old_sch->lock);
css_schedule_eval(old_sch->schid);
}
/* Release child reference for old parent. */
put_device(&old_sch->dev);
/* Initialize new subchannel. */
- spin_lock_irq(sch->lock);
- cdev->ccwlock = sch->lock;
+ spin_lock_irq(&sch->lock);
+ cdev->ccwlock = &sch->lock;
if (!sch_is_pseudo_sch(sch))
sch_set_cdev(sch, cdev);
- spin_unlock_irq(sch->lock);
+ spin_unlock_irq(&sch->lock);
if (!sch_is_pseudo_sch(sch))
css_update_ssd_info(sch);
return 0;
@@ -1077,9 +1077,9 @@ static int io_subchannel_probe(struct subchannel *sch)
return 0;
out_schedule:
- spin_lock_irq(sch->lock);
+ spin_lock_irq(&sch->lock);
css_sched_sch_todo(sch, SCH_TODO_UNREG);
- spin_unlock_irq(sch->lock);
+ spin_unlock_irq(&sch->lock);
return 0;
}
@@ -1093,10 +1093,10 @@ static void io_subchannel_remove(struct subchannel *sch)
goto out_free;
ccw_device_unregister(cdev);
- spin_lock_irq(sch->lock);
+ spin_lock_irq(&sch->lock);
sch_set_cdev(sch, NULL);
set_io_private(sch, NULL);
- spin_unlock_irq(sch->lock);
+ spin_unlock_irq(&sch->lock);
out_free:
dma_free_coherent(&sch->dev, sizeof(*io_priv->dma_area),
io_priv->dma_area, io_priv->dma_area_dma);
@@ -1203,7 +1203,7 @@ static void io_subchannel_quiesce(struct subchannel *sch)
struct ccw_device *cdev;
int ret;
- spin_lock_irq(sch->lock);
+ spin_lock_irq(&sch->lock);
cdev = sch_get_cdev(sch);
if (cio_is_console(sch->schid))
goto out_unlock;
@@ -1220,15 +1220,15 @@ static void io_subchannel_quiesce(struct subchannel *sch)
ret = ccw_device_cancel_halt_clear(cdev);
if (ret == -EBUSY) {
ccw_device_set_timeout(cdev, HZ/10);
- spin_unlock_irq(sch->lock);
+ spin_unlock_irq(&sch->lock);
wait_event(cdev->private->wait_q,
cdev->private->state != DEV_STATE_QUIESCE);
- spin_lock_irq(sch->lock);
+ spin_lock_irq(&sch->lock);
}
ret = cio_disable_subchannel(sch);
}
out_unlock:
- spin_unlock_irq(sch->lock);
+ spin_unlock_irq(&sch->lock);
}
static void io_subchannel_shutdown(struct subchannel *sch)
@@ -1439,7 +1439,7 @@ static int io_subchannel_sch_event(struct subchannel *sch, int process)
enum io_sch_action action;
int rc = -EAGAIN;
- spin_lock_irqsave(sch->lock, flags);
+ spin_lock_irqsave(&sch->lock, flags);
if (!device_is_registered(&sch->dev))
goto out_unlock;
if (work_pending(&sch->todo_work))
@@ -1492,7 +1492,7 @@ static int io_subchannel_sch_event(struct subchannel *sch, int process)
default:
break;
}
- spin_unlock_irqrestore(sch->lock, flags);
+ spin_unlock_irqrestore(&sch->lock, flags);
/* All other actions require process context. */
if (!process)
goto out;
@@ -1507,9 +1507,9 @@ static int io_subchannel_sch_event(struct subchannel *sch, int process)
break;
case IO_SCH_UNREG_CDEV:
case IO_SCH_UNREG_ATTACH:
- spin_lock_irqsave(sch->lock, flags);
+ spin_lock_irqsave(&sch->lock, flags);
sch_set_cdev(sch, NULL);
- spin_unlock_irqrestore(sch->lock, flags);
+ spin_unlock_irqrestore(&sch->lock, flags);
/* Unregister ccw device. */
ccw_device_unregister(cdev);
break;
@@ -1538,9 +1538,9 @@ static int io_subchannel_sch_event(struct subchannel *sch, int process)
put_device(&cdev->dev);
goto out;
}
- spin_lock_irqsave(sch->lock, flags);
+ spin_lock_irqsave(&sch->lock, flags);
ccw_device_trigger_reprobe(cdev);
- spin_unlock_irqrestore(sch->lock, flags);
+ spin_unlock_irqrestore(&sch->lock, flags);
/* Release reference from get_ccwdev_by_dev_id() */
put_device(&cdev->dev);
break;
@@ -1550,7 +1550,7 @@ static int io_subchannel_sch_event(struct subchannel *sch, int process)
return 0;
out_unlock:
- spin_unlock_irqrestore(sch->lock, flags);
+ spin_unlock_irqrestore(&sch->lock, flags);
out:
return rc;
}
@@ -1846,9 +1846,9 @@ static void ccw_device_todo(struct work_struct *work)
css_schedule_eval(sch->schid);
fallthrough;
case CDEV_TODO_UNREG:
- spin_lock_irq(sch->lock);
+ spin_lock_irq(&sch->lock);
sch_set_cdev(sch, NULL);
- spin_unlock_irq(sch->lock);
+ spin_unlock_irq(&sch->lock);
ccw_device_unregister(cdev);
break;
default:
diff --git a/drivers/s390/cio/device_ops.c b/drivers/s390/cio/device_ops.c
index c533d1dadc6b..a5dba3829769 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/device_pgid.c b/drivers/s390/cio/device_pgid.c
index 3862961697eb..ad90045873e2 100644
--- a/drivers/s390/cio/device_pgid.c
+++ b/drivers/s390/cio/device_pgid.c
@@ -698,29 +698,29 @@ int ccw_device_stlck(struct ccw_device *cdev)
return -ENOMEM;
init_completion(&data.done);
data.rc = -EIO;
- spin_lock_irq(sch->lock);
+ spin_lock_irq(&sch->lock);
rc = cio_enable_subchannel(sch, (u32)virt_to_phys(sch));
if (rc)
goto out_unlock;
/* Perform operation. */
cdev->private->state = DEV_STATE_STEAL_LOCK;
ccw_device_stlck_start(cdev, &data, &buffer[0], &buffer[32]);
- spin_unlock_irq(sch->lock);
+ spin_unlock_irq(&sch->lock);
/* Wait for operation to finish. */
if (wait_for_completion_interruptible(&data.done)) {
/* Got a signal. */
- spin_lock_irq(sch->lock);
+ spin_lock_irq(&sch->lock);
ccw_request_cancel(cdev);
- spin_unlock_irq(sch->lock);
+ spin_unlock_irq(&sch->lock);
wait_for_completion(&data.done);
}
rc = data.rc;
/* Check results. */
- spin_lock_irq(sch->lock);
+ spin_lock_irq(&sch->lock);
cio_disable_subchannel(sch);
cdev->private->state = DEV_STATE_BOXED;
out_unlock:
- spin_unlock_irq(sch->lock);
+ spin_unlock_irq(&sch->lock);
kfree(buffer);
return rc;
diff --git a/drivers/s390/cio/eadm_sch.c b/drivers/s390/cio/eadm_sch.c
index 826364d2facd..1caedf931a5f 100644
--- a/drivers/s390/cio/eadm_sch.c
+++ b/drivers/s390/cio/eadm_sch.c
@@ -101,12 +101,12 @@ static void eadm_subchannel_timeout(struct timer_list *t)
struct eadm_private *private = from_timer(private, t, timer);
struct subchannel *sch = private->sch;
- spin_lock_irq(sch->lock);
+ spin_lock_irq(&sch->lock);
EADM_LOG(1, "timeout");
EADM_LOG_HEX(1, &sch->schid, sizeof(sch->schid));
if (eadm_subchannel_clear(sch))
EADM_LOG(0, "clear failed");
- spin_unlock_irq(sch->lock);
+ spin_unlock_irq(&sch->lock);
}
static void eadm_subchannel_set_timeout(struct subchannel *sch, int expires)
@@ -163,16 +163,16 @@ static struct subchannel *eadm_get_idle_sch(void)
spin_lock_irqsave(&list_lock, flags);
list_for_each_entry(private, &eadm_list, head) {
sch = private->sch;
- spin_lock(sch->lock);
+ spin_lock(&sch->lock);
if (private->state == EADM_IDLE) {
private->state = EADM_BUSY;
list_move_tail(&private->head, &eadm_list);
- spin_unlock(sch->lock);
+ spin_unlock(&sch->lock);
spin_unlock_irqrestore(&list_lock, flags);
return sch;
}
- spin_unlock(sch->lock);
+ spin_unlock(&sch->lock);
}
spin_unlock_irqrestore(&list_lock, flags);
@@ -190,7 +190,7 @@ int eadm_start_aob(struct aob *aob)
if (!sch)
return -EBUSY;
- spin_lock_irqsave(sch->lock, flags);
+ spin_lock_irqsave(&sch->lock, flags);
eadm_subchannel_set_timeout(sch, EADM_TIMEOUT);
ret = eadm_subchannel_start(sch, aob);
if (!ret)
@@ -203,7 +203,7 @@ int eadm_start_aob(struct aob *aob)
css_sched_sch_todo(sch, SCH_TODO_EVAL);
out_unlock:
- spin_unlock_irqrestore(sch->lock, flags);
+ spin_unlock_irqrestore(&sch->lock, flags);
return ret;
}
@@ -221,7 +221,7 @@ static int eadm_subchannel_probe(struct subchannel *sch)
INIT_LIST_HEAD(&private->head);
timer_setup(&private->timer, eadm_subchannel_timeout, 0);
- spin_lock_irq(sch->lock);
+ spin_lock_irq(&sch->lock);
set_eadm_private(sch, private);
private->state = EADM_IDLE;
private->sch = sch;
@@ -229,11 +229,11 @@ static int eadm_subchannel_probe(struct subchannel *sch)
ret = cio_enable_subchannel(sch, (u32)virt_to_phys(sch));
if (ret) {
set_eadm_private(sch, NULL);
- spin_unlock_irq(sch->lock);
+ spin_unlock_irq(&sch->lock);
kfree(private);
goto out;
}
- spin_unlock_irq(sch->lock);
+ spin_unlock_irq(&sch->lock);
spin_lock_irq(&list_lock);
list_add(&private->head, &eadm_list);
@@ -248,7 +248,7 @@ static void eadm_quiesce(struct subchannel *sch)
DECLARE_COMPLETION_ONSTACK(completion);
int ret;
- spin_lock_irq(sch->lock);
+ spin_lock_irq(&sch->lock);
if (private->state != EADM_BUSY)
goto disable;
@@ -256,11 +256,11 @@ static void eadm_quiesce(struct subchannel *sch)
goto disable;
private->completion = &completion;
- spin_unlock_irq(sch->lock);
+ spin_unlock_irq(&sch->lock);
wait_for_completion_io(&completion);
- spin_lock_irq(sch->lock);
+ spin_lock_irq(&sch->lock);
private->completion = NULL;
disable:
@@ -269,7 +269,7 @@ disable:
ret = cio_disable_subchannel(sch);
} while (ret == -EBUSY);
- spin_unlock_irq(sch->lock);
+ spin_unlock_irq(&sch->lock);
}
static void eadm_subchannel_remove(struct subchannel *sch)
@@ -282,9 +282,9 @@ static void eadm_subchannel_remove(struct subchannel *sch)
eadm_quiesce(sch);
- spin_lock_irq(sch->lock);
+ spin_lock_irq(&sch->lock);
set_eadm_private(sch, NULL);
- spin_unlock_irq(sch->lock);
+ spin_unlock_irq(&sch->lock);
kfree(private);
}
@@ -309,7 +309,7 @@ static int eadm_subchannel_sch_event(struct subchannel *sch, int process)
struct eadm_private *private;
unsigned long flags;
- spin_lock_irqsave(sch->lock, flags);
+ spin_lock_irqsave(&sch->lock, flags);
if (!device_is_registered(&sch->dev))
goto out_unlock;
@@ -325,7 +325,7 @@ static int eadm_subchannel_sch_event(struct subchannel *sch, int process)
private->state = EADM_IDLE;
out_unlock:
- spin_unlock_irqrestore(sch->lock, flags);
+ spin_unlock_irqrestore(&sch->lock, flags);
return 0;
}
diff --git a/drivers/s390/cio/vfio_ccw_chp.c b/drivers/s390/cio/vfio_ccw_chp.c
index d3f3a611f95b..38c176cf6295 100644
--- a/drivers/s390/cio/vfio_ccw_chp.c
+++ b/drivers/s390/cio/vfio_ccw_chp.c
@@ -115,7 +115,7 @@ static ssize_t vfio_ccw_crw_region_read(struct vfio_ccw_private *private,
/* Notify the guest if more CRWs are on our queue */
if (!list_empty(&private->crw) && private->crw_trigger)
- eventfd_signal(private->crw_trigger, 1);
+ eventfd_signal(private->crw_trigger);
return ret;
}
diff --git a/drivers/s390/cio/vfio_ccw_drv.c b/drivers/s390/cio/vfio_ccw_drv.c
index 43601816ea4e..8ad49030a7bf 100644
--- a/drivers/s390/cio/vfio_ccw_drv.c
+++ b/drivers/s390/cio/vfio_ccw_drv.c
@@ -65,14 +65,14 @@ int vfio_ccw_sch_quiesce(struct subchannel *sch)
* cancel/halt/clear completion.
*/
private->completion = &completion;
- spin_unlock_irq(sch->lock);
+ spin_unlock_irq(&sch->lock);
if (ret == -EBUSY)
wait_for_completion_timeout(&completion, 3*HZ);
private->completion = NULL;
flush_workqueue(vfio_ccw_work_q);
- spin_lock_irq(sch->lock);
+ spin_lock_irq(&sch->lock);
ret = cio_disable_subchannel(sch);
} while (ret == -EBUSY);
@@ -112,7 +112,7 @@ void vfio_ccw_sch_io_todo(struct work_struct *work)
private->state = VFIO_CCW_STATE_IDLE;
if (private->io_trigger)
- eventfd_signal(private->io_trigger, 1);
+ eventfd_signal(private->io_trigger);
}
void vfio_ccw_crw_todo(struct work_struct *work)
@@ -122,7 +122,7 @@ void vfio_ccw_crw_todo(struct work_struct *work)
private = container_of(work, struct vfio_ccw_private, crw_work);
if (!list_empty(&private->crw) && private->crw_trigger)
- eventfd_signal(private->crw_trigger, 1);
+ eventfd_signal(private->crw_trigger);
}
/*
@@ -249,7 +249,7 @@ static int vfio_ccw_sch_event(struct subchannel *sch, int process)
unsigned long flags;
int rc = -EAGAIN;
- spin_lock_irqsave(sch->lock, flags);
+ spin_lock_irqsave(&sch->lock, flags);
if (!device_is_registered(&sch->dev))
goto out_unlock;
@@ -264,7 +264,7 @@ static int vfio_ccw_sch_event(struct subchannel *sch, int process)
}
out_unlock:
- spin_unlock_irqrestore(sch->lock, flags);
+ spin_unlock_irqrestore(&sch->lock, flags);
return rc;
}
diff --git a/drivers/s390/cio/vfio_ccw_fsm.c b/drivers/s390/cio/vfio_ccw_fsm.c
index 757b73141246..09877b46181d 100644
--- a/drivers/s390/cio/vfio_ccw_fsm.c
+++ b/drivers/s390/cio/vfio_ccw_fsm.c
@@ -25,7 +25,7 @@ static int fsm_io_helper(struct vfio_ccw_private *private)
unsigned long flags;
int ret;
- spin_lock_irqsave(sch->lock, flags);
+ spin_lock_irqsave(&sch->lock, flags);
orb = cp_get_orb(&private->cp, sch);
if (!orb) {
@@ -72,7 +72,7 @@ static int fsm_io_helper(struct vfio_ccw_private *private)
ret = ccode;
}
out:
- spin_unlock_irqrestore(sch->lock, flags);
+ spin_unlock_irqrestore(&sch->lock, flags);
return ret;
}
@@ -83,7 +83,7 @@ static int fsm_do_halt(struct vfio_ccw_private *private)
int ccode;
int ret;
- spin_lock_irqsave(sch->lock, flags);
+ spin_lock_irqsave(&sch->lock, flags);
VFIO_CCW_TRACE_EVENT(2, "haltIO");
VFIO_CCW_TRACE_EVENT(2, dev_name(&sch->dev));
@@ -111,7 +111,7 @@ static int fsm_do_halt(struct vfio_ccw_private *private)
default:
ret = ccode;
}
- spin_unlock_irqrestore(sch->lock, flags);
+ spin_unlock_irqrestore(&sch->lock, flags);
return ret;
}
@@ -122,7 +122,7 @@ static int fsm_do_clear(struct vfio_ccw_private *private)
int ccode;
int ret;
- spin_lock_irqsave(sch->lock, flags);
+ spin_lock_irqsave(&sch->lock, flags);
VFIO_CCW_TRACE_EVENT(2, "clearIO");
VFIO_CCW_TRACE_EVENT(2, dev_name(&sch->dev));
@@ -147,7 +147,7 @@ static int fsm_do_clear(struct vfio_ccw_private *private)
default:
ret = ccode;
}
- spin_unlock_irqrestore(sch->lock, flags);
+ spin_unlock_irqrestore(&sch->lock, flags);
return ret;
}
@@ -376,18 +376,18 @@ static void fsm_open(struct vfio_ccw_private *private,
struct subchannel *sch = to_subchannel(private->vdev.dev->parent);
int ret;
- spin_lock_irq(sch->lock);
+ spin_lock_irq(&sch->lock);
sch->isc = VFIO_CCW_ISC;
ret = cio_enable_subchannel(sch, (u32)(unsigned long)sch);
if (ret)
goto err_unlock;
private->state = VFIO_CCW_STATE_IDLE;
- spin_unlock_irq(sch->lock);
+ spin_unlock_irq(&sch->lock);
return;
err_unlock:
- spin_unlock_irq(sch->lock);
+ spin_unlock_irq(&sch->lock);
vfio_ccw_fsm_event(private, VFIO_CCW_EVENT_NOT_OPER);
}
@@ -397,7 +397,7 @@ static void fsm_close(struct vfio_ccw_private *private,
struct subchannel *sch = to_subchannel(private->vdev.dev->parent);
int ret;
- spin_lock_irq(sch->lock);
+ spin_lock_irq(&sch->lock);
if (!sch->schib.pmcw.ena)
goto err_unlock;
@@ -409,12 +409,12 @@ static void fsm_close(struct vfio_ccw_private *private,
goto err_unlock;
private->state = VFIO_CCW_STATE_STANDBY;
- spin_unlock_irq(sch->lock);
+ spin_unlock_irq(&sch->lock);
cp_free(&private->cp);
return;
err_unlock:
- spin_unlock_irq(sch->lock);
+ spin_unlock_irq(&sch->lock);
vfio_ccw_fsm_event(private, VFIO_CCW_EVENT_NOT_OPER);
}
diff --git a/drivers/s390/cio/vfio_ccw_ops.c b/drivers/s390/cio/vfio_ccw_ops.c
index cba4971618ff..ea532a8a4a0c 100644
--- a/drivers/s390/cio/vfio_ccw_ops.c
+++ b/drivers/s390/cio/vfio_ccw_ops.c
@@ -421,7 +421,7 @@ static int vfio_ccw_mdev_set_irqs(struct vfio_ccw_private *private,
case VFIO_IRQ_SET_DATA_NONE:
{
if (*ctx)
- eventfd_signal(*ctx, 1);
+ eventfd_signal(*ctx);
return 0;
}
case VFIO_IRQ_SET_DATA_BOOL:
@@ -432,7 +432,7 @@ static int vfio_ccw_mdev_set_irqs(struct vfio_ccw_private *private,
return -EFAULT;
if (trigger && *ctx)
- eventfd_signal(*ctx, 1);
+ eventfd_signal(*ctx);
return 0;
}
case VFIO_IRQ_SET_DATA_EVENTFD:
@@ -612,7 +612,7 @@ static void vfio_ccw_mdev_request(struct vfio_device *vdev, unsigned int count)
"Relaying device request to user (#%u)\n",
count);
- eventfd_signal(private->req_trigger, 1);
+ eventfd_signal(private->req_trigger);
} else if (count == 0) {
dev_notice(dev,
"No device request channel registered, blocked until released by user\n");
diff --git a/drivers/s390/crypto/ap_bus.c b/drivers/s390/crypto/ap_bus.c
index 5dd33155d5d5..f46dd6abacd7 100644
--- a/drivers/s390/crypto/ap_bus.c
+++ b/drivers/s390/crypto/ap_bus.c
@@ -357,13 +357,12 @@ EXPORT_SYMBOL(ap_test_config_ctrl_domain);
* -1 invalid APQN, TAPQ error or AP queue status which
* indicates there is no APQN.
*/
-static int ap_queue_info(ap_qid_t qid, int *q_type, unsigned int *q_fac,
- int *q_depth, int *q_ml, bool *q_decfg, bool *q_cstop)
+static int ap_queue_info(ap_qid_t qid, struct ap_tapq_hwinfo *hwinfo,
+ bool *decfg, bool *cstop)
{
struct ap_queue_status status;
- struct ap_tapq_gr2 tapq_info;
- tapq_info.value = 0;
+ hwinfo->value = 0;
/* make sure we don't run into a specifiation exception */
if (AP_QID_CARD(qid) > ap_max_adapter_id ||
@@ -371,7 +370,7 @@ static int ap_queue_info(ap_qid_t qid, int *q_type, unsigned int *q_fac,
return -1;
/* call TAPQ on this APQN */
- status = ap_test_queue(qid, ap_apft_available(), &tapq_info);
+ status = ap_test_queue(qid, ap_apft_available(), hwinfo);
switch (status.response_code) {
case AP_RESPONSE_NORMAL:
@@ -389,15 +388,11 @@ static int ap_queue_info(ap_qid_t qid, int *q_type, unsigned int *q_fac,
}
/* There should be at least one of the mode bits set */
- if (WARN_ON_ONCE(!tapq_info.value))
+ if (WARN_ON_ONCE(!hwinfo->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;
+ *decfg = status.response_code == AP_RESPONSE_DECONFIGURED;
+ *cstop = status.response_code == AP_RESPONSE_CHECKSTOPPED;
return 1;
}
@@ -642,11 +637,11 @@ static int ap_uevent(const struct device *dev, struct kobj_uevent_env *env)
return rc;
/* Add MODE=<accel|cca|ep11> */
- if (ap_test_bit(&ac->functions, AP_FUNC_ACCEL))
+ if (ac->hwinfo.accel)
rc = add_uevent_var(env, "MODE=accel");
- else if (ap_test_bit(&ac->functions, AP_FUNC_COPRO))
+ else if (ac->hwinfo.cca)
rc = add_uevent_var(env, "MODE=cca");
- else if (ap_test_bit(&ac->functions, AP_FUNC_EP11))
+ else if (ac->hwinfo.ep11)
rc = add_uevent_var(env, "MODE=ep11");
if (rc)
return rc;
@@ -654,11 +649,11 @@ static int ap_uevent(const struct device *dev, struct kobj_uevent_env *env)
struct ap_queue *aq = to_ap_queue(&ap_dev->device);
/* Add MODE=<accel|cca|ep11> */
- if (ap_test_bit(&aq->card->functions, AP_FUNC_ACCEL))
+ if (aq->card->hwinfo.accel)
rc = add_uevent_var(env, "MODE=accel");
- else if (ap_test_bit(&aq->card->functions, AP_FUNC_COPRO))
+ else if (aq->card->hwinfo.cca)
rc = add_uevent_var(env, "MODE=cca");
- else if (ap_test_bit(&aq->card->functions, AP_FUNC_EP11))
+ else if (aq->card->hwinfo.ep11)
rc = add_uevent_var(env, "MODE=ep11");
if (rc)
return rc;
@@ -1799,12 +1794,12 @@ static inline void ap_scan_rm_card_dev_and_queue_devs(struct ap_card *ac)
*/
static inline void ap_scan_domains(struct ap_card *ac)
{
- int rc, dom, depth, type, ml;
+ struct ap_tapq_hwinfo hwinfo;
bool decfg, chkstop;
struct ap_queue *aq;
struct device *dev;
- unsigned int func;
ap_qid_t qid;
+ int rc, dom;
/*
* Go through the configuration for the domains and compare them
@@ -1827,8 +1822,7 @@ static inline void ap_scan_domains(struct ap_card *ac)
goto put_dev_and_continue;
}
/* domain is valid, get info from this APQN */
- rc = ap_queue_info(qid, &type, &func, &depth,
- &ml, &decfg, &chkstop);
+ rc = ap_queue_info(qid, &hwinfo, &decfg, &chkstop);
switch (rc) {
case -1:
if (dev) {
@@ -1853,6 +1847,7 @@ static inline void ap_scan_domains(struct ap_card *ac)
aq->card = ac;
aq->config = !decfg;
aq->chkstop = chkstop;
+ aq->se_bstate = hwinfo.bs;
dev = &aq->ap_dev.device;
dev->bus = &ap_bus_type;
dev->parent = &ac->ap_dev.device;
@@ -1882,6 +1877,8 @@ static inline void ap_scan_domains(struct ap_card *ac)
}
/* handle state changes on already existing queue device */
spin_lock_bh(&aq->lock);
+ /* SE bind state */
+ aq->se_bstate = hwinfo.bs;
/* checkstop state */
if (chkstop && !aq->chkstop) {
/* checkstop on */
@@ -1955,11 +1952,11 @@ put_dev_and_continue:
*/
static inline void ap_scan_adapter(int ap)
{
- int rc, dom, depth, type, comp_type, ml;
+ struct ap_tapq_hwinfo hwinfo;
+ int rc, dom, comp_type;
bool decfg, chkstop;
struct ap_card *ac;
struct device *dev;
- unsigned int func;
ap_qid_t qid;
/* Is there currently a card device for this adapter ? */
@@ -1989,8 +1986,7 @@ static inline void ap_scan_adapter(int ap)
for (dom = 0; dom <= ap_max_domain_id; dom++)
if (ap_test_config_usage_domain(dom)) {
qid = AP_MKQID(ap, dom);
- if (ap_queue_info(qid, &type, &func, &depth,
- &ml, &decfg, &chkstop) > 0)
+ if (ap_queue_info(qid, &hwinfo, &decfg, &chkstop) > 0)
break;
}
if (dom > ap_max_domain_id) {
@@ -2006,7 +2002,7 @@ static inline void ap_scan_adapter(int ap)
}
return;
}
- if (!type) {
+ if (!hwinfo.at) {
/* No apdater type info available, an unusable adapter */
if (ac) {
AP_DBF_INFO("%s(%d) no valid type (0) info, rm card and queue devs\n",
@@ -2019,18 +2015,18 @@ static inline void ap_scan_adapter(int ap)
}
return;
}
+ hwinfo.value &= TAPQ_CARD_HWINFO_MASK; /* filter card specific hwinfo */
if (ac) {
/* Check APQN against existing card device for changes */
- if (ac->raw_hwtype != type) {
+ if (ac->hwinfo.at != hwinfo.at) {
AP_DBF_INFO("%s(%d) hwtype %d changed, rm card and queue devs\n",
- __func__, ap, type);
+ __func__, ap, hwinfo.at);
ap_scan_rm_card_dev_and_queue_devs(ac);
put_device(dev);
ac = NULL;
- } else if ((ac->functions & TAPQ_CARD_FUNC_CMP_MASK) !=
- (func & TAPQ_CARD_FUNC_CMP_MASK)) {
+ } else if (ac->hwinfo.fac != hwinfo.fac) {
AP_DBF_INFO("%s(%d) functions 0x%08x changed, rm card and queue devs\n",
- __func__, ap, func);
+ __func__, ap, hwinfo.fac);
ap_scan_rm_card_dev_and_queue_devs(ac);
put_device(dev);
ac = NULL;
@@ -2064,13 +2060,13 @@ static inline void ap_scan_adapter(int ap)
if (!ac) {
/* Build a new card device */
- comp_type = ap_get_compatible_type(qid, type, func);
+ comp_type = ap_get_compatible_type(qid, hwinfo.at, hwinfo.fac);
if (!comp_type) {
AP_DBF_WARN("%s(%d) type %d, can't get compatibility type\n",
- __func__, ap, type);
+ __func__, ap, hwinfo.at);
return;
}
- ac = ap_card_create(ap, depth, type, comp_type, func, ml);
+ ac = ap_card_create(ap, hwinfo, comp_type);
if (!ac) {
AP_DBF_WARN("%s(%d) ap_card_create() failed\n",
__func__, ap);
@@ -2101,13 +2097,13 @@ static inline void ap_scan_adapter(int ap)
get_device(dev);
if (decfg)
AP_DBF_INFO("%s(%d) new (decfg) card dev type=%d func=0x%08x created\n",
- __func__, ap, type, func);
+ __func__, ap, hwinfo.at, hwinfo.fac);
else if (chkstop)
AP_DBF_INFO("%s(%d) new (chkstop) card dev type=%d func=0x%08x created\n",
- __func__, ap, type, func);
+ __func__, ap, hwinfo.at, hwinfo.fac);
else
AP_DBF_INFO("%s(%d) new card dev type=%d func=0x%08x created\n",
- __func__, ap, type, func);
+ __func__, ap, hwinfo.at, hwinfo.fac);
}
/* Verify the domains and the queue devices for this card */
diff --git a/drivers/s390/crypto/ap_bus.h b/drivers/s390/crypto/ap_bus.h
index b0771ca0849b..98814839ef30 100644
--- a/drivers/s390/crypto/ap_bus.h
+++ b/drivers/s390/crypto/ap_bus.h
@@ -76,16 +76,6 @@ static inline int ap_test_bit(unsigned int *ptr, unsigned int nr)
#define AP_DEVICE_TYPE_CEX8 14
/*
- * Known function facilities
- */
-#define AP_FUNC_MEX4K 1
-#define AP_FUNC_CRT4K 2
-#define AP_FUNC_COPRO 3
-#define AP_FUNC_ACCEL 4
-#define AP_FUNC_EP11 5
-#define AP_FUNC_APXA 6
-
-/*
* AP queue state machine states
*/
enum ap_sm_state {
@@ -182,9 +172,7 @@ struct ap_device {
struct ap_card {
struct ap_device ap_dev;
- int raw_hwtype; /* AP raw hardware type. */
- unsigned int functions; /* TAPQ GR2 upper 32 facility bits */
- int queue_depth; /* AP queue depth.*/
+ struct ap_tapq_hwinfo hwinfo; /* TAPQ GR2 content */
int id; /* AP card number. */
unsigned int maxmsgsize; /* AP msg limit for this card */
bool config; /* configured state */
@@ -192,7 +180,7 @@ struct ap_card {
atomic64_t total_request_count; /* # requests ever for this AP device.*/
};
-#define TAPQ_CARD_FUNC_CMP_MASK 0xFFFF0000
+#define TAPQ_CARD_HWINFO_MASK 0xFEFF0000FFFF0F0FUL
#define ASSOC_IDX_INVALID 0x10000
#define to_ap_card(x) container_of((x), struct ap_card, ap_dev.device)
@@ -206,7 +194,7 @@ struct ap_queue {
bool config; /* configured state */
bool chkstop; /* checkstop state */
ap_qid_t qid; /* AP queue id. */
- bool se_bound; /* SE bound state */
+ unsigned int se_bstate; /* SE bind state (BS) */
unsigned int assoc_idx; /* SE association index */
int queue_count; /* # messages currently on AP queue. */
int pendingq_count; /* # requests on pendingq list. */
@@ -290,8 +278,8 @@ void ap_queue_remove(struct ap_queue *aq);
void ap_queue_init_state(struct ap_queue *aq);
void _ap_queue_init_state(struct ap_queue *aq);
-struct ap_card *ap_card_create(int id, int queue_depth, int raw_type,
- int comp_type, unsigned int functions, int ml);
+struct ap_card *ap_card_create(int id, struct ap_tapq_hwinfo info,
+ int comp_type);
#define APMASKSIZE (BITS_TO_LONGS(AP_DEVICES) * sizeof(unsigned long))
#define AQMASKSIZE (BITS_TO_LONGS(AP_DOMAINS) * sizeof(unsigned long))
diff --git a/drivers/s390/crypto/ap_card.c b/drivers/s390/crypto/ap_card.c
index b2bd477659a7..ce953cbbd564 100644
--- a/drivers/s390/crypto/ap_card.c
+++ b/drivers/s390/crypto/ap_card.c
@@ -34,7 +34,7 @@ static ssize_t raw_hwtype_show(struct device *dev,
{
struct ap_card *ac = to_ap_card(dev);
- return sysfs_emit(buf, "%d\n", ac->raw_hwtype);
+ return sysfs_emit(buf, "%d\n", ac->hwinfo.at);
}
static DEVICE_ATTR_RO(raw_hwtype);
@@ -44,7 +44,7 @@ static ssize_t depth_show(struct device *dev, struct device_attribute *attr,
{
struct ap_card *ac = to_ap_card(dev);
- return sysfs_emit(buf, "%d\n", ac->queue_depth);
+ return sysfs_emit(buf, "%d\n", ac->hwinfo.qd);
}
static DEVICE_ATTR_RO(depth);
@@ -54,7 +54,7 @@ static ssize_t ap_functions_show(struct device *dev,
{
struct ap_card *ac = to_ap_card(dev);
- return sysfs_emit(buf, "0x%08X\n", ac->functions);
+ return sysfs_emit(buf, "0x%08X\n", ac->hwinfo.fac);
}
static DEVICE_ATTR_RO(ap_functions);
@@ -229,8 +229,8 @@ static void ap_card_device_release(struct device *dev)
kfree(ac);
}
-struct ap_card *ap_card_create(int id, int queue_depth, int raw_type,
- int comp_type, unsigned int functions, int ml)
+struct ap_card *ap_card_create(int id, struct ap_tapq_hwinfo hwinfo,
+ int comp_type)
{
struct ap_card *ac;
@@ -240,12 +240,10 @@ struct ap_card *ap_card_create(int id, int queue_depth, int raw_type,
ac->ap_dev.device.release = ap_card_device_release;
ac->ap_dev.device.type = &ap_card_type;
ac->ap_dev.device_type = comp_type;
- ac->raw_hwtype = raw_type;
- ac->queue_depth = queue_depth;
- ac->functions = functions;
+ ac->hwinfo = hwinfo;
ac->id = id;
- ac->maxmsgsize = ml > 0 ?
- ml * AP_TAPQ_ML_FIELD_CHUNK_SIZE : AP_DEFAULT_MAX_MSG_SIZE;
+ ac->maxmsgsize = hwinfo.ml > 0 ?
+ hwinfo.ml * AP_TAPQ_ML_FIELD_CHUNK_SIZE : AP_DEFAULT_MAX_MSG_SIZE;
return ac;
}
diff --git a/drivers/s390/crypto/ap_queue.c b/drivers/s390/crypto/ap_queue.c
index 3934a0cc13e7..682595443145 100644
--- a/drivers/s390/crypto/ap_queue.c
+++ b/drivers/s390/crypto/ap_queue.c
@@ -24,13 +24,12 @@ static void __ap_flush_queue(struct ap_queue *aq);
static inline bool ap_q_supports_bind(struct ap_queue *aq)
{
- return ap_test_bit(&aq->card->functions, AP_FUNC_EP11) ||
- ap_test_bit(&aq->card->functions, AP_FUNC_ACCEL);
+ return aq->card->hwinfo.ep11 || aq->card->hwinfo.accel;
}
static inline bool ap_q_supports_assoc(struct ap_queue *aq)
{
- return ap_test_bit(&aq->card->functions, AP_FUNC_EP11);
+ return aq->card->hwinfo.ep11;
}
static inline bool ap_q_needs_bind(struct ap_queue *aq)
@@ -257,7 +256,7 @@ static enum ap_sm_wait ap_sm_write(struct ap_queue *aq)
list_move_tail(&ap_msg->list, &aq->pendingq);
aq->requestq_count--;
aq->pendingq_count++;
- if (aq->queue_count < aq->card->queue_depth) {
+ if (aq->queue_count < aq->card->hwinfo.qd) {
aq->sm_state = AP_SM_STATE_WORKING;
return AP_SM_WAIT_AGAIN;
}
@@ -318,7 +317,6 @@ static enum ap_sm_wait ap_sm_reset(struct ap_queue *aq)
case AP_RESPONSE_RESET_IN_PROGRESS:
aq->sm_state = AP_SM_STATE_RESET_WAIT;
aq->rapq_fbit = 0;
- aq->se_bound = false;
return AP_SM_WAIT_LOW_TIMEOUT;
default:
aq->dev_state = AP_DEV_STATE_ERROR;
@@ -339,17 +337,15 @@ static enum ap_sm_wait ap_sm_reset(struct ap_queue *aq)
static enum ap_sm_wait ap_sm_reset_wait(struct ap_queue *aq)
{
struct ap_queue_status status;
+ struct ap_tapq_hwinfo hwinfo;
void *lsi_ptr;
- if (aq->queue_count > 0 && aq->reply)
- /* Try to read a completed message and get the status */
- status = ap_sm_recv(aq);
- else
- /* Get the status with TAPQ */
- status = ap_tapq(aq->qid, NULL);
+ /* Get the status with TAPQ */
+ status = ap_test_queue(aq->qid, 1, &hwinfo);
switch (status.response_code) {
case AP_RESPONSE_NORMAL:
+ aq->se_bstate = hwinfo.bs;
lsi_ptr = ap_airq_ptr();
if (lsi_ptr && ap_queue_enable_irq(aq, lsi_ptr) == 0)
aq->sm_state = AP_SM_STATE_SETIRQ_WAIT;
@@ -421,9 +417,9 @@ static enum ap_sm_wait ap_sm_setirq_wait(struct ap_queue *aq)
static enum ap_sm_wait ap_sm_assoc_wait(struct ap_queue *aq)
{
struct ap_queue_status status;
- struct ap_tapq_gr2 info;
+ struct ap_tapq_hwinfo hwinfo;
- status = ap_test_queue(aq->qid, 1, &info);
+ status = ap_test_queue(aq->qid, 1, &hwinfo);
/* handle asynchronous error on this queue */
if (status.async && status.response_code) {
aq->dev_state = AP_DEV_STATE_ERROR;
@@ -442,8 +438,11 @@ static enum ap_sm_wait ap_sm_assoc_wait(struct ap_queue *aq)
return AP_SM_WAIT_NONE;
}
+ /* update queue's SE bind state */
+ aq->se_bstate = hwinfo.bs;
+
/* check bs bits */
- switch (info.bs) {
+ switch (hwinfo.bs) {
case AP_BS_Q_USABLE:
/* association is through */
aq->sm_state = AP_SM_STATE_IDLE;
@@ -460,7 +459,7 @@ static enum ap_sm_wait ap_sm_assoc_wait(struct ap_queue *aq)
aq->dev_state = AP_DEV_STATE_ERROR;
aq->last_err_rc = status.response_code;
AP_DBF_WARN("%s bs 0x%02x on 0x%02x.%04x -> AP_DEV_STATE_ERROR\n",
- __func__, info.bs,
+ __func__, hwinfo.bs,
AP_QID_CARD(aq->qid), AP_QID_QUEUE(aq->qid));
return AP_SM_WAIT_NONE;
}
@@ -687,9 +686,9 @@ static ssize_t ap_functions_show(struct device *dev,
{
struct ap_queue *aq = to_ap_queue(dev);
struct ap_queue_status status;
- struct ap_tapq_gr2 info;
+ struct ap_tapq_hwinfo hwinfo;
- status = ap_test_queue(aq->qid, 1, &info);
+ status = ap_test_queue(aq->qid, 1, &hwinfo);
if (status.response_code > AP_RESPONSE_BUSY) {
AP_DBF_DBG("%s RC 0x%02x on tapq(0x%02x.%04x)\n",
__func__, status.response_code,
@@ -697,7 +696,7 @@ static ssize_t ap_functions_show(struct device *dev,
return -EIO;
}
- return sysfs_emit(buf, "0x%08X\n", info.fac);
+ return sysfs_emit(buf, "0x%08X\n", hwinfo.fac);
}
static DEVICE_ATTR_RO(ap_functions);
@@ -840,19 +839,25 @@ static ssize_t se_bind_show(struct device *dev,
{
struct ap_queue *aq = to_ap_queue(dev);
struct ap_queue_status status;
- struct ap_tapq_gr2 info;
+ struct ap_tapq_hwinfo hwinfo;
if (!ap_q_supports_bind(aq))
return sysfs_emit(buf, "-\n");
- status = ap_test_queue(aq->qid, 1, &info);
+ status = ap_test_queue(aq->qid, 1, &hwinfo);
if (status.response_code > AP_RESPONSE_BUSY) {
AP_DBF_DBG("%s RC 0x%02x on tapq(0x%02x.%04x)\n",
__func__, status.response_code,
AP_QID_CARD(aq->qid), AP_QID_QUEUE(aq->qid));
return -EIO;
}
- switch (info.bs) {
+
+ /* update queue's SE bind state */
+ spin_lock_bh(&aq->lock);
+ aq->se_bstate = hwinfo.bs;
+ spin_unlock_bh(&aq->lock);
+
+ switch (hwinfo.bs) {
case AP_BS_Q_USABLE:
case AP_BS_Q_USABLE_NO_SECURE_KEY:
return sysfs_emit(buf, "bound\n");
@@ -867,6 +872,7 @@ static ssize_t se_bind_store(struct device *dev,
{
struct ap_queue *aq = to_ap_queue(dev);
struct ap_queue_status status;
+ struct ap_tapq_hwinfo hwinfo;
bool value;
int rc;
@@ -878,39 +884,80 @@ static ssize_t se_bind_store(struct device *dev,
if (rc)
return rc;
- if (value) {
- /* bind, do BAPQ */
- spin_lock_bh(&aq->lock);
- if (aq->sm_state < AP_SM_STATE_IDLE) {
- spin_unlock_bh(&aq->lock);
- return -EBUSY;
- }
- status = ap_bapq(aq->qid);
- spin_unlock_bh(&aq->lock);
- 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),
- AP_QID_QUEUE(aq->qid));
- return -EIO;
- }
- } else {
- /* unbind, set F bit arg and trigger RAPQ */
+ if (!value) {
+ /* Unbind. Set F bit arg and trigger RAPQ */
spin_lock_bh(&aq->lock);
__ap_flush_queue(aq);
aq->rapq_fbit = 1;
- aq->assoc_idx = ASSOC_IDX_INVALID;
- aq->sm_state = AP_SM_STATE_RESET_START;
- ap_wait(ap_sm_event(aq, AP_SM_EVENT_POLL));
- spin_unlock_bh(&aq->lock);
+ _ap_queue_init_state(aq);
+ rc = count;
+ goto out;
}
- return count;
+ /* Bind. Check current SE bind state */
+ status = ap_test_queue(aq->qid, 1, &hwinfo);
+ if (status.response_code) {
+ AP_DBF_WARN("%s RC 0x%02x on tapq(0x%02x.%04x)\n",
+ __func__, status.response_code,
+ AP_QID_CARD(aq->qid), AP_QID_QUEUE(aq->qid));
+ return -EIO;
+ }
+
+ /* Update BS state */
+ spin_lock_bh(&aq->lock);
+ aq->se_bstate = hwinfo.bs;
+ if (hwinfo.bs != AP_BS_Q_AVAIL_FOR_BINDING) {
+ AP_DBF_WARN("%s bind attempt with bs %d on queue 0x%02x.%04x\n",
+ __func__, hwinfo.bs,
+ AP_QID_CARD(aq->qid), AP_QID_QUEUE(aq->qid));
+ rc = -EINVAL;
+ goto out;
+ }
+
+ /* Check SM state */
+ if (aq->sm_state < AP_SM_STATE_IDLE) {
+ rc = -EBUSY;
+ goto out;
+ }
+
+ /* invoke BAPQ */
+ status = ap_bapq(aq->qid);
+ if (status.response_code) {
+ AP_DBF_WARN("%s RC 0x%02x on bapq(0x%02x.%04x)\n",
+ __func__, status.response_code,
+ AP_QID_CARD(aq->qid), AP_QID_QUEUE(aq->qid));
+ rc = -EIO;
+ goto out;
+ }
+ aq->assoc_idx = ASSOC_IDX_INVALID;
+
+ /* verify SE bind state */
+ status = ap_test_queue(aq->qid, 1, &hwinfo);
+ if (status.response_code) {
+ AP_DBF_WARN("%s RC 0x%02x on tapq(0x%02x.%04x)\n",
+ __func__, status.response_code,
+ AP_QID_CARD(aq->qid), AP_QID_QUEUE(aq->qid));
+ rc = -EIO;
+ goto out;
+ }
+ aq->se_bstate = hwinfo.bs;
+ if (!(hwinfo.bs == AP_BS_Q_USABLE ||
+ hwinfo.bs == AP_BS_Q_USABLE_NO_SECURE_KEY)) {
+ AP_DBF_WARN("%s BAPQ success, but bs shows %d on queue 0x%02x.%04x\n",
+ __func__, hwinfo.bs,
+ AP_QID_CARD(aq->qid), AP_QID_QUEUE(aq->qid));
+ rc = -EIO;
+ goto out;
+ }
+
+ /* SE bind was successful */
+ AP_DBF_INFO("%s bapq(0x%02x.%04x) success\n", __func__,
+ AP_QID_CARD(aq->qid), AP_QID_QUEUE(aq->qid));
+ rc = count;
+
+out:
+ spin_unlock_bh(&aq->lock);
+ return rc;
}
static DEVICE_ATTR_RW(se_bind);
@@ -920,12 +967,12 @@ static ssize_t se_associate_show(struct device *dev,
{
struct ap_queue *aq = to_ap_queue(dev);
struct ap_queue_status status;
- struct ap_tapq_gr2 info;
+ struct ap_tapq_hwinfo hwinfo;
if (!ap_q_supports_assoc(aq))
return sysfs_emit(buf, "-\n");
- status = ap_test_queue(aq->qid, 1, &info);
+ status = ap_test_queue(aq->qid, 1, &hwinfo);
if (status.response_code > AP_RESPONSE_BUSY) {
AP_DBF_DBG("%s RC 0x%02x on tapq(0x%02x.%04x)\n",
__func__, status.response_code,
@@ -933,7 +980,12 @@ static ssize_t se_associate_show(struct device *dev,
return -EIO;
}
- switch (info.bs) {
+ /* update queue's SE bind state */
+ spin_lock_bh(&aq->lock);
+ aq->se_bstate = hwinfo.bs;
+ spin_unlock_bh(&aq->lock);
+
+ switch (hwinfo.bs) {
case AP_BS_Q_USABLE:
if (aq->assoc_idx == ASSOC_IDX_INVALID) {
AP_DBF_WARN("%s AP_BS_Q_USABLE but invalid assoc_idx\n", __func__);
@@ -955,6 +1007,7 @@ static ssize_t se_associate_store(struct device *dev,
{
struct ap_queue *aq = to_ap_queue(dev);
struct ap_queue_status status;
+ struct ap_tapq_hwinfo hwinfo;
unsigned int value;
int rc;
@@ -968,18 +1021,28 @@ static ssize_t se_associate_store(struct device *dev,
if (value >= ASSOC_IDX_INVALID)
return -EINVAL;
+ /* check current SE bind state */
+ status = ap_test_queue(aq->qid, 1, &hwinfo);
+ if (status.response_code) {
+ AP_DBF_WARN("%s RC 0x%02x on tapq(0x%02x.%04x)\n",
+ __func__, status.response_code,
+ AP_QID_CARD(aq->qid), AP_QID_QUEUE(aq->qid));
+ return -EIO;
+ }
spin_lock_bh(&aq->lock);
-
- /* sm should be in idle state */
- if (aq->sm_state != AP_SM_STATE_IDLE) {
- spin_unlock_bh(&aq->lock);
- return -EBUSY;
+ aq->se_bstate = hwinfo.bs;
+ if (hwinfo.bs != AP_BS_Q_USABLE_NO_SECURE_KEY) {
+ AP_DBF_WARN("%s association attempt with bs %d on queue 0x%02x.%04x\n",
+ __func__, hwinfo.bs,
+ AP_QID_CARD(aq->qid), AP_QID_QUEUE(aq->qid));
+ rc = -EINVAL;
+ goto out;
}
- /* already associated or association pending ? */
- if (aq->assoc_idx != ASSOC_IDX_INVALID) {
- spin_unlock_bh(&aq->lock);
- return -EINVAL;
+ /* check SM state */
+ if (aq->sm_state != AP_SM_STATE_IDLE) {
+ rc = -EBUSY;
+ goto out;
}
/* trigger the asynchronous association request */
@@ -990,17 +1053,20 @@ static ssize_t se_associate_store(struct device *dev,
aq->sm_state = AP_SM_STATE_ASSOC_WAIT;
aq->assoc_idx = value;
ap_wait(ap_sm_event(aq, AP_SM_EVENT_POLL));
- spin_unlock_bh(&aq->lock);
break;
default:
- spin_unlock_bh(&aq->lock);
AP_DBF_WARN("%s RC 0x%02x on aapq(0x%02x.%04x)\n",
__func__, status.response_code,
AP_QID_CARD(aq->qid), AP_QID_QUEUE(aq->qid));
- return -EIO;
+ rc = -EIO;
+ goto out;
}
- return count;
+ rc = count;
+
+out:
+ spin_unlock_bh(&aq->lock);
+ return rc;
}
static DEVICE_ATTR_RW(se_associate);
@@ -1123,7 +1189,9 @@ bool ap_queue_usable(struct ap_queue *aq)
}
/* SE guest's queues additionally need to be bound */
- if (ap_q_needs_bind(aq) && !aq->se_bound)
+ if (ap_q_needs_bind(aq) &&
+ !(aq->se_bstate == AP_BS_Q_USABLE ||
+ aq->se_bstate == AP_BS_Q_USABLE_NO_SECURE_KEY))
rc = false;
unlock_and_out:
diff --git a/drivers/s390/crypto/vfio_ap_ops.c b/drivers/s390/crypto/vfio_ap_ops.c
index 4db538a55192..983b3b16196c 100644
--- a/drivers/s390/crypto/vfio_ap_ops.c
+++ b/drivers/s390/crypto/vfio_ap_ops.c
@@ -32,7 +32,8 @@
#define AP_RESET_INTERVAL 20 /* Reset sleep interval (20ms) */
-static int vfio_ap_mdev_reset_queues(struct ap_queue_table *qtable);
+static int vfio_ap_mdev_reset_queues(struct ap_matrix_mdev *matrix_mdev);
+static int vfio_ap_mdev_reset_qlist(struct list_head *qlist);
static struct vfio_ap_queue *vfio_ap_find_queue(int apqn);
static const struct vfio_device_ops vfio_ap_matrix_dev_ops;
static void vfio_ap_mdev_reset_queue(struct vfio_ap_queue *q);
@@ -393,8 +394,8 @@ static int ensure_nib_shared(unsigned long addr, struct gmap *gmap)
* Register the guest ISC to GIB interface and retrieve the
* host ISC to issue the host side PQAP/AQIC
*
- * Response.status may be set to AP_RESPONSE_INVALID_ADDRESS in case the
- * vfio_pin_pages failed.
+ * status.response_code may be set to AP_RESPONSE_INVALID_ADDRESS in case the
+ * vfio_pin_pages or kvm_s390_gisc_register failed.
*
* Otherwise return the ap_queue_status returned by the ap_aqic(),
* all retry handling will be done by the guest.
@@ -457,7 +458,8 @@ static struct ap_queue_status vfio_ap_irq_enable(struct vfio_ap_queue *q,
VFIO_AP_DBF_WARN("%s: gisc registration failed: nisc=%d, isc=%d, apqn=%#04x\n",
__func__, nisc, isc, q->apqn);
- status.response_code = AP_RESPONSE_INVALID_GISA;
+ vfio_unpin_pages(&q->matrix_mdev->vdev, nib, 1);
+ status.response_code = AP_RESPONSE_INVALID_ADDRESS;
return status;
}
@@ -475,8 +477,11 @@ static struct ap_queue_status vfio_ap_irq_enable(struct vfio_ap_queue *q,
break;
case AP_RESPONSE_OTHERWISE_CHANGED:
/* We could not modify IRQ settings: clear new configuration */
+ ret = kvm_s390_gisc_unregister(kvm, isc);
+ if (ret)
+ VFIO_AP_DBF_WARN("%s: kvm_s390_gisc_unregister: rc=%d isc=%d, apqn=%#04x\n",
+ __func__, ret, isc, q->apqn);
vfio_unpin_pages(&q->matrix_mdev->vdev, nib, 1);
- kvm_s390_gisc_unregister(kvm, isc);
break;
default:
pr_warn("%s: apqn %04x: response: %02x\n", __func__, q->apqn,
@@ -661,17 +666,23 @@ static bool vfio_ap_mdev_filter_cdoms(struct ap_matrix_mdev *matrix_mdev)
* device driver.
*
* @matrix_mdev: the matrix mdev whose matrix is to be filtered.
+ * @apm_filtered: a 256-bit bitmap for storing the APIDs filtered from the
+ * guest's AP configuration that are still in the host's AP
+ * configuration.
*
* Note: If an APQN referencing a queue device that is not bound to the vfio_ap
* driver, its APID will be filtered from the guest's APCB. The matrix
* structure precludes filtering an individual APQN, so its APID will be
- * filtered.
+ * filtered. Consequently, all queues associated with the adapter that
+ * are in the host's AP configuration must be reset. If queues are
+ * subsequently made available again to the guest, they should re-appear
+ * in a reset state
*
* Return: a boolean value indicating whether the KVM guest's APCB was changed
* by the filtering or not.
*/
-static bool vfio_ap_mdev_filter_matrix(unsigned long *apm, unsigned long *aqm,
- struct ap_matrix_mdev *matrix_mdev)
+static bool vfio_ap_mdev_filter_matrix(struct ap_matrix_mdev *matrix_mdev,
+ unsigned long *apm_filtered)
{
unsigned long apid, apqi, apqn;
DECLARE_BITMAP(prev_shadow_apm, AP_DEVICES);
@@ -681,6 +692,7 @@ static bool vfio_ap_mdev_filter_matrix(unsigned long *apm, unsigned long *aqm,
bitmap_copy(prev_shadow_apm, matrix_mdev->shadow_apcb.apm, AP_DEVICES);
bitmap_copy(prev_shadow_aqm, matrix_mdev->shadow_apcb.aqm, AP_DOMAINS);
vfio_ap_matrix_init(&matrix_dev->info, &matrix_mdev->shadow_apcb);
+ bitmap_clear(apm_filtered, 0, AP_DEVICES);
/*
* Copy the adapters, domains and control domains to the shadow_apcb
@@ -692,8 +704,9 @@ static bool vfio_ap_mdev_filter_matrix(unsigned long *apm, unsigned long *aqm,
bitmap_and(matrix_mdev->shadow_apcb.aqm, matrix_mdev->matrix.aqm,
(unsigned long *)matrix_dev->info.aqm, AP_DOMAINS);
- for_each_set_bit_inv(apid, apm, AP_DEVICES) {
- for_each_set_bit_inv(apqi, aqm, AP_DOMAINS) {
+ for_each_set_bit_inv(apid, matrix_mdev->shadow_apcb.apm, AP_DEVICES) {
+ for_each_set_bit_inv(apqi, matrix_mdev->shadow_apcb.aqm,
+ AP_DOMAINS) {
/*
* If the APQN is not bound to the vfio_ap device
* driver, then we can't assign it to the guest's
@@ -705,8 +718,16 @@ static bool vfio_ap_mdev_filter_matrix(unsigned long *apm, unsigned long *aqm,
apqn = AP_MKQID(apid, apqi);
q = vfio_ap_mdev_get_queue(matrix_mdev, apqn);
if (!q || q->reset_status.response_code) {
- clear_bit_inv(apid,
- matrix_mdev->shadow_apcb.apm);
+ clear_bit_inv(apid, matrix_mdev->shadow_apcb.apm);
+
+ /*
+ * If the adapter was previously plugged into
+ * the guest, let's let the caller know that
+ * the APID was filtered.
+ */
+ if (test_bit_inv(apid, prev_shadow_apm))
+ set_bit_inv(apid, apm_filtered);
+
break;
}
}
@@ -808,7 +829,7 @@ static void vfio_ap_mdev_remove(struct mdev_device *mdev)
mutex_lock(&matrix_dev->guests_lock);
mutex_lock(&matrix_dev->mdevs_lock);
- vfio_ap_mdev_reset_queues(&matrix_mdev->qtable);
+ vfio_ap_mdev_reset_queues(matrix_mdev);
vfio_ap_mdev_unlink_fr_queues(matrix_mdev);
list_del(&matrix_mdev->node);
mutex_unlock(&matrix_dev->mdevs_lock);
@@ -918,6 +939,47 @@ static void vfio_ap_mdev_link_adapter(struct ap_matrix_mdev *matrix_mdev,
AP_MKQID(apid, apqi));
}
+static void collect_queues_to_reset(struct ap_matrix_mdev *matrix_mdev,
+ unsigned long apid,
+ struct list_head *qlist)
+{
+ struct vfio_ap_queue *q;
+ unsigned long apqi;
+
+ for_each_set_bit_inv(apqi, matrix_mdev->shadow_apcb.aqm, AP_DOMAINS) {
+ q = vfio_ap_mdev_get_queue(matrix_mdev, AP_MKQID(apid, apqi));
+ if (q)
+ list_add_tail(&q->reset_qnode, qlist);
+ }
+}
+
+static void reset_queues_for_apid(struct ap_matrix_mdev *matrix_mdev,
+ unsigned long apid)
+{
+ struct list_head qlist;
+
+ INIT_LIST_HEAD(&qlist);
+ collect_queues_to_reset(matrix_mdev, apid, &qlist);
+ vfio_ap_mdev_reset_qlist(&qlist);
+}
+
+static int reset_queues_for_apids(struct ap_matrix_mdev *matrix_mdev,
+ unsigned long *apm_reset)
+{
+ struct list_head qlist;
+ unsigned long apid;
+
+ if (bitmap_empty(apm_reset, AP_DEVICES))
+ return 0;
+
+ INIT_LIST_HEAD(&qlist);
+
+ for_each_set_bit_inv(apid, apm_reset, AP_DEVICES)
+ collect_queues_to_reset(matrix_mdev, apid, &qlist);
+
+ return vfio_ap_mdev_reset_qlist(&qlist);
+}
+
/**
* assign_adapter_store - parses the APID from @buf and sets the
* corresponding bit in the mediated matrix device's APM
@@ -958,7 +1020,7 @@ static ssize_t assign_adapter_store(struct device *dev,
{
int ret;
unsigned long apid;
- DECLARE_BITMAP(apm_delta, AP_DEVICES);
+ DECLARE_BITMAP(apm_filtered, AP_DEVICES);
struct ap_matrix_mdev *matrix_mdev = dev_get_drvdata(dev);
mutex_lock(&ap_perms_mutex);
@@ -987,12 +1049,11 @@ static ssize_t assign_adapter_store(struct device *dev,
}
vfio_ap_mdev_link_adapter(matrix_mdev, apid);
- memset(apm_delta, 0, sizeof(apm_delta));
- set_bit_inv(apid, apm_delta);
- if (vfio_ap_mdev_filter_matrix(apm_delta,
- matrix_mdev->matrix.aqm, matrix_mdev))
+ if (vfio_ap_mdev_filter_matrix(matrix_mdev, apm_filtered)) {
vfio_ap_mdev_update_guest_apcb(matrix_mdev);
+ reset_queues_for_apids(matrix_mdev, apm_filtered);
+ }
ret = count;
done:
@@ -1023,11 +1084,12 @@ static struct vfio_ap_queue
* adapter was assigned.
* @matrix_mdev: the matrix mediated device to which the adapter was assigned.
* @apid: the APID of the unassigned adapter.
- * @qtable: table for storing queues associated with unassigned adapter.
+ * @qlist: list for storing queues associated with unassigned adapter that
+ * need to be reset.
*/
static void vfio_ap_mdev_unlink_adapter(struct ap_matrix_mdev *matrix_mdev,
unsigned long apid,
- struct ap_queue_table *qtable)
+ struct list_head *qlist)
{
unsigned long apqi;
struct vfio_ap_queue *q;
@@ -1035,11 +1097,10 @@ static void vfio_ap_mdev_unlink_adapter(struct ap_matrix_mdev *matrix_mdev,
for_each_set_bit_inv(apqi, matrix_mdev->matrix.aqm, AP_DOMAINS) {
q = vfio_ap_unlink_apqn_fr_mdev(matrix_mdev, apid, apqi);
- if (q && qtable) {
+ if (q && qlist) {
if (test_bit_inv(apid, matrix_mdev->shadow_apcb.apm) &&
test_bit_inv(apqi, matrix_mdev->shadow_apcb.aqm))
- hash_add(qtable->queues, &q->mdev_qnode,
- q->apqn);
+ list_add_tail(&q->reset_qnode, qlist);
}
}
}
@@ -1047,26 +1108,23 @@ static void vfio_ap_mdev_unlink_adapter(struct ap_matrix_mdev *matrix_mdev,
static void vfio_ap_mdev_hot_unplug_adapter(struct ap_matrix_mdev *matrix_mdev,
unsigned long apid)
{
- int loop_cursor;
- struct vfio_ap_queue *q;
- struct ap_queue_table *qtable = kzalloc(sizeof(*qtable), GFP_KERNEL);
+ struct vfio_ap_queue *q, *tmpq;
+ struct list_head qlist;
- hash_init(qtable->queues);
- vfio_ap_mdev_unlink_adapter(matrix_mdev, apid, qtable);
+ INIT_LIST_HEAD(&qlist);
+ vfio_ap_mdev_unlink_adapter(matrix_mdev, apid, &qlist);
if (test_bit_inv(apid, matrix_mdev->shadow_apcb.apm)) {
clear_bit_inv(apid, matrix_mdev->shadow_apcb.apm);
vfio_ap_mdev_update_guest_apcb(matrix_mdev);
}
- vfio_ap_mdev_reset_queues(qtable);
+ vfio_ap_mdev_reset_qlist(&qlist);
- hash_for_each(qtable->queues, loop_cursor, q, mdev_qnode) {
+ list_for_each_entry_safe(q, tmpq, &qlist, reset_qnode) {
vfio_ap_unlink_mdev_fr_queue(q);
- hash_del(&q->mdev_qnode);
+ list_del(&q->reset_qnode);
}
-
- kfree(qtable);
}
/**
@@ -1167,7 +1225,7 @@ static ssize_t assign_domain_store(struct device *dev,
{
int ret;
unsigned long apqi;
- DECLARE_BITMAP(aqm_delta, AP_DOMAINS);
+ DECLARE_BITMAP(apm_filtered, AP_DEVICES);
struct ap_matrix_mdev *matrix_mdev = dev_get_drvdata(dev);
mutex_lock(&ap_perms_mutex);
@@ -1196,12 +1254,11 @@ static ssize_t assign_domain_store(struct device *dev,
}
vfio_ap_mdev_link_domain(matrix_mdev, apqi);
- memset(aqm_delta, 0, sizeof(aqm_delta));
- set_bit_inv(apqi, aqm_delta);
- if (vfio_ap_mdev_filter_matrix(matrix_mdev->matrix.apm, aqm_delta,
- matrix_mdev))
+ if (vfio_ap_mdev_filter_matrix(matrix_mdev, apm_filtered)) {
vfio_ap_mdev_update_guest_apcb(matrix_mdev);
+ reset_queues_for_apids(matrix_mdev, apm_filtered);
+ }
ret = count;
done:
@@ -1214,7 +1271,7 @@ static DEVICE_ATTR_WO(assign_domain);
static void vfio_ap_mdev_unlink_domain(struct ap_matrix_mdev *matrix_mdev,
unsigned long apqi,
- struct ap_queue_table *qtable)
+ struct list_head *qlist)
{
unsigned long apid;
struct vfio_ap_queue *q;
@@ -1222,11 +1279,10 @@ static void vfio_ap_mdev_unlink_domain(struct ap_matrix_mdev *matrix_mdev,
for_each_set_bit_inv(apid, matrix_mdev->matrix.apm, AP_DEVICES) {
q = vfio_ap_unlink_apqn_fr_mdev(matrix_mdev, apid, apqi);
- if (q && qtable) {
+ if (q && qlist) {
if (test_bit_inv(apid, matrix_mdev->shadow_apcb.apm) &&
test_bit_inv(apqi, matrix_mdev->shadow_apcb.aqm))
- hash_add(qtable->queues, &q->mdev_qnode,
- q->apqn);
+ list_add_tail(&q->reset_qnode, qlist);
}
}
}
@@ -1234,26 +1290,23 @@ static void vfio_ap_mdev_unlink_domain(struct ap_matrix_mdev *matrix_mdev,
static void vfio_ap_mdev_hot_unplug_domain(struct ap_matrix_mdev *matrix_mdev,
unsigned long apqi)
{
- int loop_cursor;
- struct vfio_ap_queue *q;
- struct ap_queue_table *qtable = kzalloc(sizeof(*qtable), GFP_KERNEL);
+ struct vfio_ap_queue *q, *tmpq;
+ struct list_head qlist;
- hash_init(qtable->queues);
- vfio_ap_mdev_unlink_domain(matrix_mdev, apqi, qtable);
+ INIT_LIST_HEAD(&qlist);
+ vfio_ap_mdev_unlink_domain(matrix_mdev, apqi, &qlist);
if (test_bit_inv(apqi, matrix_mdev->shadow_apcb.aqm)) {
clear_bit_inv(apqi, matrix_mdev->shadow_apcb.aqm);
vfio_ap_mdev_update_guest_apcb(matrix_mdev);
}
- vfio_ap_mdev_reset_queues(qtable);
+ vfio_ap_mdev_reset_qlist(&qlist);
- hash_for_each(qtable->queues, loop_cursor, q, mdev_qnode) {
+ list_for_each_entry_safe(q, tmpq, &qlist, reset_qnode) {
vfio_ap_unlink_mdev_fr_queue(q);
- hash_del(&q->mdev_qnode);
+ list_del(&q->reset_qnode);
}
-
- kfree(qtable);
}
/**
@@ -1608,7 +1661,7 @@ static void vfio_ap_mdev_unset_kvm(struct ap_matrix_mdev *matrix_mdev)
get_update_locks_for_kvm(kvm);
kvm_arch_crypto_clear_masks(kvm);
- vfio_ap_mdev_reset_queues(&matrix_mdev->qtable);
+ vfio_ap_mdev_reset_queues(matrix_mdev);
kvm_put_kvm(kvm);
matrix_mdev->kvm = NULL;
@@ -1744,15 +1797,33 @@ static void vfio_ap_mdev_reset_queue(struct vfio_ap_queue *q)
}
}
-static int vfio_ap_mdev_reset_queues(struct ap_queue_table *qtable)
+static int vfio_ap_mdev_reset_queues(struct ap_matrix_mdev *matrix_mdev)
{
int ret = 0, loop_cursor;
struct vfio_ap_queue *q;
- hash_for_each(qtable->queues, loop_cursor, q, mdev_qnode)
+ hash_for_each(matrix_mdev->qtable.queues, loop_cursor, q, mdev_qnode)
vfio_ap_mdev_reset_queue(q);
- hash_for_each(qtable->queues, loop_cursor, q, mdev_qnode) {
+ hash_for_each(matrix_mdev->qtable.queues, loop_cursor, q, mdev_qnode) {
+ flush_work(&q->reset_work);
+
+ if (q->reset_status.response_code)
+ ret = -EIO;
+ }
+
+ return ret;
+}
+
+static int vfio_ap_mdev_reset_qlist(struct list_head *qlist)
+{
+ int ret = 0;
+ struct vfio_ap_queue *q;
+
+ list_for_each_entry(q, qlist, reset_qnode)
+ vfio_ap_mdev_reset_queue(q);
+
+ list_for_each_entry(q, qlist, reset_qnode) {
flush_work(&q->reset_work);
if (q->reset_status.response_code)
@@ -1794,7 +1865,7 @@ static void vfio_ap_mdev_request(struct vfio_device *vdev, unsigned int count)
"Relaying device request to user (#%u)\n",
count);
- eventfd_signal(matrix_mdev->req_trigger, 1);
+ eventfd_signal(matrix_mdev->req_trigger);
} else if (count == 0) {
dev_notice(dev,
"No device request registered, blocked until released by user\n");
@@ -1938,7 +2009,7 @@ static ssize_t vfio_ap_mdev_ioctl(struct vfio_device *vdev,
ret = vfio_ap_mdev_get_device_info(arg);
break;
case VFIO_DEVICE_RESET:
- ret = vfio_ap_mdev_reset_queues(&matrix_mdev->qtable);
+ ret = vfio_ap_mdev_reset_queues(matrix_mdev);
break;
case VFIO_DEVICE_GET_IRQ_INFO:
ret = vfio_ap_get_irq_info(arg);
@@ -1976,6 +2047,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);
@@ -1983,8 +2055,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
@@ -2070,6 +2155,7 @@ int vfio_ap_mdev_probe_queue(struct ap_device *apdev)
{
int ret;
struct vfio_ap_queue *q;
+ DECLARE_BITMAP(apm_filtered, AP_DEVICES);
struct ap_matrix_mdev *matrix_mdev;
ret = sysfs_create_group(&apdev->device.kobj, &vfio_queue_attr_group);
@@ -2091,15 +2177,28 @@ int vfio_ap_mdev_probe_queue(struct ap_device *apdev)
if (matrix_mdev) {
vfio_ap_mdev_link_queue(matrix_mdev, q);
- if (vfio_ap_mdev_filter_matrix(matrix_mdev->matrix.apm,
- matrix_mdev->matrix.aqm,
- matrix_mdev))
+ /*
+ * If we're in the process of handling the adding of adapters or
+ * domains to the host's AP configuration, then let the
+ * vfio_ap device driver's on_scan_complete callback filter the
+ * matrix and update the guest's AP configuration after all of
+ * the new queue devices are probed.
+ */
+ if (!bitmap_empty(matrix_mdev->apm_add, AP_DEVICES) ||
+ !bitmap_empty(matrix_mdev->aqm_add, AP_DOMAINS))
+ goto done;
+
+ if (vfio_ap_mdev_filter_matrix(matrix_mdev, apm_filtered)) {
vfio_ap_mdev_update_guest_apcb(matrix_mdev);
+ reset_queues_for_apids(matrix_mdev, apm_filtered);
+ }
}
+
+done:
dev_set_drvdata(&apdev->device, q);
release_update_locks_for_mdev(matrix_mdev);
- return 0;
+ return ret;
err_remove_group:
sysfs_remove_group(&apdev->device.kobj, &vfio_queue_attr_group);
@@ -2116,26 +2215,40 @@ void vfio_ap_mdev_remove_queue(struct ap_device *apdev)
q = dev_get_drvdata(&apdev->device);
get_update_locks_for_queue(q);
matrix_mdev = q->matrix_mdev;
+ apid = AP_QID_CARD(q->apqn);
+ apqi = AP_QID_QUEUE(q->apqn);
if (matrix_mdev) {
- vfio_ap_unlink_queue_fr_mdev(q);
-
- apid = AP_QID_CARD(q->apqn);
- apqi = AP_QID_QUEUE(q->apqn);
-
- /*
- * If the queue is assigned to the guest's APCB, then remove
- * the adapter's APID from the APCB and hot it into the guest.
- */
+ /* If the queue is assigned to the guest's AP configuration */
if (test_bit_inv(apid, matrix_mdev->shadow_apcb.apm) &&
test_bit_inv(apqi, matrix_mdev->shadow_apcb.aqm)) {
+ /*
+ * Since the queues are defined via a matrix of adapters
+ * and domains, it is not possible to hot unplug a
+ * single queue; so, let's unplug the adapter.
+ */
clear_bit_inv(apid, matrix_mdev->shadow_apcb.apm);
vfio_ap_mdev_update_guest_apcb(matrix_mdev);
+ reset_queues_for_apid(matrix_mdev, apid);
+ goto done;
}
}
- vfio_ap_mdev_reset_queue(q);
- flush_work(&q->reset_work);
+ /*
+ * If the queue is not in the host's AP configuration, then resetting
+ * it will fail with response code 01, (APQN not valid); so, let's make
+ * sure it is in the host's config.
+ */
+ if (test_bit_inv(apid, (unsigned long *)matrix_dev->info.apm) &&
+ test_bit_inv(apqi, (unsigned long *)matrix_dev->info.aqm)) {
+ vfio_ap_mdev_reset_queue(q);
+ flush_work(&q->reset_work);
+ }
+
+done:
+ if (matrix_mdev)
+ vfio_ap_unlink_queue_fr_mdev(q);
+
dev_set_drvdata(&apdev->device, NULL);
kfree(q);
release_update_locks_for_mdev(matrix_mdev);
@@ -2297,7 +2410,7 @@ static void vfio_ap_filter_apid_by_qtype(unsigned long *apm, unsigned long *aqm)
bool apid_cleared;
struct ap_queue_status status;
unsigned long apid, apqi;
- struct ap_tapq_gr2 info;
+ struct ap_tapq_hwinfo info;
for_each_set_bit_inv(apid, apm, AP_DEVICES) {
apid_cleared = false;
@@ -2443,39 +2556,30 @@ void vfio_ap_on_cfg_changed(struct ap_config_info *cur_cfg_info,
static void vfio_ap_mdev_hot_plug_cfg(struct ap_matrix_mdev *matrix_mdev)
{
- bool do_hotplug = false;
- int filter_domains = 0;
- int filter_adapters = 0;
- DECLARE_BITMAP(apm, AP_DEVICES);
- DECLARE_BITMAP(aqm, AP_DOMAINS);
+ DECLARE_BITMAP(apm_filtered, AP_DEVICES);
+ bool filter_domains, filter_adapters, filter_cdoms, do_hotplug = false;
mutex_lock(&matrix_mdev->kvm->lock);
mutex_lock(&matrix_dev->mdevs_lock);
- filter_adapters = bitmap_and(apm, matrix_mdev->matrix.apm,
- matrix_mdev->apm_add, AP_DEVICES);
- filter_domains = bitmap_and(aqm, matrix_mdev->matrix.aqm,
- matrix_mdev->aqm_add, AP_DOMAINS);
-
- if (filter_adapters && filter_domains)
- do_hotplug |= vfio_ap_mdev_filter_matrix(apm, aqm, matrix_mdev);
- else if (filter_adapters)
- do_hotplug |=
- vfio_ap_mdev_filter_matrix(apm,
- matrix_mdev->shadow_apcb.aqm,
- matrix_mdev);
- else
- do_hotplug |=
- vfio_ap_mdev_filter_matrix(matrix_mdev->shadow_apcb.apm,
- aqm, matrix_mdev);
+ filter_adapters = bitmap_intersects(matrix_mdev->matrix.apm,
+ matrix_mdev->apm_add, AP_DEVICES);
+ filter_domains = bitmap_intersects(matrix_mdev->matrix.aqm,
+ matrix_mdev->aqm_add, AP_DOMAINS);
+ filter_cdoms = bitmap_intersects(matrix_mdev->matrix.adm,
+ matrix_mdev->adm_add, AP_DOMAINS);
- if (bitmap_intersects(matrix_mdev->matrix.adm, matrix_mdev->adm_add,
- AP_DOMAINS))
+ if (filter_adapters || filter_domains)
+ do_hotplug = vfio_ap_mdev_filter_matrix(matrix_mdev, apm_filtered);
+
+ if (filter_cdoms)
do_hotplug |= vfio_ap_mdev_filter_cdoms(matrix_mdev);
if (do_hotplug)
vfio_ap_mdev_update_guest_apcb(matrix_mdev);
+ reset_queues_for_apids(matrix_mdev, apm_filtered);
+
mutex_unlock(&matrix_dev->mdevs_lock);
mutex_unlock(&matrix_mdev->kvm->lock);
}
diff --git a/drivers/s390/crypto/vfio_ap_private.h b/drivers/s390/crypto/vfio_ap_private.h
index 88aff8b81f2f..98d37aa27044 100644
--- a/drivers/s390/crypto/vfio_ap_private.h
+++ b/drivers/s390/crypto/vfio_ap_private.h
@@ -133,6 +133,8 @@ struct ap_matrix_mdev {
* @apqn: the APQN of the AP queue device
* @saved_isc: the guest ISC registered with the GIB interface
* @mdev_qnode: allows the vfio_ap_queue struct to be added to a hashtable
+ * @reset_qnode: allows the vfio_ap_queue struct to be added to a list of queues
+ * that need to be reset
* @reset_status: the status from the last reset of the queue
* @reset_work: work to wait for queue reset to complete
*/
@@ -143,6 +145,7 @@ struct vfio_ap_queue {
#define VFIO_AP_ISC_INVALID 0xff
unsigned char saved_isc;
struct hlist_node mdev_qnode;
+ struct list_head reset_qnode;
struct ap_queue_status reset_status;
struct work_struct reset_work;
};
diff --git a/drivers/s390/crypto/zcrypt_api.c b/drivers/s390/crypto/zcrypt_api.c
index dcd6c7299fa9..74200f54dfff 100644
--- a/drivers/s390/crypto/zcrypt_api.c
+++ b/drivers/s390/crypto/zcrypt_api.c
@@ -673,7 +673,7 @@ static long zcrypt_rsa_modexpo(struct ap_perms *perms,
for_each_zcrypt_card(zc) {
/* Check for usable accelerator or CCA card */
if (!zc->online || !zc->card->config || zc->card->chkstop ||
- !(zc->card->functions & 0x18000000))
+ !(zc->card->hwinfo.accel || zc->card->hwinfo.cca))
continue;
/* Check for size limits */
if (zc->min_mod_size > mex->inputdatalength ||
@@ -778,7 +778,7 @@ static long zcrypt_rsa_crt(struct ap_perms *perms,
for_each_zcrypt_card(zc) {
/* Check for usable accelerator or CCA card */
if (!zc->online || !zc->card->config || zc->card->chkstop ||
- !(zc->card->functions & 0x18000000))
+ !(zc->card->hwinfo.accel || zc->card->hwinfo.cca))
continue;
/* Check for size limits */
if (zc->min_mod_size > crt->inputdatalength ||
@@ -893,7 +893,7 @@ static long _zcrypt_send_cprb(bool userspace, struct ap_perms *perms,
for_each_zcrypt_card(zc) {
/* Check for usable CCA card */
if (!zc->online || !zc->card->config || zc->card->chkstop ||
- !(zc->card->functions & 0x10000000))
+ !zc->card->hwinfo.cca)
continue;
/* Check for user selected CCA card */
if (xcrb->user_defined != AUTOSELECT &&
@@ -1064,7 +1064,7 @@ static long _zcrypt_send_ep11_cprb(bool userspace, struct ap_perms *perms,
for_each_zcrypt_card(zc) {
/* Check for usable EP11 card */
if (!zc->online || !zc->card->config || zc->card->chkstop ||
- !(zc->card->functions & 0x04000000))
+ !zc->card->hwinfo.ep11)
continue;
/* Check for user selected EP11 card */
if (targets &&
@@ -1177,7 +1177,7 @@ static long zcrypt_rng(char *buffer)
for_each_zcrypt_card(zc) {
/* Check for usable CCA card */
if (!zc->online || !zc->card->config || zc->card->chkstop ||
- !(zc->card->functions & 0x10000000))
+ !zc->card->hwinfo.cca)
continue;
/* get weight index of the card device */
wgt = zc->speed_rating[func_code];
@@ -1238,7 +1238,7 @@ static void zcrypt_device_status_mask(struct zcrypt_device_status *devstatus)
queue = AP_QID_QUEUE(zq->queue->qid);
stat = &devstatus[card * AP_DOMAINS + queue];
stat->hwtype = zc->card->ap_dev.device_type;
- stat->functions = zc->card->functions >> 26;
+ stat->functions = zc->card->hwinfo.fac >> 26;
stat->qid = zq->queue->qid;
stat->online = zq->online ? 0x01 : 0x00;
}
@@ -1263,7 +1263,7 @@ void zcrypt_device_status_mask_ext(struct zcrypt_device_status_ext *devstatus)
queue = AP_QID_QUEUE(zq->queue->qid);
stat = &devstatus[card * AP_DOMAINS + queue];
stat->hwtype = zc->card->ap_dev.device_type;
- stat->functions = zc->card->functions >> 26;
+ stat->functions = zc->card->hwinfo.fac >> 26;
stat->qid = zq->queue->qid;
stat->online = zq->online ? 0x01 : 0x00;
}
@@ -1286,7 +1286,7 @@ int zcrypt_device_status_ext(int card, int queue,
if (card == AP_QID_CARD(zq->queue->qid) &&
queue == AP_QID_QUEUE(zq->queue->qid)) {
devstat->hwtype = zc->card->ap_dev.device_type;
- devstat->functions = zc->card->functions >> 26;
+ devstat->functions = zc->card->hwinfo.fac >> 26;
devstat->qid = zq->queue->qid;
devstat->online = zq->online ? 0x01 : 0x00;
spin_unlock(&zcrypt_list_lock);
diff --git a/drivers/s390/crypto/zcrypt_cex4.c b/drivers/s390/crypto/zcrypt_cex4.c
index 5c4532ab0040..64df7d2f6266 100644
--- a/drivers/s390/crypto/zcrypt_cex4.c
+++ b/drivers/s390/crypto/zcrypt_cex4.c
@@ -477,7 +477,7 @@ static int zcrypt_cex4_card_probe(struct ap_device *ap_dev)
return -ENOMEM;
zc->card = ac;
dev_set_drvdata(&ap_dev->device, zc);
- if (ap_test_bit(&ac->functions, AP_FUNC_ACCEL)) {
+ if (ac->hwinfo.accel) {
if (ac->ap_dev.device_type == AP_DEVICE_TYPE_CEX4) {
zc->type_string = "CEX4A";
zc->user_space_type = ZCRYPT_CEX4;
@@ -506,8 +506,7 @@ static int zcrypt_cex4_card_probe(struct ap_device *ap_dev)
zc->user_space_type = ZCRYPT_CEX6;
}
zc->min_mod_size = CEX4A_MIN_MOD_SIZE;
- if (ap_test_bit(&ac->functions, AP_FUNC_MEX4K) &&
- ap_test_bit(&ac->functions, AP_FUNC_CRT4K)) {
+ if (ac->hwinfo.mex4k && ac->hwinfo.crt4k) {
zc->max_mod_size = CEX4A_MAX_MOD_SIZE_4K;
zc->max_exp_bit_length =
CEX4A_MAX_MOD_SIZE_4K;
@@ -516,7 +515,7 @@ static int zcrypt_cex4_card_probe(struct ap_device *ap_dev)
zc->max_exp_bit_length =
CEX4A_MAX_MOD_SIZE_2K;
}
- } else if (ap_test_bit(&ac->functions, AP_FUNC_COPRO)) {
+ } else if (ac->hwinfo.cca) {
if (ac->ap_dev.device_type == AP_DEVICE_TYPE_CEX4) {
zc->type_string = "CEX4C";
zc->speed_rating = CEX4C_SPEED_IDX;
@@ -556,7 +555,7 @@ static int zcrypt_cex4_card_probe(struct ap_device *ap_dev)
zc->min_mod_size = CEX4C_MIN_MOD_SIZE;
zc->max_mod_size = CEX4C_MAX_MOD_SIZE;
zc->max_exp_bit_length = CEX4C_MAX_MOD_SIZE;
- } else if (ap_test_bit(&ac->functions, AP_FUNC_EP11)) {
+ } else if (ac->hwinfo.ep11) {
if (ac->ap_dev.device_type == AP_DEVICE_TYPE_CEX4) {
zc->type_string = "CEX4P";
zc->user_space_type = ZCRYPT_CEX4;
@@ -599,14 +598,14 @@ static int zcrypt_cex4_card_probe(struct ap_device *ap_dev)
return rc;
}
- if (ap_test_bit(&ac->functions, AP_FUNC_COPRO)) {
+ if (ac->hwinfo.cca) {
rc = sysfs_create_group(&ap_dev->device.kobj,
&cca_card_attr_grp);
if (rc) {
zcrypt_card_unregister(zc);
zcrypt_card_free(zc);
}
- } else if (ap_test_bit(&ac->functions, AP_FUNC_EP11)) {
+ } else if (ac->hwinfo.ep11) {
rc = sysfs_create_group(&ap_dev->device.kobj,
&ep11_card_attr_grp);
if (rc) {
@@ -627,9 +626,9 @@ static void zcrypt_cex4_card_remove(struct ap_device *ap_dev)
struct zcrypt_card *zc = dev_get_drvdata(&ap_dev->device);
struct ap_card *ac = to_ap_card(&ap_dev->device);
- if (ap_test_bit(&ac->functions, AP_FUNC_COPRO))
+ if (ac->hwinfo.cca)
sysfs_remove_group(&ap_dev->device.kobj, &cca_card_attr_grp);
- else if (ap_test_bit(&ac->functions, AP_FUNC_EP11))
+ else if (ac->hwinfo.ep11)
sysfs_remove_group(&ap_dev->device.kobj, &ep11_card_attr_grp);
zcrypt_card_unregister(zc);
@@ -654,19 +653,19 @@ static int zcrypt_cex4_queue_probe(struct ap_device *ap_dev)
struct zcrypt_queue *zq;
int rc;
- if (ap_test_bit(&aq->card->functions, AP_FUNC_ACCEL)) {
+ if (aq->card->hwinfo.accel) {
zq = zcrypt_queue_alloc(aq->card->maxmsgsize);
if (!zq)
return -ENOMEM;
zq->ops = zcrypt_msgtype(MSGTYPE50_NAME,
MSGTYPE50_VARIANT_DEFAULT);
- } else if (ap_test_bit(&aq->card->functions, AP_FUNC_COPRO)) {
+ } else if (aq->card->hwinfo.cca) {
zq = zcrypt_queue_alloc(aq->card->maxmsgsize);
if (!zq)
return -ENOMEM;
zq->ops = zcrypt_msgtype(MSGTYPE06_NAME,
MSGTYPE06_VARIANT_DEFAULT);
- } else if (ap_test_bit(&aq->card->functions, AP_FUNC_EP11)) {
+ } else if (aq->card->hwinfo.ep11) {
zq = zcrypt_queue_alloc(aq->card->maxmsgsize);
if (!zq)
return -ENOMEM;
@@ -689,14 +688,14 @@ static int zcrypt_cex4_queue_probe(struct ap_device *ap_dev)
return rc;
}
- if (ap_test_bit(&aq->card->functions, AP_FUNC_COPRO)) {
+ if (aq->card->hwinfo.cca) {
rc = sysfs_create_group(&ap_dev->device.kobj,
&cca_queue_attr_grp);
if (rc) {
zcrypt_queue_unregister(zq);
zcrypt_queue_free(zq);
}
- } else if (ap_test_bit(&aq->card->functions, AP_FUNC_EP11)) {
+ } else if (aq->card->hwinfo.ep11) {
rc = sysfs_create_group(&ap_dev->device.kobj,
&ep11_queue_attr_grp);
if (rc) {
@@ -717,9 +716,9 @@ static void zcrypt_cex4_queue_remove(struct ap_device *ap_dev)
struct zcrypt_queue *zq = dev_get_drvdata(&ap_dev->device);
struct ap_queue *aq = to_ap_queue(&ap_dev->device);
- if (ap_test_bit(&aq->card->functions, AP_FUNC_COPRO))
+ if (aq->card->hwinfo.cca)
sysfs_remove_group(&ap_dev->device.kobj, &cca_queue_attr_grp);
- else if (ap_test_bit(&aq->card->functions, AP_FUNC_EP11))
+ else if (aq->card->hwinfo.ep11)
sysfs_remove_group(&ap_dev->device.kobj, &ep11_queue_attr_grp);
zcrypt_queue_unregister(zq);
diff --git a/drivers/s390/net/ism.h b/drivers/s390/net/ism.h
index 70c5bbda0fea..047fa6101555 100644
--- a/drivers/s390/net/ism.h
+++ b/drivers/s390/net/ism.h
@@ -16,7 +16,6 @@
*/
#define ISM_DMB_WORD_OFFSET 1
#define ISM_DMB_BIT_OFFSET (ISM_DMB_WORD_OFFSET * 32)
-#define ISM_IDENT_MASK 0x00FFFF
#define ISM_REG_SBA 0x1
#define ISM_REG_IEQ 0x2
@@ -192,12 +191,6 @@ struct ism_sba {
#define ISM_CREATE_REQ(dmb, idx, sf, offset) \
((dmb) | (idx) << 24 | (sf) << 23 | (offset))
-struct ism_systemeid {
- u8 seid_string[24];
- u8 serial_number[4];
- u8 type[4];
-};
-
static inline void __ism_read_cmd(struct ism_dev *ism, void *data,
unsigned long offset, unsigned long len)
{
diff --git a/drivers/s390/net/ism_drv.c b/drivers/s390/net/ism_drv.c
index 81aabbfbbe2c..2c8e964425dc 100644
--- a/drivers/s390/net/ism_drv.c
+++ b/drivers/s390/net/ism_drv.c
@@ -36,6 +36,7 @@ static struct ism_client *clients[MAX_CLIENTS]; /* use an array rather than */
/* a list for fast mapping */
static u8 max_client;
static DEFINE_MUTEX(clients_lock);
+static bool ism_v2_capable;
struct ism_dev_list {
struct list_head list;
struct mutex mutex; /* protects ism device list */
@@ -443,32 +444,6 @@ int ism_move(struct ism_dev *ism, u64 dmb_tok, unsigned int idx, bool sf,
}
EXPORT_SYMBOL_GPL(ism_move);
-static struct ism_systemeid SYSTEM_EID = {
- .seid_string = "IBM-SYSZ-ISMSEID00000000",
- .serial_number = "0000",
- .type = "0000",
-};
-
-static void ism_create_system_eid(void)
-{
- struct cpuid id;
- u16 ident_tail;
- char tmp[5];
-
- get_cpu_id(&id);
- ident_tail = (u16)(id.ident & ISM_IDENT_MASK);
- snprintf(tmp, 5, "%04X", ident_tail);
- memcpy(&SYSTEM_EID.serial_number, tmp, 4);
- snprintf(tmp, 5, "%04X", id.machine);
- memcpy(&SYSTEM_EID.type, tmp, 4);
-}
-
-u8 *ism_get_seid(void)
-{
- return SYSTEM_EID.seid_string;
-}
-EXPORT_SYMBOL_GPL(ism_get_seid);
-
static void ism_handle_event(struct ism_dev *ism)
{
struct ism_event *entry;
@@ -560,7 +535,9 @@ static int ism_dev_init(struct ism_dev *ism)
if (!ism_add_vlan_id(ism, ISM_RESERVED_VLANID))
/* hardware is V2 capable */
- ism_create_system_eid();
+ ism_v2_capable = true;
+ else
+ ism_v2_capable = false;
mutex_lock(&ism_dev_list.mutex);
mutex_lock(&clients_lock);
@@ -665,8 +642,7 @@ static void ism_dev_exit(struct ism_dev *ism)
}
mutex_unlock(&clients_lock);
- if (SYSTEM_EID.serial_number[0] != '0' ||
- SYSTEM_EID.type[0] != '0')
+ if (ism_v2_capable)
ism_del_vlan_id(ism, ISM_RESERVED_VLANID);
unregister_ieq(ism);
unregister_sba(ism);
@@ -743,10 +719,10 @@ static int ism_query_rgid(struct ism_dev *ism, u64 rgid, u32 vid_valid,
return ism_cmd(ism, &cmd);
}
-static int smcd_query_rgid(struct smcd_dev *smcd, u64 rgid, u32 vid_valid,
- u32 vid)
+static int smcd_query_rgid(struct smcd_dev *smcd, struct smcd_gid *rgid,
+ u32 vid_valid, u32 vid)
{
- return ism_query_rgid(smcd->priv, rgid, vid_valid, vid);
+ return ism_query_rgid(smcd->priv, rgid->gid, vid_valid, vid);
}
static int smcd_register_dmb(struct smcd_dev *smcd, struct smcd_dmb *dmb,
@@ -797,10 +773,11 @@ static int ism_signal_ieq(struct ism_dev *ism, u64 rgid, u32 trigger_irq,
return ism_cmd(ism, &cmd);
}
-static int smcd_signal_ieq(struct smcd_dev *smcd, u64 rgid, u32 trigger_irq,
- u32 event_code, u64 info)
+static int smcd_signal_ieq(struct smcd_dev *smcd, struct smcd_gid *rgid,
+ u32 trigger_irq, u32 event_code, u64 info)
{
- return ism_signal_ieq(smcd->priv, rgid, trigger_irq, event_code, info);
+ return ism_signal_ieq(smcd->priv, rgid->gid,
+ trigger_irq, event_code, info);
}
static int smcd_move(struct smcd_dev *smcd, u64 dmb_tok, unsigned int idx,
@@ -812,8 +789,7 @@ static int smcd_move(struct smcd_dev *smcd, u64 dmb_tok, unsigned int idx,
static int smcd_supports_v2(void)
{
- return SYSTEM_EID.serial_number[0] != '0' ||
- SYSTEM_EID.type[0] != '0';
+ return ism_v2_capable;
}
static u64 ism_get_local_gid(struct ism_dev *ism)
@@ -821,9 +797,11 @@ static u64 ism_get_local_gid(struct ism_dev *ism)
return ism->local_gid;
}
-static u64 smcd_get_local_gid(struct smcd_dev *smcd)
+static void smcd_get_local_gid(struct smcd_dev *smcd,
+ struct smcd_gid *smcd_gid)
{
- return ism_get_local_gid(smcd->priv);
+ smcd_gid->gid = ism_get_local_gid(smcd->priv);
+ smcd_gid->gid_ext = 0;
}
static u16 ism_get_chid(struct ism_dev *ism)
@@ -857,7 +835,6 @@ static const struct smcd_ops ism_ops = {
.signal_event = smcd_signal_ieq,
.move_data = smcd_move,
.supports_v2 = smcd_supports_v2,
- .get_system_eid = ism_get_seid,
.get_local_gid = smcd_get_local_gid,
.get_chid = smcd_get_chid,
.get_dev = smcd_get_dev,
diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c
index b92a32b4b114..04c64ce0a1ca 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);
}
diff --git a/drivers/s390/scsi/zfcp_fc.c b/drivers/s390/scsi/zfcp_fc.c
index 4f0d0e55f0d4..d6516ab00437 100644
--- a/drivers/s390/scsi/zfcp_fc.c
+++ b/drivers/s390/scsi/zfcp_fc.c
@@ -900,8 +900,19 @@ static void zfcp_fc_rspn(struct zfcp_adapter *adapter,
zfcp_fc_ct_ns_init(&rspn_req->ct_hdr, FC_NS_RSPN_ID,
FC_SYMBOLIC_NAME_SIZE);
hton24(rspn_req->rspn.fr_fid.fp_fid, fc_host_port_id(shost));
- len = strlcpy(rspn_req->rspn.fr_name, fc_host_symbolic_name(shost),
- FC_SYMBOLIC_NAME_SIZE);
+
+ BUILD_BUG_ON(sizeof(rspn_req->name) !=
+ sizeof(fc_host_symbolic_name(shost)));
+ BUILD_BUG_ON(sizeof(rspn_req->name) !=
+ type_max(typeof(rspn_req->rspn.fr_name_len)) + 1);
+ len = strscpy(rspn_req->name, fc_host_symbolic_name(shost),
+ sizeof(rspn_req->name));
+ /*
+ * It should be impossible for this to truncate (see BUILD_BUG_ON()
+ * above), but be robust anyway.
+ */
+ if (WARN_ON(len < 0))
+ len = sizeof(rspn_req->name) - 1;
rspn_req->rspn.fr_name_len = len;
sg_init_one(&fc_req->sg_req, rspn_req, sizeof(*rspn_req));