aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/powerpc/platforms/iseries/dt.c7
-rw-r--r--arch/powerpc/platforms/iseries/vio.c149
-rw-r--r--drivers/char/viotape.c124
-rw-r--r--include/asm-powerpc/iseries/vio.h41
4 files changed, 192 insertions, 129 deletions
diff --git a/arch/powerpc/platforms/iseries/dt.c b/arch/powerpc/platforms/iseries/dt.c
index 84fcee15eb25..2e4ad6b34506 100644
--- a/arch/powerpc/platforms/iseries/dt.c
+++ b/arch/powerpc/platforms/iseries/dt.c
@@ -73,7 +73,6 @@ static char __initdata device_type_memory[] = "memory";
73static char __initdata device_type_serial[] = "serial"; 73static char __initdata device_type_serial[] = "serial";
74static char __initdata device_type_network[] = "network"; 74static char __initdata device_type_network[] = "network";
75static char __initdata device_type_block[] = "block"; 75static char __initdata device_type_block[] = "block";
76static char __initdata device_type_byte[] = "byte";
77static char __initdata device_type_pci[] = "pci"; 76static char __initdata device_type_pci[] = "pci";
78static char __initdata device_type_vdevice[] = "vdevice"; 77static char __initdata device_type_vdevice[] = "vdevice";
79static char __initdata device_type_vscsi[] = "vscsi"; 78static char __initdata device_type_vscsi[] = "vscsi";
@@ -380,12 +379,6 @@ static void __init dt_vdevices(struct iseries_flat_dt *dt)
380 for (i = 0; i < HVMAXARCHITECTEDVIRTUALDISKS; i++) 379 for (i = 0; i < HVMAXARCHITECTEDVIRTUALDISKS; i++)
381 dt_do_vdevice(dt, "viodasd", reg, i, device_type_block, 380 dt_do_vdevice(dt, "viodasd", reg, i, device_type_block,
382 "IBM,iSeries-viodasd", 1); 381 "IBM,iSeries-viodasd", 1);
383 reg += HVMAXARCHITECTEDVIRTUALDISKS;
384 reg += HVMAXARCHITECTEDVIRTUALCDROMS;
385
386 for (i = 0; i < HVMAXARCHITECTEDVIRTUALTAPES; i++)
387 dt_do_vdevice(dt, "viotape", reg, i, device_type_byte,
388 "IBM,iSeries-viotape", 1);
389 382
390 dt_end_node(dt); 383 dt_end_node(dt);
391} 384}
diff --git a/arch/powerpc/platforms/iseries/vio.c b/arch/powerpc/platforms/iseries/vio.c
index f61a97441c3d..a4cc990a26a0 100644
--- a/arch/powerpc/platforms/iseries/vio.c
+++ b/arch/powerpc/platforms/iseries/vio.c
@@ -45,6 +45,18 @@
45#define FIRST_VIOTAPE (FIRST_VIOCD + NUM_VIOCDS) 45#define FIRST_VIOTAPE (FIRST_VIOCD + NUM_VIOCDS)
46#define NUM_VIOTAPES HVMAXARCHITECTEDVIRTUALTAPES 46#define NUM_VIOTAPES HVMAXARCHITECTEDVIRTUALTAPES
47 47
48struct vio_waitevent {
49 struct completion com;
50 int rc;
51 u16 sub_result;
52};
53
54struct vio_resource {
55 char rsrcname[10];
56 char type[4];
57 char model[3];
58};
59
48static struct property * __init new_property(const char *name, int length, 60static struct property * __init new_property(const char *name, int length,
49 const void *value) 61 const void *value)
50{ 62{
@@ -123,22 +135,10 @@ static int __init add_raw_property(struct device_node *np, const char *name,
123 return 1; 135 return 1;
124} 136}
125 137
126struct viocd_waitevent {
127 struct completion com;
128 int rc;
129 u16 sub_result;
130};
131
132struct cdrom_info {
133 char rsrcname[10];
134 char type[4];
135 char model[3];
136};
137
138static void __init handle_cd_event(struct HvLpEvent *event) 138static void __init handle_cd_event(struct HvLpEvent *event)
139{ 139{
140 struct viocdlpevent *bevent; 140 struct viocdlpevent *bevent;
141 struct viocd_waitevent *pwe; 141 struct vio_waitevent *pwe;
142 142
143 if (!event) 143 if (!event)
144 /* Notification that a partition went away! */ 144 /* Notification that a partition went away! */
@@ -158,7 +158,7 @@ static void __init handle_cd_event(struct HvLpEvent *event)
158 158
159 switch (event->xSubtype & VIOMINOR_SUBTYPE_MASK) { 159 switch (event->xSubtype & VIOMINOR_SUBTYPE_MASK) {
160 case viocdgetinfo: 160 case viocdgetinfo:
161 pwe = (struct viocd_waitevent *)event->xCorrelationToken; 161 pwe = (struct vio_waitevent *)event->xCorrelationToken;
162 pwe->rc = event->xRc; 162 pwe->rc = event->xRc;
163 pwe->sub_result = bevent->sub_result; 163 pwe->sub_result = bevent->sub_result;
164 complete(&pwe->com); 164 complete(&pwe->com);
@@ -179,8 +179,8 @@ static void __init get_viocd_info(struct device_node *vio_root)
179{ 179{
180 HvLpEvent_Rc hvrc; 180 HvLpEvent_Rc hvrc;
181 u32 unit; 181 u32 unit;
182 struct viocd_waitevent we; 182 struct vio_waitevent we;
183 struct cdrom_info *unitinfo; 183 struct vio_resource *unitinfo;
184 dma_addr_t unitinfo_dmaaddr; 184 dma_addr_t unitinfo_dmaaddr;
185 int ret; 185 int ret;
186 186
@@ -286,6 +286,122 @@ static void __init get_viocd_info(struct device_node *vio_root)
286 viopath_close(viopath_hostLp, viomajorsubtype_cdio, 2); 286 viopath_close(viopath_hostLp, viomajorsubtype_cdio, 2);
287} 287}
288 288
289/* Handle interrupt events for tape */
290static void __init handle_tape_event(struct HvLpEvent *event)
291{
292 struct vio_waitevent *we;
293 struct viotapelpevent *tevent = (struct viotapelpevent *)event;
294
295 if (event == NULL)
296 /* Notification that a partition went away! */
297 return;
298
299 we = (struct vio_waitevent *)event->xCorrelationToken;
300 switch (event->xSubtype & VIOMINOR_SUBTYPE_MASK) {
301 case viotapegetinfo:
302 we->rc = tevent->sub_type_result;
303 complete(&we->com);
304 break;
305 default:
306 printk(KERN_WARNING "handle_tape_event: weird ack\n");
307 }
308}
309
310static void __init get_viotape_info(struct device_node *vio_root)
311{
312 HvLpEvent_Rc hvrc;
313 u32 unit;
314 struct vio_resource *unitinfo;
315 dma_addr_t unitinfo_dmaaddr;
316 size_t len = sizeof(*unitinfo) * HVMAXARCHITECTEDVIRTUALTAPES;
317 struct vio_waitevent we;
318 int ret;
319
320 ret = viopath_open(viopath_hostLp, viomajorsubtype_tape, 2);
321 if (ret) {
322 printk(KERN_WARNING "get_viotape_info: "
323 "error on viopath_open to hostlp %d\n", ret);
324 return;
325 }
326
327 vio_setHandler(viomajorsubtype_tape, handle_tape_event);
328
329 unitinfo = iseries_hv_alloc(len, &unitinfo_dmaaddr, GFP_ATOMIC);
330 if (!unitinfo)
331 goto clear_handler;
332
333 memset(unitinfo, 0, len);
334
335 hvrc = HvCallEvent_signalLpEventFast(viopath_hostLp,
336 HvLpEvent_Type_VirtualIo,
337 viomajorsubtype_tape | viotapegetinfo,
338 HvLpEvent_AckInd_DoAck, HvLpEvent_AckType_ImmediateAck,
339 viopath_sourceinst(viopath_hostLp),
340 viopath_targetinst(viopath_hostLp),
341 (u64)(unsigned long)&we, VIOVERSION << 16,
342 unitinfo_dmaaddr, len, 0, 0);
343 if (hvrc != HvLpEvent_Rc_Good) {
344 printk(KERN_WARNING "get_viotape_info: hv error on op %d\n",
345 (int)hvrc);
346 goto hv_free;
347 }
348
349 wait_for_completion(&we.com);
350
351 for (unit = 0; (unit < HVMAXARCHITECTEDVIRTUALTAPES) &&
352 unitinfo[unit].rsrcname[0]; unit++) {
353 struct device_node *np;
354 char name[64];
355 u32 reg = FIRST_VIOTAPE + unit;
356
357 snprintf(name, sizeof(name), "/vdevice/viotape@%08x", reg);
358 np = new_node(name, vio_root);
359 if (!np)
360 goto hv_free;
361 if (!add_string_property(np, "name", "viotape") ||
362 !add_string_property(np, "device_type", "byte") ||
363 !add_string_property(np, "compatible",
364 "IBM,iSeries-viotape") ||
365 !add_raw_property(np, "reg", sizeof(reg), &reg) ||
366 !add_raw_property(np, "linux,unit_address",
367 sizeof(unit), &unit) ||
368 !add_raw_property(np, "linux,vio_rsrcname",
369 sizeof(unitinfo[unit].rsrcname),
370 unitinfo[unit].rsrcname) ||
371 !add_raw_property(np, "linux,vio_type",
372 sizeof(unitinfo[unit].type),
373 unitinfo[unit].type) ||
374 !add_raw_property(np, "linux,vio_model",
375 sizeof(unitinfo[unit].model),
376 unitinfo[unit].model))
377 goto node_free;
378 np->name = of_get_property(np, "name", NULL);
379 np->type = of_get_property(np, "device_type", NULL);
380 of_attach_node(np);
381#ifdef CONFIG_PROC_DEVICETREE
382 if (vio_root->pde) {
383 struct proc_dir_entry *ent;
384
385 ent = proc_mkdir(strrchr(np->full_name, '/') + 1,
386 vio_root->pde);
387 if (ent)
388 proc_device_tree_add_node(np, ent);
389 }
390#endif
391 continue;
392
393 node_free:
394 free_node(np);
395 break;
396 }
397
398 hv_free:
399 iseries_hv_free(len, unitinfo, unitinfo_dmaaddr);
400 clear_handler:
401 vio_clearHandler(viomajorsubtype_tape);
402 viopath_close(viopath_hostLp, viomajorsubtype_tape, 2);
403}
404
289static int __init iseries_vio_init(void) 405static int __init iseries_vio_init(void)
290{ 406{
291 struct device_node *vio_root; 407 struct device_node *vio_root;
@@ -307,6 +423,7 @@ static int __init iseries_vio_init(void)
307 } 423 }
308 424
309 get_viocd_info(vio_root); 425 get_viocd_info(vio_root);
426 get_viotape_info(vio_root);
310 427
311 return 0; 428 return 0;
312 429
diff --git a/drivers/char/viotape.c b/drivers/char/viotape.c
index 064c09195215..f1d60f0cef8f 100644
--- a/drivers/char/viotape.c
+++ b/drivers/char/viotape.c
@@ -92,47 +92,6 @@ struct viot_devinfo_struct {
92#define VIOTAPOP_SETPART 14 92#define VIOTAPOP_SETPART 14
93#define VIOTAPOP_UNLOAD 15 93#define VIOTAPOP_UNLOAD 15
94 94
95struct viotapelpevent {
96 struct HvLpEvent event;
97 u32 reserved;
98 u16 version;
99 u16 sub_type_result;
100 u16 tape;
101 u16 flags;
102 u32 token;
103 u64 len;
104 union {
105 struct {
106 u32 tape_op;
107 u32 count;
108 } op;
109 struct {
110 u32 type;
111 u32 resid;
112 u32 dsreg;
113 u32 gstat;
114 u32 erreg;
115 u32 file_no;
116 u32 block_no;
117 } get_status;
118 struct {
119 u32 block_no;
120 } get_pos;
121 } u;
122};
123
124enum viotapesubtype {
125 viotapeopen = 0x0001,
126 viotapeclose = 0x0002,
127 viotaperead = 0x0003,
128 viotapewrite = 0x0004,
129 viotapegetinfo = 0x0005,
130 viotapeop = 0x0006,
131 viotapegetpos = 0x0007,
132 viotapesetpos = 0x0008,
133 viotapegetstatus = 0x0009
134};
135
136enum viotaperc { 95enum viotaperc {
137 viotape_InvalidRange = 0x0601, 96 viotape_InvalidRange = 0x0601,
138 viotape_InvalidToken = 0x0602, 97 viotape_InvalidToken = 0x0602,
@@ -223,14 +182,11 @@ static const struct vio_error_entry viotape_err_table[] = {
223#define VIOT_WRITING 2 182#define VIOT_WRITING 2
224 183
225/* Our info on the tapes */ 184/* Our info on the tapes */
226struct tape_descr { 185static struct {
227 char rsrcname[10]; 186 const char *rsrcname;
228 char type[4]; 187 const char *type;
229 char model[3]; 188 const char *model;
230}; 189} viotape_unitinfo[VIOTAPE_MAX_TAPE];
231
232static struct tape_descr *viotape_unitinfo;
233static dma_addr_t viotape_unitinfo_token;
234 190
235static struct mtget viomtget[VIOTAPE_MAX_TAPE]; 191static struct mtget viomtget[VIOTAPE_MAX_TAPE];
236 192
@@ -381,53 +337,6 @@ int tape_rc_to_errno(int tape_rc, char *operation, int tapeno)
381 return -err->errno; 337 return -err->errno;
382} 338}
383 339
384/* Get info on all tapes from OS/400 */
385static int get_viotape_info(void)
386{
387 HvLpEvent_Rc hvrc;
388 int i;
389 size_t len = sizeof(*viotape_unitinfo) * VIOTAPE_MAX_TAPE;
390 struct op_struct *op = get_op_struct();
391
392 if (op == NULL)
393 return -ENOMEM;
394
395 viotape_unitinfo = iseries_hv_alloc(len, &viotape_unitinfo_token,
396 GFP_ATOMIC);
397 if (viotape_unitinfo == NULL) {
398 free_op_struct(op);
399 return -ENOMEM;
400 }
401
402 memset(viotape_unitinfo, 0, len);
403
404 hvrc = HvCallEvent_signalLpEventFast(viopath_hostLp,
405 HvLpEvent_Type_VirtualIo,
406 viomajorsubtype_tape | viotapegetinfo,
407 HvLpEvent_AckInd_DoAck, HvLpEvent_AckType_ImmediateAck,
408 viopath_sourceinst(viopath_hostLp),
409 viopath_targetinst(viopath_hostLp),
410 (u64) (unsigned long) op, VIOVERSION << 16,
411 viotape_unitinfo_token, len, 0, 0);
412 if (hvrc != HvLpEvent_Rc_Good) {
413 printk(VIOTAPE_KERN_WARN "hv error on op %d\n",
414 (int)hvrc);
415 free_op_struct(op);
416 return -EIO;
417 }
418
419 wait_for_completion(&op->com);
420
421 free_op_struct(op);
422
423 for (i = 0;
424 ((i < VIOTAPE_MAX_TAPE) && (viotape_unitinfo[i].rsrcname[0]));
425 i++)
426 viotape_numdev++;
427 return 0;
428}
429
430
431/* Write */ 340/* Write */
432static ssize_t viotap_write(struct file *file, const char *buf, 341static ssize_t viotap_write(struct file *file, const char *buf,
433 size_t count, loff_t * ppos) 342 size_t count, loff_t * ppos)
@@ -899,7 +808,6 @@ static void vioHandleTapeEvent(struct HvLpEvent *event)
899 tapeminor = event->xSubtype & VIOMINOR_SUBTYPE_MASK; 808 tapeminor = event->xSubtype & VIOMINOR_SUBTYPE_MASK;
900 op = (struct op_struct *)event->xCorrelationToken; 809 op = (struct op_struct *)event->xCorrelationToken;
901 switch (tapeminor) { 810 switch (tapeminor) {
902 case viotapegetinfo:
903 case viotapeopen: 811 case viotapeopen:
904 case viotapeclose: 812 case viotapeclose:
905 op->rc = tevent->sub_type_result; 813 op->rc = tevent->sub_type_result;
@@ -942,11 +850,23 @@ static int viotape_probe(struct vio_dev *vdev, const struct vio_device_id *id)
942{ 850{
943 int i = vdev->unit_address; 851 int i = vdev->unit_address;
944 int j; 852 int j;
853 struct device_node *node = vdev->dev.archdata.of_node;
945 854
946 if (i >= viotape_numdev) 855 if (i > VIOTAPE_MAX_TAPE)
856 return -ENODEV;
857 if (!node)
947 return -ENODEV; 858 return -ENODEV;
948 859
860 if (i >= viotape_numdev)
861 viotape_numdev = i + 1;
862
949 tape_device[i] = &vdev->dev; 863 tape_device[i] = &vdev->dev;
864 viotape_unitinfo[i].rsrcname = of_get_property(node,
865 "linux,vio_rsrcname", NULL);
866 viotape_unitinfo[i].type = of_get_property(node, "linux,vio_type",
867 NULL);
868 viotape_unitinfo[i].model = of_get_property(node, "linux,vio_model",
869 NULL);
950 870
951 state[i].cur_part = 0; 871 state[i].cur_part = 0;
952 for (j = 0; j < MAX_PARTITIONS; ++j) 872 for (j = 0; j < MAX_PARTITIONS; ++j)
@@ -1044,11 +964,6 @@ int __init viotap_init(void)
1044 goto unreg_chrdev; 964 goto unreg_chrdev;
1045 } 965 }
1046 966
1047 if ((ret = get_viotape_info()) < 0) {
1048 printk(VIOTAPE_KERN_WARN "Unable to obtain virtual device information");
1049 goto unreg_class;
1050 }
1051
1052 ret = vio_register_driver(&viotape_driver); 967 ret = vio_register_driver(&viotape_driver);
1053 if (ret) 968 if (ret)
1054 goto unreg_class; 969 goto unreg_class;
@@ -1102,9 +1017,6 @@ static void __exit viotap_exit(void)
1102 vio_unregister_driver(&viotape_driver); 1017 vio_unregister_driver(&viotape_driver);
1103 class_destroy(tape_class); 1018 class_destroy(tape_class);
1104 unregister_chrdev(VIOTAPE_MAJOR, "viotape"); 1019 unregister_chrdev(VIOTAPE_MAJOR, "viotape");
1105 if (viotape_unitinfo)
1106 iseries_hv_free(sizeof(viotape_unitinfo[0]) * VIOTAPE_MAX_TAPE,
1107 viotape_unitinfo, viotape_unitinfo_token);
1108 viopath_close(viopath_hostLp, viomajorsubtype_tape, VIOTAPE_MAXREQ + 2); 1020 viopath_close(viopath_hostLp, viomajorsubtype_tape, VIOTAPE_MAXREQ + 2);
1109 vio_clearHandler(viomajorsubtype_tape); 1021 vio_clearHandler(viomajorsubtype_tape);
1110 clear_op_struct_pool(); 1022 clear_op_struct_pool();
diff --git a/include/asm-powerpc/iseries/vio.h b/include/asm-powerpc/iseries/vio.h
index e5a405b8d461..2555dfd6fac6 100644
--- a/include/asm-powerpc/iseries/vio.h
+++ b/include/asm-powerpc/iseries/vio.h
@@ -75,6 +75,47 @@ enum viocdsubtype {
75 viocdcheck = 0x0007 75 viocdcheck = 0x0007
76}; 76};
77 77
78struct viotapelpevent {
79 struct HvLpEvent event;
80 u32 reserved;
81 u16 version;
82 u16 sub_type_result;
83 u16 tape;
84 u16 flags;
85 u32 token;
86 u64 len;
87 union {
88 struct {
89 u32 tape_op;
90 u32 count;
91 } op;
92 struct {
93 u32 type;
94 u32 resid;
95 u32 dsreg;
96 u32 gstat;
97 u32 erreg;
98 u32 file_no;
99 u32 block_no;
100 } get_status;
101 struct {
102 u32 block_no;
103 } get_pos;
104 } u;
105};
106
107enum viotapesubtype {
108 viotapeopen = 0x0001,
109 viotapeclose = 0x0002,
110 viotaperead = 0x0003,
111 viotapewrite = 0x0004,
112 viotapegetinfo = 0x0005,
113 viotapeop = 0x0006,
114 viotapegetpos = 0x0007,
115 viotapesetpos = 0x0008,
116 viotapegetstatus = 0x0009
117};
118
78/* 119/*
79 * Each subtype can register a handler to process their events. 120 * Each subtype can register a handler to process their events.
80 * The handler must have this interface. 121 * The handler must have this interface.