host-drivers/base-driver/vca/vop/vop_kvec_buff.c
int vop_kvec_get(
	struct vop_dev_common *cdev,
	struct vop_device *vdev,
	struct buffer_dma_item *item)
{
	u16 cur_idx, next_idx, num, first;
	u16 avail_cnt;
	size_t num_kvec;
	u16 head;
	struct vop_kvec_ring *ring = NULL;

	BUG_ON(item->kvec_buff_id < 0);

	ring = &cdev->kvec_buff.local_write_kvecs.rings[item->kvec_buff_id];
	num_kvec =  ring->num;

	mutex_lock(&cdev->kvec_buff.local_write_kvecs.mutex);

	/* skip cancelled requests */
	while (ring->last_cnt != *ring->cnt) {
		cur_idx = KVEC_COUNTER_TO_IDX(ring->last_cnt, num_kvec);

		if (!(ring->buf[cur_idx].flags & VOP_KVEC_FLAG_CANCELLED))
			/* Check first and non-cancelled descriptor found */
			break;
		head = ring->buf[cur_idx].head;
		dev_dbg(&vdev->dev, "%s skipping cancelled request descriptor no %u ring no %u\n",
			__func__, cur_idx, item->kvec_buff_id);
		ring->buf[cur_idx].flags = 0;
		ring->buf[cur_idx].head = 0;
		ring->last_cnt = KVEC_COUNTER_ADD(ring->last_cnt, 1, ring->num);
	}

	if (ring->last_cnt == *ring->cnt) {
		// no data available
		item->head_to = USHRT_MAX;
		mutex_unlock(&cdev->kvec_buff.local_write_kvecs.mutex);
		return -EAGAIN;
	}

	/* fetch descriptors */
	avail_cnt = *ring->cnt;
	rmb();
	first = ring->last_cnt % num_kvec;
	cur_idx = first;
	next_idx = KVEC_COUNTER_TO_IDX(ring->last_cnt + 1, num_kvec);
	head = ring->buf[cur_idx].head;
	num = 1;
	++ring->stats_num;

	dev_dbg(&vdev->dev,"%s peer_kvec[%d]: "
		"desc:(%p, %x) head:%x\n", __func__,
		cur_idx,
		ring->buf[cur_idx].iov.iov_base,
		(u32)ring->buf[cur_idx].iov.iov_len,
		ring->buf[cur_idx].head);

	ring->buf[cur_idx].head = 0;

	/* fetch all adjecent iovs with the same head value */
	while (!KVEC_COUNTER_EQ(ring->last_cnt + num, avail_cnt, ring->num) &&
	       head == ring->buf[next_idx].head &&
	       num < ring->num) {
			num++;
			cur_idx = next_idx;
			next_idx = KVEC_COUNTER_TO_IDX(next_idx + 1, num_kvec);
			dev_dbg(&vdev->dev,
				"%s peer_kvec[%d]: desc"
				":(%p, %x) head:%x\n",
				__func__,
				cur_idx,
				ring->buf[cur_idx].iov.iov_base,
				(u32)ring->buf[cur_idx].iov.iov_len,
				ring->buf[cur_idx].head);
			ring->buf[cur_idx].head = 0;
	}

	item->head_to = head;
	item->num_kvecs_to = num;
	item->kvec_to = ring->buf + first;

	/* mark avail ring buffer item as used */
	item->kvec_to->flags = VOP_KVEC_FLAG_IN_USE;

	dev_dbg(&vdev->dev,
		"%s dma_item head_to:%x num_kvecs_to:%x first_kiov: (%p %x)\n",
		__func__, item->head_to, item->num_kvecs_to,
		item->kvec_to->iov.iov_base,
		(u32)item->kvec_to->iov.iov_len);

	dev_dbg(&vdev->dev,
		"%s avail_cnt is%x (last seen: %x)\n", __func__,
		avail_cnt, ring->last_cnt);

	ring->last_cnt = KVEC_COUNTER_ADD(ring->last_cnt, num, ring->num);

