Lines Matching +full:de +full:- +full:serialized
1 // SPDX-License-Identifier: GPL-2.0
8 * Michael Holzheu <holzheu@de.ibm.com>
9 * Frank Munzert <munzert@de.ibm.com>
38 * is used to read spool data page-wise.
91 * (cdev) using the urd->cdev pointer. Each ccw device has a reference to the
92 * ur device using dev_get_drvdata(&cdev->dev) pointer.
95 * - ur_probe gets a urd reference, ur_remove drops the reference
96 * dev_get_drvdata(&cdev->dev)
97 * - ur_open gets a urd reference, ur_release drops the reference
98 * (urf->urd)
101 * - urdev_alloc get a cdev reference (urd->cdev)
102 * - urdev_free drops the cdev reference (urd->cdev)
104 * Setting and clearing of dev_get_drvdata(&cdev->dev) is protected by the ccwdev lock
113 urd->reclen = cdev->id.driver_info; in urdev_alloc()
114 ccw_device_get_id(cdev, &urd->dev_id); in urdev_alloc()
115 mutex_init(&urd->io_mutex); in urdev_alloc()
116 init_waitqueue_head(&urd->wait); in urdev_alloc()
117 INIT_WORK(&urd->uevent_work, ur_uevent); in urdev_alloc()
118 spin_lock_init(&urd->open_lock); in urdev_alloc()
119 refcount_set(&urd->ref_count, 1); in urdev_alloc()
120 urd->cdev = cdev; in urdev_alloc()
121 get_device(&cdev->dev); in urdev_alloc()
128 if (urd->cdev) in urdev_free()
129 put_device(&urd->cdev->dev); in urdev_free()
135 refcount_inc(&urd->ref_count); in urdev_get()
144 urd = dev_get_drvdata(&cdev->dev); in urdev_get_from_cdev()
162 put_device(&cdev->dev); in urdev_get_from_devno()
168 if (refcount_dec_and_test(&urd->ref_count)) in urdev_put()
173 * Low-level functions to do I/O to a ur device.
183 * on a completion event it publishes at urd->io_done. The function
199 while (ptr->cda) { in free_chan_prog()
200 kfree(dma32_to_virt(ptr->cda)); in free_chan_prog()
209 * with a final NOP CCW command-chained on (which ensures that CE and DE
224 * We chain a NOP onto the writes to force CE+DE together. in alloc_chan_prog()
231 return ERR_PTR(-ENOMEM); in alloc_chan_prog()
240 return ERR_PTR(-ENOMEM); in alloc_chan_prog()
245 return ERR_PTR(-EFAULT); in alloc_chan_prog()
249 /* The following NOP CCW forces CE+DE to be presented together */ in alloc_chan_prog()
257 struct ccw_device *cdev = urd->cdev; in do_ur_io()
262 rc = mutex_lock_interruptible(&urd->io_mutex); in do_ur_io()
266 urd->io_done = &event; in do_ur_io()
281 mutex_unlock(&urd->io_mutex); in do_ur_io()
289 "EVENT=unsol_de", /* Unsolicited device-end interrupt */ in ur_uevent()
293 kobject_uevent_env(&urd->cdev->dev.kobj, KOBJ_CHANGE, envp); in ur_uevent()
307 intparm, irb->scsw.cmd.cstat, irb->scsw.cmd.dstat, in ur_int_handler()
308 irb->scsw.cmd.count); in ur_int_handler()
310 urd = dev_get_drvdata(&cdev->dev); in ur_int_handler()
314 if (scsw_dstat(&irb->scsw) & DEV_STAT_DEV_END) { in ur_int_handler()
317 * device-ready state. in ur_int_handler()
320 schedule_work(&urd->uevent_work); in ur_int_handler()
327 urd->io_request_rc = PTR_ERR(irb); in ur_int_handler()
328 else if (irb->scsw.cmd.dstat == (DEV_STAT_CHN_END | DEV_STAT_DEV_END)) in ur_int_handler()
329 urd->io_request_rc = 0; in ur_int_handler()
331 urd->io_request_rc = -EIO; in ur_int_handler()
333 complete(urd->io_done); in ur_int_handler()
337 * reclen sysfs attribute - The record length to be used for write CCWs
347 return -ENODEV; in ur_attr_reclen_show()
348 rc = sprintf(buf, "%zu\n", urd->reclen); in ur_attr_reclen_show()
366 * diagnose code 0x210 - retrieve device information
377 ur_diag210.vrdcdvno = urd->dev_id.devno; in get_urd_class()
383 return -EOPNOTSUPP; in get_urd_class()
387 return -ENODEV; in get_urd_class()
389 return -EIO; in get_urd_class()
403 urf->urd = urd; in urfile_alloc()
406 urf->dev_reclen); in urfile_alloc()
413 TRACE("urfile_free: urf=%p urd=%p\n", urf, urf->urd); in urfile_free()
434 if (urd->io_request_rc) { in do_write()
435 rc = urd->io_request_rc; in do_write()
449 struct urfile *urf = file->private_data; in ur_write()
456 if (count % urf->dev_reclen) in ur_write()
457 return -EINVAL; /* count must be a multiple of reclen */ in ur_write()
459 if (count > urf->dev_reclen * MAX_RECS_PER_IO) in ur_write()
460 count = urf->dev_reclen * MAX_RECS_PER_IO; in ur_write()
462 return do_write(urf->urd, udata, count, urf->dev_reclen, ppos); in ur_write()
466 * diagnose code 0x14 subcode 0x0028 - position spool file to designated
481 return -ENOMEDIUM; in diag_position_to_record()
483 return -ENODATA; /* position beyond end of file */ in diag_position_to_record()
485 return -EIO; in diag_position_to_record()
490 * diagnose code 0x14 subcode 0x0000 - read next spool file buffer
506 return -ENODATA; in diag_read_file()
508 return -ENOMEDIUM; in diag_read_file()
510 return -EIO; in diag_read_file()
523 urd = ((struct urfile *) file->private_data)->urd; in diag14_read()
524 reclen = ((struct urfile *) file->private_data)->file_reclen; in diag14_read()
526 rc = diag_position_to_record(urd->dev_id.devno, *offs / PAGE_SIZE + 1); in diag14_read()
527 if (rc == -ENODATA) in diag14_read()
535 return -ENOMEM; in diag14_read()
540 rc = diag_read_file(urd->dev_id.devno, buf); in diag14_read()
541 if (rc == -ENODATA) { in diag14_read()
548 len = min(count - copied, PAGE_SIZE - res); in diag14_read()
550 rc = -EFAULT; in diag14_read()
575 urd = ((struct urfile *) file->private_data)->urd; in ur_read()
576 rc = mutex_lock_interruptible(&urd->io_mutex); in ur_read()
580 mutex_unlock(&urd->io_mutex); in ur_read()
585 * diagnose code 0x14 subcode 0x0fff - retrieve next file descriptor
599 return -ENODATA; in diag_read_next_file_info()
611 return -ENOMEM; in verify_uri_device()
619 if (fcb->file_stat & (FLG_SYSTEM_HOLD | FLG_USER_HOLD)) { in verify_uri_device()
620 rc = -EPERM; in verify_uri_device()
627 rc = -ENOMEM; in verify_uri_device()
630 rc = diag_read_file(urd->dev_id.devno, buf); in verify_uri_device()
631 if ((rc != 0) && (rc != -ENODATA)) /* EOF does not hurt */ in verify_uri_device()
638 if (!(fcb->file_stat & FLG_IN_USE)) { in verify_uri_device()
639 rc = -EMFILE; in verify_uri_device()
653 switch (urd->class) { in verify_device()
659 return -EOPNOTSUPP; in verify_device()
670 return -ENOMEM; in get_uri_file_reclen()
674 if (fcb->file_stat & FLG_CP_DUMP) in get_uri_file_reclen()
677 rc = fcb->rec_len; in get_uri_file_reclen()
686 switch (urd->class) { in get_file_reclen()
692 return -EOPNOTSUPP; in get_file_reclen()
704 accmode = file->f_flags & O_ACCMODE; in ur_open()
707 return -EACCES; in ur_open()
716 rc = -ENXIO; in ur_open()
720 spin_lock(&urd->open_lock); in ur_open()
721 while (urd->open_flag) { in ur_open()
722 spin_unlock(&urd->open_lock); in ur_open()
723 if (file->f_flags & O_NONBLOCK) { in ur_open()
724 rc = -EBUSY; in ur_open()
727 if (wait_event_interruptible(urd->wait, urd->open_flag == 0)) { in ur_open()
728 rc = -ERESTARTSYS; in ur_open()
731 spin_lock(&urd->open_lock); in ur_open()
733 urd->open_flag++; in ur_open()
734 spin_unlock(&urd->open_lock); in ur_open()
738 if (((accmode == O_RDONLY) && (urd->class != DEV_CLASS_UR_I)) || in ur_open()
739 ((accmode == O_WRONLY) && (urd->class != DEV_CLASS_UR_O))) { in ur_open()
740 TRACE("ur_open: unsupported dev class (%d)\n", urd->class); in ur_open()
741 rc = -EACCES; in ur_open()
751 rc = -ENOMEM; in ur_open()
755 urf->dev_reclen = urd->reclen; in ur_open()
759 urf->file_reclen = rc; in ur_open()
760 file->private_data = urf; in ur_open()
766 spin_lock(&urd->open_lock); in ur_open()
767 urd->open_flag--; in ur_open()
768 spin_unlock(&urd->open_lock); in ur_open()
777 struct urfile *urf = file->private_data; in ur_release()
780 spin_lock(&urf->urd->open_lock); in ur_release()
781 urf->urd->open_flag--; in ur_release()
782 spin_unlock(&urf->urd->open_lock); in ur_release()
783 wake_up_interruptible(&urf->urd->wait); in ur_release()
784 urdev_put(urf->urd); in ur_release()
791 if ((file->f_flags & O_ACCMODE) != O_RDONLY) in ur_llseek()
792 return -ESPIPE; /* seek allowed only for reader */ in ur_llseek()
794 return -ESPIPE; /* only multiples of 4K allowed */ in ur_llseek()
815 * ur_probe, ur_remove, ur_set_online and ur_set_offline are serialized
818 * urd->char_device is used as indication that the online function has
831 rc = -ENOMEM; in ur_probe()
835 rc = ur_create_attributes(&cdev->dev); in ur_probe()
837 rc = -ENOMEM; in ur_probe()
842 urd->class = get_urd_class(urd); in ur_probe()
843 if (urd->class < 0) { in ur_probe()
844 rc = urd->class; in ur_probe()
847 if ((urd->class != DEV_CLASS_UR_I) && (urd->class != DEV_CLASS_UR_O)) { in ur_probe()
848 rc = -EOPNOTSUPP; in ur_probe()
852 dev_set_drvdata(&cdev->dev, urd); in ur_probe()
853 cdev->handler = ur_int_handler; in ur_probe()
860 ur_remove_attributes(&cdev->dev); in ur_probe()
880 rc = -ENODEV; in ur_set_online()
884 if (urd->char_device) { in ur_set_online()
886 rc = -EBUSY; in ur_set_online()
890 minor = urd->dev_id.devno; in ur_set_online()
893 urd->char_device = cdev_alloc(); in ur_set_online()
894 if (!urd->char_device) { in ur_set_online()
895 rc = -ENOMEM; in ur_set_online()
899 urd->char_device->ops = &ur_fops; in ur_set_online()
900 urd->char_device->owner = ur_fops.owner; in ur_set_online()
902 rc = cdev_add(urd->char_device, MKDEV(major, minor), 1); in ur_set_online()
905 if (urd->cdev->id.cu_type == READER_PUNCH_DEVTYPE) { in ur_set_online()
906 if (urd->class == DEV_CLASS_UR_I) in ur_set_online()
907 sprintf(node_id, "vmrdr-%s", dev_name(&cdev->dev)); in ur_set_online()
908 if (urd->class == DEV_CLASS_UR_O) in ur_set_online()
909 sprintf(node_id, "vmpun-%s", dev_name(&cdev->dev)); in ur_set_online()
910 } else if (urd->cdev->id.cu_type == PRINTER_DEVTYPE) { in ur_set_online()
911 sprintf(node_id, "vmprt-%s", dev_name(&cdev->dev)); in ur_set_online()
913 rc = -EOPNOTSUPP; in ur_set_online()
917 urd->device = device_create(&vmur_class, &cdev->dev, in ur_set_online()
918 urd->char_device->dev, NULL, "%s", node_id); in ur_set_online()
919 if (IS_ERR(urd->device)) { in ur_set_online()
920 rc = PTR_ERR(urd->device); in ur_set_online()
929 cdev_del(urd->char_device); in ur_set_online()
930 urd->char_device = NULL; in ur_set_online()
947 return -ENODEV; in ur_set_offline_force()
948 if (!urd->char_device) { in ur_set_offline_force()
950 rc = -EBUSY; in ur_set_offline_force()
953 if (!force && (refcount_read(&urd->ref_count) > 2)) { in ur_set_offline_force()
956 rc = -EBUSY; in ur_set_offline_force()
959 if (cancel_work_sync(&urd->uevent_work)) { in ur_set_offline_force()
960 /* Work not run yet - need to release reference here */ in ur_set_offline_force()
963 device_destroy(&vmur_class, urd->char_device->dev); in ur_set_offline_force()
964 cdev_del(urd->char_device); in ur_set_offline_force()
965 urd->char_device = NULL; in ur_set_offline_force()
991 if (cdev->online) in ur_remove()
993 ur_remove_attributes(&cdev->dev); in ur_remove()
996 urdev_put(dev_get_drvdata(&cdev->dev)); in ur_remove()
997 dev_set_drvdata(&cdev->dev, NULL); in ur_remove()
998 cdev->handler = NULL; in ur_remove()
1015 return -ENODEV; in ur_init()
1020 return -ENOMEM; in ur_init()