int mux_ipc_sdio_read(char *buf, size_t  count)
{
        int ret = 0;

        wait_event_interruptible(s_mux_read_rts, !kfifo_is_empty(&s_mipc_rx_cache_kfifo) || s_mux_ipc_event_flags);

        if(s_mux_ipc_event_flags & MUX_IPC_READ_DISABLE) {
                printk("[mipc] mux ipc  read disable!\r\n");
                return -1;
        }

        IPC_DBG("[mipc]mux_ipc_sdio_read read len:%d\r\n", count);
        ret = kfifo_out(&s_mipc_rx_cache_kfifo,buf,count);

        ipc_info_mux_read(ret);

        ipc_info_sdio_read_saved_count(kfifo_len(&s_mipc_rx_cache_kfifo));

        return ret;
}
Beispiel #2
0
void ath10k_htt_tx_free(struct ath10k_htt *htt)
{
	int size;

	tasklet_kill(&htt->txrx_compl_task);

	idr_for_each(&htt->pending_tx, ath10k_htt_tx_clean_up_pending, htt->ar);
	idr_destroy(&htt->pending_tx);

	if (htt->txbuf.vaddr) {
		size = htt->max_num_pending_tx *
				  sizeof(struct ath10k_htt_txbuf);
		dma_free_coherent(htt->ar->dev, size, htt->txbuf.vaddr,
				  htt->txbuf.paddr);
	}

	ath10k_htt_tx_free_txq(htt);
	ath10k_htt_tx_free_cont_frag_desc(htt);
	WARN_ON(!kfifo_is_empty(&htt->txdone_fifo));
	kfifo_free(&htt->txdone_fifo);
}
static void delayed_work_cb(struct work_struct *work)
{
	struct hidpp_device *hidpp_device =
		container_of(work, struct hidpp_device, work);
	unsigned long flags;
	int count;
	enum delayed_work_type work_type;

	dbg_hid("%s\n", __func__);

	spin_lock_irqsave(&hidpp_device->lock, flags);

	count = kfifo_out(&hidpp_device->delayed_work_fifo, &work_type,
				sizeof(enum delayed_work_type));

	if (count != sizeof(enum delayed_work_type)) {
		dev_err(&hidpp_device->hid_dev->dev, "%s: workitem triggered without "
			"notifications available\n", __func__);
		spin_unlock_irqrestore(&hidpp_device->lock, flags);
		return;
	}

	if (!kfifo_is_empty(&hidpp_device->delayed_work_fifo)) {
		if (schedule_work(&hidpp_device->work) == 0) {
			dbg_hid("%s: did not schedule the work item, was "
				"already queued\n", __func__);
		}
	}

	spin_unlock_irqrestore(&hidpp_device->lock, flags);

	switch (work_type) {
	case HIDPP_INIT:
		hidpp_delayed_init(hidpp_device);
		break;
	default:
		dbg_hid("%s: unexpected report type\n", __func__);
	}
}
/*****************************************************************************
* FUNCTION
*  hal_btif_is_tx_complete
* DESCRIPTION
*  get tx complete flag
* PARAMETERS
* p_base   [IN]        BTIF module's base address
* RETURNS
*  true means tx complete, false means tx in process
*****************************************************************************/
bool hal_btif_is_tx_complete(P_MTK_BTIF_INFO_STR p_btif)
{
    /*Chaozhong: To be implement*/
    bool b_ret = false;
    unsigned int lsr = 0;
    unsigned long flags = 0;
    unsigned int base = p_btif->base;
    unsigned int tx_empty = 0;
    unsigned int rx_dr = 0;
    unsigned int tx_irq_disable = 0;

    /*3 conditions allow clock to be disable
    1. if TEMT is set or not
    2. if DR is set or not
    3. Tx IRQ is disabled or not*/
    lsr = BTIF_READ32(BTIF_LSR(base));
    tx_empty = lsr & BTIF_LSR_TEMT_BIT;
    rx_dr = lsr & BTIF_LSR_DR_BIT;
    tx_irq_disable = BTIF_READ32(BTIF_IER(base)) & BTIF_IER_TXEEN;

    b_ret =
        (tx_empty && (0 == tx_irq_disable) && (0 == rx_dr)) ? true : false;
    if (!b_ret) {
        BTIF_DBG_FUNC
        ("BTIF flag, tx_empty:%d, rx_dr:%d, tx_irq_disable:%d\n",
         tx_empty, rx_dr, tx_irq_disable);
    }
#if NEW_TX_HANDLING_SUPPORT
    spin_lock_irqsave(&(p_btif->tx_fifo_spinlock), flags);
    /*clear Tx enable flag if necessary*/
    if (!(kfifo_is_empty(p_btif->p_tx_fifo))) {
        BTIF_DBG_FUNC("BTIF tx FIFO is not empty\n");
        b_ret = false;
    }
    spin_unlock_irqrestore(&(p_btif->tx_fifo_spinlock), flags);
#endif
    return b_ret;
}
static void stp_uart_rx_worker (struct work_struct *work)
{
    unsigned int read;

    if (unlikely(!g_stp_uart_rx_fifo)) {
        UART_ERR_FUNC("NULL rx fifo!\n");
        return;
    }
    if (unlikely(!g_stp_uart_rx_buf)) {
        UART_ERR_FUNC("NULL rx buf!\n");
        return;
    }
	

    /* run until fifo becomes empty */
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33))
    while (kfifo_len(g_stp_uart_rx_fifo)) {
        read = kfifo_get(g_stp_uart_rx_fifo, g_stp_uart_rx_buf, LDISC_RX_BUF_SIZE);
        //UART_LOUD_FUNC("kfifo_get(%d)\n", read);
        if (likely(read)) {
            mtk_wcn_stp_parser_data((UINT8 *)g_stp_uart_rx_buf, read);
        }
    }
