mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Mark Brown <broonie@kernel.org>
To: Qais Yousef <qais.yousef@imgtec.com>
Cc: alsa-devel@alsa-project.org, Liam Girdwood <lgirdwood@gmail.com>,
	Jaroslav Kysela <perex@perex.cz>, Takashi Iwai <tiwai@suse.com>,
	linux-kernel@vger.kernel.org
Subject: Re: [PATCH 03/10] ALSA: add AXD Audio Processing IP alsa driver
Date: Wed, 26 Aug 2015 19:37:00 +0100	[thread overview]
Message-ID: <20150826183700.GD28760@sirena.org.uk> (raw)
In-Reply-To: <1440419959-14315-4-git-send-email-qais.yousef@imgtec.com>

[-- Attachment #1: Type: text/plain, Size: 8180 bytes --]

On Mon, Aug 24, 2015 at 01:39:12PM +0100, Qais Yousef wrote:

> +#define THREAD_COUNT 4

This is a very generic name that looks likely to collide with something
else, please namespace.

> +#define AXD_INPUT_DESCRIPTORS 10
> +struct axd_input {
> +	struct axd_buffer_desc descriptors[AXD_INPUT_DESCRIPTORS];
> +};

Where do these numbers come from?  Are they hardware limits or something
else?

> +/* this is required by MIPS ioremap_cachable() */
> +#include <asm/pgtable.h>

Don't work around this here, fix it in the relevant header.

> +#define AXD_BASE_VADDR		0xD0000000

This sounds like something that is going to be platform dependant,
should this be supplied from board configuration?

> +extern struct snd_compr_ops axd_compr_ops;

Prototype shared definitions in headers not in C files please so we know
the definition matches.

> +static struct snd_soc_dai_driver axd_dai[] = {
> +	{

Why an array with only one entry?

> +	if (!*offp) {
> +		unsigned int flags = axd_platform_lock();
> +		unsigned int log_offset = ioread32(log_addr);
> +		unsigned int log_wrapped = ioread32(log_addr + 8);
> +		char __iomem *log_buff = (char __iomem *)(log_addr + 12);
> +
> +		/* new read from beginning, fill up our internal buffer */
> +		if (!log_wrapped) {
> +			memcpy_fromio(axd->log_rbuf, log_buff, log_offset);
> +			axd->log_rbuf_rem = log_offset;
> +		} else {
> +			char __iomem *pos = log_buff + log_offset;
> +			unsigned int rem = log_size - log_offset;
> +
> +			memcpy_fromio(axd->log_rbuf, pos, rem);
> +			memcpy_fromio(axd->log_rbuf + rem, log_buff, log_offset);
> +			axd->log_rbuf_rem = log_size;
> +		}
> +		axd_platform_unlock(flags);

I didn't see the lock being taken?

> +static ssize_t axd_write_mask(struct file *filep,
> +				const char __user *buff, size_t count, loff_t *offp)
> +{
> +	struct axd_dev *axd = filep->f_inode->i_private;
> +	unsigned int mask;
> +	char buffer[32] = {};
> +	int ret;
> +
> +	/* ensure we always have null at the end */
> +	ret = copy_from_user(buffer, buff, min(31u, count));
> +	if (ret < 0)
> +		return ret;
> +
> +	if (!kstrtouint(buffer, 0, &mask))
> +		axd_write_reg(&axd->cmd, AXD_REG_DEBUG_MASK, mask);

What are we writing here?  If we're going behind the driver's back on
something that might confuse it it's generally better to taint the
kernel so we know dodgy stuff happened later on.

> +static void axd_debugfs_create(struct axd_dev *axd)
> +{
> +	axd->debugfs = debugfs_create_dir(dev_name(axd->dev), NULL);
> +	if (IS_ERR_OR_NULL(axd->debugfs)) {
> +		dev_err(axd->dev, "failed to create debugfs node\n");
> +		return;
> +	}

It'd be nicer to create this under the relevant ASoC debugfs directory
so it's easier to find.

> +#ifdef CONFIG_CRYPTO_LZO
> +#include <linux/crypto.h>

This include should be with all the other includes, not down here.

> +	size = axd->fw_size;
> +	cached_fw_base = (char *)CAC_ADDR((int)axd->fw_base_m);
> +	ret = crypto_comp_decompress(tfm, fw->data + 8,
> +				fw->size - 8, cached_fw_base, &size);
> +	if (ret)
> +		dev_err(axd->dev, "Failed to decompress the firmware\n");

Print return codes if you get them.

> +
> +	if (size != axd->fw_size) {
> +		dev_err(axd->dev, "Uncompressed file size doesn't match reported file size\n");
> +		ret = -EINVAL;
> +	}

Should we be checking this if the decompression failed?

> +}
> +#else /* !CONFIG_CRYPTO_LZO */
> +static int decompress_fw(struct axd_dev *axd, const struct firmware *fw)

Blank lines between things please.

> +{
> +	dev_err(axd->dev, "The firmware must be lzo decompressed first, compile driver again with CONFIG_CRYPTO_LZO enabled in kernel or do the decompression in user space.\n");

Please split this up into a few prints for wrapping, similarly in
several other places.

> +	return -EIO;

-ENOTSUPP.

> +		return -EIO;
> +	}
> +	/*

More vertical blanks missing.

> +	 * We copy through the cache, fw will do the necessary cache
> +	 * flushes and syncing at startup.
> +	 * Copying from uncached makes it more difficult for the
> +	 * firmware to keep the caches coherent with memory when it sets
> +	 * tlbs and start running.
> +	 */
> +	memcpy_toio((void *)cached_fw_base, fw->data, fw->size);

Why the cast here?  I'm also not seeing where we handled the copying to
I/O in the decompression case?

> +	dev_info(axd->dev, "Loading firmware at 0x%p ...\n", axd->fw_base_m);

This should be _dbg() at most, otherwise it's going to get noisy.

> +	t0_new_pc = (unsigned long) axd->fw_base_m + (t0_new_pc - AXD_BASE_VADDR);

Those casts look fishy...

> +	for (i = 0; i < AXD_LDFW_RETRIES; i++) {
> +		ret = axd_wait_ready(axd_cmd->message);
> +		if (!ret) {
> +			/*
> +			 * Let the firmware know the address of the buffer
> +			 * region
> +			 */
> +			ret = axd_write_reg(axd_cmd,
> +					AXD_REG_BUFFER_BASE, axd->buf_base_p);
> +			if (ret) {
> +				dev_err(axd->dev,
> +					"Failed to setup buffers base address\n");

Again print errors please.

> +				goto out;
> +			}
> +			return 0;
> +
> +		}
> +	}

I'm not seeing any diagnostics if we fall out of the retry loop here?

> +static void axd_reset(struct work_struct *work)
> +{
> +	unsigned int major, minor, patch;
> +	int i;
> +
> +	struct axd_dev *axd = container_of(work, struct axd_dev, watchdogwork);
> +
> +
> +	/* if we got a fatal error, don't reset if watchdog is disabled */
> +	if (unlikely(!axd->cmd.watchdogenabled))
> +		return;

There's generally no need for unlikely() annotations outside of hot
paths.

> +	/* stop the watchdog timer until we restart */
> +	del_timer(&axd->watchdogtimer);

I'd expect del_timer_sync() to make sure that the timer stopped.

> +	if (!axd_get_flag(&axd->cmd.fw_stopped_flg)) {
> +		/* ping the firmware by requesting its version info */
> +		axd_cmd_get_version(&axd->cmd, &major, &minor, &patch);
> +		if (!major && !minor && !patch) {
> +			dev_warn(axd->dev, "Firmware stopped responding...\n");
> +			axd_set_flag(&axd->cmd.fw_stopped_flg, 1);
> +		} else {
> +			goto out;
> +		}
> +	}

It might be useful to display the firmware version we loaded.

> +	axd_platform_print_regs();
> +	dev_warn(axd->dev, "Reloading AXD firmware...\n");

This is going to get noisy and isn't adding much.

> +	/* wake up any task sleeping on command response */
> +	wake_up(&axd->cmd.wait);
> +	/* give chance to user land tasks to react to the crash */
> +	ssleep(2);

This looks horribly racy, I'd expect us to be trashing and/or killing
off any active work and resources here.

> +static void axd_watchdog_timer(unsigned long arg)
> +{
> +	struct axd_dev *axd = (struct axd_dev *)arg;
> +
> +	/* skip if watchdog is not enabled */
> +	if (unlikely(!axd->cmd.watchdogenabled))
> +		goto out;
> +
> +	schedule_work(&axd->watchdogwork);
> +	return;
> +out:
> +	mod_timer(&axd->watchdogtimer, jiffies + WATCHDOG_TIMEOUT);
> +}

So we have a timer that just schedules some work?  Why not just
schedule_delayed_work()?

> +	/*
> +	 * Verify that the firmware is ready. In normal cases the firmware
> +	 * should start immediately, but to be more robust we do this
> +	 * verification and give the firmware a chance of 3 seconds to be ready
> +	 * otherwise we exit in failure.
> +	 */
> +	for (i = 0; i < AXD_LDFW_RETRIES; i++) {
> +		axd_cmd_get_version(&axd->cmd, &major, &minor, &patch);
> +		if (major || minor || patch) {
> +			/* firmware is ready */
> +			break;
> +		}
> +		/* if we couldn't read the version after 3 tries, error */
> +		if (i == AXD_LDFW_RETRIES - 1) {
> +			dev_err(axd->dev, "Failed to communicate with the firmware\n");
> +			ret = -EIO;
> +			goto error;
> +		}
> +		/* wait for 10 ms for the firmware to start */
> +		msleep(10);
> +	}
> +	dev_info(axd->dev, "Running firmware version %u.%u.%u %s\n",
> +				major, minor, patch, axd_hdr_get_build_str());

Why is this code not shared with the restart case?

> +	ret = of_property_read_u32_array(of_node, "gic-irq", val, 2);
> +	if (ret) {
> +		dev_err(&pdev->dev,
> +				"'gic-irq' parameter must be set\n");
> +		return ret;
> +	}

This appears to have a DT binding but the binding is not documented.
All new DT bindings must be documented.  I'm concerned that some of the
properties being read from DT may not be ideal here...

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 473 bytes --]

  reply	other threads:[~2015-08-26 18:37 UTC|newest]

Thread overview: 58+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-08-24 12:39 [PATCH 00/10] Add support for img AXD audio hardware decoder Qais Yousef
2015-08-24 12:39 ` [PATCH 01/10] irqchip: irq-mips-gic: export gic_send_ipi Qais Yousef
2015-08-24 12:49   ` Thomas Gleixner
2015-08-24 13:02     ` Qais Yousef
2015-08-24 13:32       ` Marc Zyngier
2015-08-24 14:27         ` Qais Yousef
2015-08-24 15:07           ` Thomas Gleixner
2015-08-24 16:39             ` Qais Yousef
2015-08-24 17:17               ` Marc Zyngier
2015-08-26 11:23                 ` Qais Yousef
2015-08-26 13:19                   ` Thomas Gleixner
2015-08-26 14:57                     ` Qais Yousef
2015-08-26 15:08                       ` Thomas Gleixner
2015-08-26 15:41                         ` Qais Yousef
2015-08-26 21:40                           ` Thomas Gleixner
2015-08-27  2:22                             ` Jiang Liu
2015-08-28 10:38                             ` Qais Yousef
2015-08-28 14:22                               ` Thomas Gleixner
2015-08-28 15:12                                 ` Qais Yousef
2015-09-02  9:33                                 ` Qais Yousef
2015-09-02  9:55                                   ` Marc Zyngier
2015-09-02 10:48                                     ` Qais Yousef
2015-09-02 11:53                                       ` Marc Zyngier
2015-09-02 13:25                                         ` Qais Yousef
2015-09-02 14:14                                           ` Marc Zyngier
2015-09-02 12:12                                     ` Jason Cooper
2015-08-24 14:55       ` Thomas Gleixner
2015-08-24 15:11         ` Qais Yousef
2015-08-24 12:39 ` [PATCH 02/10] dt: add img,axd.txt device tree binding document Qais Yousef
2015-08-24 13:26   ` Mark Rutland
2015-08-24 13:49     ` Qais Yousef
2015-08-24 12:39 ` [PATCH 03/10] ALSA: add AXD Audio Processing IP alsa driver Qais Yousef
2015-08-26 18:37   ` Mark Brown [this message]
2015-08-27 12:15     ` Qais Yousef
2015-08-27 15:32       ` Mark Brown
2015-08-28  9:22         ` Qais Yousef
2015-09-03 12:46           ` Mark Brown
2015-08-24 12:39 ` [PATCH 04/10] ALSA: axd: add fw binary header manipulation files Qais Yousef
2015-08-24 12:39 ` [PATCH 05/10] ALSA: axd: add buffers " Qais Yousef
2015-08-26 18:43   ` Mark Brown
2015-08-27 14:21     ` Qais Yousef
2015-08-29  9:47       ` Mark Brown
2015-09-01 10:00         ` Qais Yousef
2015-09-03 12:32           ` Mark Brown
2015-09-14  9:11             ` Qais Yousef
2015-09-14 18:50               ` Mark Brown
2015-08-24 12:39 ` [PATCH 06/10] ALSA: axd: add basic files for sending/receiving axd cmds Qais Yousef
2015-08-26 19:16   ` Mark Brown
2015-08-27 15:40     ` Qais Yousef
2015-08-29 10:18       ` Mark Brown
2015-09-01 10:46         ` Qais Yousef
2015-09-03 12:40           ` Mark Brown
2015-08-24 12:39 ` [PATCH 07/10] ALSA: axd: add cmd interface helper functions Qais Yousef
2015-08-24 12:39 ` [PATCH 08/10] ALSA: axd: add low level AXD platform setup files Qais Yousef
2015-08-24 12:39 ` [PATCH 09/10] ALSA: axd: add alsa compress offload operations Qais Yousef
2015-08-24 12:39 ` [PATCH 10/10] ALSA: axd: add Makefile Qais Yousef
2015-08-26 18:04 ` [PATCH 00/10] Add support for img AXD audio hardware decoder Mark Brown
2015-08-27  9:07   ` Qais Yousef

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20150826183700.GD28760@sirena.org.uk \
    --to=broonie@kernel.org \
    --cc=alsa-devel@alsa-project.org \
    --cc=lgirdwood@gmail.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=perex@perex.cz \
    --cc=qais.yousef@imgtec.com \
    --cc=tiwai@suse.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®