/* only allow one open process at a time to open each channel */ static int rtlx_open(struct inode *inode, struct file *filp) { int minor, ret; struct rtlx_channel *chan; /* assume only 1 device at the mo. */ minor = MINOR(inode->i_rdev); if (rtlx == NULL) { struct rtlx_info **p; if( (p = vpe_get_shared(RTLX_TARG_VPE)) == NULL) { printk(KERN_ERR "vpe_get_shared is NULL. " "Has an SP program been loaded?\n"); return -EFAULT; } if (*p == NULL) { printk(KERN_ERR "vpe_shared %p %p\n", p, *p); return -EFAULT; } if ((ret = rtlx_init(*p)) < 0) return ret; } chan = &rtlx->channel[minor]; if (test_and_set_bit(RTLX_STATE_OPENED, &chan->lx_state)) return -EBUSY; return 0; }
/* only allow one open process at a time to open each channel */ static int rtlx_open(struct inode *inode, struct file *filp) { int minor, ret; struct rtlx_channel *chan; /* assume only 1 device at the mo. */ minor = MINOR(inode->i_rdev); if (rtlx == NULL) { struct rtlx_info **p; if( (p = vpe_get_shared(RTLX_TARG_VPE)) == NULL) { printk(" vpe_get_shared is NULL. Has an SP program been loaded?\n"); return (-EFAULT); } if (*p == NULL) { printk(" vpe_shared %p %p\n", p, *p); return (-EFAULT); } if ((ret = rtlx_init(*p)) < 0) return (ret); } chan = &rtlx->channel[minor]; /* already open? */ if (chan->lx_state == RTLX_STATE_OPENED) return (-EBUSY); chan->lx_state = RTLX_STATE_OPENED; return (0); }
static void rtlx_interrupt(void) { int i; struct rtlx_info *info; struct rtlx_info **p = vpe_get_shared(aprp_cpu_index()); if (p == NULL || *p == NULL) return; info = *p; if (info->ap_int_pending == 1 && smp_processor_id() == 0) { for (i = 0; i < RTLX_CHANNELS; i++) { wake_up(&channel_wqs[i].lx_queue); wake_up(&channel_wqs[i].rt_queue); } info->ap_int_pending = 0; } }
int rtlx_open(int index, int can_sleep) { struct rtlx_info **p; struct rtlx_channel *chan; enum rtlx_state state; int ret = 0; if (index >= RTLX_CHANNELS) { printk(KERN_DEBUG "rtlx_open index out of range\n"); return -ENOSYS; } if (atomic_inc_return(&channel_wqs[index].in_open) > 1) { printk(KERN_DEBUG "rtlx_open channel %d already opened\n", index); ret = -EBUSY; goto out_fail; } if (rtlx == NULL) { if( (p = vpe_get_shared(tclimit)) == NULL) { if (can_sleep) { __wait_event_interruptible(channel_wqs[index].lx_queue, (p = vpe_get_shared(tclimit)), ret); if (ret) goto out_fail; } else { printk(KERN_DEBUG "No SP program loaded, and device " "opened with O_NONBLOCK\n"); ret = -ENOSYS; goto out_fail; } } smp_rmb(); if (*p == NULL) { if (can_sleep) { DEFINE_WAIT(wait); for (;;) { prepare_to_wait( &channel_wqs[index].lx_queue, &wait, TASK_INTERRUPTIBLE); smp_rmb(); if (*p != NULL) break; if (!signal_pending(current)) { schedule(); continue; } ret = -ERESTARTSYS; goto out_fail; } finish_wait(&channel_wqs[index].lx_queue, &wait); } else { pr_err(" *vpe_get_shared is NULL. " "Has an SP program been loaded?\n"); ret = -ENOSYS; goto out_fail; } } if ((unsigned int)*p < KSEG0) { printk(KERN_WARNING "vpe_get_shared returned an " "invalid pointer maybe an error code %d\n", (int)*p); ret = -ENOSYS; goto out_fail; } if ((ret = rtlx_init(*p)) < 0) goto out_ret; } chan = &rtlx->channel[index]; state = xchg(&chan->lx_state, RTLX_STATE_OPENED); if (state == RTLX_STATE_OPENED) { ret = -EBUSY; goto out_fail; } out_fail: smp_mb(); atomic_dec(&channel_wqs[index].in_open); smp_mb(); out_ret: return ret; }
int rtlx_open(int index, int can_sleep) { int ret; struct rtlx_channel *chan; volatile struct rtlx_info **p; if (index >= RTLX_CHANNELS) { printk(KERN_DEBUG "rtlx_open index out of range\n"); return -ENOSYS; } if (channel_wqs[index].in_open) { printk(KERN_DEBUG "rtlx_open channel %d already opened\n", index); return -EBUSY; } channel_wqs[index].in_open++; if (rtlx == NULL) { if( (p = vpe_get_shared(RTLX_TARG_VPE)) == NULL) { if (can_sleep) { DECLARE_WAITQUEUE(wait, current); /* go to sleep */ add_wait_queue(&channel_wqs[index].lx_queue, &wait); set_current_state(TASK_INTERRUPTIBLE); while ((p = vpe_get_shared(RTLX_TARG_VPE)) == NULL) { schedule(); set_current_state(TASK_INTERRUPTIBLE); } set_current_state(TASK_RUNNING); remove_wait_queue(&channel_wqs[index].lx_queue, &wait); /* back running */ } else { printk( KERN_DEBUG "No SP program loaded, and device " "opened with O_NONBLOCK\n"); channel_wqs[index].in_open = 0; return -ENOSYS; } } if (*p == NULL) { if (can_sleep) { DECLARE_WAITQUEUE(wait, current); /* go to sleep */ add_wait_queue(&channel_wqs[index].lx_queue, &wait); set_current_state(TASK_INTERRUPTIBLE); while (*p == NULL) { schedule(); /* reset task state to interruptable otherwise we'll whizz round here like a very fast loopy thing. schedule() appears to return with state set to TASK_RUNNING. If the loaded SP program, for whatever reason, doesn't set up the shared structure *p will never become true. So whoever connected to either /dev/rt? or if it was kspd, will then take up rather a lot of processor cycles. */ set_current_state(TASK_INTERRUPTIBLE); } set_current_state(TASK_RUNNING); remove_wait_queue(&channel_wqs[index].lx_queue, &wait); /* back running */ } else { printk(" *vpe_get_shared is NULL. " "Has an SP program been loaded?\n"); channel_wqs[index].in_open = 0; return -ENOSYS; } } if ((unsigned int)*p < KSEG0) { printk(KERN_WARNING "vpe_get_shared returned an invalid pointer " "maybe an error code %d\n", (int)*p); channel_wqs[index].in_open = 0; return -ENOSYS; } if ((ret = rtlx_init(*p)) < 0) { channel_wqs[index].in_open = 0; return ret; } } chan = &rtlx->channel[index]; if (chan->lx_state == RTLX_STATE_OPENED) { channel_wqs[index].in_open = 0; return -EBUSY; } chan->lx_state = RTLX_STATE_OPENED; channel_wqs[index].in_open = 0; return 0; }
int rtlx_open(int index, int can_sleep) { volatile struct rtlx_info **p; struct rtlx_channel *chan; enum rtlx_state state; int ret = 0; if (index >= RTLX_CHANNELS) { printk(KERN_DEBUG "rtlx_open index out of range\n"); return -ENOSYS; } if (atomic_inc_return(&channel_wqs[index].in_open) > 1) { printk(KERN_DEBUG "rtlx_open channel %d already opened\n", index); ret = -EBUSY; goto out_fail; } if (rtlx == NULL) { if( (p = vpe_get_shared(RTLX_TARG_VPE)) == NULL) { if (can_sleep) { __wait_event_interruptible(channel_wqs[index].lx_queue, (p = vpe_get_shared(RTLX_TARG_VPE)), ret); if (ret) goto out_fail; } else { printk(KERN_DEBUG "No SP program loaded, and device " "opened with O_NONBLOCK\n"); ret = -ENOSYS; goto out_fail; } } if (*p == NULL) { if (can_sleep) { __wait_event_interruptible(channel_wqs[index].lx_queue, *p != NULL, ret); if (ret) goto out_fail; } else { printk(" *vpe_get_shared is NULL. " "Has an SP program been loaded?\n"); ret = -ENOSYS; goto out_fail; } } if ((unsigned int)*p < KSEG0) { printk(KERN_WARNING "vpe_get_shared returned an invalid pointer " "maybe an error code %d\n", (int)*p); ret = -ENOSYS; goto out_fail; } if ((ret = rtlx_init(*p)) < 0) goto out_ret; } chan = &rtlx->channel[index]; state = xchg(&chan->lx_state, RTLX_STATE_OPENED); if (state == RTLX_STATE_OPENED) { ret = -EBUSY; goto out_fail; } out_fail: smp_mb(); atomic_dec(&channel_wqs[index].in_open); smp_mb(); out_ret: return ret; }