#else
    while (!kfifo_is_empty(g_stp_uart_rx_fifo)) {
        read = kfifo_out(g_stp_uart_rx_fifo, g_stp_uart_rx_buf, LDISC_RX_BUF_SIZE);
        UART_DBG_FUNC("kfifo_out(%d)\n", read);
		//printk("rx_work:%d\n\r",read);
        if (likely(read)) {
            //UART_LOUD_FUNC("->%d\n", read);
            mtk_wcn_stp_parser_data((UINT8 *)g_stp_uart_rx_buf, read);
            //UART_LOUD_FUNC("<-\n", read);
        }
    }
#endif

    return;
}
Beispiel #6
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;
}
Beispiel #7
0
static ssize_t emd_dev_read(struct file *file, char *buf, size_t count, loff_t *ppos)
{
    emd_dev_client_t *client=(emd_dev_client_t *)file->private_data;
    int ret=0,size, data;

    WARN_ON(client==NULL);
    do{
        size=pop_data(client,&data);
        if( sizeof(int) == size){
            EMD_MSG_INF("chr","client%d get data:%08x, ret=%d\n", client->sub_dev_id, data, ret);
            if( copy_to_user(buf,&data,sizeof(int)) ){
                EMD_MSG_INF("chr","copy_to_user fialed\n");
                ret = -EFAULT;
                goto _OUT;
            }else{
                ret = size;
                goto _OUT;
            }
        }else{
            if (file->f_flags & O_NONBLOCK){
                ret = -EAGAIN;
                goto _OUT; 
            }else{
                ret = wait_event_interruptible(client->wait_q, !kfifo_is_empty(&client->fifo));
                if(ret == -ERESTARTSYS) {
                    EMD_MSG_INF("chr","Interrupted syscall.signal_pend=0x%llx\n",
                        *(long long *)current->pending.signal.sig);
                    ret = -EINTR;
                    goto _OUT;
                }
            }
        }
    }while(ret==0);
_OUT:
    return ret;
}
/*****************************************************************************
Syntax:      	    void voice_buf_set_data_in_rtp_stream1 
Remarks:			set data on input RTP packet to FIFO  buffer
*******************************************************************************/
unsigned short voice_buf_get_data_in_rtp_stream1 (unsigned char *in_buf , int *in_size)
{
unsigned short j=0;
//signed short empty;
signed short state=0;



//	empty=kfifo_is_empty(&test);
//	printk(KERN_INFO "emty=%d\n\r",empty);


     if(kfifo_is_empty(&test)==1)
     {
    	 //printk("++++FIFO is EMPTY++++\n\r");
    	 return 0;//FIFO is EMPTY
     }
     else
     {	 

    	 //get values into the fifo берём 4000 и если и сможем 
    	   for (j = 0; j != in_size; j++)
    	   {
    	       state=kfifo_get(&test, &in_buf[j]);
    	       if(state==0)
    	       {
    	    	   return j;
    	       }
    	     		 //Добавлю ещё кусок работы по подсчёту раземера колчества  байтов которые мы полуаем	 
    	 	         //printk("{%d|%d}",state,j);
    	 	}
    	     	 
     return j;
     }
	
}
static bool rt2800usb_tx_sta_fifo_read_completed(struct rt2x00_dev *rt2x00dev,
						 int urb_status, u32 tx_status)
{
	if (urb_status) {
		WARNING(rt2x00dev, "rt2x00usb_register_read_async failed: %d\n", urb_status);
		return false;
	}

	/* try to read all TX_STA_FIFO entries before scheduling txdone_work */
	if (rt2x00_get_field32(tx_status, TX_STA_FIFO_VALID)) {
		if (!kfifo_put(&rt2x00dev->txstatus_fifo, &tx_status)) {
			WARNING(rt2x00dev, "TX status FIFO overrun, "
				"drop tx status report.\n");
			queue_work(rt2x00dev->workqueue, &rt2x00dev->txdone_work);
		} else
			return true;
	} else if (!kfifo_is_empty(&rt2x00dev->txstatus_fifo)) {
		queue_work(rt2x00dev->workqueue, &rt2x00dev->txdone_work);
	} else if (rt2800usb_txstatus_pending(rt2x00dev)) {
		mod_timer(&rt2x00dev->txstatus_timer, jiffies + msecs_to_jiffies(2));
	}

	return false;
}
static void delayedwork_callback(struct work_struct *work)
{
	struct dj_receiver_dev *djrcv_dev =
		container_of(work, struct dj_receiver_dev, work);

	struct dj_report dj_report;
	unsigned long flags;
	int count;
	int retval;

	dbg_hid("%s\n", __func__);

	spin_lock_irqsave(&djrcv_dev->lock, flags);

	count = kfifo_out(&djrcv_dev->notif_fifo, &dj_report,
				sizeof(struct dj_report));

	if (count != sizeof(struct dj_report)) {
		dev_err(&djrcv_dev->hdev->dev, "%s: workitem triggered without "
			"notifications available\n", __func__);
		spin_unlock_irqrestore(&djrcv_dev->lock, flags);
		return;
	}

	if (!kfifo_is_empty(&djrcv_dev->notif_fifo)) {
		if (schedule_work(&djrcv_dev->work) == 0) {
			dbg_hid("%s: did not schedule the work item, was "
				"already queued\n", __func__);
		}
	}

	spin_unlock_irqrestore(&djrcv_dev->lock, flags);

	switch (dj_report.report_type) {
	case REPORT_TYPE_NOTIF_DEVICE_PAIRED:
		logi_dj_recv_add_djhid_device(djrcv_dev, &dj_report);
		break;
	case REPORT_TYPE_NOTIF_DEVICE_UNPAIRED:
		logi_dj_recv_destroy_djhid_device(djrcv_dev, &dj_report);
		break;
	default:
	/* A normal report (i. e. not belonging to a pair/unpair notification)
	 * arriving here, means that the report arrived but we did not have a
	 * paired dj_device associated to the report's device_index, this
	 * means that the original "device paired" notification corresponding
	 * to this dj_device never arrived to this driver. The reason is that
	 * hid-core discards all packets coming from a device while probe() is
	 * executing. */
	if (!djrcv_dev->paired_dj_devices[dj_report.device_index]) {
		/* ok, we don't know the device, just re-ask the
		 * receiver for the list of connected devices. */
		retval = logi_dj_recv_query_paired_devices(djrcv_dev);
		if (!retval) {
			/* everything went fine, so just leave */
			break;
		}
		dev_err(&djrcv_dev->hdev->dev,
			"%s:logi_dj_recv_query_paired_devices "
			"error:%d\n", __func__, retval);
		}
		dbg_hid("%s: unexpected report type\n", __func__);
	}
}
Beispiel #11
0
/*
 * gs_start_tx
 *
 * This function finds available write requests, calls
 * gs_send_packet to fill these packets with data, and
 * continues until either there are no more write requests
 * available or no more data to send.  This function is
 * run whenever data arrives or write requests are available.
 *
 * Context: caller owns port_lock; port_usb is non-null.
 */
