linux/drivers/s390/cio/vfio_ccw_drv.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * VFIO based Physical Subchannel device driver
   4 *
   5 * Copyright IBM Corp. 2017
   6 * Copyright Red Hat, Inc. 2019
   7 *
   8 * Author(s): Dong Jia Shi <bjsdjshi@linux.vnet.ibm.com>
   9 *            Xiao Feng Ren <renxiaof@linux.vnet.ibm.com>
  10 *            Cornelia Huck <cohuck@redhat.com>
  11 */
  12
  13#include <linux/module.h>
  14#include <linux/init.h>
  15#include <linux/device.h>
  16#include <linux/slab.h>
  17#include <linux/uuid.h>
  18#include <linux/mdev.h>
  19
  20#include <asm/isc.h>
  21
  22#include "ioasm.h"
  23#include "css.h"
  24#include "vfio_ccw_private.h"
  25
  26struct workqueue_struct *vfio_ccw_work_q;
  27static struct kmem_cache *vfio_ccw_io_region;
  28static struct kmem_cache *vfio_ccw_cmd_region;
  29
  30debug_info_t *vfio_ccw_debug_msg_id;
  31debug_info_t *vfio_ccw_debug_trace_id;
  32
  33/*
  34 * Helpers
  35 */
  36int vfio_ccw_sch_quiesce(struct subchannel *sch)
  37{
  38        struct vfio_ccw_private *private = dev_get_drvdata(&sch->dev);
  39        DECLARE_COMPLETION_ONSTACK(completion);
  40        int iretry, ret = 0;
  41
  42        spin_lock_irq(sch->lock);
  43        if (!sch->schib.pmcw.ena)
  44                goto out_unlock;
  45        ret = cio_disable_subchannel(sch);
  46        if (ret != -EBUSY)
  47                goto out_unlock;
  48
  49        iretry = 255;
  50        do {
  51
  52                ret = cio_cancel_halt_clear(sch, &iretry);
  53
  54                if (ret == -EIO) {
  55                        pr_err("vfio_ccw: could not quiesce subchannel 0.%x.%04x!\n",
  56                               sch->schid.ssid, sch->schid.sch_no);
  57                        break;
  58                }
  59
  60                /*
  61                 * Flush all I/O and wait for
  62                 * cancel/halt/clear completion.
  63                 */
  64                private->completion = &completion;
  65                spin_unlock_irq(sch->lock);
  66
  67                if (ret == -EBUSY)
  68                        wait_for_completion_timeout(&completion, 3*HZ);
  69
  70                private->completion = NULL;
  71                flush_workqueue(vfio_ccw_work_q);
  72                spin_lock_irq(sch->lock);
  73                ret = cio_disable_subchannel(sch);
  74        } while (ret == -EBUSY);
  75out_unlock:
  76        private->state = VFIO_CCW_STATE_NOT_OPER;
  77        spin_unlock_irq(sch->lock);
  78        return ret;
  79}
  80
  81static void vfio_ccw_sch_io_todo(struct work_struct *work)
  82{
  83        struct vfio_ccw_private *private;
  84        struct irb *irb;
  85        bool is_final;
  86
  87        private = container_of(work, struct vfio_ccw_private, io_work);
  88        irb = &private->irb;
  89
  90        is_final = !(scsw_actl(&irb->scsw) &
  91                     (SCSW_ACTL_DEVACT | SCSW_ACTL_SCHACT));
  92        if (scsw_is_solicited(&irb->scsw)) {
  93                cp_update_scsw(&private->cp, &irb->scsw);
  94                if (is_final && private->state == VFIO_CCW_STATE_CP_PENDING)
  95                        cp_free(&private->cp);
  96        }
  97        mutex_lock(&private->io_mutex);
  98        memcpy(private->io_region->irb_area, irb, sizeof(*irb));
  99        mutex_unlock(&private->io_mutex);
 100
 101        if (private->mdev && is_final)
 102                private->state = VFIO_CCW_STATE_IDLE;
 103
 104        if (private->io_trigger)
 105                eventfd_signal(private->io_trigger, 1);
 106}
 107
 108/*
 109 * Css driver callbacks
 110 */
 111static void vfio_ccw_sch_irq(struct subchannel *sch)
 112{
 113        struct vfio_ccw_private *private = dev_get_drvdata(&sch->dev);
 114
 115        inc_irq_stat(IRQIO_CIO);
 116        vfio_ccw_fsm_event(private, VFIO_CCW_EVENT_INTERRUPT);
 117}
 118
 119static int vfio_ccw_sch_probe(struct subchannel *sch)
 120{
 121        struct pmcw *pmcw = &sch->schib.pmcw;
 122        struct vfio_ccw_private *private;
 123        int ret = -ENOMEM;
 124
 125        if (pmcw->qf) {
 126                dev_warn(&sch->dev, "vfio: ccw: does not support QDIO: %s\n",
 127                         dev_name(&sch->dev));
 128                return -ENODEV;
 129        }
 130
 131        private = kzalloc(sizeof(*private), GFP_KERNEL | GFP_DMA);
 132        if (!private)
 133                return -ENOMEM;
 134
 135        private->cp.guest_cp = kcalloc(CCWCHAIN_LEN_MAX, sizeof(struct ccw1),
 136                                       GFP_KERNEL);
 137        if (!private->cp.guest_cp)
 138                goto out_free;
 139
 140        private->io_region = kmem_cache_zalloc(vfio_ccw_io_region,
 141                                               GFP_KERNEL | GFP_DMA);
 142        if (!private->io_region)
 143                goto out_free;
 144
 145        private->cmd_region = kmem_cache_zalloc(vfio_ccw_cmd_region,
 146                                                GFP_KERNEL | GFP_DMA);
 147        if (!private->cmd_region)
 148                goto out_free;
 149
 150        private->sch = sch;
 151        dev_set_drvdata(&sch->dev, private);
 152        mutex_init(&private->io_mutex);
 153
 154        spin_lock_irq(sch->lock);
 155        private->state = VFIO_CCW_STATE_NOT_OPER;
 156        sch->isc = VFIO_CCW_ISC;
 157        ret = cio_enable_subchannel(sch, (u32)(unsigned long)sch);
 158        spin_unlock_irq(sch->lock);
 159        if (ret)
 160                goto out_free;
 161
 162        INIT_WORK(&private->io_work, vfio_ccw_sch_io_todo);
 163        atomic_set(&private->avail, 1);
 164        private->state = VFIO_CCW_STATE_STANDBY;
 165
 166        ret = vfio_ccw_mdev_reg(sch);
 167        if (ret)
 168                goto out_disable;
 169
 170        VFIO_CCW_MSG_EVENT(4, "bound to subchannel %x.%x.%04x\n",
 171                           sch->schid.cssid, sch->schid.ssid,
 172                           sch->schid.sch_no);
 173        return 0;
 174
 175out_disable:
 176        cio_disable_subchannel(sch);
 177out_free:
 178        dev_set_drvdata(&sch->dev, NULL);
 179        if (private->cmd_region)
 180                kmem_cache_free(vfio_ccw_cmd_region, private->cmd_region);
 181        if (private->io_region)
 182                kmem_cache_free(vfio_ccw_io_region, private->io_region);
 183        kfree(private->cp.guest_cp);
 184        kfree(private);
 185        return ret;
 186}
 187
 188static int vfio_ccw_sch_remove(struct subchannel *sch)
 189{
 190        struct vfio_ccw_private *private = dev_get_drvdata(&sch->dev);
 191
 192        vfio_ccw_sch_quiesce(sch);
 193
 194        vfio_ccw_mdev_unreg(sch);
 195
 196        dev_set_drvdata(&sch->dev, NULL);
 197
 198        kmem_cache_free(vfio_ccw_cmd_region, private->cmd_region);
 199        kmem_cache_free(vfio_ccw_io_region, private->io_region);
 200        kfree(private->cp.guest_cp);
 201        kfree(private);
 202
 203        VFIO_CCW_MSG_EVENT(4, "unbound from subchannel %x.%x.%04x\n",
 204                           sch->schid.cssid, sch->schid.ssid,
 205                           sch->schid.sch_no);
 206        return 0;
 207}
 208
 209static void vfio_ccw_sch_shutdown(struct subchannel *sch)
 210{
 211        vfio_ccw_sch_quiesce(sch);
 212}
 213
 214/**
 215 * vfio_ccw_sch_event - process subchannel event
 216 * @sch: subchannel
 217 * @process: non-zero if function is called in process context
 218 *
 219 * An unspecified event occurred for this subchannel. Adjust data according
 220 * to the current operational state of the subchannel. Return zero when the
 221 * event has been handled sufficiently or -EAGAIN when this function should
 222 * be called again in process context.
 223 */
 224static int vfio_ccw_sch_event(struct subchannel *sch, int process)
 225{
 226        struct vfio_ccw_private *private = dev_get_drvdata(&sch->dev);
 227        unsigned long flags;
 228        int rc = -EAGAIN;
 229
 230        spin_lock_irqsave(sch->lock, flags);
 231        if (!device_is_registered(&sch->dev))
 232                goto out_unlock;
 233
 234        if (work_pending(&sch->todo_work))
 235                goto out_unlock;
 236
 237        if (cio_update_schib(sch)) {
 238                vfio_ccw_fsm_event(private, VFIO_CCW_EVENT_NOT_OPER);
 239                rc = 0;
 240                goto out_unlock;
 241        }
 242
 243        private = dev_get_drvdata(&sch->dev);
 244        if (private->state == VFIO_CCW_STATE_NOT_OPER) {
 245                private->state = private->mdev ? VFIO_CCW_STATE_IDLE :
 246                                 VFIO_CCW_STATE_STANDBY;
 247        }
 248        rc = 0;
 249
 250out_unlock:
 251        spin_unlock_irqrestore(sch->lock, flags);
 252
 253        return rc;
 254}
 255
 256static struct css_device_id vfio_ccw_sch_ids[] = {
 257        { .match_flags = 0x1, .type = SUBCHANNEL_TYPE_IO, },
 258        { /* end of list */ },
 259};
 260MODULE_DEVICE_TABLE(css, vfio_ccw_sch_ids);
 261
 262static struct css_driver vfio_ccw_sch_driver = {
 263        .drv = {
 264                .name = "vfio_ccw",
 265                .owner = THIS_MODULE,
 266        },
 267        .subchannel_type = vfio_ccw_sch_ids,
 268        .irq = vfio_ccw_sch_irq,
 269        .probe = vfio_ccw_sch_probe,
 270        .remove = vfio_ccw_sch_remove,
 271        .shutdown = vfio_ccw_sch_shutdown,
 272        .sch_event = vfio_ccw_sch_event,
 273};
 274
 275static int __init vfio_ccw_debug_init(void)
 276{
 277        vfio_ccw_debug_msg_id = debug_register("vfio_ccw_msg", 16, 1,
 278                                               11 * sizeof(long));
 279        if (!vfio_ccw_debug_msg_id)
 280                goto out_unregister;
 281        debug_register_view(vfio_ccw_debug_msg_id, &debug_sprintf_view);
 282        debug_set_level(vfio_ccw_debug_msg_id, 2);
 283        vfio_ccw_debug_trace_id = debug_register("vfio_ccw_trace", 16, 1, 16);
 284        if (!vfio_ccw_debug_trace_id)
 285                goto out_unregister;
 286        debug_register_view(vfio_ccw_debug_trace_id, &debug_hex_ascii_view);
 287        debug_set_level(vfio_ccw_debug_trace_id, 2);
 288        return 0;
 289
 290out_unregister:
 291        debug_unregister(vfio_ccw_debug_msg_id);
 292        debug_unregister(vfio_ccw_debug_trace_id);
 293        return -1;
 294}
 295
 296static void vfio_ccw_debug_exit(void)
 297{
 298        debug_unregister(vfio_ccw_debug_msg_id);
 299        debug_unregister(vfio_ccw_debug_trace_id);
 300}
 301
 302static int __init vfio_ccw_sch_init(void)
 303{
 304        int ret;
 305
 306        ret = vfio_ccw_debug_init();
 307        if (ret)
 308                return ret;
 309
 310        vfio_ccw_work_q = create_singlethread_workqueue("vfio-ccw");
 311        if (!vfio_ccw_work_q) {
 312                ret = -ENOMEM;
 313                goto out_err;
 314        }
 315
 316        vfio_ccw_io_region = kmem_cache_create_usercopy("vfio_ccw_io_region",
 317                                        sizeof(struct ccw_io_region), 0,
 318                                        SLAB_ACCOUNT, 0,
 319                                        sizeof(struct ccw_io_region), NULL);
 320        if (!vfio_ccw_io_region) {
 321                ret = -ENOMEM;
 322                goto out_err;
 323        }
 324
 325        vfio_ccw_cmd_region = kmem_cache_create_usercopy("vfio_ccw_cmd_region",
 326                                        sizeof(struct ccw_cmd_region), 0,
 327                                        SLAB_ACCOUNT, 0,
 328                                        sizeof(struct ccw_cmd_region), NULL);
 329        if (!vfio_ccw_cmd_region) {
 330                ret = -ENOMEM;
 331                goto out_err;
 332        }
 333
 334        isc_register(VFIO_CCW_ISC);
 335        ret = css_driver_register(&vfio_ccw_sch_driver);
 336        if (ret) {
 337                isc_unregister(VFIO_CCW_ISC);
 338                goto out_err;
 339        }
 340
 341        return ret;
 342
 343out_err:
 344        kmem_cache_destroy(vfio_ccw_cmd_region);
 345        kmem_cache_destroy(vfio_ccw_io_region);
 346        destroy_workqueue(vfio_ccw_work_q);
 347        vfio_ccw_debug_exit();
 348        return ret;
 349}
 350
 351static void __exit vfio_ccw_sch_exit(void)
 352{
 353        css_driver_unregister(&vfio_ccw_sch_driver);
 354        isc_unregister(VFIO_CCW_ISC);
 355        kmem_cache_destroy(vfio_ccw_io_region);
 356        kmem_cache_destroy(vfio_ccw_cmd_region);
 357        destroy_workqueue(vfio_ccw_work_q);
 358        vfio_ccw_debug_exit();
 359}
 360module_init(vfio_ccw_sch_init);
 361module_exit(vfio_ccw_sch_exit);
 362
 363MODULE_LICENSE("GPL v2");
 364