diff options
Diffstat (limited to 'drivers/block/viodasd.c')
-rw-r--r-- | drivers/block/viodasd.c | 77 |
1 files changed, 25 insertions, 52 deletions
diff --git a/drivers/block/viodasd.c b/drivers/block/viodasd.c index af3969a9c963..e824b672e05a 100644 --- a/drivers/block/viodasd.c +++ b/drivers/block/viodasd.c | |||
@@ -74,53 +74,9 @@ enum { | |||
74 | static DEFINE_SPINLOCK(viodasd_spinlock); | 74 | static DEFINE_SPINLOCK(viodasd_spinlock); |
75 | 75 | ||
76 | #define VIOMAXREQ 16 | 76 | #define VIOMAXREQ 16 |
77 | #define VIOMAXBLOCKDMA 12 | ||
78 | 77 | ||
79 | #define DEVICE_NO(cell) ((struct viodasd_device *)(cell) - &viodasd_devices[0]) | 78 | #define DEVICE_NO(cell) ((struct viodasd_device *)(cell) - &viodasd_devices[0]) |
80 | 79 | ||
81 | struct open_data { | ||
82 | u64 disk_size; | ||
83 | u16 max_disk; | ||
84 | u16 cylinders; | ||
85 | u16 tracks; | ||
86 | u16 sectors; | ||
87 | u16 bytes_per_sector; | ||
88 | }; | ||
89 | |||
90 | struct rw_data { | ||
91 | u64 offset; | ||
92 | struct { | ||
93 | u32 token; | ||
94 | u32 reserved; | ||
95 | u64 len; | ||
96 | } dma_info[VIOMAXBLOCKDMA]; | ||
97 | }; | ||
98 | |||
99 | struct vioblocklpevent { | ||
100 | struct HvLpEvent event; | ||
101 | u32 reserved; | ||
102 | u16 version; | ||
103 | u16 sub_result; | ||
104 | u16 disk; | ||
105 | u16 flags; | ||
106 | union { | ||
107 | struct open_data open_data; | ||
108 | struct rw_data rw_data; | ||
109 | u64 changed; | ||
110 | } u; | ||
111 | }; | ||
112 | |||
113 | #define vioblockflags_ro 0x0001 | ||
114 | |||
115 | enum vioblocksubtype { | ||
116 | vioblockopen = 0x0001, | ||
117 | vioblockclose = 0x0002, | ||
118 | vioblockread = 0x0003, | ||
119 | vioblockwrite = 0x0004, | ||
120 | vioblockflush = 0x0005, | ||
121 | vioblockcheck = 0x0007 | ||
122 | }; | ||
123 | |||
124 | struct viodasd_waitevent { | 80 | struct viodasd_waitevent { |
125 | struct completion com; | 81 | struct completion com; |
126 | int rc; | 82 | int rc; |
@@ -429,7 +385,7 @@ static void do_viodasd_request(struct request_queue *q) | |||
429 | * Probe a single disk and fill in the viodasd_device structure | 385 | * Probe a single disk and fill in the viodasd_device structure |
430 | * for it. | 386 | * for it. |
431 | */ | 387 | */ |
432 | static void probe_disk(struct viodasd_device *d) | 388 | static int probe_disk(struct viodasd_device *d) |
433 | { | 389 | { |
434 | HvLpEvent_Rc hvrc; | 390 | HvLpEvent_Rc hvrc; |
435 | struct viodasd_waitevent we; | 391 | struct viodasd_waitevent we; |
@@ -453,14 +409,14 @@ retry: | |||
453 | 0, 0, 0); | 409 | 0, 0, 0); |
454 | if (hvrc != 0) { | 410 | if (hvrc != 0) { |
455 | printk(VIOD_KERN_WARNING "bad rc on HV open %d\n", (int)hvrc); | 411 | printk(VIOD_KERN_WARNING "bad rc on HV open %d\n", (int)hvrc); |
456 | return; | 412 | return 0; |
457 | } | 413 | } |
458 | 414 | ||
459 | wait_for_completion(&we.com); | 415 | wait_for_completion(&we.com); |
460 | 416 | ||
461 | if (we.rc != 0) { | 417 | if (we.rc != 0) { |
462 | if (flags != 0) | 418 | if (flags != 0) |
463 | return; | 419 | return 0; |
464 | /* try again with read only flag set */ | 420 | /* try again with read only flag set */ |
465 | flags = vioblockflags_ro; | 421 | flags = vioblockflags_ro; |
466 | goto retry; | 422 | goto retry; |
@@ -490,15 +446,32 @@ retry: | |||
490 | if (hvrc != 0) { | 446 | if (hvrc != 0) { |
491 | printk(VIOD_KERN_WARNING | 447 | printk(VIOD_KERN_WARNING |
492 | "bad rc sending event to OS/400 %d\n", (int)hvrc); | 448 | "bad rc sending event to OS/400 %d\n", (int)hvrc); |
493 | return; | 449 | return 0; |
494 | } | 450 | } |
451 | |||
452 | if (d->dev == NULL) { | ||
453 | /* this is when we reprobe for new disks */ | ||
454 | if (vio_create_viodasd(dev_no) == NULL) { | ||
455 | printk(VIOD_KERN_WARNING | ||
456 | "cannot allocate virtual device for disk %d\n", | ||
457 | dev_no); | ||
458 | return 0; | ||
459 | } | ||
460 | /* | ||
461 | * The vio_create_viodasd will have recursed into this | ||
462 | * routine with d->dev set to the new vio device and | ||
463 | * will finish the setup of the disk below. | ||
464 | */ | ||
465 | return 1; | ||
466 | } | ||
467 | |||
495 | /* create the request queue for the disk */ | 468 | /* create the request queue for the disk */ |
496 | spin_lock_init(&d->q_lock); | 469 | spin_lock_init(&d->q_lock); |
497 | q = blk_init_queue(do_viodasd_request, &d->q_lock); | 470 | q = blk_init_queue(do_viodasd_request, &d->q_lock); |
498 | if (q == NULL) { | 471 | if (q == NULL) { |
499 | printk(VIOD_KERN_WARNING "cannot allocate queue for disk %d\n", | 472 | printk(VIOD_KERN_WARNING "cannot allocate queue for disk %d\n", |
500 | dev_no); | 473 | dev_no); |
501 | return; | 474 | return 0; |
502 | } | 475 | } |
503 | g = alloc_disk(1 << PARTITION_SHIFT); | 476 | g = alloc_disk(1 << PARTITION_SHIFT); |
504 | if (g == NULL) { | 477 | if (g == NULL) { |
@@ -506,7 +479,7 @@ retry: | |||
506 | "cannot allocate disk structure for disk %d\n", | 479 | "cannot allocate disk structure for disk %d\n", |
507 | dev_no); | 480 | dev_no); |
508 | blk_cleanup_queue(q); | 481 | blk_cleanup_queue(q); |
509 | return; | 482 | return 0; |
510 | } | 483 | } |
511 | 484 | ||
512 | d->disk = g; | 485 | d->disk = g; |
@@ -538,6 +511,7 @@ retry: | |||
538 | 511 | ||
539 | /* register us in the global list */ | 512 | /* register us in the global list */ |
540 | add_disk(g); | 513 | add_disk(g); |
514 | return 1; | ||
541 | } | 515 | } |
542 | 516 | ||
543 | /* returns the total number of scatterlist elements converted */ | 517 | /* returns the total number of scatterlist elements converted */ |
@@ -718,8 +692,7 @@ static int viodasd_probe(struct vio_dev *vdev, const struct vio_device_id *id) | |||
718 | struct viodasd_device *d = &viodasd_devices[vdev->unit_address]; | 692 | struct viodasd_device *d = &viodasd_devices[vdev->unit_address]; |
719 | 693 | ||
720 | d->dev = &vdev->dev; | 694 | d->dev = &vdev->dev; |
721 | probe_disk(d); | 695 | if (!probe_disk(d)) |
722 | if (d->disk == NULL) | ||
723 | return -ENODEV; | 696 | return -ENODEV; |
724 | return 0; | 697 | return 0; |
725 | } | 698 | } |