static int scdrv_open(struct inode *inode, struct file *file) { struct sysctl_data_s *scd; struct subch_data_s *sd; int rv; /* look up device info for this device file */ scd = container_of(inode->i_cdev, struct sysctl_data_s, scd_cdev); /* allocate memory for subchannel data */ sd = kzalloc(sizeof (struct subch_data_s), GFP_KERNEL); if (sd == NULL) { printk("%s: couldn't allocate subchannel data\n", __func__); return -ENOMEM; } /* initialize subch_data_s fields */ sd->sd_nasid = scd->scd_nasid; sd->sd_subch = ia64_sn_irtr_open(scd->scd_nasid); if (sd->sd_subch < 0) { kfree(sd); printk("%s: couldn't allocate subchannel\n", __func__); return -EBUSY; } spin_lock_init(&sd->sd_rlock); spin_lock_init(&sd->sd_wlock); init_waitqueue_head(&sd->sd_rq); init_waitqueue_head(&sd->sd_wq); sema_init(&sd->sd_rbs, 1); sema_init(&sd->sd_wbs, 1); file->private_data = sd; /* hook this subchannel up to the system controller interrupt */ lock_kernel(); rv = request_irq(SGI_UART_VECTOR, scdrv_interrupt, IRQF_SHARED | IRQF_DISABLED, SYSCTL_BASENAME, sd); if (rv) { ia64_sn_irtr_close(sd->sd_nasid, sd->sd_subch); kfree(sd); printk("%s: irq request failed (%d)\n", __func__, rv); unlock_kernel(); return -EBUSY; } unlock_kernel(); return 0; }
static int scdrv_release(struct inode *inode, struct file *file) { struct subch_data_s *sd = (struct subch_data_s *) file->private_data; int rv; /* free the interrupt */ free_irq(SGI_UART_VECTOR, sd); /* ask SAL to close the subchannel */ rv = ia64_sn_irtr_close(sd->sd_nasid, sd->sd_subch); kfree(sd); return rv; }