예제 #1
0
static struct iscsi_r2t_info *iscsi_tcp_get_curr_r2t(struct iscsi_task *task)
{
	struct iscsi_session *session = task->conn->session;
	struct iscsi_tcp_task *tcp_task = task->dd_data;
	struct iscsi_r2t_info *r2t = NULL;

	if (iscsi_task_has_unsol_data(task))
		r2t = &task->unsol_r2t;
	else {
		spin_lock_bh(&session->lock);
		if (tcp_task->r2t) {
			r2t = tcp_task->r2t;
			/* Continue with this R2T? */
			if (r2t->data_length <= r2t->sent) {
				ISCSI_DBG_TCP(task->conn,
					      "  done with r2t %p\n", r2t);
				__kfifo_put(tcp_task->r2tpool.queue,
					    (void *)&tcp_task->r2t,
					    sizeof(void *));
				tcp_task->r2t = r2t = NULL;
			}
		}

		if (r2t == NULL) {
			__kfifo_get(tcp_task->r2tqueue,
				    (void *)&tcp_task->r2t, sizeof(void *));
			r2t = tcp_task->r2t;
		}
		spin_unlock_bh(&session->lock);
	}

	return r2t;
}
예제 #2
0
파일: mailbox.c 프로젝트: kpykc/ARDrone2.0
/*
 * message sender
 */
int omap_mbox_msg_send(struct omap_mbox *mbox, mbox_msg_t msg)
{
	struct omap_mbox_queue *mq = mbox->txq;
	int ret = 0, len;

	spin_lock_bh(&mq->lock);
	if ((FIFO_SIZE - (__kfifo_len(mq->fifo))) < sizeof(msg)) {
		ret = -ENOMEM;
		goto out;
	}

	if (!__kfifo_len(mq->fifo)) {
		if (!mbox_fifo_full(mbox)) {
			if (mbox->txq->callback)
				ret = mbox->txq->callback(NULL);
			mbox_fifo_write(mbox, msg);
			goto out;
		}
	}

	len = __kfifo_put(mq->fifo, (unsigned char *)&msg, sizeof(msg));
	if (unlikely(len != sizeof(msg))) {
		pr_err("%s: __kfifo_put anomaly detected\n", __func__);
		ret = -ENOMEM;
	}
	tasklet_schedule(&mbox->txq->tasklet);

out:
	spin_unlock_bh(&mq->lock);
	return ret;
}
예제 #3
0
static int srp_iu_pool_alloc(struct srp_queue *q, size_t max,
			     struct srp_buf **ring)
{
	int i;
	struct iu_entry *iue;

	q->pool = kcalloc(max, sizeof(struct iu_entry *), GFP_KERNEL);
	if (!q->pool)
		return -ENOMEM;
	q->items = kcalloc(max, sizeof(struct iu_entry), GFP_KERNEL);
	if (!q->items)
		goto free_pool;

	spin_lock_init(&q->lock);
	q->queue = kfifo_init((void *) q->pool, max * sizeof(void *),
			      GFP_KERNEL, &q->lock);
	if (IS_ERR(q->queue))
		goto free_item;