static int gs_start_tx(struct gs_port *port)
/*
__releases(&port->port_lock)
__acquires(&port->port_lock)
*/
{
	struct list_head	*pool = &port->write_pool;
	struct usb_ep		*in;
	int			status = 0;
	bool			do_tty_wake = false;

	if (!port->port_usb)
		return status;

	in = port->port_usb->in;

	while (!port->write_busy && !list_empty(pool)) {
		struct usb_request	*req;
		int			len;

		if (port->write_started >= QUEUE_SIZE)
			break;

		req = list_entry(pool->next, struct usb_request, list);
		len = gs_send_packet(port, req->buf, in->maxpacket);
		if (len == 0) {
			wake_up_interruptible(&port->drain_wait);
			break;
		}
		do_tty_wake = true;

		req->length = len;
		list_del(&req->list);
		req->zero = kfifo_is_empty(&port->port_write_buf);

		pr_vdebug("ttyGS%d: tx len=%d, 0x%02x 0x%02x 0x%02x ...\n",
			  port->port_num, len, *((u8 *)req->buf),
			  *((u8 *)req->buf+1), *((u8 *)req->buf+2));

		/* Drop lock while we call out of driver; completions
		 * could be issued while we do so.  Disconnection may
		 * happen too; maybe immediately before we queue this!
		 *
		 * NOTE that we may keep sending data for a while after
		 * the TTY closed (dev->ioport->port_tty is NULL).
		 */
		port->write_busy = true;
		spin_unlock(&port->port_lock);
		status = usb_ep_queue(in, req, GFP_ATOMIC);
		spin_lock(&port->port_lock);
		port->write_busy = false;

		if (status) {
			pr_debug("%s: %s %s err %d\n",
					__func__, "queue", in->name, status);
			list_add(&req->list, pool);
			break;
		}

		port->write_started++;

		/* abort immediately after disconnect */
		if (!port->port_usb)
			break;
	}

	if (do_tty_wake && port->port.tty)
		tty_wakeup(port->port.tty);
	return status;
}
Beispiel #12
0
irqreturn_t interrupt_handler(int irq_no, void *data)
{
        int device_status;
        uint32_t device_port = 0x0;
        /*
         * TODO: Write the code that handles a hardware interrupt.
         * TODO: Populate device_port with the port of the correct device.
         */

        int ret = IRQ_HANDLED;
        if(irq_no == COM1_IRQ) {
            device_port = COM1_BASEPORT;
        }
        else if(irq_no == COM2_IRQ) {
            device_port = COM2_BASEPORT;
        }
        if(device_port)
        {

            disable_irq(irq_no);
            device_status = uart16550_hw_get_device_status(device_port);

            struct task_struct **task_user_get_data = ftask_user_get_data(data);
            struct task_struct **task_user_push_data = ftask_user_push_data(data);
            struct kfifo * data_from_user = fdata_from_user (data);
            struct kfifo * data_from_device = fdata_from_device (data);

            while (uart16550_hw_device_can_send(device_status) && !kfifo_is_empty(data_from_user)) {
                    uint8_t byte_value;
                    /*
                     * TODO: Populate byte_value with the next value
                     *      from the kernel device outgoing buffer.
                     */
                    
                    kfifo_get(data_from_user,&byte_value);
                    if(*task_user_push_data)
                        wake_up_process(*task_user_push_data);
                    

                    uart16550_hw_write_to_device(device_port, byte_value);
                    device_status = uart16550_hw_get_device_status(device_port);
            }

            while (uart16550_hw_device_has_data(device_status) && !kfifo_is_full(data_from_device)) {
                    uint8_t byte_value;
                    byte_value = uart16550_hw_read_from_device(device_port);
                    /*
                     * TODO: Store the read byte_value in the kernel device
                     *      incoming buffer.
                     */
                     kfifo_put(data_from_device,byte_value);
                     if(*task_user_get_data)
                        wake_up_process(*task_user_get_data);
                     
                    device_status = uart16550_hw_get_device_status(device_port);
            }
            enable_irq(irq_no);
        }
        else
        {
            ret = -1;
        }
        
        return ret;
}
Beispiel #13
0
/*
 * uart_device_read() - used for reading from the device buffer
 * to the userspace buffer
 */
