Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit cfbaf337 authored by Steven Toth's avatar Steven Toth Committed by Mauro Carvalho Chehab
Browse files

[media] saa7164: irqhandler cleanup and helper function added

parent b31f1222
Loading
Loading
Loading
Loading
+78 −174
Original line number Diff line number Diff line
@@ -239,54 +239,15 @@ static void saa7164_histogram_print(struct saa7164_port *port,
	printk(KERN_ERR "Total: %d\n", entries);
}

static void saa7164_work_enchandler(struct work_struct *w)
static void saa7164_work_enchandler_helper(struct saa7164_port *port, int bufnr)
{
	struct saa7164_port *port =
		container_of(w, struct saa7164_port, workenc);
	struct saa7164_dev *dev = port->dev;
	struct saa7164_buffer *buf;
	struct saa7164_user_buffer *ubuf;
	struct saa7164_buffer *buf = 0;
	struct saa7164_user_buffer *ubuf = 0;
	struct list_head *c, *n;
	int wp, rp, i = 0;
	u32 crc, ok = 0;
	u8 *p;

	port->last_svc_msecs_diff = port->last_svc_msecs;
	port->last_svc_msecs = jiffies_to_msecs(jiffies);
	port->last_svc_wp = saa7164_readl(port->bufcounter);
	port->last_svc_rp = port->last_irq_rp;
	wp = port->last_svc_wp;
	rp = port->last_svc_rp;


	port->last_svc_msecs_diff = port->last_svc_msecs -
		port->last_svc_msecs_diff;

	saa7164_histogram_update(&port->svc_interval,
		port->last_svc_msecs_diff);

	port->last_irq_svc_msecs_diff = port->last_svc_msecs -
		port->last_irq_msecs;

	saa7164_histogram_update(&port->irq_svc_interval,
		port->last_irq_svc_msecs_diff);

	dprintk(DBGLVL_IRQ,
		"%s() %Ldms elapsed irq->deferred %Ldms wp: %d rp: %d\n",
		__func__,
		port->last_svc_msecs_diff,
		port->last_irq_svc_msecs_diff,
		port->last_svc_wp,
		port->last_svc_rp
		);

	if ((rp < 0) || (rp > 7)) {
		printk(KERN_ERR "%s() illegal rp count %d\n", __func__, rp);
		return;
	}
	int i = 0;

	mutex_lock(&port->dmaqueue_lock);

	list_for_each_safe(c, n, &port->dmaqueue.list) {

		buf = list_entry(c, struct saa7164_buffer, list);
@@ -296,33 +257,10 @@ static void saa7164_work_enchandler(struct work_struct *w)
			break;
		}

		p = (u8 *)buf->cpu;
		if (	(*(p + buf->actual_size + 0) != 0xff) ||
			(*(p + buf->actual_size + 1) != 0xff) ||
			(*(p + buf->actual_size + 2) != 0xff) ||
			(*(p + buf->actual_size + 3) != 0xff) ||
			(*(p + buf->actual_size + 0x10) != 0xff) ||
			(*(p + buf->actual_size + 0x11) != 0xff) ||
			(*(p + buf->actual_size + 0x12) != 0xff) ||
			(*(p + buf->actual_size + 0x13) != 0xff) )
		{
			printk(KERN_ERR "%s() buf %p failed guard check\n", __func__, buf);
			saa7164_dumphex16(dev, p + buf->actual_size - 32, 64);
		}

		if (buf->idx == wp) {
			/* Ignore this, it's being updated currently by the dma engine */
		} else
		if (buf->idx == rp) {

			crc = crc32(0, buf->cpu, buf->actual_size);
//			if (crc != port->shadow_crc[rp])
//				printk(KERN_ERR "%s crc didn't match shadow was 0x%x now 0x%x\n",
//					__func__, port->shadow_crc[rp], crc);
		if (buf->idx == bufnr) {

			/* Found the buffer, deal with it */
			dprintk(DBGLVL_IRQ, "%s() wp: %d processing: %d crc32: 0x%x\n",
				__func__, wp, rp, buf->crc);
			dprintk(DBGLVL_IRQ, "%s() rp: %d\n", __func__, bufnr);

			/* Validate the incoming buffer content */
			if (port->encoder_params.stream_type == V4L2_MPEG_STREAM_TYPE_MPEG2_TS)
@@ -339,17 +277,12 @@ static void saa7164_work_enchandler(struct work_struct *w)

				if (buf->actual_size <= ubuf->actual_size) {

					memcpy_fromio(ubuf->data, port->shadow_buf[rp],
					memcpy_fromio(ubuf->data, buf->cpu,
						ubuf->actual_size);

					/* Throw a new checksum on the read buffer */
					ubuf->crc = crc32(0, ubuf->data, ubuf->actual_size);

					if ((crc == port->shadow_crc[rp]) && (crc == ubuf->crc))
						ok = 1;
					else
						ok = 0;

					/* Requeue the buffer on the free list */
					ubuf->pos = 0;

@@ -369,26 +302,81 @@ static void saa7164_work_enchandler(struct work_struct *w)
			/* Ensure offset into buffer remains 0, fill buffer
			 * with known bad data. We check for this data at a later point
			 * in time. */
			saa7164_buffer_zero_offsets(port, rp);
			saa7164_buffer_zero_offsets(port, bufnr);
			memset_io(buf->cpu, 0xff, buf->pci_size);
			buf->crc = crc32(0, buf->cpu, buf->actual_size);

			break;
		} else {
			/* Validate all other checksums, on previous buffers - they should never change */
			crc = crc32(0, buf->cpu, buf->actual_size);
			if (crc != buf->crc) {
				printk(KERN_ERR "buf[%d].crc became invalid, was 0x%x became 0x%x rp: %d wp: %d\n",
					buf->idx, buf->crc, crc, rp, wp);
				//saa7164_dumphex16FF(dev, (u8 *)buf->cpu, buf->actual_size);
				saa7164_dumphex16FF(dev, (u8 *)buf->cpu, 256);
				buf->crc = crc;
		}
	}
	mutex_unlock(&port->dmaqueue_lock);
}

static void saa7164_work_enchandler(struct work_struct *w)
{
	struct saa7164_port *port =
		container_of(w, struct saa7164_port, workenc);
	struct saa7164_dev *dev = port->dev;

	u32 wp, mcb, rp, cnt = 0;

	port->last_svc_msecs_diff = port->last_svc_msecs;
	port->last_svc_msecs = jiffies_to_msecs(jiffies);

	port->last_svc_msecs_diff = port->last_svc_msecs -
		port->last_svc_msecs_diff;

	saa7164_histogram_update(&port->svc_interval,
		port->last_svc_msecs_diff);

	port->last_irq_svc_msecs_diff = port->last_svc_msecs -
		port->last_irq_msecs;

	saa7164_histogram_update(&port->irq_svc_interval,
		port->last_irq_svc_msecs_diff);

	dprintk(DBGLVL_IRQ,
		"%s() %Ldms elapsed irq->deferred %Ldms wp: %d rp: %d\n",
		__func__,
		port->last_svc_msecs_diff,
		port->last_irq_svc_msecs_diff,
		port->last_svc_wp,
		port->last_svc_rp
		);

	/* Current write position */
	wp = saa7164_readl(port->bufcounter);
	if (wp > (port->hwcfg.buffercount - 1)) {
		printk(KERN_ERR "%s() illegal buf count %d\n", __func__, wp);
		return;
	}

	/* Most current complete buffer */
	if (wp == 0)
		mcb = 7;
	else
		mcb = wp - 1;

	while (1) {
		rp = (port->last_svc_rp + 1) % 8;

		if ((rp < 0) || (rp > 7)) {
			printk(KERN_ERR "%s() illegal rp count %d\n", __func__, rp);
			break;
		}
	mutex_unlock(&port->dmaqueue_lock);

		/* Process a buffer */
		if (port->nr == SAA7164_PORT_ENC1)
			printk(KERN_ERR "Port enc1 processing buffer %d\n", rp);
		saa7164_work_enchandler_helper(port, rp);
		port->last_svc_rp = rp;
		cnt++;

		if (rp == mcb)
			break;
	}

	if (port->nr == SAA7164_PORT_ENC1)
		printk(KERN_ERR "Enc1 processed %d buffers for port %p\n", cnt, port);

	if (print_histogram == port->nr) {
		saa7164_histogram_print(port, &port->irq_interval);
@@ -399,6 +387,7 @@ static void saa7164_work_enchandler(struct work_struct *w)
		print_histogram = 64 + port->nr;
	}
}

static void saa7164_work_cmdhandler(struct work_struct *w)
{
	struct saa7164_dev *dev = container_of(w, struct saa7164_dev, workcmd);
@@ -420,49 +409,12 @@ static void saa7164_buffer_deliver(struct saa7164_buffer *buf)
static irqreturn_t saa7164_irq_encoder(struct saa7164_port *port)
{
	struct saa7164_dev *dev = port->dev;
	struct saa7164_buffer *buf;
	struct list_head *c, *n;
	int wp, rp, i = 0;
	u8 *p;
	u32 *up, j;

	/* Find the current write point from the hardware */
	wp = saa7164_readl(port->bufcounter);
	if (wp > (port->hwcfg.buffercount - 1)) {
		printk(KERN_ERR "%s() illegal buf count %d\n", __func__, wp);
		return 0;
	}

	printk(KERN_ERR "port %p wp = %d\n", port, wp);

	/* Find the previous buffer to the current write point */
	if (wp == 0)
		rp = 7;
	else
		rp = wp - 1;

	if ((rp < 0) || (rp > 7)) {
		printk(KERN_ERR "%s() illegal rp count %d\n", __func__, rp);
		return 0;
	}

	if (rp == port->last_irq_rp) {
		printk(KERN_ERR "%s() Duplicate rp = %d port %p\n",
			__func__, rp, port);
	}

	if (rp != ((port->last_irq_rp + 1) % 8)) {
		printk(KERN_ERR "%s() Multiple bufs on interrupt, port %p\n",
			__func__, port);
	}

	/* Store old time */
	port->last_irq_msecs_diff = port->last_irq_msecs;

	/* Collect new stats */
	port->last_irq_msecs = jiffies_to_msecs(jiffies);
	port->last_irq_wp = wp;
	port->last_irq_rp = rp;

	/* Calculate stats */
	port->last_irq_msecs_diff = port->last_irq_msecs -
@@ -471,58 +423,10 @@ static irqreturn_t saa7164_irq_encoder(struct saa7164_port *port)
	saa7164_histogram_update(&port->irq_interval,
		port->last_irq_msecs_diff);

	dprintk(DBGLVL_IRQ, "%s() %Ldms elapsed wp: %d rp: %d\n",
		__func__,
		port->last_irq_msecs_diff,
		port->last_irq_wp,
		port->last_irq_rp
		);
	/* Find the used buffer, shadow copy it before we've
	 * acked the interrupt.
	 */
//	mutex_lock(&port->dmaqueue_lock);
	list_for_each_safe(c, n, &port->dmaqueue.list) {

		buf = list_entry(c, struct saa7164_buffer, list);
		if (i++ > port->hwcfg.buffercount) {
			printk(KERN_ERR "%s() illegal i count %d\n",
				__func__, i);
			break;
		}

		p = (u8 *)buf->cpu;
		if (	(*(p + buf->actual_size + 0) != 0xff) ||
			(*(p + buf->actual_size + 1) != 0xff) ||
			(*(p + buf->actual_size + 2) != 0xff) ||
			(*(p + buf->actual_size + 3) != 0xff) ||
			(*(p + buf->actual_size + 0x10) != 0xff) ||
			(*(p + buf->actual_size + 0x11) != 0xff) ||
			(*(p + buf->actual_size + 0x12) != 0xff) ||
			(*(p + buf->actual_size + 0x13) != 0xff) )
		{
			printk(KERN_ERR "buf %p failed guard check\n", buf);
			saa7164_dumphex16(dev, p + buf->actual_size - 32, 64);
		}

		if (buf->idx == rp) {
			up = (u32 *)port->shadow_buf[rp];
			for (j = 0 ; j < (buf->actual_size / sizeof(u32)); j++) {
				*(up + j) = (rp << 28) | port->counter++;
			}
			port->shadow_crc[rp] = crc32(0, port->shadow_buf[rp], buf->actual_size);

			buf->crc = crc32(0, buf->cpu, buf->actual_size);

//			if (port->shadow_crc[rp] != buf->crc)
//				printk(KERN_ERR "%s() crc check failed 0x%x vs 0x%x\n",
//					__func__, port->shadow_crc[rp], buf->crc);
			break;
		}
	dprintk(DBGLVL_IRQ, "%s() %Ldms elapsed\n", __func__,
		port->last_irq_msecs_diff);

	}
//	mutex_unlock(&port->dmaqueue_lock);
	schedule_work(&port->workenc);

	return 0;
}

+2 −2
Original line number Diff line number Diff line
@@ -330,8 +330,8 @@ struct saa7164_port {

	u64 last_irq_msecs, last_svc_msecs;
	u64 last_irq_msecs_diff, last_svc_msecs_diff;
	u32 last_irq_wp, last_svc_wp;
	u32 last_irq_rp, last_svc_rp;
	u32 last_svc_wp;
	u32 last_svc_rp;
	u64 last_irq_svc_msecs_diff;
	u64 last_read_msecs, last_read_msecs_diff;
	u64 last_poll_msecs, last_poll_msecs_diff;