	for (i = 0, iue = q->items; i < max; i++) {
		__kfifo_put(q->queue, (void *) &iue, sizeof(void *));
		iue->sbuf = ring[i];
		iue++;
	}
	return 0;

free_item:
	kfree(q->items);
free_pool:
	kfree(q->pool);
	return -ENOMEM;
}
예제 #4
0
static void rfbi_push_cmd(struct update_param *p)
{
	int ret;

	while (1) {
		unsigned long flags;
		int available;

		spin_lock_irqsave(rfbi.cmd_fifo->lock, flags);
		available = RFBI_CMD_FIFO_LEN_BYTES -
			__kfifo_len(rfbi.cmd_fifo);

/*		DSSDBG("%d bytes left in fifo\n", available); */
		if (available < sizeof(struct update_param)) {
			DSSDBG("Going to wait because FIFO FULL..\n");
			spin_unlock_irqrestore(rfbi.cmd_fifo->lock, flags);
			atomic_inc(&rfbi.cmd_fifo_full);
			wait_for_completion(&rfbi.cmd_done);
			/*DSSDBG("Woke up because fifo not full anymore\n");*/
			continue;
		}

		ret = __kfifo_put(rfbi.cmd_fifo, (unsigned char *)p,
				  sizeof(struct update_param));
/*		DSSDBG("pushed %d bytes\n", ret);*/

		spin_unlock_irqrestore(rfbi.cmd_fifo->lock, flags);

		BUG_ON(ret != sizeof(struct update_param));

		break;
	}
}
예제 #5
0
ssize_t venus_ir_wo_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos) {
    uint32_t uintBuf;
    int writeCount;

    if ((p_venus_ir_fifo == NULL) || (p_venus_ir_read_wait == NULL)) {
        return -EFAULT;
    }

    if (count < sizeof(uint32_t)) {
        return 0;
    }

    for (writeCount=0; writeCount<count; writeCount+=sizeof(uint32_t)) {
        if (copy_from_user(&uintBuf, buf, sizeof(uint32_t))) {
            return -EFAULT;
        }
        __kfifo_put(*p_venus_ir_fifo, (unsigned char*)&uintBuf, sizeof(uint32_t));
        dbg("wrote 0x%08x to IR fifo\n", uintBuf);
    }
    /* Wake up all pending processes on FIFO data */
    if (writeCount > 0) {
        wake_up_interruptible(p_venus_ir_read_wait);
    }

    return writeCount;
}
예제 #6
0
파일: mailbox.c 프로젝트: kpykc/ARDrone2.0
static void __mbox_rx_interrupt(struct omap_mbox *mbox)
{
	struct omap_mbox_queue *mq = mbox->rxq;
	mbox_msg_t msg;
	int len;

	while (!mbox_fifo_empty(mbox)) {
		if (unlikely(__kfifo_len(mq->fifo) >=
				FIFO_SIZE - sizeof(msg))) {
			omap_mbox_disable_irq(mbox, IRQ_RX);
			rq_full = true;
			goto nomem;
		}

		msg = mbox_fifo_read(mbox);

		len = __kfifo_put(mq->fifo, (unsigned char *)&msg, sizeof(msg));
		if (unlikely(len != sizeof(msg)))
			pr_err("%s: __kfifo_put anomaly detected\n", __func__);
		if (mbox->ops->type == OMAP_MBOX_TYPE1)
			break;
	}

	/* no more messages in the fifo. clear IRQ source. */
	ack_mbox_irq(mbox, IRQ_RX);
nomem:
	queue_work(mboxd, &mbox->rxq->work);
}
예제 #7
0
static irqreturn_t stylus_updown(int irq, void *dev_id)
{
	unsigned long data0;
	unsigned long data1;
	int event_type;

	data0 = readl(base_addr+S3C2410_ADCDAT0);
	data1 = readl(base_addr+S3C2410_ADCDAT1);

	ts.is_down = (!(data0 & S3C2410_ADCDAT0_UPDOWN)) &&
					    (!(data1 & S3C2410_ADCDAT0_UPDOWN));

	event_type = ts.is_down ? 'D' : 'U';

	if (unlikely(__kfifo_put(ts.event_fifo, (unsigned char *)&event_type,
		     sizeof(int)) != sizeof(int))) /* should not happen */
		printk(KERN_ERR __FILE__": stylus_updown lost event!\n");

	if (ts.is_down)
		s3c2410_ts_start_adc_conversion();
	else
		writel(WAIT4INT(0), base_addr+S3C2410_ADCTSC);

	mod_timer(&event_send_timer, jiffies + 1);

	return IRQ_HANDLED;
}
예제 #8
0
/*
* Create a 'fakekey' sysfs parameter - this allows to issue:
*   echo 'fa05ff00' > /sys/devices/platform/VenusIR_W/fakekey
* to add a new IR key to the VenusIR FIFO
*/
static ssize_t store_fakekey(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) {
    char *endp;
    uint32_t key = simple_strtoul(buf, &endp, 16);
    if (endp != buf && (*endp == '\0' || *endp == '\n')) {
        __kfifo_put(*p_venus_ir_fifo, (unsigned char *)&key, sizeof(uint32_t));
        dbg("wrote 0x%08x to IR fifo\n", key);
        wake_up_interruptible(p_venus_ir_read_wait);
    }
    return count;
}
예제 #9
0
unsigned int gx_push_link_buffer(int link_index, unsigned int len, const char *buf){
	if(s_gx){
		Link *l = s_gx->getLink(link_index);
		if(l){
			unsigned int r = __kfifo_put(&l->write_fifo_, buf,len);
			return r;
		}
	}

	return 0;
}
예제 #10
0
/**
 * iscsi_tcp_cleanup_task - free tcp_task resources
 * @task: iscsi task
 *
 * must be called with session lock
 */
