static struct subchannel * css_alloc_subchannel(struct subchannel_id schid) { struct subchannel *sch; int ret; sch = kmalloc (sizeof (*sch), GFP_KERNEL | GFP_DMA); if (sch == NULL) return ERR_PTR(-ENOMEM); ret = cio_validate_subchannel (sch, schid); if (ret < 0) { kfree(sch); return ERR_PTR(ret); } if (sch->st != SUBCHANNEL_TYPE_IO) { /* For now we ignore all non-io subchannels. */ kfree(sch); return ERR_PTR(-EINVAL); } /* * Set intparm to subchannel address. * This is fine even on 64bit since the subchannel is always located * under 2G. */ sch->schib.pmcw.intparm = (__u32)(unsigned long)sch; ret = cio_modify(sch); if (ret) { kfree(sch); return ERR_PTR(ret); } return sch; }
struct subchannel * cio_probe_console(void) { int irq, ret; if (xchg(&console_subchannel_in_use, 1) != 0) return ERR_PTR(-EBUSY); irq = cio_console_irq(); if (irq == -1) { console_subchannel_in_use = 0; return ERR_PTR(-ENODEV); } memset(&console_subchannel, 0, sizeof(struct subchannel)); ret = cio_validate_subchannel(&console_subchannel, irq); if (ret) { console_subchannel_in_use = 0; return ERR_PTR(-ENODEV); } /* * enable console I/O-interrupt subclass 7 */ ctl_set_bit(6, 24); console_subchannel.schib.pmcw.isc = 7; ioinfo[irq] = &console_subchannel; return &console_subchannel; }
struct subchannel *css_alloc_subchannel(struct subchannel_id schid) { struct subchannel *sch; int ret; sch = kzalloc(sizeof(*sch), GFP_KERNEL | GFP_DMA); if (!sch) return ERR_PTR(-ENOMEM); ret = cio_validate_subchannel(sch, schid); if (ret < 0) goto err; ret = css_sch_create_locks(sch); if (ret) goto err; INIT_WORK(&sch->todo_work, css_sch_todo); sch->dev.release = &css_subchannel_release; device_initialize(&sch->dev); return sch; err: kfree(sch); return ERR_PTR(ret); }
struct subchannel * cio_probe_console(void) { int sch_no, ret; struct subchannel_id schid; if (xchg(&console_subchannel_in_use, 1) != 0) return ERR_PTR(-EBUSY); sch_no = cio_get_console_sch_no(); if (sch_no == -1) { console_subchannel_in_use = 0; pr_warning("No CCW console was found\n"); return ERR_PTR(-ENODEV); } memset(&console_subchannel, 0, sizeof(struct subchannel)); init_subchannel_id(&schid); schid.sch_no = sch_no; ret = cio_validate_subchannel(&console_subchannel, schid); if (ret) { console_subchannel_in_use = 0; return ERR_PTR(-ENODEV); } /* * enable console I/O-interrupt subclass */ isc_register(CONSOLE_ISC); console_subchannel.config.isc = CONSOLE_ISC; console_subchannel.config.intparm = (u32)(addr_t)&console_subchannel; ret = cio_commit_config(&console_subchannel); if (ret) { isc_unregister(CONSOLE_ISC); console_subchannel_in_use = 0; return ERR_PTR(ret); } return &console_subchannel; }
struct subchannel * cio_probe_console(void) { int sch_no, ret; struct subchannel_id schid; if (xchg(&console_subchannel_in_use, 1) != 0) return ERR_PTR(-EBUSY); sch_no = cio_get_console_sch_no(); if (sch_no == -1) { console_subchannel_in_use = 0; return ERR_PTR(-ENODEV); } memset(&console_subchannel, 0, sizeof(struct subchannel)); init_subchannel_id(&schid); schid.sch_no = sch_no; ret = cio_validate_subchannel(&console_subchannel, schid); if (ret) { console_subchannel_in_use = 0; return ERR_PTR(-ENODEV); } /* * enable console I/O-interrupt subclass 7 */ ctl_set_bit(6, 24); console_subchannel.schib.pmcw.isc = 7; console_subchannel.schib.pmcw.intparm = (__u32)(unsigned long)&console_subchannel; ret = cio_modify(&console_subchannel); if (ret) { console_subchannel_in_use = 0; return ERR_PTR(ret); } return &console_subchannel; }