static ssize_t
uart_device_read(struct file *file, char __user *user_buffer,
		 size_t size, loff_t *offset)
{
	int bytes;
	unsigned char byte;
	unsigned long flags;
	size_t to_read;
	struct uart_device_data *dev_data =
	    (struct uart_device_data *)file->private_data;
	size_t rb_len = kfifo_len(&dev_data->read_buffer);
	if (rb_len == 0) {
		/*
		 * no dev_data available right now, try again later
		 */
		if (file->f_flags & O_NONBLOCK) {

			return -EAGAIN;
		} else {
			/*
			 * enable Received dev_data Available Interrupt
			 */
			byte = inb(dev_data->base_addr + IER) | 1;
			outb(byte, dev_data->base_addr + IER);
			/*
			 * wait until read buffer is not empty
			 */
			if (wait_event_interruptible(dev_data->read_wq,
					!kfifo_is_empty(&dev_data->read_buffer))) {
				return -ERESTARTSYS;
			}
		}
	}
	/*
	 * save interrupts
	 */
	spin_lock_irqsave(&dev_data->read_lock, flags);
	/*
	 * don't read more than read_buffer length
	 */
	rb_len = kfifo_len(&dev_data->read_buffer);
	if (size > rb_len)
		to_read = rb_len;
	else
		to_read = size;
	/*
	 * copy dev_data in userspace buffer
	 */
	bytes = 0;
	while (bytes < to_read) {
		if (kfifo_get(&dev_data->read_buffer, &byte)) {
			if (put_user(byte, &user_buffer[bytes])) {
				spin_unlock_irqrestore(&dev_data->read_lock, flags);
				return -EFAULT;
			}
			bytes++;
		}
	}

	/*
	 * restore interrupts
	 */
	spin_unlock_irqrestore(&dev_data->read_lock, flags);
	return to_read;

}
Beispiel #14
0
/*
 * Interrupt functions.
 */
