get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

GET /api/patches/813448/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 813448,
    "url": "http://patchwork.ozlabs.org/api/patches/813448/?format=api",
    "web_url": "http://patchwork.ozlabs.org/project/qemu-devel/patch/20170913132752.8484-3-pasic@linux.vnet.ibm.com/",
    "project": {
        "id": 14,
        "url": "http://patchwork.ozlabs.org/api/projects/14/?format=api",
        "name": "QEMU Development",
        "link_name": "qemu-devel",
        "list_id": "qemu-devel.nongnu.org",
        "list_email": "qemu-devel@nongnu.org",
        "web_url": "",
        "scm_url": "",
        "webscm_url": "",
        "list_archive_url": "",
        "list_archive_url_format": "",
        "commit_url_format": ""
    },
    "msgid": "<20170913132752.8484-3-pasic@linux.vnet.ibm.com>",
    "list_archive_url": null,
    "date": "2017-09-13T13:27:52",
    "name": "[2/2,NOT,QEMU] a tester device for ccw I/O",
    "commit_ref": null,
    "pull_url": null,
    "state": "new",
    "archived": false,
    "hash": "bd8f8c185543e14abdf36b723aa1d68f3531be42",
    "submitter": {
        "id": 68297,
        "url": "http://patchwork.ozlabs.org/api/people/68297/?format=api",
        "name": "Halil Pasic",
        "email": "pasic@linux.vnet.ibm.com"
    },
    "delegate": null,
    "mbox": "http://patchwork.ozlabs.org/project/qemu-devel/patch/20170913132752.8484-3-pasic@linux.vnet.ibm.com/mbox/",
    "series": [
        {
            "id": 2918,
            "url": "http://patchwork.ozlabs.org/api/series/2918/?format=api",
            "web_url": "http://patchwork.ozlabs.org/project/qemu-devel/list/?series=2918",
            "date": "2017-09-13T13:27:52",
            "name": "tests for CCW IDA",
            "version": 1,
            "mbox": "http://patchwork.ozlabs.org/series/2918/mbox/"
        }
    ],
    "comments": "http://patchwork.ozlabs.org/api/patches/813448/comments/",
    "check": "pending",
    "checks": "http://patchwork.ozlabs.org/api/patches/813448/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org>",
        "X-Original-To": "incoming@patchwork.ozlabs.org",
        "Delivered-To": "patchwork-incoming@bilbo.ozlabs.org",
        "Authentication-Results": "ozlabs.org;\n\tspf=pass (mailfrom) smtp.mailfrom=nongnu.org\n\t(client-ip=2001:4830:134:3::11; helo=lists.gnu.org;\n\tenvelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org;\n\treceiver=<UNKNOWN>)",
        "Received": [
            "from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11])\n\t(using TLSv1 with cipher AES256-SHA (256/256 bits))\n\t(No client certificate requested)\n\tby ozlabs.org (Postfix) with ESMTPS id 3xsjQT6hkBz9s4s\n\tfor <incoming@patchwork.ozlabs.org>;\n\tWed, 13 Sep 2017 23:37:37 +1000 (AEST)",
            "from localhost ([::1]:42577 helo=lists.gnu.org)\n\tby lists.gnu.org with esmtp (Exim 4.71) (envelope-from\n\t<qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org>)\n\tid 1ds7rE-0000rq-2h\n\tfor incoming@patchwork.ozlabs.org; Wed, 13 Sep 2017 09:37:36 -0400",
            "from eggs.gnu.org ([2001:4830:134:3::10]:40461)\n\tby lists.gnu.org with esmtp (Exim 4.71)\n\t(envelope-from <pasic@linux.vnet.ibm.com>) id 1ds7iD-0008W3-3U\n\tfor qemu-devel@nongnu.org; Wed, 13 Sep 2017 09:28:19 -0400",
            "from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71)\n\t(envelope-from <pasic@linux.vnet.ibm.com>) id 1ds7i9-0006MC-Rz\n\tfor qemu-devel@nongnu.org; Wed, 13 Sep 2017 09:28:17 -0400",
            "from mx0b-001b2d01.pphosted.com ([148.163.158.5]:45222\n\thelo=mx0a-001b2d01.pphosted.com)\n\tby eggs.gnu.org with esmtps (TLS1.0:RSA_AES_256_CBC_SHA1:32)\n\t(Exim 4.71) (envelope-from <pasic@linux.vnet.ibm.com>)\n\tid 1ds7i9-0006Ls-Le\n\tfor qemu-devel@nongnu.org; Wed, 13 Sep 2017 09:28:13 -0400",
            "from pps.filterd (m0098417.ppops.net [127.0.0.1])\n\tby mx0a-001b2d01.pphosted.com (8.16.0.21/8.16.0.21) with SMTP id\n\tv8DDO5Bj097576\n\tfor <qemu-devel@nongnu.org>; Wed, 13 Sep 2017 09:28:13 -0400",
            "from e06smtp15.uk.ibm.com (e06smtp15.uk.ibm.com [195.75.94.111])\n\tby mx0a-001b2d01.pphosted.com with ESMTP id 2cy3ddqbtr-1\n\t(version=TLSv1.2 cipher=AES256-SHA bits=256 verify=NOT)\n\tfor <qemu-devel@nongnu.org>; Wed, 13 Sep 2017 09:28:12 -0400",
            "from localhost\n\tby e06smtp15.uk.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use\n\tOnly! Violators will be prosecuted\n\tfor <qemu-devel@nongnu.org> from <pasic@linux.vnet.ibm.com>;\n\tWed, 13 Sep 2017 14:28:10 +0100",
            "from b06cxnps4074.portsmouth.uk.ibm.com (9.149.109.196)\n\tby e06smtp15.uk.ibm.com (192.168.101.145) with IBM ESMTP SMTP\n\tGateway: Authorized Use Only! Violators will be prosecuted; \n\tWed, 13 Sep 2017 14:28:09 +0100",
            "from d06av23.portsmouth.uk.ibm.com (d06av23.portsmouth.uk.ibm.com\n\t[9.149.105.59])\n\tby b06cxnps4074.portsmouth.uk.ibm.com (8.14.9/8.14.9/NCO v10.0) with\n\tESMTP id v8DDS8Af26476786; Wed, 13 Sep 2017 13:28:08 GMT",
            "from d06av23.portsmouth.uk.ibm.com (unknown [127.0.0.1])\n\tby IMSVA (Postfix) with ESMTP id 9596BA4040;\n\tWed, 13 Sep 2017 14:24:18 +0100 (BST)",
            "from d06av23.portsmouth.uk.ibm.com (unknown [127.0.0.1])\n\tby IMSVA (Postfix) with ESMTP id 5C80DA4051;\n\tWed, 13 Sep 2017 14:24:18 +0100 (BST)",
            "from tuxmaker.boeblingen.de.ibm.com (unknown [9.152.85.9])\n\tby d06av23.portsmouth.uk.ibm.com (Postfix) with ESMTPS;\n\tWed, 13 Sep 2017 14:24:18 +0100 (BST)"
        ],
        "From": "Halil Pasic <pasic@linux.vnet.ibm.com>",
        "To": "Cornelia Huck <cohuck@redhat.com>",
        "Date": "Wed, 13 Sep 2017 15:27:52 +0200",
        "X-Mailer": "git-send-email 2.13.5",
        "In-Reply-To": "<20170913132752.8484-1-pasic@linux.vnet.ibm.com>",
        "References": "<20170913132752.8484-1-pasic@linux.vnet.ibm.com>",
        "X-TM-AS-GCONF": "00",
        "x-cbid": "17091313-0020-0000-0000-000003B7A9D0",
        "X-IBM-AV-DETECTION": "SAVI=unused REMOTE=unused XFE=unused",
        "x-cbparentid": "17091313-0021-0000-0000-000042491B3E",
        "Message-Id": "<20170913132752.8484-3-pasic@linux.vnet.ibm.com>",
        "X-Proofpoint-Virus-Version": "vendor=fsecure engine=2.50.10432:, ,\n\tdefinitions=2017-09-13_04:, , signatures=0",
        "X-Proofpoint-Spam-Details": "rule=outbound_notspam policy=outbound score=0\n\tspamscore=0 suspectscore=2\n\tmalwarescore=0 phishscore=0 adultscore=0 bulkscore=0 classifier=spam\n\tadjust=0 reason=mlx scancount=1 engine=8.0.1-1707230000\n\tdefinitions=main-1709130210",
        "X-detected-operating-system": "by eggs.gnu.org: GNU/Linux 3.x [generic] [fuzzy]",
        "X-Received-From": "148.163.158.5",
        "Subject": "[Qemu-devel] [PATCH 2/2 NOT QEMU] a tester device for ccw I/O",
        "X-BeenThere": "qemu-devel@nongnu.org",
        "X-Mailman-Version": "2.1.21",
        "Precedence": "list",
        "List-Id": "<qemu-devel.nongnu.org>",
        "List-Unsubscribe": "<https://lists.nongnu.org/mailman/options/qemu-devel>,\n\t<mailto:qemu-devel-request@nongnu.org?subject=unsubscribe>",
        "List-Archive": "<http://lists.nongnu.org/archive/html/qemu-devel/>",
        "List-Post": "<mailto:qemu-devel@nongnu.org>",
        "List-Help": "<mailto:qemu-devel-request@nongnu.org?subject=help>",
        "List-Subscribe": "<https://lists.nongnu.org/mailman/listinfo/qemu-devel>,\n\t<mailto:qemu-devel-request@nongnu.org?subject=subscribe>",
        "Cc": "Dong Jia Shi <bjsdjshi@linux.vnet.ibm.com>,\n\tHalil Pasic <pasic@linux.vnet.ibm.com>,\n\tPierre Morel <pmorel@linux.vnet.ibm.com>, qemu-devel@nongnu.org",
        "Errors-To": "qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org",
        "Sender": "\"Qemu-devel\"\n\t<qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org>"
    },
    "content": "Let's introduce a device driver for doing ccw I/O tests. The initial\nfocus is on indirect data access.\n\nThe driver is impemented as an out-of-tree Linux kernel module. A module\nparameter cu_type is used for matching ccw devices. The parameter\ndefaults to 0x3831 which is the default cu_type for the qemu\ncounterpart of this (a fully emulated ccw device just for test).\n\nThe current status of the module is means to an end where the end\nis testing my IDA implementation.\n\nUsage:\n\nYou load the module.  The driver is supposed to auto detect and auto\nonline the device and provide sysfs atributes for the tests available.\nTests are triggered by writing to the attributes. Reoprting is done via\nprintk in almost TAP format (could use improvement if more ambitious).\nWe run one test at a time and do that async to the write. If you try to\nstart more in parallel you will get -EBUSY.\n\nCurrently all you can do something like:\n* echo 1 > /sys/bus/ccw/devices/<devno>/w_fib\n  To test good old ccw.\n* echo 1 > /sys/bus/ccw/devices/<devno>/w_fib_idal\n  To test IDA ccw.\n\nThese tests are designed to wrok together with the qemu device mentioned\nbefore. The basic idea is that a device is expecting a stream of words\nsuch that the sequence words interpreted as uint32_t is a Fibonacci\nsequence (that is for n > 2 a_{n} = a_{n-1} + a{n-2}).\n\nUsing his simple scheme one can check that the right bytes are\ntransferred (with reasonable confidence). If the device detects an\nelement violating the Fibonacci property the driver expects the device\nposts a device exception indicating that element.\n\nSigned-off-by: Halil Pasic <pasic@linux.vnet.ibm.com>\n---\n\nDo not try to apply this to a QEMU tree. Use an empty repo.\n\n---\n .gitignore   |   8 ++\n Makefile     |  10 ++\n ccw_tester.c | 420 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n 3 files changed, 438 insertions(+)\n create mode 100644 .gitignore\n create mode 100644 Makefile\n create mode 100644 ccw_tester.c",
    "diff": "diff --git a/.gitignore b/.gitignore\nnew file mode 100644\nindex 0000000..1b9eac9\n--- /dev/null\n+++ b/.gitignore\n@@ -0,0 +1,8 @@\n+#ignore these\n+*.o\n+*.cmd\n+*.ko\n+*.mod.c\n+Module.symvers\n+modules.order\n+.tmp_versions/\ndiff --git a/Makefile b/Makefile\nnew file mode 100644\nindex 0000000..0583456\n--- /dev/null\n+++ b/Makefile\n@@ -0,0 +1,10 @@\n+ifneq ($(KERNELRELEASE),)\n+obj-m  := ccw_tester.o\n+else\n+# normal makefile\n+KDIR ?= /lib/modules/`uname -r`/build\n+\n+default:\n+\t$(MAKE) -C $(KDIR) M=$$PWD\n+\n+endif\ndiff --git a/ccw_tester.c b/ccw_tester.c\nnew file mode 100644\nindex 0000000..320486a\n--- /dev/null\n+++ b/ccw_tester.c\n@@ -0,0 +1,420 @@\n+#include <linux/kernel_stat.h>\n+#include <linux/init.h>\n+#include <linux/bootmem.h>\n+#include <linux/err.h>\n+#include <linux/slab.h>\n+#include <linux/interrupt.h>\n+#include <linux/pfn.h>\n+#include <linux/async.h>\n+#include <linux/wait.h>\n+#include <linux/list.h>\n+#include <linux/bitops.h>\n+#include <linux/module.h>\n+#include <linux/moduleparam.h>\n+#include <linux/io.h>\n+#include <linux/kvm_para.h>\n+#include <linux/notifier.h>\n+#include <asm/diag.h>\n+#include <asm/setup.h>\n+#include <asm/irq.h>\n+#include <asm/cio.h>\n+#include <asm/ccwdev.h>\n+#include <asm/isc.h>\n+#include <asm/airq.h>\n+#include <asm/idals.h>\n+\n+inline bool _ccw_test_assert(bool expr, const char *loc, int ln,\n+\t\t\t     const char *expl)\n+{\n+\tif (expr)\n+\t\tprintk(KERN_NOTICE \"ok -- %s:%d\\n\", loc, ln);\n+\telse\n+\t\tprintk(KERN_WARNING \"not ok  -- %s:%d (%s)\\n\", loc, ln, expl);\n+\treturn expr;\n+}\n+\n+\n+#define ccw_test_assert(_expr, _expl) ({_ccw_test_assert((_expr), \\\n+\t\t\t__func__,  __LINE__, (_expl)); })\n+\n+struct workqueue_struct *work_q;\n+\n+static __u16 cu_type = 0x3831;\n+module_param(cu_type, ushort, 0000);\n+MODULE_PARM_DESC(cu_type, \"Use this cu type for matching (default 0x3831)\");\n+\n+\n+static struct ccw_device_id ccw_tester_ids[] = {\n+\t{ CCW_DEVICE(0, 0) }, /* placeholder */\n+\t{},\n+};\n+\n+struct ccw_test_work {\n+\tstruct work_struct work;\n+\tstruct ccw1 *ccw;\n+\t__u32  intparm;\n+\tvoid *private;\n+\tvoid (*setup)(struct ccw_test_work *w);\n+\tvoid (*do_test)(struct ccw_test_work *w);\n+\tvoid (*teardown)(struct ccw_test_work *w);\n+\tstruct irb irb;\n+\tint ret;\n+\tbool doing_io;\n+};\n+\n+struct ccw_tester_device {\n+\tspinlock_t lock;\n+\twait_queue_head_t wait_q;\n+\tstruct ccw_device *cdev;\n+\tstruct ccw_test_work work;\n+\tbool work_pending;\n+};\n+\n+static struct ccw_tester_device *to_mydev(struct ccw_device *cdev)\n+{\n+\treturn dev_get_drvdata(&(cdev->dev));\n+}\n+\n+\n+static void ccw_tester_auto_online(void *data, async_cookie_t cookie)\n+{\n+\tstruct ccw_device *cdev = data;\n+\tint ret;\n+\n+\tret = ccw_device_set_online(cdev);\n+\tif (ret)\n+\t\tdev_warn(&cdev->dev, \"Failed to set online: %d\\n\", ret);\n+}\n+\n+static void do_io_work(struct ccw_tester_device *tdev)\n+{\n+\tstruct ccw_test_work *w = &tdev->work;\n+\tunsigned long flags;\n+\tint retry = 124;\n+\n+\tdo {\n+\t\tspin_lock_irqsave(get_ccwdev_lock(tdev->cdev), flags);\n+\t\ttdev->work.doing_io = true;\n+\t\tw->ret = ccw_device_start(tdev->cdev, w->ccw, w->intparm, 0, 0);\n+\t\tspin_unlock_irqrestore(get_ccwdev_lock(tdev->cdev), flags);\n+\t\tcpu_relax();\n+\t} while (w->ret == -EBUSY && --retry > 0);\n+\twait_event(tdev->wait_q, w->doing_io == false);\n+}\n+\n+\n+static void w_fib_w_setup(struct ccw_test_work *w)\n+{\n+\tconst int test_fib_length = 32;\n+\tu32 *test_fib;\n+\tint i;\n+\n+\ttest_fib = kcalloc(test_fib_length, sizeof(u32),\n+\t\t\t\t       GFP_DMA | GFP_KERNEL);\n+\tif (!test_fib)\n+\t\tw->ret = -ENOMEM;\n+\tw->private = test_fib;\n+\n+\ttest_fib[0] = 1;\n+\ttest_fib[1] = 2;\n+\tfor (i = 2; i < test_fib_length; ++i)\n+\t\ttest_fib[i] = test_fib[i - 1] + test_fib[i - 2];\n+\n+\tw->ccw->cmd_code = 0x02;\n+\tw->ccw->count = sizeof(*test_fib) * test_fib_length;\n+\tw->ccw->cda = (__u32)(unsigned long) test_fib;\n+}\n+\n+static void do_test_do_io(struct ccw_test_work *w)\n+{\n+\tstruct ccw_tester_device *tdev;\n+\n+\ttdev = container_of(w, struct ccw_tester_device, work);\n+\tdo_io_work(tdev);\n+}\n+\n+static void basic_teardown(struct ccw_test_work *w)\n+{\n+\tkfree(w->private);\n+\tw->private = NULL;\n+\tif (w->ret)\n+\t\tprintk(KERN_WARNING \"w_fib_w_teardown ret = %d\\n\", w->ret);\n+}\n+\n+static int irb_is_error(struct irb *irb)\n+{\n+\tif (scsw_cstat(&irb->scsw) != 0)\n+\t\treturn 1;\n+\tif (scsw_dstat(&irb->scsw) & ~(DEV_STAT_CHN_END | DEV_STAT_DEV_END))\n+\t\treturn 1;\n+\tif (scsw_cc(&irb->scsw) != 0)\n+\t\treturn 1;\n+\treturn 0;\n+}\n+\n+static void ccw_tester_int_handler(struct ccw_device *cdev,\n+\t\t\t\t   unsigned long intparm,\n+\t\t\t\t   struct irb *irb)\n+{\n+\tstruct ccw_tester_device *tdev = to_mydev(cdev);\n+\n+\tmemcpy(&tdev->work.irb, irb, sizeof(*irb));\n+\ttdev->work.doing_io = false;\n+\twake_up(&tdev->wait_q);\n+}\n+\n+static bool expect_is_not_fib(struct irb *irb, int count_expected)\n+{\n+\tif (!(irb_is_error(irb)\n+\t\t&& (scsw_dstat(&irb->scsw) & DEV_STAT_UNIT_EXCEP)\n+\t\t&& scsw_stctl(&irb->scsw) & SCSW_STCTL_ALERT_STATUS))\n+\t\treturn false;\n+\tif (irb->scsw.cmd.count == count_expected)\n+\t\treturn true;\n+\tprintk(KERN_NOTICE\n+\t\t\"expected residual count of %d got %d (fib at wrong place)\\n\",\n+\t\tcount_expected, irb->scsw.cmd.count);\n+\treturn false;\n+}\n+\n+\n+static void w_fib_do_test(struct ccw_test_work *w)\n+{\n+\tu32 *test_fib = w->private;\n+\n+\tdo_test_do_io(w);\n+\tccw_test_assert(!irb_is_error(&w->irb), \"completion expected\");\n+\ttest_fib[25] = 0;\n+\tdo_test_do_io(w);\n+\tccw_test_assert(expect_is_not_fib(&w->irb,\n+\t\t(31-25)*sizeof(u32)), \"expected non fib\");\n+}\n+\n+\n+static int queue_ccw_test_work(struct ccw_tester_device *tdev,\n+\t\tvoid (*setup)(struct ccw_test_work *),\n+\t\tvoid (*do_test)(struct ccw_test_work *),\n+\t\tvoid (*teardown)(struct ccw_test_work *))\n+{\n+\tif (!spin_trylock(&tdev->lock))\n+\t\treturn -EBUSY;\n+\tif (tdev->work_pending) {\n+\t\tspin_unlock(&tdev->lock);\n+\t\treturn -EBUSY;\n+\t}\n+\ttdev->work_pending = true;\n+\ttdev->work.setup = setup;\n+\ttdev->work.do_test = do_test;\n+\ttdev->work.teardown = teardown;\n+\tqueue_work(work_q, &tdev->work.work);\n+\tspin_unlock(&tdev->lock);\n+\treturn 0;\n+}\n+\n+\n+static ssize_t w_fib_store(struct device *dev, struct device_attribute *attr,\n+\t\t\t     const char *buf, size_t count)\n+{\n+\tstruct ccw_tester_device *tdev = to_mydev(to_ccwdev(dev));\n+\tint ret;\n+\n+\tret = queue_ccw_test_work(tdev,\n+\t\tw_fib_w_setup, w_fib_do_test, basic_teardown);\n+\treturn ret ? ret : count;\n+}\n+\n+static u32 *u32_arr_in_idal_buf_at(struct idal_buffer const *ib, int i)\n+{\n+\tu64 b = IDA_BLOCK_SIZE/sizeof(u32);\n+\n+\treturn  (u32 *)(ib->data[i/b]) + i % b;\n+}\n+\n+#define IDAL_TEST_BYTES  (IDA_BLOCK_SIZE * 3 + IDA_BLOCK_SIZE/2)\n+#define IDAL_TEST_ELEMENTS  (IDAL_TEST_BYTES/sizeof(u32))\n+\n+static void w_fib_idal_setup(struct ccw_test_work *w)\n+{\n+\tstruct idal_buffer *ib = NULL;\n+\tu32 n, n_1 = 2, n_2 = 1;\n+\tint i = 0;\n+\n+\tib = idal_buffer_alloc(IDAL_TEST_BYTES, 0);\n+\tif (IS_ERR(ib)) {\n+\t\tw->ret = PTR_ERR(ib);\n+\t\treturn;\n+\t}\n+\tw->private = ib;\n+\t*u32_arr_in_idal_buf_at(ib, 0) = n_2;\n+\t*u32_arr_in_idal_buf_at(ib, 1) = n_1;\n+\tfor (i = 2; i < IDAL_TEST_ELEMENTS; ++i) {\n+\t\tn = n_1 + n_2;\n+\t\tn_2 = n_1;\n+\t\tn_1 = n;\n+\t\t*u32_arr_in_idal_buf_at(ib, i) = n;\n+\t}\n+\tidal_buffer_set_cda(ib, w->ccw);\n+\tw->ccw->count = IDAL_TEST_BYTES;\n+\tw->ccw->cmd_code = 0x02;\n+}\n+\n+static void idal_teardown(struct ccw_test_work *w)\n+{\n+\tif (w->private) {\n+\t\tidal_buffer_free(w->private);\n+\t\tw->private = NULL;\n+\t}\n+\tif (w->ret)\n+\t\tprintk(KERN_WARNING \"w_fib_w_teardown ret = %d\\n\", w->ret);\n+}\n+\n+static void w_fib_do_idal_test(struct ccw_test_work *w)\n+{\n+\tstruct idal_buffer *ib = w->private;\n+\n+\t/* we have one already set up, fire it */\n+\tdo_test_do_io(w);\n+\tccw_test_assert(!irb_is_error(&w->irb), \"completion expected\");\n+\n+\t/* let's break fib and check if the device detects it */\n+\t++(*u32_arr_in_idal_buf_at(ib, IDAL_TEST_ELEMENTS - 5));\n+\tdo_test_do_io(w);\n+\tccw_test_assert(expect_is_not_fib(&w->irb,\n+\t\t\t4 * sizeof(u32)), \"expected non fib\");\n+\t/* shorten the seq so the broken element is not included */\n+\tw->ccw->count = IDAL_TEST_BYTES - 5 * sizeof(u32);\n+\tdo_test_do_io(w);\n+\tccw_test_assert(!irb_is_error(&w->irb), \"completion expected\");\n+}\n+\n+static ssize_t w_fib_idal_store(struct device *dev,\n+\t\t\t\tstruct device_attribute *attr,\n+\t\t\t\tconst char *buf, size_t count)\n+{\n+\tint ret;\n+\tstruct ccw_tester_device *tdev = to_mydev(to_ccwdev(dev));\n+\n+\tret = queue_ccw_test_work(tdev,\n+\t\t\tw_fib_idal_setup, w_fib_do_idal_test, idal_teardown);\n+\treturn ret ? ret : count;\n+}\n+\n+\n+static DEVICE_ATTR_WO(w_fib);\n+static DEVICE_ATTR_WO(w_fib_idal);\n+\n+static void do_ccw_test_work(struct work_struct *work)\n+{\n+\n+\tstruct ccw_test_work *w;\n+\tstruct ccw_tester_device *tdev;\n+\n+\tw = container_of(work, struct ccw_test_work, work);\n+\ttdev = container_of(w, struct ccw_tester_device, work);\n+\n+\tw->ret = 0;\n+\tw->setup(w);\n+\tw->do_test(w);\n+\tw->teardown(w);\n+\tspin_lock(&tdev->lock);\n+\ttdev->work_pending = false;\n+\tspin_unlock(&tdev->lock);\n+\tmemset(w->ccw, 0, sizeof(*(w->ccw)));\n+\tmemset(&w->irb, 0, sizeof(w->irb));\n+}\n+\n+static int ccw_tester_offline(struct ccw_device *cdev)\n+{\n+\tstruct ccw_tester_device *tdev = to_mydev(cdev);\n+\n+\tif (!tdev)\n+\t\treturn 0;\n+\tdevice_remove_file(&(cdev->dev), &dev_attr_w_fib);\n+\tdevice_remove_file(&(cdev->dev), &dev_attr_w_fib_idal);\n+\tspin_lock(&tdev->lock);\n+\ttdev->work_pending = true;\n+\tspin_unlock(&tdev->lock);\n+\tkfree(tdev->work.ccw);\n+\ttdev->work.ccw = NULL;\n+\tkfree(tdev);\n+\tdev_set_drvdata(&cdev->dev, NULL);\n+\treturn 0;\n+}\n+\n+static int ccw_tester_online(struct ccw_device *cdev)\n+{\n+\tint ret;\n+\tstruct ccw_tester_device *tdev;\n+\n+\ttdev = kzalloc(sizeof(*tdev), GFP_KERNEL);\n+\tif (!tdev) {\n+\t\tdev_warn(&cdev->dev, \"Could not get memory\\n\");\n+\t\treturn -ENOMEM;\n+\t}\n+\tinit_waitqueue_head(&tdev->wait_q);\n+\tINIT_WORK(&(tdev->work.work), do_ccw_test_work);\n+\tspin_lock_init(&tdev->lock);\n+\ttdev->work.ccw = kzalloc(sizeof(*tdev->work.ccw), GFP_DMA | GFP_KERNEL);\n+\tif (!tdev) {\n+\t\tdev_warn(&cdev->dev, \"Could not get memory\\n\");\n+\t\tret = -ENOMEM;\n+\t\tgoto out_free;\n+\t}\n+\tdev_set_drvdata(&cdev->dev, tdev);\n+\ttdev->cdev = cdev;\n+\n+\tret = device_create_file(&(cdev->dev), &dev_attr_w_fib);\n+\tif (ret)\n+\t\tgoto out_free;\n+\tret = device_create_file(&(cdev->dev), &dev_attr_w_fib_idal);\n+\tif (ret)\n+\t\tgoto out_free;\n+\treturn ret;\n+out_free:\n+\tccw_tester_offline(cdev);\n+\treturn ret;\n+}\n+\n+static void ccw_tester_remove(struct ccw_device *cdev)\n+{\n+\tccw_device_set_offline(cdev);\n+}\n+\n+static int ccw_tester_probe(struct ccw_device *cdev)\n+{\n+\tcdev->handler = ccw_tester_int_handler;\n+\tasync_schedule(ccw_tester_auto_online, cdev);\n+\treturn 0;\n+}\n+\n+static struct ccw_driver ccw_tester_driver = {\n+\t.driver = {\n+\t\t.owner = THIS_MODULE,\n+\t\t.name = \"ccw_tester\",\n+\t},\n+\t.ids = ccw_tester_ids,\n+\t.probe = ccw_tester_probe,\n+\t.set_online = ccw_tester_online,\n+\t.set_offline = ccw_tester_offline,\n+\t.remove = ccw_tester_remove,\n+\t.int_class = IRQIO_VIR,\n+};\n+\n+\n+static int __init ccw_tester_init(void)\n+{\n+\twork_q = create_singlethread_workqueue(\"ccw-tester\");\n+\tccw_tester_ids[0].cu_type = cu_type;\n+\treturn ccw_driver_register(&ccw_tester_driver);\n+}\n+module_init(ccw_tester_init);\n+\n+static void __exit ccw_tester_exit(void)\n+{\n+\tccw_driver_unregister(&ccw_tester_driver);\n+}\n+module_exit(ccw_tester_exit);\n+\n+MODULE_DESCRIPTION(\"ccw test driver -- throw ccws at devices\");\n+MODULE_LICENSE(\"GPL v2\");\n+MODULE_AUTHOR(\"Halil Pasic <pasic@linux.vnet.ibm.com>\");\n",
    "prefixes": [
        "2/2",
        "NOT",
        "QEMU"
    ]
}