Lines Matching +full:io +full:- +full:backends
1 // SPDX-License-Identifier: GPL-2.0
9 * Tuan Ngo-Anh <ngoanh@de.ibm.com>
84 return dev_id->devno + (dev_id->ssid << 16); in devid_to_int()
99 return sysfs_emit(buf, "%i\n", tdev->medium_state); in tape_medium_state_show()
111 return sysfs_emit(buf, "%i\n", tdev->first_minor); in tape_first_minor_show()
123 return sysfs_emit(buf, "%s\n", (tdev->first_minor < 0) ? in tape_state_show()
124 "OFFLINE" : tape_state_verbose[tdev->tape_state]); in tape_state_show()
137 if (tdev->first_minor < 0) in tape_operation_show()
140 spin_lock_irq(get_ccwdev_lock(tdev->cdev)); in tape_operation_show()
141 if (list_empty(&tdev->req_queue)) in tape_operation_show()
142 rc = sysfs_emit(buf, "---\n"); in tape_operation_show()
146 req = list_entry(tdev->req_queue.next, struct tape_request, in tape_operation_show()
148 rc = sysfs_emit(buf, "%s\n", tape_op_verbose[req->op]); in tape_operation_show()
150 spin_unlock_irq(get_ccwdev_lock(tdev->cdev)); in tape_operation_show()
164 return sysfs_emit(buf, "%i\n", tdev->char_data.block_size); in tape_blocksize_show()
191 if (device->tape_state == TS_NOT_OPER) { in tape_state_set()
195 DBF_EVENT(4, "ts. dev: %x\n", device->first_minor); in tape_state_set()
197 if (device->tape_state < TS_SIZE && device->tape_state >=0 ) in tape_state_set()
198 str = tape_state_verbose[device->tape_state]; in tape_state_set()
208 device->tape_state = newstate; in tape_state_set()
209 wake_up(&device->state_change_wq); in tape_state_set()
225 struct tape_device *device = p->device; in tape_med_state_work_handler()
228 switch (p->state) { in tape_med_state_work_handler()
231 "unloaded\n", dev_name(&device->cdev->dev)); in tape_med_state_work_handler()
233 kobject_uevent_env(&device->cdev->dev.kobj, KOBJ_CHANGE, envp); in tape_med_state_work_handler()
237 dev_name(&device->cdev->dev)); in tape_med_state_work_handler()
239 kobject_uevent_env(&device->cdev->dev.kobj, KOBJ_CHANGE, envp); in tape_med_state_work_handler()
255 INIT_WORK(&p->work, tape_med_state_work_handler); in tape_med_state_work()
256 p->device = tape_get_device(device); in tape_med_state_work()
257 p->state = state; in tape_med_state_work()
258 schedule_work(&p->work); in tape_med_state_work()
267 oldstate = device->medium_state; in tape_med_state_set()
270 device->medium_state = newstate; in tape_med_state_set()
273 device->tape_generic_status |= GMT_DR_OPEN(~0); in tape_med_state_set()
278 device->tape_generic_status &= ~GMT_DR_OPEN(~0); in tape_med_state_set()
285 wake_up(&device->state_change_wq); in tape_med_state_set()
298 if (request->callback == NULL) in __tape_cancel_io()
303 rc = ccw_device_clear(device->cdev, (long) request); in __tape_cancel_io()
307 request->status = TAPE_REQUEST_DONE; in __tape_cancel_io()
309 case -EBUSY: in __tape_cancel_io()
310 request->status = TAPE_REQUEST_CANCEL; in __tape_cancel_io()
311 schedule_delayed_work(&device->tape_dnr, 0); in __tape_cancel_io()
313 case -ENODEV: in __tape_cancel_io()
316 case -EIO: in __tape_cancel_io()
340 if (minor < tmp->first_minor) in tape_assign_minor()
346 return -ENODEV; in tape_assign_minor()
348 device->first_minor = minor; in tape_assign_minor()
349 list_add_tail(&device->node, &tmp->node); in tape_assign_minor()
359 list_del_init(&device->node); in tape_remove_minor()
360 device->first_minor = -1; in tape_remove_minor()
380 if (device->tape_state != TS_INIT) { in tape_generic_online()
381 DBF_LH(3, "Tapestate not INIT (%d)\n", device->tape_state); in tape_generic_online()
382 return -EINVAL; in tape_generic_online()
385 timer_setup(&device->lb_timeout, tape_long_busy_timeout, 0); in tape_generic_online()
388 device->discipline = discipline; in tape_generic_online()
389 if (!try_module_get(discipline->owner)) { in tape_generic_online()
390 return -EINVAL; in tape_generic_online()
393 rc = discipline->setup_device(device); in tape_generic_online()
406 DBF_LH(3, "(%08x): Drive set online\n", device->cdev_id); in tape_generic_online()
413 device->discipline->cleanup_device(device); in tape_generic_online()
414 device->discipline = NULL; in tape_generic_online()
416 module_put(discipline->owner); in tape_generic_online()
424 device->discipline->cleanup_device(device); in tape_cleanup_device()
425 module_put(device->discipline->owner); in tape_cleanup_device()
442 device = dev_get_drvdata(&cdev->dev); in tape_generic_offline()
444 return -ENODEV; in tape_generic_offline()
448 device->cdev_id, device); in tape_generic_offline()
450 spin_lock_irq(get_ccwdev_lock(device->cdev)); in tape_generic_offline()
451 switch (device->tape_state) { in tape_generic_offline()
454 spin_unlock_irq(get_ccwdev_lock(device->cdev)); in tape_generic_offline()
458 spin_unlock_irq(get_ccwdev_lock(device->cdev)); in tape_generic_offline()
463 "- drive in use.\n", in tape_generic_offline()
464 device->cdev_id); in tape_generic_offline()
465 spin_unlock_irq(get_ccwdev_lock(device->cdev)); in tape_generic_offline()
466 return -EBUSY; in tape_generic_offline()
469 DBF_LH(3, "(%08x): Drive set offline.\n", device->cdev_id); in tape_generic_offline()
484 return ERR_PTR(-ENOMEM); in tape_alloc_device()
486 device->modeset_byte = kmalloc(1, GFP_KERNEL | GFP_DMA); in tape_alloc_device()
487 if (device->modeset_byte == NULL) { in tape_alloc_device()
490 return ERR_PTR(-ENOMEM); in tape_alloc_device()
492 mutex_init(&device->mutex); in tape_alloc_device()
493 INIT_LIST_HEAD(&device->req_queue); in tape_alloc_device()
494 INIT_LIST_HEAD(&device->node); in tape_alloc_device()
495 init_waitqueue_head(&device->state_change_wq); in tape_alloc_device()
496 init_waitqueue_head(&device->wait_queue); in tape_alloc_device()
497 device->tape_state = TS_INIT; in tape_alloc_device()
498 device->medium_state = MS_UNKNOWN; in tape_alloc_device()
499 *device->modeset_byte = 0; in tape_alloc_device()
500 device->first_minor = -1; in tape_alloc_device()
501 atomic_set(&device->ref_count, 1); in tape_alloc_device()
502 INIT_DELAYED_WORK(&device->tape_dnr, tape_delayed_next_request); in tape_alloc_device()
516 count = atomic_inc_return(&device->ref_count); in tape_get_device()
532 count = atomic_dec_return(&device->ref_count); in tape_put_device()
533 DBF_EVENT(4, "tape_put_device(%p) -> %i\n", device, count); in tape_put_device()
536 kfree(device->modeset_byte); in tape_put_device()
549 device = ERR_PTR(-ENODEV); in tape_find_device()
552 if (tmp->first_minor / TAPE_MINORS_PER_DEV == devindex) { in tape_find_device()
573 return -ENODEV; in tape_generic_probe()
576 ret = sysfs_create_group(&cdev->dev.kobj, &tape_attr_group); in tape_generic_probe()
581 dev_set_drvdata(&cdev->dev, device); in tape_generic_probe()
582 cdev->handler = __tape_do_irq; in tape_generic_probe()
583 device->cdev = cdev; in tape_generic_probe()
585 device->cdev_id = devid_to_int(&dev_id); in tape_generic_probe()
595 list_for_each_safe(l, n, &device->req_queue) { in __tape_discard_requests()
597 if (request->status == TAPE_REQUEST_IN_IO) in __tape_discard_requests()
598 request->status = TAPE_REQUEST_DONE; in __tape_discard_requests()
599 list_del(&request->list); in __tape_discard_requests()
602 request->device = NULL; in __tape_discard_requests()
604 request->rc = -EIO; in __tape_discard_requests()
605 if (request->callback != NULL) in __tape_discard_requests()
606 request->callback(request, request->callback_data); in __tape_discard_requests()
621 device = dev_get_drvdata(&cdev->dev); in tape_generic_remove()
625 DBF_LH(3, "(%08x): tape_generic_remove(%p)\n", device->cdev_id, cdev); in tape_generic_remove()
627 spin_lock_irq(get_ccwdev_lock(device->cdev)); in tape_generic_remove()
628 switch (device->tape_state) { in tape_generic_remove()
636 spin_unlock_irq(get_ccwdev_lock(device->cdev)); in tape_generic_remove()
643 spin_unlock_irq(get_ccwdev_lock(device->cdev)); in tape_generic_remove()
653 device->cdev_id); in tape_generic_remove()
655 dev_name(&device->cdev->dev)); in tape_generic_remove()
658 spin_unlock_irq(get_ccwdev_lock(device->cdev)); in tape_generic_remove()
662 device = dev_get_drvdata(&cdev->dev); in tape_generic_remove()
664 sysfs_remove_group(&cdev->dev.kobj, &tape_attr_group); in tape_generic_remove()
665 dev_set_drvdata(&cdev->dev, NULL); in tape_generic_remove()
685 return ERR_PTR(-ENOMEM); in tape_alloc_request()
689 request->cpaddr = kcalloc(cplength, sizeof(struct ccw1), in tape_alloc_request()
691 if (request->cpaddr == NULL) { in tape_alloc_request()
694 return ERR_PTR(-ENOMEM); in tape_alloc_request()
699 request->cpdata = kzalloc(datasize, GFP_KERNEL | GFP_DMA); in tape_alloc_request()
700 if (request->cpdata == NULL) { in tape_alloc_request()
702 kfree(request->cpaddr); in tape_alloc_request()
704 return ERR_PTR(-ENOMEM); in tape_alloc_request()
707 DBF_LH(6, "New request %p(%p/%p)\n", request, request->cpaddr, in tape_alloc_request()
708 request->cpdata); in tape_alloc_request()
721 if (request->device) in tape_free_request()
722 tape_put_device(request->device); in tape_free_request()
723 kfree(request->cpdata); in tape_free_request()
724 kfree(request->cpaddr); in tape_free_request()
734 device->cdev, in __tape_start_io()
735 request->cpaddr, in __tape_start_io()
738 request->options in __tape_start_io()
741 request->status = TAPE_REQUEST_IN_IO; in __tape_start_io()
742 } else if (rc == -EBUSY) { in __tape_start_io()
744 request->status = TAPE_REQUEST_QUEUED; in __tape_start_io()
745 schedule_delayed_work(&device->tape_dnr, 0); in __tape_start_io()
766 list_for_each_safe(l, n, &device->req_queue) { in __tape_start_next_request()
770 * Avoid race condition if bottom-half was triggered more than in __tape_start_next_request()
773 if (request->status == TAPE_REQUEST_IN_IO) in __tape_start_next_request()
780 if (request->status == TAPE_REQUEST_DONE) in __tape_start_next_request()
789 if (request->status == TAPE_REQUEST_CANCEL) { in __tape_start_next_request()
798 request->rc = rc; in __tape_start_next_request()
799 request->status = TAPE_REQUEST_DONE; in __tape_start_next_request()
802 list_del(&request->list); in __tape_start_next_request()
805 if (request->callback != NULL) in __tape_start_next_request()
806 request->callback(request, request->callback_data); in __tape_start_next_request()
817 spin_lock_irq(get_ccwdev_lock(device->cdev)); in tape_delayed_next_request()
819 spin_unlock_irq(get_ccwdev_lock(device->cdev)); in tape_delayed_next_request()
827 spin_lock_irq(get_ccwdev_lock(device->cdev)); in tape_long_busy_timeout()
828 request = list_entry(device->req_queue.next, struct tape_request, list); in tape_long_busy_timeout()
829 BUG_ON(request->status != TAPE_REQUEST_LONG_BUSY); in tape_long_busy_timeout()
830 DBF_LH(6, "%08x: Long busy timeout.\n", device->cdev_id); in tape_long_busy_timeout()
833 spin_unlock_irq(get_ccwdev_lock(device->cdev)); in tape_long_busy_timeout()
844 request->rc = rc; in __tape_end_request()
845 request->status = TAPE_REQUEST_DONE; in __tape_end_request()
848 list_del(&request->list); in __tape_end_request()
851 if (request->callback != NULL) in __tape_end_request()
852 request->callback(request, request->callback_data); in __tape_end_request()
856 if (!list_empty(&device->req_queue)) in __tape_end_request()
871 op = tape_op_verbose[request->op]; in tape_dump_sense_dbf()
873 op = "---"; in tape_dump_sense_dbf()
875 irb->scsw.cmd.dstat, irb->scsw.cmd.cstat); in tape_dump_sense_dbf()
876 DBF_EVENT(3, "DEVICE: %08x OP\t: %s\n", device->cdev_id, op); in tape_dump_sense_dbf()
877 sptr = (unsigned int *) irb->ecw; in tape_dump_sense_dbf()
894 switch (request->op) { in __tape_start_request()
900 if (device->tape_state == TS_INIT) in __tape_start_request()
902 if (device->tape_state == TS_UNUSED) in __tape_start_request()
906 if (device->tape_state == TS_BLKUSE) in __tape_start_request()
908 if (device->tape_state != TS_IN_USE) in __tape_start_request()
909 return -ENODEV; in __tape_start_request()
913 request->device = tape_get_device(device); in __tape_start_request()
915 if (list_empty(&device->req_queue)) { in __tape_start_request()
922 list_add(&request->list, &device->req_queue); in __tape_start_request()
925 request->status = TAPE_REQUEST_QUEUED; in __tape_start_request()
926 list_add_tail(&request->list, &device->req_queue); in __tape_start_request()
942 spin_lock_irq(get_ccwdev_lock(device->cdev)); in tape_do_io_async()
945 spin_unlock_irq(get_ccwdev_lock(device->cdev)); in tape_do_io_async()
957 request->callback = NULL; in __tape_wake_up()
966 spin_lock_irq(get_ccwdev_lock(device->cdev)); in tape_do_io()
968 request->callback = __tape_wake_up; in tape_do_io()
969 request->callback_data = &device->wait_queue; in tape_do_io()
972 spin_unlock_irq(get_ccwdev_lock(device->cdev)); in tape_do_io()
976 wait_event(device->wait_queue, (request->callback == NULL)); in tape_do_io()
978 return request->rc; in tape_do_io()
989 request->callback = NULL; in __tape_wake_up_interruptible()
999 spin_lock_irq(get_ccwdev_lock(device->cdev)); in tape_do_io_interruptible()
1001 request->callback = __tape_wake_up_interruptible; in tape_do_io_interruptible()
1002 request->callback_data = &device->wait_queue; in tape_do_io_interruptible()
1004 spin_unlock_irq(get_ccwdev_lock(device->cdev)); in tape_do_io_interruptible()
1008 rc = wait_event_interruptible(device->wait_queue, in tape_do_io_interruptible()
1009 (request->callback == NULL)); in tape_do_io_interruptible()
1010 if (rc != -ERESTARTSYS) in tape_do_io_interruptible()
1012 return request->rc; in tape_do_io_interruptible()
1015 spin_lock_irq(get_ccwdev_lock(device->cdev)); in tape_do_io_interruptible()
1017 spin_unlock_irq(get_ccwdev_lock(device->cdev)); in tape_do_io_interruptible()
1022 device->wait_queue, in tape_do_io_interruptible()
1023 (request->callback == NULL) in tape_do_io_interruptible()
1025 } while (rc == -ERESTARTSYS); in tape_do_io_interruptible()
1027 DBF_EVENT(3, "IO stopped on %08x\n", device->cdev_id); in tape_do_io_interruptible()
1028 rc = -ERESTARTSYS; in tape_do_io_interruptible()
1041 spin_lock_irq(get_ccwdev_lock(device->cdev)); in tape_cancel_io()
1043 spin_unlock_irq(get_ccwdev_lock(device->cdev)); in tape_cancel_io()
1057 device = dev_get_drvdata(&cdev->dev); in __tape_do_irq()
1069 case -ETIMEDOUT: in __tape_do_irq()
1071 device->cdev_id); in __tape_do_irq()
1073 case -EIO: in __tape_do_irq()
1074 __tape_end_request(device, request, -EIO); in __tape_do_irq()
1078 device->cdev_id, PTR_ERR(irb)); in __tape_do_irq()
1090 if (irb->scsw.cmd.cc != 0 && in __tape_do_irq()
1091 (irb->scsw.cmd.fctl & SCSW_FCTL_START_FUNC) && in __tape_do_irq()
1092 (request->status == TAPE_REQUEST_IN_IO)) { in __tape_do_irq()
1094 device->cdev_id, irb->scsw.cmd.cc, irb->scsw.cmd.fctl); in __tape_do_irq()
1095 request->status = TAPE_REQUEST_QUEUED; in __tape_do_irq()
1096 schedule_delayed_work(&device->tape_dnr, HZ); in __tape_do_irq()
1102 request->rescnt = irb->scsw.cmd.count; in __tape_do_irq()
1103 else if ((irb->scsw.cmd.dstat == 0x85 || irb->scsw.cmd.dstat == 0x80) && in __tape_do_irq()
1104 !list_empty(&device->req_queue)) { in __tape_do_irq()
1107 req = list_entry(device->req_queue.next, in __tape_do_irq()
1109 if (req->status == TAPE_REQUEST_LONG_BUSY) { in __tape_do_irq()
1110 DBF_EVENT(3, "(%08x): del timer\n", device->cdev_id); in __tape_do_irq()
1111 if (timer_delete(&device->lb_timeout)) { in __tape_do_irq()
1118 if (irb->scsw.cmd.dstat != 0x0c) { in __tape_do_irq()
1120 if(*(((__u8 *) irb->ecw) + 1) & SENSE_DRIVE_ONLINE) in __tape_do_irq()
1121 device->tape_generic_status |= GMT_ONLINE(~0); in __tape_do_irq()
1123 device->tape_generic_status &= ~GMT_ONLINE(~0); in __tape_do_irq()
1129 DBF_EVENT(3,"-- Tape Interrupthandler --\n"); in __tape_do_irq()
1133 device->tape_generic_status |= GMT_ONLINE(~0); in __tape_do_irq()
1135 if (device->tape_state == TS_NOT_OPER) { in __tape_do_irq()
1144 if(request != NULL && request->status == TAPE_REQUEST_DONE) { in __tape_do_irq()
1145 __tape_end_request(device, request, -EIO); in __tape_do_irq()
1149 rc = device->discipline->irq(device, request, irb); in __tape_do_irq()
1160 device->tape_generic_status |= GMT_ONLINE(~0); in __tape_do_irq()
1166 device->lb_timeout.expires = jiffies + in __tape_do_irq()
1168 DBF_EVENT(3, "(%08x): add timer\n", device->cdev_id); in __tape_do_irq()
1169 add_timer(&device->lb_timeout); in __tape_do_irq()
1170 request->status = TAPE_REQUEST_LONG_BUSY; in __tape_do_irq()
1185 __tape_end_request(device, request, -EIO); in __tape_do_irq()
1201 spin_lock_irq(get_ccwdev_lock(device->cdev)); in tape_open()
1202 if (device->tape_state == TS_NOT_OPER) { in tape_open()
1204 rc = -ENODEV; in tape_open()
1205 } else if (device->tape_state == TS_IN_USE) { in tape_open()
1207 rc = -EBUSY; in tape_open()
1208 } else if (device->tape_state == TS_BLKUSE) { in tape_open()
1210 rc = -EBUSY; in tape_open()
1211 } else if (device->discipline != NULL && in tape_open()
1212 !try_module_get(device->discipline->owner)) { in tape_open()
1214 rc = -ENODEV; in tape_open()
1219 spin_unlock_irq(get_ccwdev_lock(device->cdev)); in tape_open()
1229 spin_lock_irq(get_ccwdev_lock(device->cdev)); in tape_release()
1230 if (device->tape_state == TS_IN_USE) in tape_release()
1232 module_put(device->discipline->owner); in tape_release()
1233 spin_unlock_irq(get_ccwdev_lock(device->cdev)); in tape_release()
1251 return -EINVAL; in tape_mtop()
1252 fn = device->discipline->mtop_array[mt_op]; in tape_mtop()
1254 return -EINVAL; in tape_mtop()
1256 /* We assume that the backends can handle count up to 500. */ in tape_mtop()
1260 for (; mt_count > 500; mt_count -= 500) in tape_mtop()