/* 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;
}
예제 #2
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);
}
예제 #3
0
파일: rtlx-cmp.c 프로젝트: 24hours/linux
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;
	}
}
예제 #4
0
파일: rtlx.c 프로젝트: Herysutrisno/mpc5200
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;
}
예제 #5
0
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;
}
예제 #6
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;
}