diff options
author | Stephen Rothwell <sfr@canb.auug.org.au> | 2007-10-11 00:58:31 -0400 |
---|---|---|
committer | Paul Mackerras <paulus@samba.org> | 2007-10-11 06:40:47 -0400 |
commit | 7465ce0db310d2fa29f721da7e3aacd1dad7090f (patch) | |
tree | ce8cd473877948310b2e86f685ab09686b79ea23 /arch | |
parent | b833b481c10cf591b15cc674948cc514e55d3b94 (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.c | 7 | ||||
-rw-r--r-- | arch/powerpc/platforms/iseries/vio.c | 149 |
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"; | |||
73 | static char __initdata device_type_serial[] = "serial"; | 73 | static char __initdata device_type_serial[] = "serial"; |
74 | static char __initdata device_type_network[] = "network"; | 74 | static char __initdata device_type_network[] = "network"; |
75 | static char __initdata device_type_block[] = "block"; | 75 | static char __initdata device_type_block[] = "block"; |
76 | static char __initdata device_type_byte[] = "byte"; | ||
77 | static char __initdata device_type_pci[] = "pci"; | 76 | static char __initdata device_type_pci[] = "pci"; |
78 | static char __initdata device_type_vdevice[] = "vdevice"; | 77 | static char __initdata device_type_vdevice[] = "vdevice"; |
79 | static char __initdata device_type_vscsi[] = "vscsi"; | 78 | static 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 | ||
48 | struct vio_waitevent { | ||
49 | struct completion com; | ||
50 | int rc; | ||
51 | u16 sub_result; | ||
52 | }; | ||
53 | |||
54 | struct vio_resource { | ||
55 | char rsrcname[10]; | ||
56 | char type[4]; | ||
57 | char model[3]; | ||
58 | }; | ||
59 | |||
48 | static struct property * __init new_property(const char *name, int length, | 60 | static 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 | ||
126 | struct viocd_waitevent { | ||
127 | struct completion com; | ||
128 | int rc; | ||
129 | u16 sub_result; | ||
130 | }; | ||
131 | |||
132 | struct cdrom_info { | ||
133 | char rsrcname[10]; | ||
134 | char type[4]; | ||
135 | char model[3]; | ||
136 | }; | ||
137 | |||
138 | static void __init handle_cd_event(struct HvLpEvent *event) | 138 | static 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 */ | ||
290 | static 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 | |||
310 | static 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), ®) || | ||
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 | |||
289 | static int __init iseries_vio_init(void) | 405 | static 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 | ||