void iscsi_tcp_cleanup_task(struct iscsi_task *task)
{
	struct iscsi_tcp_task *tcp_task = task->dd_data;
	struct iscsi_r2t_info *r2t;

	/* nothing to do for mgmt */
	if (!task->sc)
		return;

	/* flush task's r2t queues */
	while (__kfifo_get(tcp_task->r2tqueue, (void*)&r2t, sizeof(void*))) {
		__kfifo_put(tcp_task->r2tpool.queue, (void*)&r2t,
			    sizeof(void*));
		ISCSI_DBG_TCP(task->conn, "pending r2t dropped\n");
	}

	r2t = tcp_task->r2t;
	if (r2t != NULL) {
		__kfifo_put(tcp_task->r2tpool.queue, (void*)&r2t,
			    sizeof(void*));
		tcp_task->r2t = NULL;
	}
}
예제 #11
0
void lbs_queue_event(struct lbs_private *priv, u32 event)
{
  //unsigned long flags;
	lbs_deb_enter(LBS_DEB_THREAD);
	//spin_lock_irqsave(&priv->driver_lock, flags);

	if (priv->psstate == PS_STATE_SLEEP)
		priv->psstate = PS_STATE_AWAKE;

	__kfifo_put(priv->event_fifo, (unsigned char *)&event, sizeof(u32));
	//wake_up_interruptible(&priv->waitq);
	lbs_thread(priv);

	//spin_unlock_irqrestore(&priv->driver_lock, flags);
	lbs_deb_leave(LBS_DEB_THREAD);
}
예제 #12
0
void iser_snd_completion(struct iser_desc *tx_desc)
{
	struct iser_dto        *dto = &tx_desc->dto;
	struct iser_conn       *ib_conn = dto->ib_conn;
	struct iscsi_iser_conn *iser_conn = ib_conn->iser_conn;
	struct iscsi_conn      *conn = iser_conn->iscsi_conn;
	struct iscsi_mgmt_task *mtask;
	int resume_tx = 0;

	iser_dbg("Initiator, Data sent dto=0x%p\n", dto);

	iser_dto_buffs_release(dto);

	if (tx_desc->type == ISCSI_TX_DATAOUT)
		kmem_cache_free(ig.desc_cache, tx_desc);

	if (atomic_read(&iser_conn->ib_conn->post_send_buf_count) ==
	    ISER_QP_MAX_REQ_DTOS)
		resume_tx = 1;

	atomic_dec(&ib_conn->post_send_buf_count);

	if (resume_tx) {
		iser_dbg("%ld resuming tx\n",jiffies);
		scsi_queue_work(conn->session->host, &conn->xmitwork);
	}

	if (tx_desc->type == ISCSI_TX_CONTROL) {
		/* this arithmetic is legal by libiscsi dd_data allocation */
		mtask = (void *) ((long)(void *)tx_desc -
				  sizeof(struct iscsi_mgmt_task));
		if (mtask->hdr->itt == cpu_to_be32(ISCSI_RESERVED_TAG)) {
			struct iscsi_session *session = conn->session;

			spin_lock(&conn->session->lock);
			list_del(&mtask->running);
			__kfifo_put(session->mgmtpool.queue, (void*)&mtask,
				    sizeof(void*));
			spin_unlock(&session->lock);
		}
	}
}
예제 #13
0
static irqreturn_t stylus_action(int irq, void *dev_id)
{
	int buf[3];

	/* Grab the ADC results. */
	buf[1] = readl(base_addr + S3C2410_ADCDAT0) &
		       S3C2410_ADCDAT0_XPDATA_MASK;
	buf[2] = readl(base_addr + S3C2410_ADCDAT1) &
		       S3C2410_ADCDAT1_YPDATA_MASK;

	switch (ts_filter_chain_feed(ts.chain, &buf[1])) {
	case 0:
		/* The filter wants more points. */
		s3c2410_ts_start_adc_conversion();
		return IRQ_HANDLED;
	case 1:
		/* We have a point from the filters or no filtering enabled. */
		buf[0] = 'P';
		break;
	default:
		printk(KERN_ERR __FILE__
		       ":%d Invalid ts_filter_chain_feed return value.\n",
		       __LINE__);
	case -1:
		/* Error. Ignore the event. */
		ts_filter_chain_clear(ts.chain);
		writel(WAIT4INT(1), base_addr + S3C2410_ADCTSC);
		return IRQ_HANDLED;
	};

	if (unlikely(__kfifo_put(ts.event_fifo, (unsigned char *)buf,
		     sizeof(int) * 3) != sizeof(int) * 3))
		printk(KERN_ERR __FILE__":stylus_action bug.\n");

	writel(WAIT4INT(1), base_addr + S3C2410_ADCTSC);
	mod_timer(&event_send_timer, jiffies + 1);

	return IRQ_HANDLED;
}
예제 #14
0
/**
 * iscsi_tcp_r2t_rsp - iSCSI R2T Response processing
 * @conn: iscsi connection
 * @task: scsi command task
 */
