Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

KVM: s390: Add a channel I/O based virtio transport driver.

Add a driver for kvm guests that matches virtual ccw devices provided
by the host as virtio bridge devices.

These virtio-ccw devices use a special set of channel commands in order
to perform virtio functions.

Reviewed-by: Marcelo Tosatti <mtosatti@redhat.com>
Reviewed-by: Alexander Graf <agraf@suse.de>
Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
Signed-off-by: Gleb Natapov <gleb@redhat.com>

authored by

Cornelia Huck and committed by
Gleb Natapov
7e64e059 0abbe448

+856 -1
+1
arch/s390/include/asm/irq.h
··· 35 35 IOINT_CSC, 36 36 IOINT_PCI, 37 37 IOINT_MSI, 38 + IOINT_VIR, 38 39 NMI_NMI, 39 40 NR_IRQS, 40 41 };
+1
arch/s390/kernel/irq.c
··· 60 60 [IOINT_CSC] = {.name = "CSC", .desc = "[I/O] CHSC Subchannel"}, 61 61 [IOINT_PCI] = {.name = "PCI", .desc = "[I/O] PCI Interrupt" }, 62 62 [IOINT_MSI] = {.name = "MSI", .desc = "[I/O] MSI Interrupt" }, 63 + [IOINT_VIR] = {.name = "VIR", .desc = "[I/O] Virtual I/O Devices"}, 63 64 [NMI_NMI] = {.name = "NMI", .desc = "[NMI] Machine Check"}, 64 65 }; 65 66
+1 -1
drivers/s390/kvm/Makefile
··· 6 6 # it under the terms of the GNU General Public License (version 2 only) 7 7 # as published by the Free Software Foundation. 8 8 9 - obj-$(CONFIG_S390_GUEST) += kvm_virtio.o 9 + obj-$(CONFIG_S390_GUEST) += kvm_virtio.o virtio_ccw.o
+853
drivers/s390/kvm/virtio_ccw.c
··· 1 + /* 2 + * ccw based virtio transport 3 + * 4 + * Copyright IBM Corp. 2012 5 + * 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) 8 + * as published by the Free Software Foundation. 9 + * 10 + * Author(s): Cornelia Huck <cornelia.huck@de.ibm.com> 11 + */ 12 + 13 + #include <linux/kernel_stat.h> 14 + #include <linux/init.h> 15 + #include <linux/bootmem.h> 16 + #include <linux/err.h> 17 + #include <linux/virtio.h> 18 + #include <linux/virtio_config.h> 19 + #include <linux/slab.h> 20 + #include <linux/interrupt.h> 21 + #include <linux/virtio_ring.h> 22 + #include <linux/pfn.h> 23 + #include <linux/async.h> 24 + #include <linux/wait.h> 25 + #include <linux/list.h> 26 + #include <linux/bitops.h> 27 + #include <linux/module.h> 28 + #include <linux/io.h> 29 + #include <linux/kvm_para.h> 30 + #include <asm/setup.h> 31 + #include <asm/irq.h> 32 + #include <asm/cio.h> 33 + #include <asm/ccwdev.h> 34 + 35 + /* 36 + * virtio related functions 37 + */ 38 + 39 + struct vq_config_block { 40 + __u16 index; 41 + __u16 num; 42 + } __packed; 43 + 44 + #define VIRTIO_CCW_CONFIG_SIZE 0x100 45 + /* same as PCI config space size, should be enough for all drivers */ 46 + 47 + struct virtio_ccw_device { 48 + struct virtio_device vdev; 49 + __u8 status; 50 + __u8 config[VIRTIO_CCW_CONFIG_SIZE]; 51 + struct ccw_device *cdev; 52 + struct ccw1 *ccw; 53 + __u32 area; 54 + __u32 curr_io; 55 + int err; 56 + wait_queue_head_t wait_q; 57 + spinlock_t lock; 58 + struct list_head virtqueues; 59 + unsigned long indicators; 60 + unsigned long indicators2; 61 + struct vq_config_block *config_block; 62 + }; 63 + 64 + struct vq_info_block { 65 + __u64 queue; 66 + __u32 align; 67 + __u16 index; 68 + __u16 num; 69 + } __packed; 70 + 71 + struct virtio_feature_desc { 72 + __u32 features; 73 + __u8 index; 74 + } __packed; 75 + 76 + struct virtio_ccw_vq_info { 77 + struct virtqueue *vq; 78 + int num; 79 + void *queue; 80 + struct vq_info_block *info_block; 81 + struct list_head node; 82 + }; 83 + 84 + #define KVM_VIRTIO_CCW_RING_ALIGN 4096 85 + 86 + #define KVM_S390_VIRTIO_CCW_NOTIFY 3 87 + 88 + #define CCW_CMD_SET_VQ 0x13 89 + #define CCW_CMD_VDEV_RESET 0x33 90 + #define CCW_CMD_SET_IND 0x43 91 + #define CCW_CMD_SET_CONF_IND 0x53 92 + #define CCW_CMD_READ_FEAT 0x12 93 + #define CCW_CMD_WRITE_FEAT 0x11 94 + #define CCW_CMD_READ_CONF 0x22 95 + #define CCW_CMD_WRITE_CONF 0x21 96 + #define CCW_CMD_WRITE_STATUS 0x31 97 + #define CCW_CMD_READ_VQ_CONF 0x32 98 + 99 + #define VIRTIO_CCW_DOING_SET_VQ 0x00010000 100 + #define VIRTIO_CCW_DOING_RESET 0x00040000 101 + #define VIRTIO_CCW_DOING_READ_FEAT 0x00080000 102 + #define VIRTIO_CCW_DOING_WRITE_FEAT 0x00100000 103 + #define VIRTIO_CCW_DOING_READ_CONFIG 0x00200000 104 + #define VIRTIO_CCW_DOING_WRITE_CONFIG 0x00400000 105 + #define VIRTIO_CCW_DOING_WRITE_STATUS 0x00800000 106 + #define VIRTIO_CCW_DOING_SET_IND 0x01000000 107 + #define VIRTIO_CCW_DOING_READ_VQ_CONF 0x02000000 108 + #define VIRTIO_CCW_DOING_SET_CONF_IND 0x04000000 109 + #define VIRTIO_CCW_INTPARM_MASK 0xffff0000 110 + 111 + static struct virtio_ccw_device *to_vc_device(struct virtio_device *vdev) 112 + { 113 + return container_of(vdev, struct virtio_ccw_device, vdev); 114 + } 115 + 116 + static int doing_io(struct virtio_ccw_device *vcdev, __u32 flag) 117 + { 118 + unsigned long flags; 119 + __u32 ret; 120 + 121 + spin_lock_irqsave(get_ccwdev_lock(vcdev->cdev), flags); 122 + if (vcdev->err) 123 + ret = 0; 124 + else 125 + ret = vcdev->curr_io & flag; 126 + spin_unlock_irqrestore(get_ccwdev_lock(vcdev->cdev), flags); 127 + return ret; 128 + } 129 + 130 + static int ccw_io_helper(struct virtio_ccw_device *vcdev, __u32 intparm) 131 + { 132 + int ret; 133 + unsigned long flags; 134 + int flag = intparm & VIRTIO_CCW_INTPARM_MASK; 135 + 136 + spin_lock_irqsave(get_ccwdev_lock(vcdev->cdev), flags); 137 + ret = ccw_device_start(vcdev->cdev, vcdev->ccw, intparm, 0, 0); 138 + if (!ret) 139 + vcdev->curr_io |= flag; 140 + spin_unlock_irqrestore(get_ccwdev_lock(vcdev->cdev), flags); 141 + wait_event(vcdev->wait_q, doing_io(vcdev, flag) == 0); 142 + return ret ? ret : vcdev->err; 143 + } 144 + 145 + static inline long do_kvm_notify(struct subchannel_id schid, 146 + unsigned long queue_index) 147 + { 148 + register unsigned long __nr asm("1") = KVM_S390_VIRTIO_CCW_NOTIFY; 149 + register struct subchannel_id __schid asm("2") = schid; 150 + register unsigned long __index asm("3") = queue_index; 151 + register long __rc asm("2"); 152 + 153 + asm volatile ("diag 2,4,0x500\n" 154 + : "=d" (__rc) : "d" (__nr), "d" (__schid), "d" (__index) 155 + : "memory", "cc"); 156 + return __rc; 157 + } 158 + 159 + static void virtio_ccw_kvm_notify(struct virtqueue *vq) 160 + { 161 + struct virtio_ccw_vq_info *info = vq->priv; 162 + struct virtio_ccw_device *vcdev; 163 + struct subchannel_id schid; 164 + 165 + vcdev = to_vc_device(info->vq->vdev); 166 + ccw_device_get_schid(vcdev->cdev, &schid); 167 + do_kvm_notify(schid, virtqueue_get_queue_index(vq)); 168 + } 169 + 170 + static int virtio_ccw_read_vq_conf(struct virtio_ccw_device *vcdev, int index) 171 + { 172 + vcdev->config_block->index = index; 173 + vcdev->ccw->cmd_code = CCW_CMD_READ_VQ_CONF; 174 + vcdev->ccw->flags = 0; 175 + vcdev->ccw->count = sizeof(struct vq_config_block); 176 + vcdev->ccw->cda = (__u32)(unsigned long)(vcdev->config_block); 177 + ccw_io_helper(vcdev, VIRTIO_CCW_DOING_READ_VQ_CONF); 178 + return vcdev->config_block->num; 179 + } 180 + 181 + static void virtio_ccw_del_vq(struct virtqueue *vq) 182 + { 183 + struct virtio_ccw_device *vcdev = to_vc_device(vq->vdev); 184 + struct virtio_ccw_vq_info *info = vq->priv; 185 + unsigned long flags; 186 + unsigned long size; 187 + int ret; 188 + unsigned int index = virtqueue_get_queue_index(vq); 189 + 190 + /* Remove from our list. */ 191 + spin_lock_irqsave(&vcdev->lock, flags); 192 + list_del(&info->node); 193 + spin_unlock_irqrestore(&vcdev->lock, flags); 194 + 195 + /* Release from host. */ 196 + info->info_block->queue = 0; 197 + info->info_block->align = 0; 198 + info->info_block->index = index; 199 + info->info_block->num = 0; 200 + vcdev->ccw->cmd_code = CCW_CMD_SET_VQ; 201 + vcdev->ccw->flags = 0; 202 + vcdev->ccw->count = sizeof(*info->info_block); 203 + vcdev->ccw->cda = (__u32)(unsigned long)(info->info_block); 204 + ret = ccw_io_helper(vcdev, VIRTIO_CCW_DOING_SET_VQ | index); 205 + /* 206 + * -ENODEV isn't considered an error: The device is gone anyway. 207 + * This may happen on device detach. 208 + */ 209 + if (ret && (ret != -ENODEV)) 210 + dev_warn(&vq->vdev->dev, "Error %d while deleting queue %d", 211 + ret, index); 212 + 213 + vring_del_virtqueue(vq); 214 + size = PAGE_ALIGN(vring_size(info->num, KVM_VIRTIO_CCW_RING_ALIGN)); 215 + free_pages_exact(info->queue, size); 216 + kfree(info->info_block); 217 + kfree(info); 218 + } 219 + 220 + static void virtio_ccw_del_vqs(struct virtio_device *vdev) 221 + { 222 + struct virtqueue *vq, *n; 223 + 224 + list_for_each_entry_safe(vq, n, &vdev->vqs, list) 225 + virtio_ccw_del_vq(vq); 226 + } 227 + 228 + static struct virtqueue *virtio_ccw_setup_vq(struct virtio_device *vdev, 229 + int i, vq_callback_t *callback, 230 + const char *name) 231 + { 232 + struct virtio_ccw_device *vcdev = to_vc_device(vdev); 233 + int err; 234 + struct virtqueue *vq; 235 + struct virtio_ccw_vq_info *info; 236 + unsigned long size; 237 + unsigned long flags; 238 + 239 + /* Allocate queue. */ 240 + info = kzalloc(sizeof(struct virtio_ccw_vq_info), GFP_KERNEL); 241 + if (!info) { 242 + dev_warn(&vcdev->cdev->dev, "no info\n"); 243 + err = -ENOMEM; 244 + goto out_err; 245 + } 246 + info->info_block = kzalloc(sizeof(*info->info_block), 247 + GFP_DMA | GFP_KERNEL); 248 + if (!info->info_block) { 249 + dev_warn(&vcdev->cdev->dev, "no info block\n"); 250 + err = -ENOMEM; 251 + goto out_err; 252 + } 253 + info->num = virtio_ccw_read_vq_conf(vcdev, i); 254 + size = PAGE_ALIGN(vring_size(info->num, KVM_VIRTIO_CCW_RING_ALIGN)); 255 + info->queue = alloc_pages_exact(size, GFP_KERNEL | __GFP_ZERO); 256 + if (info->queue == NULL) { 257 + dev_warn(&vcdev->cdev->dev, "no queue\n"); 258 + err = -ENOMEM; 259 + goto out_err; 260 + } 261 + 262 + vq = vring_new_virtqueue(i, info->num, KVM_VIRTIO_CCW_RING_ALIGN, vdev, 263 + true, info->queue, virtio_ccw_kvm_notify, 264 + callback, name); 265 + if (!vq) { 266 + /* For now, we fail if we can't get the requested size. */ 267 + dev_warn(&vcdev->cdev->dev, "no vq\n"); 268 + err = -ENOMEM; 269 + free_pages_exact(info->queue, size); 270 + goto out_err; 271 + } 272 + info->vq = vq; 273 + vq->priv = info; 274 + 275 + /* Register it with the host. */ 276 + info->info_block->queue = (__u64)info->queue; 277 + info->info_block->align = KVM_VIRTIO_CCW_RING_ALIGN; 278 + info->info_block->index = i; 279 + info->info_block->num = info->num; 280 + vcdev->ccw->cmd_code = CCW_CMD_SET_VQ; 281 + vcdev->ccw->flags = 0; 282 + vcdev->ccw->count = sizeof(*info->info_block); 283 + vcdev->ccw->cda = (__u32)(unsigned long)(info->info_block); 284 + err = ccw_io_helper(vcdev, VIRTIO_CCW_DOING_SET_VQ | i); 285 + if (err) { 286 + dev_warn(&vcdev->cdev->dev, "SET_VQ failed\n"); 287 + free_pages_exact(info->queue, size); 288 + info->vq = NULL; 289 + vq->priv = NULL; 290 + goto out_err; 291 + } 292 + 293 + /* Save it to our list. */ 294 + spin_lock_irqsave(&vcdev->lock, flags); 295 + list_add(&info->node, &vcdev->virtqueues); 296 + spin_unlock_irqrestore(&vcdev->lock, flags); 297 + 298 + return vq; 299 + 300 + out_err: 301 + if (info) 302 + kfree(info->info_block); 303 + kfree(info); 304 + return ERR_PTR(err); 305 + } 306 + 307 + static int virtio_ccw_find_vqs(struct virtio_device *vdev, unsigned nvqs, 308 + struct virtqueue *vqs[], 309 + vq_callback_t *callbacks[], 310 + const char *names[]) 311 + { 312 + struct virtio_ccw_device *vcdev = to_vc_device(vdev); 313 + unsigned long *indicatorp = NULL; 314 + int ret, i; 315 + 316 + for (i = 0; i < nvqs; ++i) { 317 + vqs[i] = virtio_ccw_setup_vq(vdev, i, callbacks[i], names[i]); 318 + if (IS_ERR(vqs[i])) { 319 + ret = PTR_ERR(vqs[i]); 320 + vqs[i] = NULL; 321 + goto out; 322 + } 323 + } 324 + ret = -ENOMEM; 325 + /* We need a data area under 2G to communicate. */ 326 + indicatorp = kmalloc(sizeof(&vcdev->indicators), GFP_DMA | GFP_KERNEL); 327 + if (!indicatorp) 328 + goto out; 329 + *indicatorp = (unsigned long) &vcdev->indicators; 330 + /* Register queue indicators with host. */ 331 + vcdev->indicators = 0; 332 + vcdev->ccw->cmd_code = CCW_CMD_SET_IND; 333 + vcdev->ccw->flags = 0; 334 + vcdev->ccw->count = sizeof(vcdev->indicators); 335 + vcdev->ccw->cda = (__u32)(unsigned long) indicatorp; 336 + ret = ccw_io_helper(vcdev, VIRTIO_CCW_DOING_SET_IND); 337 + if (ret) 338 + goto out; 339 + /* Register indicators2 with host for config changes */ 340 + *indicatorp = (unsigned long) &vcdev->indicators2; 341 + vcdev->indicators2 = 0; 342 + vcdev->ccw->cmd_code = CCW_CMD_SET_CONF_IND; 343 + vcdev->ccw->flags = 0; 344 + vcdev->ccw->count = sizeof(vcdev->indicators2); 345 + vcdev->ccw->cda = (__u32)(unsigned long) indicatorp; 346 + ret = ccw_io_helper(vcdev, VIRTIO_CCW_DOING_SET_CONF_IND); 347 + if (ret) 348 + goto out; 349 + 350 + kfree(indicatorp); 351 + return 0; 352 + out: 353 + kfree(indicatorp); 354 + virtio_ccw_del_vqs(vdev); 355 + return ret; 356 + } 357 + 358 + static void virtio_ccw_reset(struct virtio_device *vdev) 359 + { 360 + struct virtio_ccw_device *vcdev = to_vc_device(vdev); 361 + 362 + /* Zero status bits. */ 363 + vcdev->status = 0; 364 + 365 + /* Send a reset ccw on device. */ 366 + vcdev->ccw->cmd_code = CCW_CMD_VDEV_RESET; 367 + vcdev->ccw->flags = 0; 368 + vcdev->ccw->count = 0; 369 + vcdev->ccw->cda = 0; 370 + ccw_io_helper(vcdev, VIRTIO_CCW_DOING_RESET); 371 + } 372 + 373 + static u32 virtio_ccw_get_features(struct virtio_device *vdev) 374 + { 375 + struct virtio_ccw_device *vcdev = to_vc_device(vdev); 376 + struct virtio_feature_desc features; 377 + int ret; 378 + 379 + /* Read the feature bits from the host. */ 380 + /* TODO: Features > 32 bits */ 381 + features.index = 0; 382 + vcdev->ccw->cmd_code = CCW_CMD_READ_FEAT; 383 + vcdev->ccw->flags = 0; 384 + vcdev->ccw->count = sizeof(features); 385 + vcdev->ccw->cda = vcdev->area; 386 + ret = ccw_io_helper(vcdev, VIRTIO_CCW_DOING_READ_FEAT); 387 + if (ret) 388 + return 0; 389 + 390 + memcpy(&features, (void *)(unsigned long)vcdev->area, 391 + sizeof(features)); 392 + return le32_to_cpu(features.features); 393 + } 394 + 395 + static void virtio_ccw_finalize_features(struct virtio_device *vdev) 396 + { 397 + struct virtio_ccw_device *vcdev = to_vc_device(vdev); 398 + struct virtio_feature_desc features; 399 + int i; 400 + 401 + /* Give virtio_ring a chance to accept features. */ 402 + vring_transport_features(vdev); 403 + 404 + for (i = 0; i < sizeof(*vdev->features) / sizeof(features.features); 405 + i++) { 406 + int highbits = i % 2 ? 32 : 0; 407 + features.index = i; 408 + features.features = cpu_to_le32(vdev->features[i / 2] 409 + >> highbits); 410 + memcpy((void *)(unsigned long)vcdev->area, &features, 411 + sizeof(features)); 412 + /* Write the feature bits to the host. */ 413 + vcdev->ccw->cmd_code = CCW_CMD_WRITE_FEAT; 414 + vcdev->ccw->flags = 0; 415 + vcdev->ccw->count = sizeof(features); 416 + vcdev->ccw->cda = vcdev->area; 417 + ccw_io_helper(vcdev, VIRTIO_CCW_DOING_WRITE_FEAT); 418 + } 419 + } 420 + 421 + static void virtio_ccw_get_config(struct virtio_device *vdev, 422 + unsigned int offset, void *buf, unsigned len) 423 + { 424 + struct virtio_ccw_device *vcdev = to_vc_device(vdev); 425 + int ret; 426 + 427 + /* Read the config area from the host. */ 428 + vcdev->ccw->cmd_code = CCW_CMD_READ_CONF; 429 + vcdev->ccw->flags = 0; 430 + vcdev->ccw->count = offset + len; 431 + vcdev->ccw->cda = vcdev->area; 432 + ret = ccw_io_helper(vcdev, VIRTIO_CCW_DOING_READ_CONFIG); 433 + if (ret) 434 + return; 435 + 436 + memcpy(vcdev->config, (void *)(unsigned long)vcdev->area, 437 + sizeof(vcdev->config)); 438 + memcpy(buf, &vcdev->config[offset], len); 439 + } 440 + 441 + static void virtio_ccw_set_config(struct virtio_device *vdev, 442 + unsigned int offset, const void *buf, 443 + unsigned len) 444 + { 445 + struct virtio_ccw_device *vcdev = to_vc_device(vdev); 446 + 447 + memcpy(&vcdev->config[offset], buf, len); 448 + /* Write the config area to the host. */ 449 + memcpy((void *)(unsigned long)vcdev->area, vcdev->config, 450 + sizeof(vcdev->config)); 451 + vcdev->ccw->cmd_code = CCW_CMD_WRITE_CONF; 452 + vcdev->ccw->flags = 0; 453 + vcdev->ccw->count = offset + len; 454 + vcdev->ccw->cda = vcdev->area; 455 + ccw_io_helper(vcdev, VIRTIO_CCW_DOING_WRITE_CONFIG); 456 + } 457 + 458 + static u8 virtio_ccw_get_status(struct virtio_device *vdev) 459 + { 460 + struct virtio_ccw_device *vcdev = to_vc_device(vdev); 461 + 462 + return vcdev->status; 463 + } 464 + 465 + static void virtio_ccw_set_status(struct virtio_device *vdev, u8 status) 466 + { 467 + struct virtio_ccw_device *vcdev = to_vc_device(vdev); 468 + 469 + /* Write the status to the host. */ 470 + vcdev->status = status; 471 + memcpy((void *)(unsigned long)vcdev->area, &status, sizeof(status)); 472 + vcdev->ccw->cmd_code = CCW_CMD_WRITE_STATUS; 473 + vcdev->ccw->flags = 0; 474 + vcdev->ccw->count = sizeof(status); 475 + vcdev->ccw->cda = vcdev->area; 476 + ccw_io_helper(vcdev, VIRTIO_CCW_DOING_WRITE_STATUS); 477 + } 478 + 479 + static struct virtio_config_ops virtio_ccw_config_ops = { 480 + .get_features = virtio_ccw_get_features, 481 + .finalize_features = virtio_ccw_finalize_features, 482 + .get = virtio_ccw_get_config, 483 + .set = virtio_ccw_set_config, 484 + .get_status = virtio_ccw_get_status, 485 + .set_status = virtio_ccw_set_status, 486 + .reset = virtio_ccw_reset, 487 + .find_vqs = virtio_ccw_find_vqs, 488 + .del_vqs = virtio_ccw_del_vqs, 489 + }; 490 + 491 + 492 + /* 493 + * ccw bus driver related functions 494 + */ 495 + 496 + static void virtio_ccw_release_dev(struct device *_d) 497 + { 498 + struct virtio_device *dev = container_of(_d, struct virtio_device, 499 + dev); 500 + struct virtio_ccw_device *vcdev = to_vc_device(dev); 501 + 502 + kfree((void *)(unsigned long)vcdev->area); 503 + kfree(vcdev->config_block); 504 + kfree(vcdev->ccw); 505 + kfree(vcdev); 506 + } 507 + 508 + static int irb_is_error(struct irb *irb) 509 + { 510 + if (scsw_cstat(&irb->scsw) != 0) 511 + return 1; 512 + if (scsw_dstat(&irb->scsw) & ~(DEV_STAT_CHN_END | DEV_STAT_DEV_END)) 513 + return 1; 514 + if (scsw_cc(&irb->scsw) != 0) 515 + return 1; 516 + return 0; 517 + } 518 + 519 + static struct virtqueue *virtio_ccw_vq_by_ind(struct virtio_ccw_device *vcdev, 520 + int index) 521 + { 522 + struct virtio_ccw_vq_info *info; 523 + unsigned long flags; 524 + struct virtqueue *vq; 525 + 526 + vq = NULL; 527 + spin_lock_irqsave(&vcdev->lock, flags); 528 + list_for_each_entry(info, &vcdev->virtqueues, node) { 529 + if (virtqueue_get_queue_index(info->vq) == index) { 530 + vq = info->vq; 531 + break; 532 + } 533 + } 534 + spin_unlock_irqrestore(&vcdev->lock, flags); 535 + return vq; 536 + } 537 + 538 + static void virtio_ccw_int_handler(struct ccw_device *cdev, 539 + unsigned long intparm, 540 + struct irb *irb) 541 + { 542 + __u32 activity = intparm & VIRTIO_CCW_INTPARM_MASK; 543 + struct virtio_ccw_device *vcdev = dev_get_drvdata(&cdev->dev); 544 + int i; 545 + struct virtqueue *vq; 546 + struct virtio_driver *drv; 547 + 548 + /* Check if it's a notification from the host. */ 549 + if ((intparm == 0) && 550 + (scsw_stctl(&irb->scsw) == 551 + (SCSW_STCTL_ALERT_STATUS | SCSW_STCTL_STATUS_PEND))) { 552 + /* OK */ 553 + } 554 + if (irb_is_error(irb)) 555 + vcdev->err = -EIO; /* XXX - use real error */ 556 + if (vcdev->curr_io & activity) { 557 + switch (activity) { 558 + case VIRTIO_CCW_DOING_READ_FEAT: 559 + case VIRTIO_CCW_DOING_WRITE_FEAT: 560 + case VIRTIO_CCW_DOING_READ_CONFIG: 561 + case VIRTIO_CCW_DOING_WRITE_CONFIG: 562 + case VIRTIO_CCW_DOING_WRITE_STATUS: 563 + case VIRTIO_CCW_DOING_SET_VQ: 564 + case VIRTIO_CCW_DOING_SET_IND: 565 + case VIRTIO_CCW_DOING_SET_CONF_IND: 566 + case VIRTIO_CCW_DOING_RESET: 567 + case VIRTIO_CCW_DOING_READ_VQ_CONF: 568 + vcdev->curr_io &= ~activity; 569 + wake_up(&vcdev->wait_q); 570 + break; 571 + default: 572 + /* don't know what to do... */ 573 + dev_warn(&cdev->dev, "Suspicious activity '%08x'\n", 574 + activity); 575 + WARN_ON(1); 576 + break; 577 + } 578 + } 579 + for_each_set_bit(i, &vcdev->indicators, 580 + sizeof(vcdev->indicators) * BITS_PER_BYTE) { 581 + /* The bit clear must happen before the vring kick. */ 582 + clear_bit(i, &vcdev->indicators); 583 + barrier(); 584 + vq = virtio_ccw_vq_by_ind(vcdev, i); 585 + vring_interrupt(0, vq); 586 + } 587 + if (test_bit(0, &vcdev->indicators2)) { 588 + drv = container_of(vcdev->vdev.dev.driver, 589 + struct virtio_driver, driver); 590 + 591 + if (drv && drv->config_changed) 592 + drv->config_changed(&vcdev->vdev); 593 + clear_bit(0, &vcdev->indicators2); 594 + } 595 + } 596 + 597 + /* 598 + * We usually want to autoonline all devices, but give the admin 599 + * a way to exempt devices from this. 600 + */ 601 + #define __DEV_WORDS ((__MAX_SUBCHANNEL + (8*sizeof(long) - 1)) / \ 602 + (8*sizeof(long))) 603 + static unsigned long devs_no_auto[__MAX_SSID + 1][__DEV_WORDS]; 604 + 605 + static char *no_auto = ""; 606 + 607 + module_param(no_auto, charp, 0444); 608 + MODULE_PARM_DESC(no_auto, "list of ccw bus id ranges not to be auto-onlined"); 609 + 610 + static int virtio_ccw_check_autoonline(struct ccw_device *cdev) 611 + { 612 + struct ccw_dev_id id; 613 + 614 + ccw_device_get_id(cdev, &id); 615 + if (test_bit(id.devno, devs_no_auto[id.ssid])) 616 + return 0; 617 + return 1; 618 + } 619 + 620 + static void virtio_ccw_auto_online(void *data, async_cookie_t cookie) 621 + { 622 + struct ccw_device *cdev = data; 623 + int ret; 624 + 625 + ret = ccw_device_set_online(cdev); 626 + if (ret) 627 + dev_warn(&cdev->dev, "Failed to set online: %d\n", ret); 628 + } 629 + 630 + static int virtio_ccw_probe(struct ccw_device *cdev) 631 + { 632 + cdev->handler = virtio_ccw_int_handler; 633 + 634 + if (virtio_ccw_check_autoonline(cdev)) 635 + async_schedule(virtio_ccw_auto_online, cdev); 636 + return 0; 637 + } 638 + 639 + static void virtio_ccw_remove(struct ccw_device *cdev) 640 + { 641 + struct virtio_ccw_device *vcdev = dev_get_drvdata(&cdev->dev); 642 + 643 + if (cdev->online) { 644 + unregister_virtio_device(&vcdev->vdev); 645 + dev_set_drvdata(&cdev->dev, NULL); 646 + } 647 + cdev->handler = NULL; 648 + } 649 + 650 + static int virtio_ccw_offline(struct ccw_device *cdev) 651 + { 652 + struct virtio_ccw_device *vcdev = dev_get_drvdata(&cdev->dev); 653 + 654 + unregister_virtio_device(&vcdev->vdev); 655 + dev_set_drvdata(&cdev->dev, NULL); 656 + return 0; 657 + } 658 + 659 + 660 + /* Area needs to be big enough to fit status, features or configuration. */ 661 + #define VIRTIO_AREA_SIZE VIRTIO_CCW_CONFIG_SIZE /* biggest possible use */ 662 + 663 + static int virtio_ccw_online(struct ccw_device *cdev) 664 + { 665 + int ret; 666 + struct virtio_ccw_device *vcdev; 667 + 668 + vcdev = kzalloc(sizeof(*vcdev), GFP_KERNEL); 669 + if (!vcdev) { 670 + dev_warn(&cdev->dev, "Could not get memory for virtio\n"); 671 + ret = -ENOMEM; 672 + goto out_free; 673 + } 674 + vcdev->area = (__u32)(unsigned long)kzalloc(VIRTIO_AREA_SIZE, 675 + GFP_DMA | GFP_KERNEL); 676 + if (!vcdev->area) { 677 + dev_warn(&cdev->dev, "Cound not get memory for virtio\n"); 678 + ret = -ENOMEM; 679 + goto out_free; 680 + } 681 + vcdev->config_block = kzalloc(sizeof(*vcdev->config_block), 682 + GFP_DMA | GFP_KERNEL); 683 + if (!vcdev->config_block) { 684 + ret = -ENOMEM; 685 + goto out_free; 686 + } 687 + vcdev->ccw = kzalloc(sizeof(*vcdev->ccw), GFP_DMA | GFP_KERNEL); 688 + if (!vcdev->ccw) { 689 + ret = -ENOMEM; 690 + goto out_free; 691 + } 692 + 693 + vcdev->vdev.dev.parent = &cdev->dev; 694 + vcdev->vdev.dev.release = virtio_ccw_release_dev; 695 + vcdev->vdev.config = &virtio_ccw_config_ops; 696 + vcdev->cdev = cdev; 697 + init_waitqueue_head(&vcdev->wait_q); 698 + INIT_LIST_HEAD(&vcdev->virtqueues); 699 + spin_lock_init(&vcdev->lock); 700 + 701 + dev_set_drvdata(&cdev->dev, vcdev); 702 + vcdev->vdev.id.vendor = cdev->id.cu_type; 703 + vcdev->vdev.id.device = cdev->id.cu_model; 704 + ret = register_virtio_device(&vcdev->vdev); 705 + if (ret) { 706 + dev_warn(&cdev->dev, "Failed to register virtio device: %d\n", 707 + ret); 708 + goto out_put; 709 + } 710 + return 0; 711 + out_put: 712 + dev_set_drvdata(&cdev->dev, NULL); 713 + put_device(&vcdev->vdev.dev); 714 + return ret; 715 + out_free: 716 + if (vcdev) { 717 + kfree((void *)(unsigned long)vcdev->area); 718 + kfree(vcdev->config_block); 719 + kfree(vcdev->ccw); 720 + } 721 + kfree(vcdev); 722 + return ret; 723 + } 724 + 725 + static int virtio_ccw_cio_notify(struct ccw_device *cdev, int event) 726 + { 727 + /* TODO: Check whether we need special handling here. */ 728 + return 0; 729 + } 730 + 731 + static struct ccw_device_id virtio_ids[] = { 732 + { CCW_DEVICE(0x3832, 0) }, 733 + {}, 734 + }; 735 + MODULE_DEVICE_TABLE(ccw, virtio_ids); 736 + 737 + static struct ccw_driver virtio_ccw_driver = { 738 + .driver = { 739 + .owner = THIS_MODULE, 740 + .name = "virtio_ccw", 741 + }, 742 + .ids = virtio_ids, 743 + .probe = virtio_ccw_probe, 744 + .remove = virtio_ccw_remove, 745 + .set_offline = virtio_ccw_offline, 746 + .set_online = virtio_ccw_online, 747 + .notify = virtio_ccw_cio_notify, 748 + .int_class = IOINT_VIR, 749 + }; 750 + 751 + static int __init pure_hex(char **cp, unsigned int *val, int min_digit, 752 + int max_digit, int max_val) 753 + { 754 + int diff; 755 + 756 + diff = 0; 757 + *val = 0; 758 + 759 + while (diff <= max_digit) { 760 + int value = hex_to_bin(**cp); 761 + 762 + if (value < 0) 763 + break; 764 + *val = *val * 16 + value; 765 + (*cp)++; 766 + diff++; 767 + } 768 + 769 + if ((diff < min_digit) || (diff > max_digit) || (*val > max_val)) 770 + return 1; 771 + 772 + return 0; 773 + } 774 + 775 + static int __init parse_busid(char *str, unsigned int *cssid, 776 + unsigned int *ssid, unsigned int *devno) 777 + { 778 + char *str_work; 779 + int rc, ret; 780 + 781 + rc = 1; 782 + 783 + if (*str == '\0') 784 + goto out; 785 + 786 + str_work = str; 787 + ret = pure_hex(&str_work, cssid, 1, 2, __MAX_CSSID); 788 + if (ret || (str_work[0] != '.')) 789 + goto out; 790 + str_work++; 791 + ret = pure_hex(&str_work, ssid, 1, 1, __MAX_SSID); 792 + if (ret || (str_work[0] != '.')) 793 + goto out; 794 + str_work++; 795 + ret = pure_hex(&str_work, devno, 4, 4, __MAX_SUBCHANNEL); 796 + if (ret || (str_work[0] != '\0')) 797 + goto out; 798 + 799 + rc = 0; 800 + out: 801 + return rc; 802 + } 803 + 804 + static void __init no_auto_parse(void) 805 + { 806 + unsigned int from_cssid, to_cssid, from_ssid, to_ssid, from, to; 807 + char *parm, *str; 808 + int rc; 809 + 810 + str = no_auto; 811 + while ((parm = strsep(&str, ","))) { 812 + rc = parse_busid(strsep(&parm, "-"), &from_cssid, 813 + &from_ssid, &from); 814 + if (rc) 815 + continue; 816 + if (parm != NULL) { 817 + rc = parse_busid(parm, &to_cssid, 818 + &to_ssid, &to); 819 + if ((from_ssid > to_ssid) || 820 + ((from_ssid == to_ssid) && (from > to))) 821 + rc = -EINVAL; 822 + } else { 823 + to_cssid = from_cssid; 824 + to_ssid = from_ssid; 825 + to = from; 826 + } 827 + if (rc) 828 + continue; 829 + while ((from_ssid < to_ssid) || 830 + ((from_ssid == to_ssid) && (from <= to))) { 831 + set_bit(from, devs_no_auto[from_ssid]); 832 + from++; 833 + if (from > __MAX_SUBCHANNEL) { 834 + from_ssid++; 835 + from = 0; 836 + } 837 + } 838 + } 839 + } 840 + 841 + static int __init virtio_ccw_init(void) 842 + { 843 + /* parse no_auto string before we do anything further */ 844 + no_auto_parse(); 845 + return ccw_driver_register(&virtio_ccw_driver); 846 + } 847 + module_init(virtio_ccw_init); 848 + 849 + static void __exit virtio_ccw_exit(void) 850 + { 851 + ccw_driver_unregister(&virtio_ccw_driver); 852 + } 853 + module_exit(virtio_ccw_exit);