1 2/*************************************************************************** 3 * 4 * drivers/s390/char/tapeblock.c 5 * block device frontend for tape device driver 6 * 7 * S390 and zSeries version 8 * Copyright (C) 2001 IBM Corporation 9 * Author(s): Carsten Otte <cotte@de.ibm.com> 10 * Tuan Ngo-Anh <ngoanh@de.ibm.com> 11 * 12 * 13 **************************************************************************** 14 */ 15 16#include "tapedefs.h" 17#include <linux/config.h> 18#include <linux/blkdev.h> 19#include <linux/blk.h> 20#include <linux/version.h> 21#include <linux/interrupt.h> 22#include <asm/ccwcache.h> /* CCW allocations */ 23#include <asm/debug.h> 24#include <asm/s390dyn.h> 25#include <linux/compatmac.h> 26#ifdef MODULE 27#define __NO_VERSION__ 28#include <linux/module.h> 29#endif 30#include "tape.h" 31#include "tapeblock.h" 32 33#define PRINTK_HEADER "TBLOCK:" 34 35/* 36 * file operation structure for tape devices 37 */ 38#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,3,98)) 39static struct block_device_operations tapeblock_fops = { 40#else 41static struct file_operations tapeblock_fops = { 42#endif 43 owner : THIS_MODULE, 44 open : tapeblock_open, /* open */ 45 release : tapeblock_release, /* release */ 46 }; 47 48int tapeblock_major = 0; 49 50#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,3,98)) 51static void tape_request_fn (request_queue_t * queue); 52#else 53static void tape_request_fn (void); 54#endif 55 56static request_queue_t* tapeblock_getqueue (kdev_t kdev); 57 58#ifdef CONFIG_DEVFS_FS 59void 60tapeblock_mkdevfstree (tape_info_t* ti) { 61 ti->devfs_block_dir=devfs_mk_dir (ti->devfs_dir, "block", ti); 62 ti->devfs_disc=devfs_register(ti->devfs_block_dir, "disc",DEVFS_FL_DEFAULT, 63 tapeblock_major, ti->blk_minor, 64 TAPEBLOCK_DEFAULTMODE, &tapeblock_fops, ti); 65} 66 67void 68tapeblock_rmdevfstree (tape_info_t* ti) { 69 devfs_unregister(ti->devfs_disc); 70 devfs_unregister(ti->devfs_block_dir); 71} 72#endif 73 74void 75tapeblock_setup(tape_info_t* ti) { 76 blk_size[tapeblock_major][ti->blk_minor]=0; // this will be detected 77 blksize_size[tapeblock_major][ti->blk_minor]=2048; // blocks are 2k by default. 78 hardsect_size[tapeblock_major][ti->blk_minor]=512; 79 blk_init_queue (&ti->request_queue, tape_request_fn); 80 blk_queue_headactive (&ti->request_queue, 0); 81#ifdef CONFIG_DEVFS_FS 82 tapeblock_mkdevfstree(ti); 83#endif 84} 85 86int 87tapeblock_init(void) { 88 int result; 89 tape_frontend_t* blkfront,*temp; 90 tape_info_t* ti; 91 92 tape_init(); 93 /* Register the tape major number to the kernel */ 94#ifdef CONFIG_DEVFS_FS 95 result = devfs_register_blkdev(tapeblock_major, "tBLK", &tapeblock_fops); 96#else 97 result = register_blkdev(tapeblock_major, "tBLK", &tapeblock_fops); 98#endif 99 if (result < 0) { 100 PRINT_WARN(KERN_ERR "tape: can't get major %d for block device\n", tapeblock_major); 101 panic ("cannot get major number for tape block device"); 102 } 103 if (tapeblock_major == 0) tapeblock_major = result; /* accept dynamic major number*/ 104 INIT_BLK_DEV(tapeblock_major,tape_request_fn,tapeblock_getqueue,NULL); 105 read_ahead[tapeblock_major]=TAPEBLOCK_READAHEAD; 106 PRINT_WARN(KERN_ERR " tape gets major %d for block device\n", result); 107 blk_size[tapeblock_major] = (int*) kmalloc (256*sizeof(int),GFP_ATOMIC); 108 memset(blk_size[tapeblock_major],0,256*sizeof(int)); 109 blksize_size[tapeblock_major] = (int*) kmalloc (256*sizeof(int),GFP_ATOMIC); 110 memset(blksize_size[tapeblock_major],0,256*sizeof(int)); 111 hardsect_size[tapeblock_major] = (int*) kmalloc (256*sizeof(int),GFP_ATOMIC); 112 memset(hardsect_size[tapeblock_major],0,256*sizeof(int)); 113 max_sectors[tapeblock_major] = (int*) kmalloc (256*sizeof(int),GFP_ATOMIC); 114 memset(max_sectors[tapeblock_major],0,256*sizeof(int)); 115 blkfront = kmalloc(sizeof(tape_frontend_t),GFP_KERNEL); 116 if (blkfront==NULL) panic ("no mem for tape block device structure"); 117 blkfront->device_setup=tapeblock_setup; 118#ifdef CONFIG_DEVFS_FS 119 blkfront->mkdevfstree = tapeblock_mkdevfstree; 120 blkfront->rmdevfstree = tapeblock_rmdevfstree; 121#endif 122 blkfront->next=NULL; 123 if (first_frontend==NULL) { 124 first_frontend=blkfront; 125 } else { 126 temp=first_frontend; 127 while (temp->next!=NULL) 128 temp=temp->next; 129 temp->next=blkfront; 130 } 131 ti=first_tape_info; 132 while (ti!=NULL) { 133 tapeblock_setup(ti); 134 ti=ti->next; 135 } 136 return 0; 137} 138 139 140void 141tapeblock_uninit(void) { 142 unregister_blkdev(tapeblock_major, "tBLK"); 143} 144 145int 146tapeblock_open(struct inode *inode, struct file *filp) { 147 tape_info_t *ti; 148 kdev_t dev; 149 int rc; 150 long lockflags; 151 152 inode = filp->f_dentry->d_inode; 153 ti = first_tape_info; 154 while ((ti != NULL) && (ti->blk_minor != MINOR (inode->i_rdev))) 155 ti = (tape_info_t *) ti->next; 156 if (ti == NULL) 157 return -ENODEV; 158#ifdef TAPE_DEBUG 159 debug_text_event (tape_debug_area,6,"b:open:"); 160 debug_int_event (tape_debug_area,6,ti->blk_minor); 161#endif 162 s390irq_spin_lock_irqsave (ti->devinfo.irq, lockflags); 163 if (tapestate_get (ti) != TS_UNUSED) { 164 s390irq_spin_unlock_irqrestore (ti->devinfo.irq, lockflags); 165#ifdef TAPE_DEBUG 166 debug_text_event (tape_debug_area,6,"b:dbusy"); 167#endif 168 return -EBUSY; 169 } 170 tapestate_set (ti, TS_IDLE); 171 ti->position=-1; 172 173 s390irq_spin_unlock_irqrestore (ti->devinfo.irq, lockflags); 174 rc=tapeblock_mediumdetect(ti); 175 if (rc) { 176 s390irq_spin_lock_irqsave (ti->devinfo.irq, lockflags); 177 tapestate_set (ti, TS_UNUSED); 178 s390irq_spin_unlock_irqrestore (ti->devinfo.irq, lockflags); 179 return rc; // in case of errors, we don't have a size of the medium 180 } 181 dev = MKDEV (tapeblock_major, MINOR (inode->i_rdev)); /* Get the device */ 182 s390irq_spin_lock_irqsave (ti->devinfo.irq, lockflags); 183 ti->blk_filp = filp; 184 filp->private_data = ti; /* save the dev.info for later reference */ 185 ti->cqr=NULL; 186 s390irq_spin_unlock_irqrestore (ti->devinfo.irq, lockflags); 187 188 return 0; 189} 190 191int 192tapeblock_release(struct inode *inode, struct file *filp) { 193 long lockflags; 194 tape_info_t *ti,*lastti; 195 ti = first_tape_info; 196 while ((ti != NULL) && (ti->blk_minor != MINOR (inode->i_rdev))) 197 ti = (tape_info_t *) ti->next; 198 if ((ti != NULL) && (tapestate_get (ti) == TS_NOT_OPER)) { 199 if (ti==first_tape_info) { 200 first_tape_info=ti->next; 201 } else { 202 lastti=first_tape_info; 203 while (lastti->next!=ti) lastti=lastti->next; 204 lastti->next=ti->next; 205 } 206 kfree(ti); 207 return 0; 208 } 209 if ((ti == NULL) || (tapestate_get (ti) != TS_IDLE)) { 210#ifdef TAPE_DEBUG 211 debug_text_event (tape_debug_area,3,"b:notidle!"); 212#endif 213 return -ENXIO; /* error in tape_release */ 214 } 215#ifdef TAPE_DEBUG 216 debug_text_event (tape_debug_area,6,"b:release:"); 217 debug_int_event (tape_debug_area,6,ti->blk_minor); 218#endif 219 s390irq_spin_lock_irqsave (ti->devinfo.irq, lockflags); 220 tapestate_set (ti, TS_UNUSED); 221 s390irq_spin_unlock_irqrestore (ti->devinfo.irq, lockflags); 222 invalidate_buffers(inode->i_rdev); 223 return 0; 224} 225 226static void 227tapeblock_end_request(tape_info_t* ti) { 228 struct buffer_head *bh; 229 int uptodate; 230 if ((tapestate_get(ti)!=TS_FAILED) && 231 (tapestate_get(ti)!=TS_DONE)) 232 BUG(); // A request has to be completed to end it 233 uptodate=(tapestate_get(ti)==TS_DONE); // is the buffer up to date? 234#ifdef TAPE_DEBUG 235 if (uptodate) { 236 debug_text_event (tape_debug_area,6,"b:done:"); 237 debug_int_event (tape_debug_area,6,(long)ti->cqr); 238 } else { 239 debug_text_event (tape_debug_area,3,"b:failed:"); 240 debug_int_event (tape_debug_area,3,(long)ti->cqr); 241 } 242#endif 243 // now inform ll_rw_block about a request status 244 while ((bh = ti->current_request->bh) != NULL) { 245 ti->current_request->bh = bh->b_reqnext; 246 bh->b_reqnext = NULL; 247 bh->b_end_io (bh, uptodate); 248 } 249 if (!end_that_request_first (ti->current_request, uptodate, "tBLK")) { 250#ifndef DEVICE_NO_RANDOM 251 add_blkdev_randomness (MAJOR (ti->current_request->rq_dev)); 252#endif 253 end_that_request_last (ti->current_request); 254 } 255 ti->discipline->free_bread(ti->cqr,ti); 256 ti->cqr=NULL; 257 ti->current_request=NULL; 258 if (tapestate_get(ti)!=TS_NOT_OPER) tapestate_set(ti,TS_IDLE); 259 return; 260} 261 262static void 263tapeblock_exec_IO (tape_info_t* ti) { 264 int rc; 265 struct request* req; 266 if (ti->cqr) { // process done/failed request 267 while ((tapestate_get(ti)==TS_FAILED) && 268 ti->blk_retries>0) { 269 ti->blk_retries--; 270 ti->position=-1; 271 tapestate_set(ti,TS_BLOCK_INIT); 272#ifdef TAPE_DEBUG 273 debug_text_event (tape_debug_area,3,"b:retryreq:"); 274 debug_int_event (tape_debug_area,3,(long)ti->cqr); 275#endif 276 rc = do_IO (ti->devinfo.irq, ti->cqr->cpaddr, (unsigned long) ti->cqr, 277 0x00, ti->cqr->options); 278 if (rc) { 279#ifdef TAPE_DEBUG 280 debug_text_event (tape_debug_area,3,"b:doIOfail:"); 281 debug_int_event (tape_debug_area,3,(long)ti->cqr); 282#endif 283 continue; // one retry lost 'cause doIO failed 284 } 285 return; 286 } 287 tapeblock_end_request (ti); // check state, inform user, free mem, dev=idl 288 } 289 if (ti->cqr!=NULL) BUG(); // tape should be idle now, request should be freed! 290 if (tapestate_get (ti) == TS_NOT_OPER) { 291 ti->blk_minor=ti->rew_minor=ti->nor_minor=-1; 292 ti->devinfo.irq=-1; 293 return; 294 } 295#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,3,98)) 296 if (list_empty (&ti->request_queue.queue_head)) { 297#else 298 if (ti->request_queue==NULL) { 299#endif 300 // nothing more to do or device has dissapeared;) 301#ifdef TAPE_DEBUG 302 debug_text_event (tape_debug_area,6,"b:Qempty"); 303#endif 304 tapestate_set(ti,TS_IDLE); 305 return; 306 } 307 // queue is not empty, fetch a request and start IO! 308 req=ti->current_request=tape_next_request(&ti->request_queue); 309 if (req==NULL) { 310 BUG(); // Yo. The queue was not reported empy, but no request found. This is _bad_. 311 } 312 if (req->cmd!=READ) { // we only support reading 313 tapestate_set(ti,TS_FAILED); 314 tapeblock_end_request (ti); // check state, inform user, free mem, dev=idl 315 tapestate_set(ti,TS_BLOCK_INIT); 316 schedule_tapeblock_exec_IO(ti); 317 return; 318 } 319 ti->cqr=ti->discipline->bread(req,ti,tapeblock_major); //build channel program from request 320 if (!ti->cqr) { 321 // ccw generation failed. we try again later. 322#ifdef TAPE_DEBUG 323 debug_text_event (tape_debug_area,3,"b:cqrNULL"); 324#endif 325 schedule_tapeblock_exec_IO(ti); 326 ti->current_request=NULL; 327 return; 328 } 329 ti->blk_retries = TAPEBLOCK_RETRIES; 330 rc= do_IO (ti->devinfo.irq, ti->cqr->cpaddr, 331 (unsigned long) ti->cqr, 0x00, ti->cqr->options); 332 if (rc) { 333 // okay. ssch failed. we try later. 334#ifdef TAPE_DEBUG 335 debug_text_event (tape_debug_area,3,"b:doIOfail"); 336#endif 337 ti->discipline->free_bread(ti->cqr,ti); 338 ti->cqr=NULL; 339 ti->current_request=NULL; 340 schedule_tapeblock_exec_IO(ti); 341 return; 342 } 343 // our request is in IO. we remove it from the queue and exit 344 tape_dequeue_request (&ti->request_queue,req); 345} 346 347static void 348do_tape_request (request_queue_t * queue) { 349 tape_info_t* ti; 350 long lockflags; 351 for (ti=first_tape_info; 352 ((ti!=NULL) && ((&ti->request_queue)!=queue)); 353 ti=ti->next); 354 if (ti==NULL) BUG(); 355 s390irq_spin_lock_irqsave (ti->devinfo.irq, lockflags); 356 if (tapestate_get(ti)!=TS_IDLE) { 357 s390irq_spin_unlock_irqrestore(ti->devinfo.irq,lockflags); 358 return; 359 } 360 if (tapestate_get(ti)!=TS_IDLE) BUG(); 361 tapestate_set(ti,TS_BLOCK_INIT); 362 tapeblock_exec_IO(ti); 363 s390irq_spin_unlock_irqrestore(ti->devinfo.irq,lockflags); 364} 365 366static void 367run_tapeblock_exec_IO (tape_info_t* ti) { 368 long flags_390irq,flags_ior; 369 spin_lock_irqsave (&io_request_lock, flags_ior); 370 s390irq_spin_lock_irqsave(ti->devinfo.irq,flags_390irq); 371 atomic_set(&ti->bh_scheduled,0); 372 tapeblock_exec_IO(ti); 373 s390irq_spin_unlock_irqrestore(ti->devinfo.irq,flags_390irq); 374 spin_unlock_irqrestore (&io_request_lock, flags_ior); 375} 376 377void 378schedule_tapeblock_exec_IO (tape_info_t *ti) 379{ 380 /* Protect against rescheduling, when already running */ 381 if (atomic_compare_and_swap(0,1,&ti->bh_scheduled)) { 382 return; 383 } 384#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,3,98)) 385 INIT_LIST_HEAD(&ti->bh_tq.list); 386#endif 387 ti->bh_tq.sync = 0; 388 ti->bh_tq.routine = (void *) (void *) run_tapeblock_exec_IO; 389 ti->bh_tq.data = ti; 390 391 queue_task (&ti->bh_tq, &tq_immediate); 392 mark_bh (IMMEDIATE_BH); 393 return; 394} 395 396/* wrappers around do_tape_request for different kernel versions */ 397#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,3,98)) 398static void tape_request_fn (void) { 399 tape_info_t* ti=first_tape_info; 400 while (ti!=NULL) { 401 do_tape_request(&ti->request_queue); 402 ti=ti->next; 403 } 404} 405#else 406static void tape_request_fn (request_queue_t* queue) { 407 do_tape_request(queue); 408} 409#endif 410 411static request_queue_t* tapeblock_getqueue (kdev_t kdev) { 412 tape_info_t* ti=first_tape_info; 413 while ((ti!=NULL) && (MINOR(kdev)!=ti->blk_minor)) 414 ti=ti->next; 415 if (ti!=NULL) return &ti->request_queue; 416 return NULL; 417} 418 419int tapeblock_mediumdetect(tape_info_t* ti) { 420 ccw_req_t* cqr; 421 int losize=1,hisize=1,rc; 422 long lockflags; 423#ifdef TAPE_DEBUG 424 debug_text_event (tape_debug_area,3,"b:medDet"); 425#endif 426 PRINT_WARN("Detecting media size. This will take _long_, so get yourself a coffee...\n"); 427 while (1) { //is interruped by break 428 hisize=hisize << 1; // try twice the size tested before 429 cqr=ti->discipline->mtseek (ti, hisize); 430 if (cqr == NULL) { 431#ifdef TAPE_DEBUG 432 debug_text_event (tape_debug_area,6,"b:ccwg fail"); 433#endif 434 return -ENOSPC; 435 } 436 s390irq_spin_lock_irqsave (ti->devinfo.irq, lockflags); 437 ti->cqr = cqr; 438 ti->wanna_wakeup=0; 439 rc = do_IO (ti->devinfo.irq, cqr->cpaddr, (unsigned long) cqr, 0x00, cqr->options); 440 s390irq_spin_unlock_irqrestore (ti->devinfo.irq, lockflags); 441 if (rc) return -EIO; 442 wait_event_interruptible (ti->wq,ti->wanna_wakeup); 443 ti->cqr = NULL; 444 tape_free_request (cqr); 445 if (ti->kernbuf) { 446 kfree (ti->kernbuf); 447 ti->kernbuf=NULL; 448 } 449 if (signal_pending (current)) { 450 tapestate_set (ti, TS_IDLE); 451 return -ERESTARTSYS; 452 } 453 s390irq_spin_lock_irqsave (ti->devinfo.irq, lockflags); 454 if (tapestate_get (ti) == TS_FAILED) { 455 tapestate_set (ti, TS_IDLE); 456 s390irq_spin_unlock_irqrestore (ti->devinfo.irq, lockflags); 457 break; 458 } 459 if (tapestate_get (ti) == TS_NOT_OPER) { 460 ti->blk_minor=ti->rew_minor=ti->nor_minor=-1; 461 ti->devinfo.irq=-1; 462 s390irq_spin_unlock_irqrestore (ti->devinfo.irq,lockflags); 463 return -ENODEV; 464 } 465 if (tapestate_get (ti) != TS_DONE) { 466 tapestate_set (ti, TS_IDLE); 467 s390irq_spin_unlock_irqrestore (ti->devinfo.irq, lockflags); 468 return -EIO; 469 } 470 tapestate_set (ti, TS_IDLE); 471 s390irq_spin_unlock_irqrestore (ti->devinfo.irq, lockflags); 472 losize=hisize; 473 } 474 cqr = ti->discipline->mtrew (ti, 1); 475 if (cqr == NULL) { 476#ifdef TAPE_DEBUG 477 debug_text_event (tape_debug_area,6,"b:ccwg fail"); 478#endif 479 return -ENOSPC; 480 } 481 s390irq_spin_lock_irqsave (ti->devinfo.irq, lockflags); 482 ti->cqr = cqr; 483 ti->wanna_wakeup=0; 484 rc = do_IO (ti->devinfo.irq, cqr->cpaddr, (unsigned long) cqr, 0x00, cqr->options); 485 s390irq_spin_unlock_irqrestore (ti->devinfo.irq, lockflags); 486 wait_event_interruptible (ti->wq,ti->wanna_wakeup); 487 ti->cqr = NULL; 488 tape_free_request (cqr); 489 if (signal_pending (current)) { 490 tapestate_set (ti, TS_IDLE); 491 return -ERESTARTSYS; 492 } 493 s390irq_spin_lock_irqsave (ti->devinfo.irq, lockflags); 494 if (tapestate_get (ti) == TS_FAILED) { 495 tapestate_set (ti, TS_IDLE); 496 s390irq_spin_unlock_irqrestore (ti->devinfo.irq, lockflags); 497 return -EIO; 498 } 499 if (tapestate_get (ti) == TS_NOT_OPER) { 500 ti->blk_minor=ti->rew_minor=ti->nor_minor=-1; 501 ti->devinfo.irq=-1; 502 s390irq_spin_unlock_irqrestore (ti->devinfo.irq,lockflags); 503 return -ENODEV; 504 } 505 if (tapestate_get (ti) != TS_DONE) { 506 tapestate_set (ti, TS_IDLE); 507 s390irq_spin_unlock_irqrestore (ti->devinfo.irq, lockflags); 508 return -EIO; 509 } 510 tapestate_set (ti, TS_IDLE); 511 s390irq_spin_unlock_irqrestore (ti->devinfo.irq, lockflags); 512 while (losize!=hisize) { 513 cqr=ti->discipline->mtseek (ti, (hisize+losize)/2+1); 514 if (cqr == NULL) { 515#ifdef TAPE_DEBUG 516 debug_text_event (tape_debug_area,6,"b:ccwg fail"); 517#endif 518 return -ENOSPC; 519 } 520 s390irq_spin_lock_irqsave (ti->devinfo.irq, lockflags); 521 ti->cqr = cqr; 522 ti->wanna_wakeup=0; 523 rc = do_IO (ti->devinfo.irq, cqr->cpaddr, (unsigned long) cqr, 0x00, cqr->options); 524 s390irq_spin_unlock_irqrestore (ti->devinfo.irq, lockflags); 525 if (rc) return -EIO; 526 wait_event_interruptible (ti->wq,ti->wanna_wakeup); 527 ti->cqr = NULL; 528 tape_free_request (cqr); 529 if (ti->kernbuf) { 530 kfree (ti->kernbuf); 531 ti->kernbuf=NULL; 532 } 533 if (signal_pending (current)) { 534 tapestate_set (ti, TS_IDLE); 535 return -ERESTARTSYS; 536 } 537 s390irq_spin_lock_irqsave (ti->devinfo.irq, lockflags); 538 if (tapestate_get (ti) == TS_NOT_OPER) { 539 ti->blk_minor=ti->rew_minor=ti->nor_minor=-1; 540 ti->devinfo.irq=-1; 541 s390irq_spin_unlock_irqrestore (ti->devinfo.irq,lockflags); 542 return -ENODEV; 543 } 544 if (tapestate_get (ti) == TS_FAILED) { 545 tapestate_set (ti, TS_IDLE); 546 s390irq_spin_unlock_irqrestore (ti->devinfo.irq, lockflags); 547 hisize=(hisize+losize)/2; 548 cqr = ti->discipline->mtrew (ti, 1); 549 if (cqr == NULL) { 550#ifdef TAPE_DEBUG 551 debug_text_event (tape_debug_area,6,"b:ccwg fail"); 552#endif 553 return -ENOSPC; 554 } 555 s390irq_spin_lock_irqsave (ti->devinfo.irq, lockflags); 556 ti->cqr = cqr; 557 ti->wanna_wakeup=0; 558 rc = do_IO (ti->devinfo.irq, cqr->cpaddr, (unsigned long) cqr, 0x00, cqr->options); 559 s390irq_spin_unlock_irqrestore (ti->devinfo.irq, lockflags); 560 wait_event_interruptible (ti->wq,ti->wanna_wakeup); 561 ti->cqr = NULL; 562 tape_free_request (cqr); 563 if (signal_pending (current)) { 564 tapestate_set (ti, TS_IDLE); 565 return -ERESTARTSYS; 566 } 567 s390irq_spin_lock_irqsave (ti->devinfo.irq, lockflags); 568 if (tapestate_get (ti) == TS_FAILED) { 569 tapestate_set (ti, TS_IDLE); 570 s390irq_spin_unlock_irqrestore (ti->devinfo.irq, lockflags); 571 return -EIO; 572 } 573 if (tapestate_get (ti) != TS_DONE) { 574 tapestate_set (ti, TS_IDLE); 575 s390irq_spin_unlock_irqrestore (ti->devinfo.irq, lockflags); 576 return -EIO; 577 } 578 tapestate_set (ti, TS_IDLE); 579 s390irq_spin_unlock_irqrestore (ti->devinfo.irq, lockflags); 580 continue; 581 } 582 if (tapestate_get (ti) != TS_DONE) { 583 tapestate_set (ti, TS_IDLE); 584 s390irq_spin_unlock_irqrestore (ti->devinfo.irq, lockflags); 585 return -EIO; 586 } 587 tapestate_set (ti, TS_IDLE); 588 s390irq_spin_unlock_irqrestore (ti->devinfo.irq, lockflags); 589 losize=(hisize+losize)/2+1; 590 } 591 blk_size[tapeblock_major][ti->blk_minor]=(losize)*(blksize_size[tapeblock_major][ti->blk_minor]/1024); 592 return 0; 593} 594