static void rt2800pci_wakeup(struct rt2x00_dev *rt2x00dev)
{
	struct ieee80211_conf conf = { .flags = 0 };
	struct rt2x00lib_conf libconf = { .conf = &conf };

	rt2800_config(rt2x00dev, &libconf, IEEE80211_CONF_CHANGE_PS);
}

static bool rt2800pci_txdone(struct rt2x00_dev *rt2x00dev)
{
	struct data_queue *queue;
	struct queue_entry *entry;
	u32 status;
	u8 qid;
	int max_tx_done = 16;

	while (!kfifo_is_empty(&rt2x00dev->txstatus_fifo)) {
		/* Now remove the tx status from the FIFO */
		if (kfifo_out(&rt2x00dev->txstatus_fifo, &status,
			      sizeof(status)) != sizeof(status)) {
			WARN_ON(1);
			break;
		}

		qid = rt2x00_get_field32(status, TX_STA_FIFO_PID_QUEUE);
		if (unlikely(qid >= QID_RX)) {
			/*
			 * Unknown queue, this shouldn't happen. Just drop
			 * this tx status.
			 */
			WARNING(rt2x00dev, "Got TX status report with "
					   "unexpected pid %u, dropping\n", qid);
			break;
		}

		queue = rt2x00queue_get_tx_queue(rt2x00dev, qid);
		if (unlikely(queue == NULL)) {
			/*
			 * The queue is NULL, this shouldn't happen. Stop
			 * processing here and drop the tx status
			 */
			WARNING(rt2x00dev, "Got TX status for an unavailable "
					   "queue %u, dropping\n", qid);
			break;
		}

		if (unlikely(rt2x00queue_empty(queue))) {
			/*
			 * The queue is empty. Stop processing here
			 * and drop the tx status.
			 */
			WARNING(rt2x00dev, "Got TX status for an empty "
					   "queue %u, dropping\n", qid);
			break;
		}

		entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE);
		rt2800_txdone_entry(entry, status, rt2800pci_get_txwi(entry));

		if (--max_tx_done == 0)
			break;
	}

	return !max_tx_done;
}

