/** * Kernel Queue를 2개를 생성하여 2개를 각각의 쓰레드로 실행시키는 함수. */ int __init init_fifo_test(void) { unsigned int i; printk("fifo start\n"); filp1 = filp_open("/tmp/read_sense", O_WRONLY, S_IRUSR|S_IWUSR); if (IS_ERR(filp1)) { const int open_errno = -PTR_ERR(filp1); printk("fifo1 open error: %s\n errno=%d", __FUNCTION__, open_errno); return 0; } else { printk("fifo1 open success\n"); } filp = filp_open("/tmp/read_sense2", O_WRONLY, S_IRUSR|S_IWUSR); if (IS_ERR(filp)) { const int open_errno = -PTR_ERR(filp); printk("fifo open error: %s\n errno=%d", __FUNCTION__, open_errno); return 0; } else { printk("fifo open success\n"); } printk("fifo1 module insert-----------\n"); if( kfifo_alloc(&fifo1, FIFOSIZE, GFP_KERNEL) ) { printk(KERN_WARNING "fifo1 error kfifo_alloc1 \n"); return -ENOMEM; } printk("fifo module insert-----------\n"); if( kfifo_alloc(&fifo, FIFOSIZE, GFP_KERNEL) ) { printk(KERN_WARNING "fifo error kfifo_alloc \n"); return -ENOMEM; } printk(KERN_INFO "queue1 size : %u \n", kfifo_size(&fifo1)); printk(KERN_INFO "queue size : %u \n", kfifo_size(&fifo)); printk(KERN_INFO "queue1 available : %u\n", kfifo_avail(&fifo1)); printk(KERN_INFO "queue available : %u\n", kfifo_avail(&fifo)); #if 1 printk(KERN_INFO "thread_start1\n"); t_id1 = (struct task_struct *)kthread_run(thread_loop1, NULL, "%s", "create_test1"); printk(KERN_INFO "thread_start\n"); t_id = (struct task_struct *)kthread_run(thread_loop, NULL, "%s", "create_test"); #endif return 0; }
static int whiteheat_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg) { struct usb_serial_port *port = tty->driver_data; struct serial_struct serstruct; void __user *user_arg = (void __user *)arg; dbg("%s - port %d, cmd 0x%.4x", __func__, port->number, cmd); switch (cmd) { case TIOCGSERIAL: memset(&serstruct, 0, sizeof(serstruct)); serstruct.type = PORT_16654; serstruct.line = port->serial->minor; serstruct.port = port->number; serstruct.flags = ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ; serstruct.xmit_fifo_size = kfifo_size(&port->write_fifo); serstruct.custom_divisor = 0; serstruct.baud_base = 460800; serstruct.close_delay = CLOSING_DELAY; serstruct.closing_wait = CLOSING_DELAY; if (copy_to_user(user_arg, &serstruct, sizeof(serstruct))) return -EFAULT; break; default: break; } return -ENOIOCTLCMD; }
int kfifo_ready(struct kfifo *kfifo) { if (kfifo) { return kfifo_size(kfifo) - kfifo_free(kfifo); } return 0; }
static long rpmsg_dev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { unsigned int tmp; struct _rpmsg_device *_prpmsg_device = (struct _rpmsg_device *)filp->private_data; struct _rpmsg_params *local = ( struct _rpmsg_params *)&_prpmsg_device->rpmsg_params; switch (cmd) { case IOCTL_CMD_GET_KFIFO_SIZE: tmp = kfifo_size(&local->rpmsg_kfifo); if (copy_to_user((unsigned int *)arg, &tmp, sizeof(int))) return -EACCES; break; case IOCTL_CMD_GET_AVAIL_DATA_SIZE: tmp = kfifo_len(&local->rpmsg_kfifo); pr_info("kfifo len ioctl = %d ", kfifo_len(&local->rpmsg_kfifo)); if (copy_to_user((unsigned int *)arg, &tmp, sizeof(int))) return -EACCES; break; case IOCTL_CMD_GET_FREE_BUFF_SIZE: tmp = kfifo_avail(&local->rpmsg_kfifo); if (copy_to_user((unsigned int *)arg, &tmp, sizeof(int))) return -EACCES; break; default: return -EINVAL; } return 0; }
static int __logic_dispatch_push(ccif_msg_t *msg, void *ctl_b) { logic_channel_info_t *ch_info; int ret = 0; logic_dispatch_ctl_block_t *ctl_block = (logic_dispatch_ctl_block_t*)ctl_b; int md_id = ctl_block->m_md_id; int drop = 1; if (unlikely(msg->channel >= CCCI_MAX_CH_NUM)){ CCCI_MSG_INF(md_id, "cci", "%s get invalid logic ch id:%d\n", \ __FUNCTION__, msg->channel); ret = -CCCI_ERR_INVALID_LOGIC_CHANNEL_ID; goto _out; } ch_info = &(ctl_block->m_logic_ch_table[msg->channel]); if (unlikely(ch_info->m_attrs&L_CH_ATTR_TX)){ CCCI_MSG_INF(md_id, "cci", "%s CH:%d %s is tx channel\n", __FUNCTION__, \ msg->channel, ch_info->m_ch_name); ret = -CCCI_ERR_PUSH_RX_DATA_TO_TX_CHANNEL; goto _out; } // check whether fifo is ready if (!ch_info->m_kfifo_ready){ CCCI_MSG_INF(md_id, "cci", "%s CH:%d %s's kfifo is not ready\n", \ __FUNCTION__, msg->channel, ch_info->m_ch_name); ret = -CCCI_ERR_KFIFO_IS_NOT_READY; goto _out; } // Check fifo free space if (kfifo_is_full(&ch_info->m_kfifo)) { if (ch_info->m_attrs&L_CH_DROP_TOLERATED){ CCCI_CTL_MSG(md_id, "Drop (%08X %08X %02d %08X) is tolerated\n", \ msg->data[0], msg->data[1], msg->channel, msg->reserved); ret = sizeof(ccif_msg_t); } else { // message should NOT be droped CCCI_DBG_MSG(md_id, "cci", "kfifo full: ch:%s size:%d (%08X %08X %02d %08X)\n", ch_info->m_ch_name, kfifo_size(&ch_info->m_kfifo),msg->data[0], msg->data[1], msg->channel, msg->reserved); // disalbe CCIF interrupt here???? ret = 0; // Fix this!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! } goto _out; } // Push data ret = kfifo_in(&ch_info->m_kfifo,msg,sizeof(ccif_msg_t)); WARN_ON(ret!=sizeof(ccif_msg_t)); ctl_block->m_has_pending_data = 1; drop = 0; _out: add_logic_layer_record(md_id, (ccci_msg_t*)msg, drop); return ret; }
static int iio_kfifo_remove_from(struct iio_buffer *r, void *data) { int ret; struct iio_kfifo *kf = iio_to_kfifo(r); if (kfifo_size(&kf->kf) < r->bytes_per_datum) return -EBUSY; ret = kfifo_out(&kf->kf, data, r->bytes_per_datum); if (ret != r->bytes_per_datum) return -EBUSY; wake_up_interruptible_poll(&r->pollq, POLLOUT | POLLWRNORM); return 0; }
static int whiteheat_get_serial(struct tty_struct *tty, struct serial_struct *ss) { struct usb_serial_port *port = tty->driver_data; ss->type = PORT_16654; ss->line = port->minor; ss->port = port->port_number; ss->xmit_fifo_size = kfifo_size(&port->write_fifo); ss->custom_divisor = 0; ss->baud_base = 460800; ss->close_delay = CLOSING_DELAY; ss->closing_wait = CLOSING_DELAY; return 0; }
static int __init queue_init(void) { int i; unsigned int ret; unsigned int val; printk(KERN_INFO "FIFO start\n"); if (kfifo_alloc(&fifo, FIFO_SIZE, GFP_KERNEL)) { printk(KERN_WARNING "error kfifo\n"); return -ENOMEM; } printk(KERN_INFO "queue size: %u\n", kfifo_size(&fifo)); kfifo_in(&fifo, "test", 4); for (i = 0; i < 4; i++) kfifo_in(&fifo, &i, sizeof(i)); ret = kfifo_out(&fifo, buffer, 4); if (ret != 4) return -EINVAL; printk(KERN_INFO "%s\n", buffer); printk(KERN_INFO "queue len: %u\n", kfifo_len(&fifo)); while (!kfifo_is_empty(&fifo)) { ret = kfifo_out(&fifo, &val, sizeof(val)); if (ret != sizeof(val)) return -EINVAL; printk(KERN_INFO "%u\n", val); } return 0; }
static int __init example_init(void) { int i; unsigned int ret; unsigned int nents; struct scatterlist sg[10]; printk(KERN_INFO "DMA fifo test start\n"); if (kfifo_alloc(&fifo, FIFO_SIZE, GFP_KERNEL)) { printk(KERN_WARNING "error kfifo_alloc\n"); return -ENOMEM; } printk(KERN_INFO "queue size: %u\n", kfifo_size(&fifo)); kfifo_in(&fifo, "test", 4); for (i = 0; i != 9; i++) kfifo_put(&fifo, i); /* kick away first byte */ kfifo_skip(&fifo); printk(KERN_INFO "queue len: %u\n", kfifo_len(&fifo)); /* * Configure the kfifo buffer to receive data from DMA input. * * .--------------------------------------. * | 0 | 1 | 2 | ... | 12 | 13 | ... | 31 | * |---|------------------|---------------| * \_/ \________________/ \_____________/ * \ \ \ * \ \_allocated data \ * \_*free space* \_*free space* * * We need two different SG entries: one for the free space area at the * end of the kfifo buffer (19 bytes) and another for the first free * byte at the beginning, after the kfifo_skip(). */ sg_init_table(sg, ARRAY_SIZE(sg)); nents = kfifo_dma_in_prepare(&fifo, sg, ARRAY_SIZE(sg), FIFO_SIZE); printk(KERN_INFO "DMA sgl entries: %d\n", nents); if (!nents) { /* fifo is full and no sgl was created */ printk(KERN_WARNING "error kfifo_dma_in_prepare\n"); return -EIO; } /* receive data */ printk(KERN_INFO "scatterlist for receive:\n"); for (i = 0; i < nents; i++) { printk(KERN_INFO "sg[%d] -> " "page_link 0x%.8lx offset 0x%.8x length 0x%.8x\n", i, sg[i].page_link, sg[i].offset, sg[i].length); if (sg_is_last(&sg[i])) break; } /* put here your code to setup and exectute the dma operation */ /* ... */ /* example: zero bytes received */ ret = 0; /* finish the dma operation and update the received data */ kfifo_dma_in_finish(&fifo, ret); /* Prepare to transmit data, example: 8 bytes */ nents = kfifo_dma_out_prepare(&fifo, sg, ARRAY_SIZE(sg), 8); printk(KERN_INFO "DMA sgl entries: %d\n", nents); if (!nents) { /* no data was available and no sgl was created */ printk(KERN_WARNING "error kfifo_dma_out_prepare\n"); return -EIO; } printk(KERN_INFO "scatterlist for transmit:\n"); for (i = 0; i < nents; i++) { printk(KERN_INFO "sg[%d] -> " "page_link 0x%.8lx offset 0x%.8x length 0x%.8x\n", i, sg[i].page_link, sg[i].offset, sg[i].length); if (sg_is_last(&sg[i])) break; } /* put here your code to setup and exectute the dma operation */ /* ... */ /* example: 5 bytes transmitted */ ret = 5; /* finish the dma operation and update the transmitted data */ kfifo_dma_out_finish(&fifo, ret); ret = kfifo_len(&fifo); printk(KERN_INFO "queue len: %u\n", kfifo_len(&fifo)); if (ret != 7) { printk(KERN_WARNING "size mismatch: test failed"); return -EIO; } printk(KERN_INFO "test passed\n"); return 0; }
static int __init example_init(void) { int i; unsigned int ret; struct scatterlist sg[10]; printk(KERN_INFO "DMA fifo test start\n"); if (kfifo_alloc(&fifo, FIFO_SIZE, GFP_KERNEL)) { printk(KERN_ERR "error kfifo_alloc\n"); return 1; } printk(KERN_INFO "queue size: %u\n", kfifo_size(&fifo)); kfifo_in(&fifo, "test", 4); for (i = 0; i != 9; i++) kfifo_put(&fifo, &i); /* kick away first byte */ ret = kfifo_get(&fifo, &i); printk(KERN_INFO "queue len: %u\n", kfifo_len(&fifo)); ret = kfifo_dma_in_prepare(&fifo, sg, ARRAY_SIZE(sg), FIFO_SIZE); printk(KERN_INFO "DMA sgl entries: %d\n", ret); /* if 0 was returned, fifo is full and no sgl was created */ if (ret) { printk(KERN_INFO "scatterlist for receive:\n"); for (i = 0; i < ARRAY_SIZE(sg); i++) { printk(KERN_INFO "sg[%d] -> " "page_link 0x%.8lx offset 0x%.8x length 0x%.8x\n", i, sg[i].page_link, sg[i].offset, sg[i].length); if (sg_is_last(&sg[i])) break; } /* but here your code to setup and exectute the dma operation */ /* ... */ /* example: zero bytes received */ ret = 0; /* finish the dma operation and update the received data */ kfifo_dma_in_finish(&fifo, ret); } ret = kfifo_dma_out_prepare(&fifo, sg, ARRAY_SIZE(sg), 8); printk(KERN_INFO "DMA sgl entries: %d\n", ret); /* if 0 was returned, no data was available and no sgl was created */ if (ret) { printk(KERN_INFO "scatterlist for transmit:\n"); for (i = 0; i < ARRAY_SIZE(sg); i++) { printk(KERN_INFO "sg[%d] -> " "page_link 0x%.8lx offset 0x%.8x length 0x%.8x\n", i, sg[i].page_link, sg[i].offset, sg[i].length); if (sg_is_last(&sg[i])) break; } /* but here your code to setup and exectute the dma operation */ /* ... */ /* example: 5 bytes transmitted */ ret = 5; /* finish the dma operation and update the transmitted data */ kfifo_dma_out_finish(&fifo, ret); } printk(KERN_INFO "queue len: %u\n", kfifo_len(&fifo)); return 0; }
/** * kfifo_avail - returns the number of bytes available in the FIFO * @fifo: the fifo to be used. */ unsigned int kfifo_avail(struct kfifo *fifo) { return kfifo_size(fifo) - kfifo_len(fifo); }
/** * kfifo_is_full - returns true if the fifo is full * @fifo: the fifo to be used. */ int kfifo_is_full(struct kfifo *fifo) { return kfifo_len(fifo) == kfifo_size(fifo); }