	mutex_unlock(&cdev->kvec_buff.local_write_kvecs.mutex);
	return 0;
}
/* fetch descriptors from kvec_buf ring buffer */
fetch descriptors from kvec_buf ring buffer
fetch descriptors from kvec_buf ring buffer
int vop_kvec_get(
	struct vop_dev_common *cdev,
	struct vop_device *vdev,
	struct buffer_dma_item *item)
{
	u16 cur_idx, next_idx, num, first;
	u16 avail_cnt;
	size_t num_kvec;
	u16 head;
	struct vop_kvec_ring *ring = NULL;
	BUG_ON(item->kvec_buff_id < 0);
	ring = &cdev->kvec_buff.local_write_kvecs.rings[item->kvec_buff_id];
	num_kvec =  ring->num;
	mutex_lock(&cdev->kvec_buff.local_write_kvecs.mutex);
	while (ring->last_cnt != *ring->cnt) {
		cur_idx = KVEC_COUNTER_TO_IDX(ring->last_cnt, num_kvec);
		if (!(ring->buf[cur_idx].flags & VOP_KVEC_FLAG_CANCELLED))
			break;
		head = ring->buf[cur_idx].head;
		dev_dbg(&vdev->dev, "%s skipping cancelled request descriptor no %u ring no %u\n",
			__func__, cur_idx, item->kvec_buff_id);
		ring->buf[cur_idx].flags = 0;
		ring->buf[cur_idx].head = 0;
		ring->last_cnt = KVEC_COUNTER_ADD(ring->last_cnt, 1, ring->num);
	}
	if (ring->last_cnt == *ring->cnt) {
		item->head_to = USHRT_MAX;
		mutex_unlock(&cdev->kvec_buff.local_write_kvecs.mutex);
		return -EAGAIN;
	}
	avail_cnt = *ring->cnt;
	rmb();
	first = ring->last_cnt % num_kvec;
	cur_idx = first;
	next_idx = KVEC_COUNTER_TO_IDX(ring->last_cnt + 1, num_kvec);
	head = ring->buf[cur_idx].head;
	num = 1;
	++ring->stats_num;
	dev_dbg(&vdev->dev,"%s peer_kvec[%d]: "
		"desc:(%p, %x) head:%x\n", __func__,
		cur_idx,
		ring->buf[cur_idx].iov.iov_base,
		(u32)ring->buf[cur_idx].iov.iov_len,
		ring->buf[cur_idx].head);
	ring->buf[cur_idx].head = 0;
	while (!KVEC_COUNTER_EQ(ring->last_cnt + num, avail_cnt, ring->num) &&
	       head == ring->buf[next_idx].head &&
	       num < ring->num) {
			num++;
			cur_idx = next_idx;
			next_idx = KVEC_COUNTER_TO_IDX(next_idx + 1, num_kvec);
			dev_dbg(&vdev->dev,
				"%s peer_kvec[%d]: desc"
				":(%p, %x) head:%x\n",
				__func__,
				cur_idx,
				ring->buf[cur_idx].iov.iov_base,
				(u32)ring->buf[cur_idx].iov.iov_len,
				ring->buf[cur_idx].head);
			ring->buf[cur_idx].head = 0;
	}
	item->head_to = head;
	item->num_kvecs_to = num;
	item->kvec_to = ring->buf + first;
	item->kvec_to->flags = VOP_KVEC_FLAG_IN_USE;
	dev_dbg(&vdev->dev,
		"%s dma_item head_to:%x num_kvecs_to:%x first_kiov: (%p %x)\n",
		__func__, item->head_to, item->num_kvecs_to,
		item->kvec_to->iov.iov_base,
		(u32)item->kvec_to->iov.iov_len);
	dev_dbg(&vdev->dev,
		"%s avail_cnt is%x (last seen: %x)\n", __func__,
		avail_cnt, ring->last_cnt);
	ring->last_cnt = KVEC_COUNTER_ADD(ring->last_cnt, num, ring->num);
	mutex_unlock(&cdev->kvec_buff.local_write_kvecs.mutex);
	return 0;
}
int vop_kvec_get ( struct vop_dev_common * cdev , struct vop_device * vdev , struct buffer_dma_item * item ) { u16 cur_idx , next_idx , num , first ; u16 avail_cnt ; size_t num_kvec ; u16 head ; struct vop_kvec_ring * ring = NULL ; BUG_ON ( item -> kvec_buff_id < 0 ) ; ring = & cdev -> kvec_buff . local_write_kvecs . rings [ item -> kvec_buff_id ] ; num_kvec = ring -> num ; mutex_lock ( & cdev -> kvec_buff . local_write_kvecs . mutex ) ; while ( ring -> last_cnt != * ring -> cnt ) { cur_idx = KVEC_COUNTER_TO_IDX ( ring -> last_cnt , num_kvec ) ; if ( ! ( ring -> buf [ cur_idx ] . flags & VOP_KVEC_FLAG_CANCELLED ) ) break ; head = ring -> buf [ cur_idx ] . head ; dev_dbg ( & vdev -> dev , " \n " , __func__ , cur_idx , item -> kvec_buff_id ) ; ring -> buf [ cur_idx ] . flags = 0 ; ring -> buf [ cur_idx ] . head = 0 ; ring -> last_cnt = KVEC_COUNTER_ADD ( ring -> last_cnt , 1 , ring -> num ) ; } if ( ring -> last_cnt == * ring -> cnt ) { item -> head_to = USHRT_MAX ; mutex_unlock ( & cdev -> kvec_buff . local_write_kvecs . mutex ) ; return - EAGAIN ; } avail_cnt = * ring -> cnt ; rmb ( ) ; first = ring -> last_cnt % num_kvec ; cur_idx = first ; next_idx = KVEC_COUNTER_TO_IDX ( ring -> last_cnt + 1 , num_kvec ) ; head = ring -> buf [ cur_idx ] . head ; num = 1 ; ++ ring -> stats_num ; dev_dbg ( & vdev -> dev , " " " \n " , __func__ , cur_idx , ring -> buf [ cur_idx ] . iov . iov_base , ( u32 ) ring -> buf [ cur_idx ] . iov . iov_len , ring -> buf [ cur_idx ] . head ) ; ring -> buf [ cur_idx ] . head = 0 ; while ( ! KVEC_COUNTER_EQ ( ring -> last_cnt + num , avail_cnt , ring -> num ) && head == ring -> buf [ next_idx ] . head && num < ring -> num ) { num ++ ; cur_idx = next_idx ; next_idx = KVEC_COUNTER_TO_IDX ( next_idx + 1 , num_kvec ) ; dev_dbg ( & vdev -> dev , " " " \n " , __func__ , cur_idx , ring -> buf [ cur_idx ] . iov . iov_base , ( u32 ) ring -> buf [ cur_idx ] . iov . iov_len , ring -> buf [ cur_idx ] . head ) ; ring -> buf [ cur_idx ] . head = 0 ; } item -> head_to = head ; item -> num_kvecs_to = num ; item -> kvec_to = ring -> buf + first ; item -> kvec_to -> flags = VOP_KVEC_FLAG_IN_USE ; dev_dbg ( & vdev -> dev , " \n " , __func__ , item -> head_to , item -> num_kvecs_to , item -> kvec_to -> iov . iov_base , ( u32 ) item -> kvec_to -> iov . iov_len ) ; dev_dbg ( & vdev -> dev , " \n " , __func__ , avail_cnt , ring -> last_cnt ) ; ring -> last_cnt = KVEC_COUNTER_ADD ( ring -> last_cnt , num , ring -> num ) ; mutex_unlock ( & cdev -> kvec_buff . local_write_kvecs . mutex ) ; return 0 ; }
fetch descriptors from kvec_buf ring buffer
fetch descriptors from kvec_buf ring buffer
/* skip cancelled requests */ /* Check first and non-cancelled descriptor found */ // no data available /* fetch descriptors */ /* fetch all adjecent iovs with the same head value */ /* mark avail ring buffer item as used */