static inline void rt2800pci_enable_interrupt(struct rt2x00_dev *rt2x00dev,
					      struct rt2x00_field32 irq_field)
{
	u32 reg;

	/*
	 * Enable a single interrupt. The interrupt mask register
	 * access needs locking.
	 */
	spin_lock_irq(&rt2x00dev->irqmask_lock);
	rt2x00pci_register_read(rt2x00dev, INT_MASK_CSR, &reg);
	rt2x00_set_field32(&reg, irq_field, 1);
	rt2x00pci_register_write(rt2x00dev, INT_MASK_CSR, reg);
	spin_unlock_irq(&rt2x00dev->irqmask_lock);
}
Beispiel #15
0
static bool can_read(struct kfifo *queue){ return !kfifo_is_empty(queue);}
/**
 * drm_flip_work_cleanup - cleans up flip-work
 * @work: the flip-work to cleanup
 *
 * Destroy resources allocated for the flip-work
 */
void drm_flip_work_cleanup(struct drm_flip_work *work)
{
	WARN_ON(!kfifo_is_empty(&work->fifo));
	kfifo_free(&work->fifo);
}
Beispiel #17
0
static int
pi433_tx_thread(void *data)
{
	struct pi433_device *device = data;
	struct spi_device *spi = device->spi;
	struct pi433_tx_cfg tx_cfg;
	size_t size;
	bool   rx_interrupted = false;
	int    position, repetitions;
	int    retval;

	while (1) {
		/* wait for fifo to be populated or for request to terminate*/
		dev_dbg(device->dev, "thread: going to wait for new messages");
		wait_event_interruptible(device->tx_wait_queue,
					 (!kfifo_is_empty(&device->tx_fifo) ||
					  kthread_should_stop()));
		if (kthread_should_stop())
			return 0;

		/*
		 * get data from fifo in the following order:
		 * - tx_cfg
		 * - size of message
		 * - message
		 */
		retval = kfifo_out(&device->tx_fifo, &tx_cfg, sizeof(tx_cfg));
		if (retval != sizeof(tx_cfg)) {
			dev_dbg(device->dev,
				"reading tx_cfg from fifo failed: got %d byte(s), expected %d",
				retval, (unsigned int)sizeof(tx_cfg));
			continue;
		}

		retval = kfifo_out(&device->tx_fifo, &size, sizeof(size_t));
		if (retval != sizeof(size_t)) {
			dev_dbg(device->dev,
				"reading msg size from fifo failed: got %d, expected %d",
				retval, (unsigned int)sizeof(size_t));
			continue;
		}

		/* use fixed message length, if requested */
		if (tx_cfg.fixed_message_length != 0)
			size = tx_cfg.fixed_message_length;

		/* increase size, if len byte is requested */
		if (tx_cfg.enable_length_byte == OPTION_ON)
			size++;

		/* increase size, if adr byte is requested */
		if (tx_cfg.enable_address_byte == OPTION_ON)
			size++;

		/* prime buffer */
		memset(device->buffer, 0, size);
		position = 0;

		/* add length byte, if requested */
		if (tx_cfg.enable_length_byte  == OPTION_ON)
			/*
			 * according to spec, length byte itself must be
			 * excluded from the length calculation
			 */
			device->buffer[position++] = size - 1;

		/* add adr byte, if requested */
		if (tx_cfg.enable_address_byte == OPTION_ON)
			device->buffer[position++] = tx_cfg.address_byte;

		/* finally get message data from fifo */
		retval = kfifo_out(&device->tx_fifo, &device->buffer[position],
				   sizeof(device->buffer) - position);
		dev_dbg(device->dev,
			"read %d message byte(s) from fifo queue.", retval);

		/*
		 * if rx is active, we need to interrupt the waiting for
		 * incoming telegrams, to be able to send something.
		 * We are only allowed, if currently no reception takes
		 * place otherwise we need to  wait for the incoming telegram
		 * to finish
		 */
		wait_event_interruptible(device->tx_wait_queue,
					 !device->rx_active ||
					  device->interrupt_rx_allowed);

		/*
		 * prevent race conditions
		 * irq will be reenabled after tx config is set
		 */
		disable_irq(device->irq_num[DIO0]);
		device->tx_active = true;

		/* clear fifo, set fifo threshold, set payload length */
		retval = rf69_set_mode(spi, standby); /* this clears the fifo */
		if (retval < 0)
			return retval;

		if (device->rx_active && !rx_interrupted) {
			/*
			 * rx is currently waiting for a telegram;
			 * we need to set the radio module to standby
			 */
			rx_interrupted = true;
		}

		retval = rf69_set_fifo_threshold(spi, FIFO_THRESHOLD);
		if (retval < 0)
			return retval;
		if (tx_cfg.enable_length_byte == OPTION_ON) {
			retval = rf69_set_payload_length(spi, size * tx_cfg.repetitions);
			if (retval < 0)
				return retval;
		} else {
			retval = rf69_set_payload_length(spi, 0);
			if (retval < 0)
				return retval;
		}

		/* configure the rf chip */
		retval = rf69_set_tx_cfg(device, &tx_cfg);
		if (retval < 0)
			return retval;

		/* enable fifo level interrupt */
		retval = rf69_set_dio_mapping(spi, DIO1, DIO_FIFO_LEVEL);
		if (retval < 0)
			return retval;
		device->irq_state[DIO1] = DIO_FIFO_LEVEL;
		irq_set_irq_type(device->irq_num[DIO1], IRQ_TYPE_EDGE_FALLING);

		/* enable packet sent interrupt */
		retval = rf69_set_dio_mapping(spi, DIO0, DIO_PACKET_SENT);
		if (retval < 0)
			return retval;
		device->irq_state[DIO0] = DIO_PACKET_SENT;
		irq_set_irq_type(device->irq_num[DIO0], IRQ_TYPE_EDGE_RISING);
		enable_irq(device->irq_num[DIO0]); /* was disabled by rx active check */

		/* enable transmission */
		retval = rf69_set_mode(spi, transmit);
		if (retval < 0)
			return retval;

		/* transfer this msg (and repetitions) to chip fifo */
		device->free_in_fifo = FIFO_SIZE;
		position = 0;
		repetitions = tx_cfg.repetitions;
		while ((repetitions > 0) && (size > position)) {
			if ((size - position) > device->free_in_fifo) {
				/* msg to big for fifo - take a part */
				int write_size = device->free_in_fifo;

				device->free_in_fifo = 0;
				rf69_write_fifo(spi,
						&device->buffer[position],
						write_size);
				position += write_size;
			} else {
				/* msg fits into fifo - take all */
				device->free_in_fifo -= size;
				repetitions--;
				rf69_write_fifo(spi,
						&device->buffer[position],
						(size - position));
				position = 0; /* reset for next repetition */
			}

			retval = wait_event_interruptible(device->fifo_wait_queue,
							  device->free_in_fifo > 0);
			if (retval) {
				dev_dbg(device->dev, "ABORT\n");
				goto abort;
			}
		}

		/* we are done. Wait for packet to get sent */
		dev_dbg(device->dev,
			"thread: wait for packet to get sent/fifo to be empty");
		wait_event_interruptible(device->fifo_wait_queue,
					 device->free_in_fifo == FIFO_SIZE ||
					 kthread_should_stop());
		if (kthread_should_stop())
			return 0;

		/* STOP_TRANSMISSION */
		dev_dbg(device->dev, "thread: Packet sent. Set mode to stby.");
		retval = rf69_set_mode(spi, standby);
		if (retval < 0)
			return retval;

		/* everything sent? */
		if (kfifo_is_empty(&device->tx_fifo)) {
abort:
			if (rx_interrupted) {
				rx_interrupted = false;
				pi433_start_rx(device);
			}
			device->tx_active = false;
			wake_up_interruptible(&device->rx_wait_queue);
		}
	}
}