static void tsif_notify(void *data)
{
	struct tsif_chrdev *the_dev = data;
	tsif_get_state(the_dev->cookie, &the_dev->ri, &the_dev->wi,
		       &the_dev->state);
	wake_up_interruptible(&the_dev->wq_read);
}
/**
 * Demux thread function handling data from specific TSIF.
 *
 * @arg: TSIF number
 */
static int mpq_dmx_tsif_thread(void *arg)
{
	struct mpq_demux *mpq_demux;
	struct tsif_driver_info *tsif_driver;
	size_t packets = 0;
	int tsif = (int)arg;
	int ret;

	do {
		ret = wait_event_interruptible(
			mpq_dmx_tsif_info.tsif[tsif].wait_queue,
			(atomic_read(
				&mpq_dmx_tsif_info.tsif[tsif].data_cnt) != 0) ||
			kthread_should_stop());

		if ((ret < 0) || kthread_should_stop()) {
			MPQ_DVB_DBG_PRINT("%s: exit\n", __func__);
			break;
		}

		if (mutex_lock_interruptible(
			&mpq_dmx_tsif_info.tsif[tsif].mutex))
			return -ERESTARTSYS;

		tsif_driver = &(mpq_dmx_tsif_info.tsif[tsif].tsif_driver);
		mpq_demux = mpq_dmx_tsif_info.tsif[tsif].mpq_demux;

		/* Check if driver handler is still valid */
		if (tsif_driver->tsif_handler == NULL) {
			mutex_unlock(&mpq_dmx_tsif_info.tsif[tsif].mutex);
			MPQ_DVB_DBG_PRINT(
				"%s: tsif was detached\n",
				__func__);
			continue;
		}

		tsif_get_state(
			tsif_driver->tsif_handler, &(tsif_driver->ri),
			&(tsif_driver->wi), &(tsif_driver->state));

		if ((tsif_driver->wi == tsif_driver->ri) ||
			(tsif_driver->state == tsif_state_stopped) ||
			(tsif_driver->state == tsif_state_error)) {

			mpq_demux->hw_notification_size = 0;

			mutex_unlock(&mpq_dmx_tsif_info.tsif[tsif].mutex);

			MPQ_DVB_DBG_PRINT(
				"%s: TSIF invalid state %d, %d, %d\n",
				__func__,
				tsif_driver->state,
				tsif_driver->wi,
				tsif_driver->ri);
			continue;
		}

		atomic_dec(&mpq_dmx_tsif_info.tsif[tsif].data_cnt);

		if (tsif_driver->wi > tsif_driver->ri) {
			packets = (tsif_driver->wi - tsif_driver->ri);
			mpq_demux->hw_notification_size = packets;

			dvb_dmx_swfilter_format(
				&mpq_demux->demux,
				(tsif_driver->data_buffer +
				(tsif_driver->ri * TSIF_PKT_SIZE)),
				(packets * TSIF_PKT_SIZE),
				DMX_TSP_FORMAT_192_TAIL);

			tsif_driver->ri =
				(tsif_driver->ri + packets) %
				tsif_driver->buffer_size;

			tsif_reclaim_packets(
				tsif_driver->tsif_handler,
					tsif_driver->ri);
		} else {
			/*
			 * wi < ri, means wraparound on cyclic buffer.
			 * Handle in two stages.
			 */
			packets = (tsif_driver->buffer_size - tsif_driver->ri);
			mpq_demux->hw_notification_size = packets;

			dvb_dmx_swfilter_format(
				&mpq_demux->demux,
				(tsif_driver->data_buffer +
				(tsif_driver->ri * TSIF_PKT_SIZE)),
				(packets * TSIF_PKT_SIZE),
				DMX_TSP_FORMAT_192_TAIL);

			/* tsif_driver->ri should be 0 after this */
			tsif_driver->ri =
				(tsif_driver->ri + packets) %
				tsif_driver->buffer_size;

			packets = tsif_driver->wi;
			if (packets > 0) {
				mpq_demux->hw_notification_size += packets;

				dvb_dmx_swfilter_format(
					&mpq_demux->demux,
					(tsif_driver->data_buffer +
					(tsif_driver->ri * TSIF_PKT_SIZE)),
					(packets * TSIF_PKT_SIZE),
					DMX_TSP_FORMAT_192_TAIL);

				tsif_driver->ri =
					(tsif_driver->ri + packets) %
					tsif_driver->buffer_size;
			}

			tsif_reclaim_packets(
				tsif_driver->tsif_handler,
				tsif_driver->ri);
		}

		mutex_unlock(&mpq_dmx_tsif_info.tsif[tsif].mutex);
	} while (1);

	return 0;
}
static ssize_t tsif_read(struct file *filp, char __user *buf, size_t count,
			 loff_t *f_pos)
{
	int avail = 0;
	int wi;

#ifdef FEATURE_TSIF_DEBUG_MSG
	pr_info("[%s] !!!!!!!\n", __func__);
	//g_packet_read_cnt ++;
#endif
  
	struct tsif_chrdev *the_dev = filp->private_data;
	tsif_get_state(the_dev->cookie, &the_dev->ri, &the_dev->wi,
		       &the_dev->state);
	/* consistency check */
	if (the_dev->ri != (the_dev->rptr / TSIF_PKT_SIZE)) {
		dev_err(the_dev->dev,
			"%s: inconsistent read pointers: ri %d rptr %d\n",
			__func__, the_dev->ri, the_dev->rptr);
		the_dev->rptr = the_dev->ri * TSIF_PKT_SIZE;
	}
	/* ri == wi if no data */
	if (the_dev->ri == the_dev->wi) {
		/* shall I block waiting for data? */
		if (filp->f_flags & O_NONBLOCK) {
			if (the_dev->state == tsif_state_running) {
				return -EAGAIN;
			} else {
				/* not running -> EOF */
				return 0;
			}
		}
#if 0
		if (wait_event_interruptible(the_dev->wq_read,
		      (the_dev->ri != the_dev->wi) ||
		      (the_dev->state != tsif_state_running))) {
			/* got signal -> tell FS to handle it */
			return -ERESTARTSYS;
		}
#else
        if (wait_event_interruptible_timeout(the_dev->wq_read,
              ((the_dev->ri != the_dev->wi) ||
              (the_dev->state != tsif_state_running)),msecs_to_jiffies(50))) {
          /* got signal -> tell FS to handle it */
          return -ERESTARTSYS;
        }
#endif
		if (the_dev->ri == the_dev->wi) {
			/* still no data -> EOF */
			return 0;
		}
	}
	/* contiguous chunk last up to wi or end of buffer */
	wi = (the_dev->wi > the_dev->ri) ?
		the_dev->wi : the_dev->buf_size_packets;
	avail = min(wi * TSIF_PKT_SIZE - the_dev->rptr, count);

#ifdef FEATURE_TSIF_DEBUG_MSG
	pr_info("[%s] size [%d] !!!!!!!\n", __func__, avail);
#endif
  
	//if (copy_to_user(buf, the_dev->data_buffer + the_dev->rptr, avail))
	//	return -EFAULT;

#ifdef CONFIG_SKY_TDMB_TSIF_IF
	tdmb_tsif_data_parser(buf, the_dev->data_buffer + the_dev->rptr, avail);
#endif
  
	the_dev->rptr = (the_dev->rptr + avail) %
		(TSIF_PKT_SIZE * the_dev->buf_size_packets);
	the_dev->ri = the_dev->rptr / TSIF_PKT_SIZE;
	*f_pos += avail;
	tsif_reclaim_packets(the_dev->cookie, the_dev->ri);
	return avail;
}