예제 #1
0
static ssize_t hsi_char_read(struct file *file, char __user *buf,
			     size_t count, loff_t *ppos)
{
	int ch = (int)file->private_data;
	DECLARE_WAITQUEUE(wait, current);
	u32 *data;
	unsigned int data_len;
	struct char_queue *entry;
	ssize_t ret;

	/*printk(KERN_DEBUG "%s, count = %d\n", __func__, count); */

	/* only 32bit data is supported for now */
	if ((count < 4) || (count & 3))
		return -EINVAL;

	data = kmalloc(count, GFP_ATOMIC);

	ret = if_hsi_read(ch, data, count);
	if (ret < 0) {
		kfree(data);
		goto out2;
	}

	spin_lock_bh(&hsi_char_data[ch].lock);
	add_wait_queue(&hsi_char_data[ch].rx_wait, &wait);
	spin_unlock_bh(&hsi_char_data[ch].lock);

	for (;;) {
		data = NULL;
		data_len = 0;

		set_current_state(TASK_INTERRUPTIBLE);

		spin_lock_bh(&hsi_char_data[ch].lock);
		if (!list_empty(&hsi_char_data[ch].rx_queue)) {
			entry = list_entry(hsi_char_data[ch].rx_queue.next,
					   struct char_queue, list);
			data = entry->data;
			data_len = entry->count;
			list_del(&entry->list);
			kfree(entry);
		}
		spin_unlock_bh(&hsi_char_data[ch].lock);

		pr_debug("%s, data = 0x%p, data_len = %d\n",
			 __func__, data, data_len);

		if (data_len) {
			pr_debug("%s, RX finished\n", __func__);
			spin_lock_bh(&hsi_char_data[ch].lock);
			hsi_char_data[ch].poll_event &= ~(POLLIN | POLLRDNORM);
			spin_unlock_bh(&hsi_char_data[ch].lock);
			if_hsi_poll(ch);
			break;
		} else if (file->f_flags & O_NONBLOCK) {
			pr_debug("%s, O_NONBLOCK\n", __func__);
			ret = -EAGAIN;
			goto out;
		} else if (signal_pending(current)) {
			pr_debug("%s, ERESTARTSYS\n", __func__);
			ret = -EAGAIN;
			if_hsi_cancel_read(ch);
			/* goto out; */
			break;
		}

		/*printk(KERN_DEBUG "%s, going to sleep...\n", __func__); */
		schedule();
		/*printk(KERN_DEBUG "%s, woke up\n", __func__); */
	}
예제 #2
0
int hsi_proto_read(int ch, u32 *buffer, int count)
{
        DECLARE_WAITQUEUE(wait, current);
	u32 *data;
        unsigned int data_len = 0;
        struct protocol_queue *entry;
        int ret, recv_data = 0;


        /*printk(KERN_DEBUG "%s, count = %d\n", __func__, count); */

/*        if (count > MAX_HSI_IPC_BUFFER) 
                count = MAX_HSI_IPC_BUFFER;

        data = kmalloc(count, GFP_ATOMIC);*/


        ret = if_hsi_read(ch, buffer, count);
        if (ret < 0) {
                pr_err("Can not submit read. READ Error \n");
		goto out2;
        }

        spin_lock_bh(&hsi_protocol_data[ch].lock);
        add_wait_queue(&hsi_protocol_data[ch].rx_wait, &wait);
        spin_unlock_bh(&hsi_protocol_data[ch].lock);

        for (;;) {
                data = NULL;
                data_len = 0;

                set_current_state(TASK_INTERRUPTIBLE);

                spin_lock_bh(&hsi_protocol_data[ch].lock);
                if (!list_empty(&hsi_protocol_data[ch].rx_queue)) {
                        entry = list_entry(hsi_protocol_data[ch].rx_queue.next,
                                           struct protocol_queue, list);
                        data = entry->data;
                        data_len = entry->count;
                        list_del(&entry->list);
                        kfree(entry);
                } 
                spin_unlock_bh(&hsi_protocol_data[ch].lock);

                pr_debug("%s, data = 0x%p, data_len = %d\n",
                         __func__, data, data_len);

                if (data_len) {
                        pr_debug("%s, RX finished\n", __func__);
                        //printk("%s, RX finished, ch-> %d, length = %d\n", __func__, ch, count);
                        spin_lock_bh(&hsi_protocol_data[ch].lock);
                        hsi_protocol_data[ch].poll_event &= ~(POLLIN | POLLRDNORM);
                        spin_unlock_bh(&hsi_protocol_data[ch].lock);
                        if_hsi_poll(ch);
			//memcpy(buffer, data, count); 
			recv_data += data_len;
			//buffer += data_len;
			//if ((recv_data == count) || (recv_data => MAX_HSI_IPC_BUFFER))
                        	break;
                } else if (signal_pending(current)) {
                        pr_debug("%s, ERESTARTSYS\n", __func__);
                        recv_data = -EAGAIN;
                        if_hsi_cancel_read(ch);
                        /* goto out; */
                        break;
                }

                /*printk(KERN_DEBUG "%s, going to sleep...\n", __func__); */
                schedule();
                /*printk(KERN_DEBUG "%s, woke up\n", __func__); */
        }