[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>
Esse commit está contido em:

commit de
Paul Mackerras

pai
b833b481c1
commit
7465ce0db3
@@ -73,7 +73,6 @@ static char __initdata device_type_memory[] = "memory";
|
||||
static char __initdata device_type_serial[] = "serial";
|
||||
static char __initdata device_type_network[] = "network";
|
||||
static char __initdata device_type_block[] = "block";
|
||||
static char __initdata device_type_byte[] = "byte";
|
||||
static char __initdata device_type_pci[] = "pci";
|
||||
static char __initdata device_type_vdevice[] = "vdevice";
|
||||
static char __initdata device_type_vscsi[] = "vscsi";
|
||||
@@ -380,12 +379,6 @@ static void __init dt_vdevices(struct iseries_flat_dt *dt)
|
||||
for (i = 0; i < HVMAXARCHITECTEDVIRTUALDISKS; i++)
|
||||
dt_do_vdevice(dt, "viodasd", reg, i, device_type_block,
|
||||
"IBM,iSeries-viodasd", 1);
|
||||
reg += HVMAXARCHITECTEDVIRTUALDISKS;
|
||||
reg += HVMAXARCHITECTEDVIRTUALCDROMS;
|
||||
|
||||
for (i = 0; i < HVMAXARCHITECTEDVIRTUALTAPES; i++)
|
||||
dt_do_vdevice(dt, "viotape", reg, i, device_type_byte,
|
||||
"IBM,iSeries-viotape", 1);
|
||||
|
||||
dt_end_node(dt);
|
||||
}
|
||||
|
@@ -45,6 +45,18 @@
|
||||
#define FIRST_VIOTAPE (FIRST_VIOCD + NUM_VIOCDS)
|
||||
#define NUM_VIOTAPES HVMAXARCHITECTEDVIRTUALTAPES
|
||||
|
||||
struct vio_waitevent {
|
||||
struct completion com;
|
||||
int rc;
|
||||
u16 sub_result;
|
||||
};
|
||||
|
||||
struct vio_resource {
|
||||
char rsrcname[10];
|
||||
char type[4];
|
||||
char model[3];
|
||||
};
|
||||
|
||||
static struct property * __init new_property(const char *name, int length,
|
||||
const void *value)
|
||||
{
|
||||
@@ -123,22 +135,10 @@ static int __init add_raw_property(struct device_node *np, const char *name,
|
||||
return 1;
|
||||
}
|
||||
|
||||
struct viocd_waitevent {
|
||||
struct completion com;
|
||||
int rc;
|
||||
u16 sub_result;
|
||||
};
|
||||
|
||||
struct cdrom_info {
|
||||
char rsrcname[10];
|
||||
char type[4];
|
||||
char model[3];
|
||||
};
|
||||
|
||||
static void __init handle_cd_event(struct HvLpEvent *event)
|
||||
{
|
||||
struct viocdlpevent *bevent;
|
||||
struct viocd_waitevent *pwe;
|
||||
struct vio_waitevent *pwe;
|
||||
|
||||
if (!event)
|
||||
/* Notification that a partition went away! */
|
||||
@@ -158,7 +158,7 @@ static void __init handle_cd_event(struct HvLpEvent *event)
|
||||
|
||||
switch (event->xSubtype & VIOMINOR_SUBTYPE_MASK) {
|
||||
case viocdgetinfo:
|
||||
pwe = (struct viocd_waitevent *)event->xCorrelationToken;
|
||||
pwe = (struct vio_waitevent *)event->xCorrelationToken;
|
||||
pwe->rc = event->xRc;
|
||||
pwe->sub_result = bevent->sub_result;
|
||||
complete(&pwe->com);
|
||||
@@ -179,8 +179,8 @@ static void __init get_viocd_info(struct device_node *vio_root)
|
||||
{
|
||||
HvLpEvent_Rc hvrc;
|
||||
u32 unit;
|
||||
struct viocd_waitevent we;
|
||||
struct cdrom_info *unitinfo;
|
||||
struct vio_waitevent we;
|
||||
struct vio_resource *unitinfo;
|
||||
dma_addr_t unitinfo_dmaaddr;
|
||||
int ret;
|
||||
|
||||
@@ -286,6 +286,122 @@ static void __init get_viocd_info(struct device_node *vio_root)
|
||||
viopath_close(viopath_hostLp, viomajorsubtype_cdio, 2);
|
||||
}
|
||||
|
||||
/* Handle interrupt events for tape */
|
||||
static void __init handle_tape_event(struct HvLpEvent *event)
|
||||
{
|
||||
struct vio_waitevent *we;
|
||||
struct viotapelpevent *tevent = (struct viotapelpevent *)event;
|
||||
|
||||
if (event == NULL)
|
||||
/* Notification that a partition went away! */
|
||||
return;
|
||||
|
||||
we = (struct vio_waitevent *)event->xCorrelationToken;
|
||||
switch (event->xSubtype & VIOMINOR_SUBTYPE_MASK) {
|
||||
case viotapegetinfo:
|
||||
we->rc = tevent->sub_type_result;
|
||||
complete(&we->com);
|
||||
break;
|
||||
default:
|
||||
printk(KERN_WARNING "handle_tape_event: weird ack\n");
|
||||
}
|
||||
}
|
||||
|
||||
static void __init get_viotape_info(struct device_node *vio_root)
|
||||
{
|
||||
HvLpEvent_Rc hvrc;
|
||||
u32 unit;
|
||||
struct vio_resource *unitinfo;
|
||||
dma_addr_t unitinfo_dmaaddr;
|
||||
size_t len = sizeof(*unitinfo) * HVMAXARCHITECTEDVIRTUALTAPES;
|
||||
struct vio_waitevent we;
|
||||
int ret;
|
||||
|
||||
ret = viopath_open(viopath_hostLp, viomajorsubtype_tape, 2);
|
||||
if (ret) {
|
||||
printk(KERN_WARNING "get_viotape_info: "
|
||||
"error on viopath_open to hostlp %d\n", ret);
|
||||
return;
|
||||
}
|
||||
|
||||
vio_setHandler(viomajorsubtype_tape, handle_tape_event);
|
||||
|
||||
unitinfo = iseries_hv_alloc(len, &unitinfo_dmaaddr, GFP_ATOMIC);
|
||||
if (!unitinfo)
|
||||
goto clear_handler;
|
||||
|
||||
memset(unitinfo, 0, len);
|
||||
|
||||
hvrc = HvCallEvent_signalLpEventFast(viopath_hostLp,
|
||||
HvLpEvent_Type_VirtualIo,
|
||||
viomajorsubtype_tape | viotapegetinfo,
|
||||
HvLpEvent_AckInd_DoAck, HvLpEvent_AckType_ImmediateAck,
|
||||
viopath_sourceinst(viopath_hostLp),
|
||||
viopath_targetinst(viopath_hostLp),
|
||||
(u64)(unsigned long)&we, VIOVERSION << 16,
|
||||
unitinfo_dmaaddr, len, 0, 0);
|
||||
if (hvrc != HvLpEvent_Rc_Good) {
|
||||
printk(KERN_WARNING "get_viotape_info: hv error on op %d\n",
|
||||
(int)hvrc);
|
||||
goto hv_free;
|
||||
}
|
||||
|
||||
wait_for_completion(&we.com);
|
||||
|
||||
for (unit = 0; (unit < HVMAXARCHITECTEDVIRTUALTAPES) &&
|
||||
unitinfo[unit].rsrcname[0]; unit++) {
|
||||
struct device_node *np;
|
||||
char name[64];
|
||||
u32 reg = FIRST_VIOTAPE + unit;
|
||||
|
||||
snprintf(name, sizeof(name), "/vdevice/viotape@%08x", reg);
|
||||
np = new_node(name, vio_root);
|
||||
if (!np)
|
||||
goto hv_free;
|
||||
if (!add_string_property(np, "name", "viotape") ||
|
||||
!add_string_property(np, "device_type", "byte") ||
|
||||
!add_string_property(np, "compatible",
|
||||
"IBM,iSeries-viotape") ||
|
||||
!add_raw_property(np, "reg", sizeof(reg), ®) ||
|
||||
!add_raw_property(np, "linux,unit_address",
|
||||
sizeof(unit), &unit) ||
|
||||
!add_raw_property(np, "linux,vio_rsrcname",
|
||||
sizeof(unitinfo[unit].rsrcname),
|
||||
unitinfo[unit].rsrcname) ||
|
||||
!add_raw_property(np, "linux,vio_type",
|
||||
sizeof(unitinfo[unit].type),
|
||||
unitinfo[unit].type) ||
|
||||
!add_raw_property(np, "linux,vio_model",
|
||||
sizeof(unitinfo[unit].model),
|
||||
unitinfo[unit].model))
|
||||
goto node_free;
|
||||
np->name = of_get_property(np, "name", NULL);
|
||||
np->type = of_get_property(np, "device_type", NULL);
|
||||
of_attach_node(np);
|
||||
#ifdef CONFIG_PROC_DEVICETREE
|
||||
if (vio_root->pde) {
|
||||
struct proc_dir_entry *ent;
|
||||
|
||||
ent = proc_mkdir(strrchr(np->full_name, '/') + 1,
|
||||
vio_root->pde);
|
||||
if (ent)
|
||||
proc_device_tree_add_node(np, ent);
|
||||
}
|
||||
#endif
|
||||
continue;
|
||||
|
||||
node_free:
|
||||
free_node(np);
|
||||
break;
|
||||
}
|
||||
|
||||
hv_free:
|
||||
iseries_hv_free(len, unitinfo, unitinfo_dmaaddr);
|
||||
clear_handler:
|
||||
vio_clearHandler(viomajorsubtype_tape);
|
||||
viopath_close(viopath_hostLp, viomajorsubtype_tape, 2);
|
||||
}
|
||||
|
||||
static int __init iseries_vio_init(void)
|
||||
{
|
||||
struct device_node *vio_root;
|
||||
@@ -307,6 +423,7 @@ static int __init iseries_vio_init(void)
|
||||
}
|
||||
|
||||
get_viocd_info(vio_root);
|
||||
get_viotape_info(vio_root);
|
||||
|
||||
return 0;
|
||||
|
||||
|
Referência em uma nova issue
Block a user