diff mbox

[RFC,NOT,QEMU,v2,3/3] ccw-tester: add tic test

Message ID 20171108165422.46267-4-pasic@linux.vnet.ibm.com (mailing list archive)
State New, archived
Headers show

Commit Message

Halil Pasic Nov. 8, 2017, 4:54 p.m. UTC
Let's add a test verifying that the channel subsystlem responds to a
format 1 transfer in channel ccw with non-zero count properly -- with a
channel program check.

Signed-off-by: Halil Pasic <pasic@linux.vnet.ibm.com>
---
 ccw_tester.c | 69 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 69 insertions(+)
diff mbox

Patch

diff --git a/ccw_tester.c b/ccw_tester.c
index b8e632b..6253ae7 100644
--- a/ccw_tester.c
+++ b/ccw_tester.c
@@ -347,8 +347,73 @@  static ssize_t w_fib_idal_store(struct device *dev,
 	return ret ? ret : count;
 }
 
+static void tic_setup(struct ccw_test_work *w)
+{
+	struct ccw_tester_device *tdev;
+	struct subchannel_id schid;
+
+	tdev = container_of(w, struct ccw_tester_device, work);
+	ccw_device_get_schid(tdev->cdev, &schid);
+	w->ret = set_mode_diag(schid, OP_MODE_NOP);
+	if (w->ret) {
+		printk(KERN_WARNING "tic_setup ret = %d\n", w->ret);
+		w->ret = 0;
+		return;
+	}
+	w->private = kzalloc(sizeof(*w->ccw), GFP_DMA | GFP_KERNEL);
+
+	w->ccw->count = 0x0666; /* we are evil */
+	w->ccw->cmd_code = CCW_CMD_TIC;
+	/* hope this won't get used */
+	w->ccw->cda = (__u32)(unsigned long) w->private;
+}
+
+static void tic_teardown(struct ccw_test_work *w)
+{
+	if (w->private) {
+		idal_buffer_free(w->private);
+		w->private = NULL;
+	}
+	if (w->ret)
+		printk(KERN_WARNING "tic_teardown ret = %d\n", w->ret);
+}
+
+static bool expect_pgm_chk(struct irb *irb)
+{
+	if (irb_is_error(irb)
+		&& (scsw_cstat(&irb->scsw) & SCHN_STAT_PROG_CHECK)
+		&& scsw_stctl(&irb->scsw) & SCSW_STCTL_ALERT_STATUS)
+		return true;
+	printk(KERN_NOTICE
+		"expected program check but got none (is_error == %d)\n",
+		 irb_is_error(irb));
+	return false;
+}
+
+static void do_tic_test(struct ccw_test_work *w)
+{
+	/* we have one already set up, fire it */
+	do_test_do_io(w);
+	/* TODO: check for pgm-check */
+	ccw_test_assert(expect_pgm_chk(&w->irb),
+			"expected pgm check for tic with count != 0 fib");
+}
+
+static ssize_t w_tic_store(struct device *dev,
+				struct device_attribute *attr,
+				const char *buf, size_t count)
+{
+	int ret;
+	struct ccw_tester_device *tdev = to_mydev(to_ccwdev(dev));
+
+	ret = queue_ccw_test_work(tdev,
+			tic_setup, do_tic_test, tic_teardown);
+	return ret ? ret : count;
+}
+
 static DEVICE_ATTR_WO(w_fib);
 static DEVICE_ATTR_WO(w_fib_idal);
+static DEVICE_ATTR_WO(w_tic);
 
 static void do_ccw_test_work(struct work_struct *work)
 {
@@ -378,6 +443,7 @@  static int ccw_tester_offline(struct ccw_device *cdev)
 		return 0;
 	device_remove_file(&(cdev->dev), &dev_attr_w_fib);
 	device_remove_file(&(cdev->dev), &dev_attr_w_fib_idal);
+	device_remove_file(&(cdev->dev), &dev_attr_w_tic);
 	spin_lock(&tdev->lock);
 	tdev->work_pending = true;
 	spin_unlock(&tdev->lock);
@@ -416,6 +482,9 @@  static int ccw_tester_online(struct ccw_device *cdev)
 	ret = device_create_file(&(cdev->dev), &dev_attr_w_fib_idal);
 	if (ret)
 		goto out_free;
+	ret = device_create_file(&(cdev->dev), &dev_attr_w_tic);
+	if (ret)
+		goto out_free;
 	return ret;
 out_free:
 	ccw_tester_offline(cdev);