static int iscsi_tcp_r2t_rsp(struct iscsi_conn *conn, struct iscsi_task *task)
{
	struct iscsi_session *session = conn->session;
	struct iscsi_tcp_task *tcp_task = task->dd_data;
	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
	struct iscsi_r2t_rsp *rhdr = (struct iscsi_r2t_rsp *)tcp_conn->in.hdr;
	struct iscsi_r2t_info *r2t;
	int r2tsn = be32_to_cpu(rhdr->r2tsn);
	int rc;

	if (tcp_conn->in.datalen) {
		iscsi_conn_printk(KERN_ERR, conn,
				  "invalid R2t with datalen %d\n",
				  tcp_conn->in.datalen);
		return ISCSI_ERR_DATALEN;
	}

	if (tcp_task->exp_datasn != r2tsn){
		ISCSI_DBG_TCP(conn, "task->exp_datasn(%d) != rhdr->r2tsn(%d)\n",
			      tcp_task->exp_datasn, r2tsn);
		return ISCSI_ERR_R2TSN;
	}

	/* fill-in new R2T associated with the task */
	iscsi_update_cmdsn(session, (struct iscsi_nopin*)rhdr);

	if (!task->sc || session->state != ISCSI_STATE_LOGGED_IN) {
		iscsi_conn_printk(KERN_INFO, conn,
				  "dropping R2T itt %d in recovery.\n",
				  task->itt);
		return 0;
	}

	rc = __kfifo_get(tcp_task->r2tpool.queue, (void*)&r2t, sizeof(void*));
	if (!rc) {
		iscsi_conn_printk(KERN_ERR, conn, "Could not allocate R2T. "
				  "Target has sent more R2Ts than it "
				  "negotiated for or driver has has leaked.\n");
		return ISCSI_ERR_PROTO;
	}

	r2t->exp_statsn = rhdr->statsn;
	r2t->data_length = be32_to_cpu(rhdr->data_length);
	if (r2t->data_length == 0) {
		iscsi_conn_printk(KERN_ERR, conn,
				  "invalid R2T with zero data len\n");
		__kfifo_put(tcp_task->r2tpool.queue, (void*)&r2t,
			    sizeof(void*));
		return ISCSI_ERR_DATALEN;
	}

	if (r2t->data_length > session->max_burst)
		ISCSI_DBG_TCP(conn, "invalid R2T with data len %u and max "
			      "burst %u. Attempting to execute request.\n",
			      r2t->data_length, session->max_burst);

	r2t->data_offset = be32_to_cpu(rhdr->data_offset);
	if (r2t->data_offset + r2t->data_length > scsi_out(task->sc)->length) {
		iscsi_conn_printk(KERN_ERR, conn,
				  "invalid R2T with data len %u at offset %u "
				  "and total length %d\n", r2t->data_length,
				  r2t->data_offset, scsi_out(task->sc)->length);
		__kfifo_put(tcp_task->r2tpool.queue, (void*)&r2t,
			    sizeof(void*));
		return ISCSI_ERR_DATALEN;
	}

	r2t->ttt = rhdr->ttt; /* no flip */
	r2t->datasn = 0;
	r2t->sent = 0;

	tcp_task->exp_datasn = r2tsn + 1;
	__kfifo_put(tcp_task->r2tqueue, (void*)&r2t, sizeof(void*));
	conn->r2t_pdus_cnt++;

	iscsi_requeue_task(task);
	return 0;
}