@@ -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);
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(+)