aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2014-04-02 17:50:10 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2014-04-02 17:50:10 -0400
commit7cbb39d4d4d530dff12f2ff06ed6c85c504ba91a (patch)
tree82f721591d739eca99817def86ca5b6ebd682fe6 /drivers/s390
parent64056a94256e7a476de67fbe581dfe5515c56288 (diff)
parent7227fc0666606b0df2c0d2966a7f4859b01bdf74 (diff)
Merge tag 'kvm-3.15-1' of git://git.kernel.org/pub/scm/virt/kvm/kvm
Pull kvm updates from Paolo Bonzini: "PPC and ARM do not have much going on this time. Most of the cool stuff, instead, is in s390 and (after a few releases) x86. ARM has some caching fixes and PPC has transactional memory support in guests. MIPS has some fixes, with more probably coming in 3.16 as QEMU will soon get support for MIPS KVM. For x86 there are optimizations for debug registers, which trigger on some Windows games, and other important fixes for Windows guests. We now expose to the guest Broadwell instruction set extensions and also Intel MPX. There's also a fix/workaround for OS X guests, nested virtualization features (preemption timer), and a couple kvmclock refinements. For s390, the main news is asynchronous page faults, together with improvements to IRQs (floating irqs and adapter irqs) that speed up virtio devices" * tag 'kvm-3.15-1' of git://git.kernel.org/pub/scm/virt/kvm/kvm: (96 commits) KVM: PPC: Book3S HV: Save/restore host PMU registers that are new in POWER8 KVM: PPC: Book3S HV: Fix decrementer timeouts with non-zero TB offset KVM: PPC: Book3S HV: Don't use kvm_memslots() in real mode KVM: PPC: Book3S HV: Return ENODEV error rather than EIO KVM: PPC: Book3S: Trim top 4 bits of physical address in RTAS code KVM: PPC: Book3S HV: Add get/set_one_reg for new TM state KVM: PPC: Book3S HV: Add transactional memory support KVM: Specify byte order for KVM_EXIT_MMIO KVM: vmx: fix MPX detection KVM: PPC: Book3S HV: Fix KVM hang with CONFIG_KVM_XICS=n KVM: PPC: Book3S: Introduce hypervisor call H_GET_TCE KVM: PPC: Book3S HV: Fix incorrect userspace exit on ioeventfd write KVM: s390: clear local interrupts at cpu initial reset KVM: s390: Fix possible memory leak in SIGP functions KVM: s390: fix calculation of idle_mask array size KVM: s390: randomize sca address KVM: ioapic: reinject pending interrupts on KVM_SET_IRQCHIP KVM: Bump KVM_MAX_IRQ_ROUTES for s390 KVM: s390: irq routing for adapter interrupts. KVM: s390: adapter interrupt sources ...
Diffstat (limited to 'drivers/s390')
-rw-r--r--drivers/s390/kvm/virtio_ccw.c323
1 files changed, 306 insertions, 17 deletions
diff --git a/drivers/s390/kvm/virtio_ccw.c b/drivers/s390/kvm/virtio_ccw.c
index 0fc584832001..1e1fc671f89a 100644
--- a/drivers/s390/kvm/virtio_ccw.c
+++ b/drivers/s390/kvm/virtio_ccw.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * ccw based virtio transport 2 * ccw based virtio transport
3 * 3 *
4 * Copyright IBM Corp. 2012 4 * Copyright IBM Corp. 2012, 2014
5 * 5 *
6 * This program is free software; you can redistribute it and/or modify 6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License (version 2 only) 7 * it under the terms of the GNU General Public License (version 2 only)
@@ -32,6 +32,8 @@
32#include <asm/cio.h> 32#include <asm/cio.h>
33#include <asm/ccwdev.h> 33#include <asm/ccwdev.h>
34#include <asm/virtio-ccw.h> 34#include <asm/virtio-ccw.h>
35#include <asm/isc.h>
36#include <asm/airq.h>
35 37
36/* 38/*
37 * virtio related functions 39 * virtio related functions
@@ -58,6 +60,9 @@ struct virtio_ccw_device {
58 unsigned long indicators; 60 unsigned long indicators;
59 unsigned long indicators2; 61 unsigned long indicators2;
60 struct vq_config_block *config_block; 62 struct vq_config_block *config_block;
63 bool is_thinint;
64 bool going_away;
65 void *airq_info;
61}; 66};
62 67
63struct vq_info_block { 68struct vq_info_block {
@@ -72,15 +77,38 @@ struct virtio_feature_desc {
72 __u8 index; 77 __u8 index;
73} __packed; 78} __packed;
74 79
80struct virtio_thinint_area {
81 unsigned long summary_indicator;
82 unsigned long indicator;
83 u64 bit_nr;
84 u8 isc;
85} __packed;
86
75struct virtio_ccw_vq_info { 87struct virtio_ccw_vq_info {
76 struct virtqueue *vq; 88 struct virtqueue *vq;
77 int num; 89 int num;
78 void *queue; 90 void *queue;
79 struct vq_info_block *info_block; 91 struct vq_info_block *info_block;
92 int bit_nr;
80 struct list_head node; 93 struct list_head node;
81 long cookie; 94 long cookie;
82}; 95};
83 96
97#define VIRTIO_AIRQ_ISC IO_SCH_ISC /* inherit from subchannel */
98
99#define VIRTIO_IV_BITS (L1_CACHE_BYTES * 8)
100#define MAX_AIRQ_AREAS 20
101
102static int virtio_ccw_use_airq = 1;
103
104struct airq_info {
105 rwlock_t lock;
106 u8 summary_indicator;
107 struct airq_struct airq;
108 struct airq_iv *aiv;
109};
110static struct airq_info *airq_areas[MAX_AIRQ_AREAS];
111
84#define CCW_CMD_SET_VQ 0x13 112#define CCW_CMD_SET_VQ 0x13
85#define CCW_CMD_VDEV_RESET 0x33 113#define CCW_CMD_VDEV_RESET 0x33
86#define CCW_CMD_SET_IND 0x43 114#define CCW_CMD_SET_IND 0x43
@@ -91,6 +119,7 @@ struct virtio_ccw_vq_info {
91#define CCW_CMD_WRITE_CONF 0x21 119#define CCW_CMD_WRITE_CONF 0x21
92#define CCW_CMD_WRITE_STATUS 0x31 120#define CCW_CMD_WRITE_STATUS 0x31
93#define CCW_CMD_READ_VQ_CONF 0x32 121#define CCW_CMD_READ_VQ_CONF 0x32
122#define CCW_CMD_SET_IND_ADAPTER 0x73
94 123
95#define VIRTIO_CCW_DOING_SET_VQ 0x00010000 124#define VIRTIO_CCW_DOING_SET_VQ 0x00010000
96#define VIRTIO_CCW_DOING_RESET 0x00040000 125#define VIRTIO_CCW_DOING_RESET 0x00040000
@@ -102,6 +131,7 @@ struct virtio_ccw_vq_info {
102#define VIRTIO_CCW_DOING_SET_IND 0x01000000 131#define VIRTIO_CCW_DOING_SET_IND 0x01000000
103#define VIRTIO_CCW_DOING_READ_VQ_CONF 0x02000000 132#define VIRTIO_CCW_DOING_READ_VQ_CONF 0x02000000
104#define VIRTIO_CCW_DOING_SET_CONF_IND 0x04000000 133#define VIRTIO_CCW_DOING_SET_CONF_IND 0x04000000
134#define VIRTIO_CCW_DOING_SET_IND_ADAPTER 0x08000000
105#define VIRTIO_CCW_INTPARM_MASK 0xffff0000 135#define VIRTIO_CCW_INTPARM_MASK 0xffff0000
106 136
107static struct virtio_ccw_device *to_vc_device(struct virtio_device *vdev) 137static struct virtio_ccw_device *to_vc_device(struct virtio_device *vdev)
@@ -109,6 +139,125 @@ static struct virtio_ccw_device *to_vc_device(struct virtio_device *vdev)
109 return container_of(vdev, struct virtio_ccw_device, vdev); 139 return container_of(vdev, struct virtio_ccw_device, vdev);
110} 140}
111 141
142static void drop_airq_indicator(struct virtqueue *vq, struct airq_info *info)
143{
144 unsigned long i, flags;
145
146 write_lock_irqsave(&info->lock, flags);
147 for (i = 0; i < airq_iv_end(info->aiv); i++) {
148 if (vq == (void *)airq_iv_get_ptr(info->aiv, i)) {
149 airq_iv_free_bit(info->aiv, i);
150 airq_iv_set_ptr(info->aiv, i, 0);
151 break;
152 }
153 }
154 write_unlock_irqrestore(&info->lock, flags);
155}
156
157static void virtio_airq_handler(struct airq_struct *airq)
158{
159 struct airq_info *info = container_of(airq, struct airq_info, airq);
160 unsigned long ai;
161
162 inc_irq_stat(IRQIO_VAI);
163 read_lock(&info->lock);
164 /* Walk through indicators field, summary indicator active. */
165 for (ai = 0;;) {
166 ai = airq_iv_scan(info->aiv, ai, airq_iv_end(info->aiv));
167 if (ai == -1UL)
168 break;
169 vring_interrupt(0, (void *)airq_iv_get_ptr(info->aiv, ai));
170 }
171 info->summary_indicator = 0;
172 smp_wmb();
173 /* Walk through indicators field, summary indicator not active. */
174 for (ai = 0;;) {
175 ai = airq_iv_scan(info->aiv, ai, airq_iv_end(info->aiv));
176 if (ai == -1UL)
177 break;
178 vring_interrupt(0, (void *)airq_iv_get_ptr(info->aiv, ai));
179 }
180 read_unlock(&info->lock);
181}
182
183static struct airq_info *new_airq_info(void)
184{
185 struct airq_info *info;
186 int rc;
187
188 info = kzalloc(sizeof(*info), GFP_KERNEL);
189 if (!info)
190 return NULL;
191 rwlock_init(&info->lock);
192 info->aiv = airq_iv_create(VIRTIO_IV_BITS, AIRQ_IV_ALLOC | AIRQ_IV_PTR);
193 if (!info->aiv) {
194 kfree(info);
195 return NULL;
196 }
197 info->airq.handler = virtio_airq_handler;
198 info->airq.lsi_ptr = &info->summary_indicator;
199 info->airq.lsi_mask = 0xff;
200 info->airq.isc = VIRTIO_AIRQ_ISC;
201 rc = register_adapter_interrupt(&info->airq);
202 if (rc) {
203 airq_iv_release(info->aiv);
204 kfree(info);
205 return NULL;
206 }
207 return info;
208}
209
210static void destroy_airq_info(struct airq_info *info)
211{
212 if (!info)
213 return;
214
215 unregister_adapter_interrupt(&info->airq);
216 airq_iv_release(info->aiv);
217 kfree(info);
218}
219
220static unsigned long get_airq_indicator(struct virtqueue *vqs[], int nvqs,
221 u64 *first, void **airq_info)
222{
223 int i, j;
224 struct airq_info *info;
225 unsigned long indicator_addr = 0;
226 unsigned long bit, flags;
227
228 for (i = 0; i < MAX_AIRQ_AREAS && !indicator_addr; i++) {
229 if (!airq_areas[i])
230 airq_areas[i] = new_airq_info();
231 info = airq_areas[i];
232 if (!info)
233 return 0;
234 write_lock_irqsave(&info->lock, flags);
235 bit = airq_iv_alloc(info->aiv, nvqs);
236 if (bit == -1UL) {
237 /* Not enough vacancies. */
238 write_unlock_irqrestore(&info->lock, flags);
239 continue;
240 }
241 *first = bit;
242 *airq_info = info;
243 indicator_addr = (unsigned long)info->aiv->vector;
244 for (j = 0; j < nvqs; j++) {
245 airq_iv_set_ptr(info->aiv, bit + j,
246 (unsigned long)vqs[j]);
247 }
248 write_unlock_irqrestore(&info->lock, flags);
249 }
250 return indicator_addr;
251}
252
253static void virtio_ccw_drop_indicators(struct virtio_ccw_device *vcdev)
254{
255 struct virtio_ccw_vq_info *info;
256
257 list_for_each_entry(info, &vcdev->virtqueues, node)
258 drop_airq_indicator(info->vq, vcdev->airq_info);
259}
260
112static int doing_io(struct virtio_ccw_device *vcdev, __u32 flag) 261static int doing_io(struct virtio_ccw_device *vcdev, __u32 flag)
113{ 262{
114 unsigned long flags; 263 unsigned long flags;
@@ -145,6 +294,51 @@ static int ccw_io_helper(struct virtio_ccw_device *vcdev,
145 return ret ? ret : vcdev->err; 294 return ret ? ret : vcdev->err;
146} 295}
147 296
297static void virtio_ccw_drop_indicator(struct virtio_ccw_device *vcdev,
298 struct ccw1 *ccw)
299{
300 int ret;
301 unsigned long *indicatorp = NULL;
302 struct virtio_thinint_area *thinint_area = NULL;
303 struct airq_info *airq_info = vcdev->airq_info;
304
305 if (vcdev->is_thinint) {
306 thinint_area = kzalloc(sizeof(*thinint_area),
307 GFP_DMA | GFP_KERNEL);
308 if (!thinint_area)
309 return;
310 thinint_area->summary_indicator =
311 (unsigned long) &airq_info->summary_indicator;
312 thinint_area->isc = VIRTIO_AIRQ_ISC;
313 ccw->cmd_code = CCW_CMD_SET_IND_ADAPTER;
314 ccw->count = sizeof(*thinint_area);
315 ccw->cda = (__u32)(unsigned long) thinint_area;
316 } else {
317 indicatorp = kmalloc(sizeof(&vcdev->indicators),
318 GFP_DMA | GFP_KERNEL);
319 if (!indicatorp)
320 return;
321 *indicatorp = 0;
322 ccw->cmd_code = CCW_CMD_SET_IND;
323 ccw->count = sizeof(vcdev->indicators);
324 ccw->cda = (__u32)(unsigned long) indicatorp;
325 }
326 /* Deregister indicators from host. */
327 vcdev->indicators = 0;
328 ccw->flags = 0;
329 ret = ccw_io_helper(vcdev, ccw,
330 vcdev->is_thinint ?
331 VIRTIO_CCW_DOING_SET_IND_ADAPTER :
332 VIRTIO_CCW_DOING_SET_IND);
333 if (ret && (ret != -ENODEV))
334 dev_info(&vcdev->cdev->dev,
335 "Failed to deregister indicators (%d)\n", ret);
336 else if (vcdev->is_thinint)
337 virtio_ccw_drop_indicators(vcdev);
338 kfree(indicatorp);
339 kfree(thinint_area);
340}
341
148static inline long do_kvm_notify(struct subchannel_id schid, 342static inline long do_kvm_notify(struct subchannel_id schid,
149 unsigned long queue_index, 343 unsigned long queue_index,
150 long cookie) 344 long cookie)
@@ -232,11 +426,13 @@ static void virtio_ccw_del_vqs(struct virtio_device *vdev)
232{ 426{
233 struct virtqueue *vq, *n; 427 struct virtqueue *vq, *n;
234 struct ccw1 *ccw; 428 struct ccw1 *ccw;
429 struct virtio_ccw_device *vcdev = to_vc_device(vdev);
235 430
236 ccw = kzalloc(sizeof(*ccw), GFP_DMA | GFP_KERNEL); 431 ccw = kzalloc(sizeof(*ccw), GFP_DMA | GFP_KERNEL);
237 if (!ccw) 432 if (!ccw)
238 return; 433 return;
239 434
435 virtio_ccw_drop_indicator(vcdev, ccw);
240 436
241 list_for_each_entry_safe(vq, n, &vdev->vqs, list) 437 list_for_each_entry_safe(vq, n, &vdev->vqs, list)
242 virtio_ccw_del_vq(vq, ccw); 438 virtio_ccw_del_vq(vq, ccw);
@@ -326,6 +522,54 @@ out_err:
326 return ERR_PTR(err); 522 return ERR_PTR(err);
327} 523}
328 524
525static int virtio_ccw_register_adapter_ind(struct virtio_ccw_device *vcdev,
526 struct virtqueue *vqs[], int nvqs,
527 struct ccw1 *ccw)
528{
529 int ret;
530 struct virtio_thinint_area *thinint_area = NULL;
531 struct airq_info *info;
532
533 thinint_area = kzalloc(sizeof(*thinint_area), GFP_DMA | GFP_KERNEL);
534 if (!thinint_area) {
535 ret = -ENOMEM;
536 goto out;
537 }
538 /* Try to get an indicator. */
539 thinint_area->indicator = get_airq_indicator(vqs, nvqs,
540 &thinint_area->bit_nr,
541 &vcdev->airq_info);
542 if (!thinint_area->indicator) {
543 ret = -ENOSPC;
544 goto out;
545 }
546 info = vcdev->airq_info;
547 thinint_area->summary_indicator =
548 (unsigned long) &info->summary_indicator;
549 thinint_area->isc = VIRTIO_AIRQ_ISC;
550 ccw->cmd_code = CCW_CMD_SET_IND_ADAPTER;
551 ccw->flags = CCW_FLAG_SLI;
552 ccw->count = sizeof(*thinint_area);
553 ccw->cda = (__u32)(unsigned long)thinint_area;
554 ret = ccw_io_helper(vcdev, ccw, VIRTIO_CCW_DOING_SET_IND_ADAPTER);
555 if (ret) {
556 if (ret == -EOPNOTSUPP) {
557 /*
558 * The host does not support adapter interrupts
559 * for virtio-ccw, stop trying.
560 */
561 virtio_ccw_use_airq = 0;
562 pr_info("Adapter interrupts unsupported on host\n");
563 } else
564 dev_warn(&vcdev->cdev->dev,
565 "enabling adapter interrupts = %d\n", ret);
566 virtio_ccw_drop_indicators(vcdev);
567 }
568out:
569 kfree(thinint_area);
570 return ret;
571}
572
329static int virtio_ccw_find_vqs(struct virtio_device *vdev, unsigned nvqs, 573static int virtio_ccw_find_vqs(struct virtio_device *vdev, unsigned nvqs,
330 struct virtqueue *vqs[], 574 struct virtqueue *vqs[],
331 vq_callback_t *callbacks[], 575 vq_callback_t *callbacks[],
@@ -355,15 +599,23 @@ static int virtio_ccw_find_vqs(struct virtio_device *vdev, unsigned nvqs,
355 if (!indicatorp) 599 if (!indicatorp)
356 goto out; 600 goto out;
357 *indicatorp = (unsigned long) &vcdev->indicators; 601 *indicatorp = (unsigned long) &vcdev->indicators;
358 /* Register queue indicators with host. */ 602 if (vcdev->is_thinint) {
359 vcdev->indicators = 0; 603 ret = virtio_ccw_register_adapter_ind(vcdev, vqs, nvqs, ccw);
360 ccw->cmd_code = CCW_CMD_SET_IND; 604 if (ret)
361 ccw->flags = 0; 605 /* no error, just fall back to legacy interrupts */
362 ccw->count = sizeof(vcdev->indicators); 606 vcdev->is_thinint = 0;
363 ccw->cda = (__u32)(unsigned long) indicatorp; 607 }
364 ret = ccw_io_helper(vcdev, ccw, VIRTIO_CCW_DOING_SET_IND); 608 if (!vcdev->is_thinint) {
365 if (ret) 609 /* Register queue indicators with host. */
366 goto out; 610 vcdev->indicators = 0;
611 ccw->cmd_code = CCW_CMD_SET_IND;
612 ccw->flags = 0;
613 ccw->count = sizeof(vcdev->indicators);
614 ccw->cda = (__u32)(unsigned long) indicatorp;
615 ret = ccw_io_helper(vcdev, ccw, VIRTIO_CCW_DOING_SET_IND);
616 if (ret)
617 goto out;
618 }
367 /* Register indicators2 with host for config changes */ 619 /* Register indicators2 with host for config changes */
368 *indicatorp = (unsigned long) &vcdev->indicators2; 620 *indicatorp = (unsigned long) &vcdev->indicators2;
369 vcdev->indicators2 = 0; 621 vcdev->indicators2 = 0;
@@ -636,6 +888,8 @@ static void virtio_ccw_int_handler(struct ccw_device *cdev,
636 struct virtqueue *vq; 888 struct virtqueue *vq;
637 struct virtio_driver *drv; 889 struct virtio_driver *drv;
638 890
891 if (!vcdev)
892 return;
639 /* Check if it's a notification from the host. */ 893 /* Check if it's a notification from the host. */
640 if ((intparm == 0) && 894 if ((intparm == 0) &&
641 (scsw_stctl(&irb->scsw) == 895 (scsw_stctl(&irb->scsw) ==
@@ -663,6 +917,7 @@ static void virtio_ccw_int_handler(struct ccw_device *cdev,
663 case VIRTIO_CCW_DOING_SET_CONF_IND: 917 case VIRTIO_CCW_DOING_SET_CONF_IND:
664 case VIRTIO_CCW_DOING_RESET: 918 case VIRTIO_CCW_DOING_RESET:
665 case VIRTIO_CCW_DOING_READ_VQ_CONF: 919 case VIRTIO_CCW_DOING_READ_VQ_CONF:
920 case VIRTIO_CCW_DOING_SET_IND_ADAPTER:
666 vcdev->curr_io &= ~activity; 921 vcdev->curr_io &= ~activity;
667 wake_up(&vcdev->wait_q); 922 wake_up(&vcdev->wait_q);
668 break; 923 break;
@@ -734,23 +989,46 @@ static int virtio_ccw_probe(struct ccw_device *cdev)
734 return 0; 989 return 0;
735} 990}
736 991
992static struct virtio_ccw_device *virtio_grab_drvdata(struct ccw_device *cdev)
993{
994 unsigned long flags;
995 struct virtio_ccw_device *vcdev;
996
997 spin_lock_irqsave(get_ccwdev_lock(cdev), flags);
998 vcdev = dev_get_drvdata(&cdev->dev);
999 if (!vcdev || vcdev->going_away) {
1000 spin_unlock_irqrestore(get_ccwdev_lock(cdev), flags);
1001 return NULL;
1002 }
1003 vcdev->going_away = true;
1004 spin_unlock_irqrestore(get_ccwdev_lock(cdev), flags);
1005 return vcdev;
1006}
1007
737static void virtio_ccw_remove(struct ccw_device *cdev) 1008static void virtio_ccw_remove(struct ccw_device *cdev)
738{ 1009{
739 struct virtio_ccw_device *vcdev = dev_get_drvdata(&cdev->dev); 1010 unsigned long flags;
1011 struct virtio_ccw_device *vcdev = virtio_grab_drvdata(cdev);
740 1012
741 if (cdev->online) { 1013 if (vcdev && cdev->online)
742 unregister_virtio_device(&vcdev->vdev); 1014 unregister_virtio_device(&vcdev->vdev);
743 dev_set_drvdata(&cdev->dev, NULL); 1015 spin_lock_irqsave(get_ccwdev_lock(cdev), flags);
744 } 1016 dev_set_drvdata(&cdev->dev, NULL);
1017 spin_unlock_irqrestore(get_ccwdev_lock(cdev), flags);
745 cdev->handler = NULL; 1018 cdev->handler = NULL;
746} 1019}
747 1020
748static int virtio_ccw_offline(struct ccw_device *cdev) 1021static int virtio_ccw_offline(struct ccw_device *cdev)
749{ 1022{
750 struct virtio_ccw_device *vcdev = dev_get_drvdata(&cdev->dev); 1023 unsigned long flags;
1024 struct virtio_ccw_device *vcdev = virtio_grab_drvdata(cdev);
751 1025
752 unregister_virtio_device(&vcdev->vdev); 1026 if (vcdev) {
753 dev_set_drvdata(&cdev->dev, NULL); 1027 unregister_virtio_device(&vcdev->vdev);
1028 spin_lock_irqsave(get_ccwdev_lock(cdev), flags);
1029 dev_set_drvdata(&cdev->dev, NULL);
1030 spin_unlock_irqrestore(get_ccwdev_lock(cdev), flags);
1031 }
754 return 0; 1032 return 0;
755} 1033}
756 1034
@@ -759,6 +1037,7 @@ static int virtio_ccw_online(struct ccw_device *cdev)
759{ 1037{
760 int ret; 1038 int ret;
761 struct virtio_ccw_device *vcdev; 1039 struct virtio_ccw_device *vcdev;
1040 unsigned long flags;
762 1041
763 vcdev = kzalloc(sizeof(*vcdev), GFP_KERNEL); 1042 vcdev = kzalloc(sizeof(*vcdev), GFP_KERNEL);
764 if (!vcdev) { 1043 if (!vcdev) {
@@ -778,6 +1057,8 @@ static int virtio_ccw_online(struct ccw_device *cdev)
778 goto out_free; 1057 goto out_free;
779 } 1058 }
780 1059
1060 vcdev->is_thinint = virtio_ccw_use_airq; /* at least try */
1061
781 vcdev->vdev.dev.parent = &cdev->dev; 1062 vcdev->vdev.dev.parent = &cdev->dev;
782 vcdev->vdev.dev.release = virtio_ccw_release_dev; 1063 vcdev->vdev.dev.release = virtio_ccw_release_dev;
783 vcdev->vdev.config = &virtio_ccw_config_ops; 1064 vcdev->vdev.config = &virtio_ccw_config_ops;
@@ -786,7 +1067,9 @@ static int virtio_ccw_online(struct ccw_device *cdev)
786 INIT_LIST_HEAD(&vcdev->virtqueues); 1067 INIT_LIST_HEAD(&vcdev->virtqueues);
787 spin_lock_init(&vcdev->lock); 1068 spin_lock_init(&vcdev->lock);
788 1069
1070 spin_lock_irqsave(get_ccwdev_lock(cdev), flags);
789 dev_set_drvdata(&cdev->dev, vcdev); 1071 dev_set_drvdata(&cdev->dev, vcdev);
1072 spin_unlock_irqrestore(get_ccwdev_lock(cdev), flags);
790 vcdev->vdev.id.vendor = cdev->id.cu_type; 1073 vcdev->vdev.id.vendor = cdev->id.cu_type;
791 vcdev->vdev.id.device = cdev->id.cu_model; 1074 vcdev->vdev.id.device = cdev->id.cu_model;
792 ret = register_virtio_device(&vcdev->vdev); 1075 ret = register_virtio_device(&vcdev->vdev);
@@ -797,7 +1080,9 @@ static int virtio_ccw_online(struct ccw_device *cdev)
797 } 1080 }
798 return 0; 1081 return 0;
799out_put: 1082out_put:
1083 spin_lock_irqsave(get_ccwdev_lock(cdev), flags);
800 dev_set_drvdata(&cdev->dev, NULL); 1084 dev_set_drvdata(&cdev->dev, NULL);
1085 spin_unlock_irqrestore(get_ccwdev_lock(cdev), flags);
801 put_device(&vcdev->vdev.dev); 1086 put_device(&vcdev->vdev.dev);
802 return ret; 1087 return ret;
803out_free: 1088out_free:
@@ -935,6 +1220,10 @@ module_init(virtio_ccw_init);
935 1220
936static void __exit virtio_ccw_exit(void) 1221static void __exit virtio_ccw_exit(void)
937{ 1222{
1223 int i;
1224
938 ccw_driver_unregister(&virtio_ccw_driver); 1225 ccw_driver_unregister(&virtio_ccw_driver);
1226 for (i = 0; i < MAX_AIRQ_AREAS; i++)
1227 destroy_airq_info(airq_areas[i]);
939} 1228}
940module_exit(virtio_ccw_exit); 1229module_exit(virtio_ccw_exit);