aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorStephen Rothwell <sfr@canb.auug.org.au>2007-10-11 00:58:31 -0400
committerPaul Mackerras <paulus@samba.org>2007-10-11 06:40:47 -0400
commit7465ce0db310d2fa29f721da7e3aacd1dad7090f (patch)
treece8cd473877948310b2e86f685ab09686b79ea23 /arch
parentb833b481c10cf591b15cc674948cc514e55d3b94 (diff)
[POWERPC] iSeries: Move detection of virtual tapes
Now we will only have entries in the device tree for the actual existing devices (including their OS/400 properties). This way viotape.c gets all the information about the devices from the device tree. Signed-off-by: Stephen Rothwell <sfr@canb.auug.org.au> Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch')
-rw-r--r--arch/powerpc/platforms/iseries/dt.c7
-rw-r--r--arch/powerpc/platforms/iseries/vio.c149
2 files changed, 133 insertions, 23 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