lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <200707121922.34324.david-b@pacbell.net>
Date:	Thu, 12 Jul 2007 19:22:33 -0700
From:	David Brownell <david-b@...bell.net>
To:	Andrew Morton <akpm@...ux-foundation.org>
Cc:	"Trilok Soni" <soni.trilok@...il.com>, i2c@...sensors.org,
	"Jean Delvare" <khali@...ux-fr.org>,
	"Tony Lindgren" <tony@...mide.com>, drzeus-mmc@...eus.cx,
	linux-kernel@...r.kernel.org, amit.kucheria@...il.com
Subject: Re: OMAP: Add TI TWL92330/Menelaus Power Management chip driver

On Thursday 12 July 2007, Andrew Morton wrote:
> On Tue, 10 Jul 2007 12:23:06 +0530
> "Trilok Soni" <soni.trilok@...il.com> wrote:

> > +	u8			mask1, mask2;
> > +	void			(*handlers[16])(struct menelaus_chip *);
> 
> What determined the value of this hard-wired 16?

Two 8-bit registers for IRQ status, so total of 16 potential handlers.
Of course, I think several of those bits aren't actually used.


> > +/* Handles Menelaus interrupts. Does not run in interrupt context */
> > +static void menelaus_work(struct work_struct *_menelaus)
> > +{
> > +	struct menelaus_chip *menelaus =
> > +			container_of(_menelaus, struct menelaus_chip, work);
> > +	void (*handler)(struct menelaus_chip *menelaus);
> > +
> > +	while (1) {
> > +		unsigned isr;
> > +
> > +		isr = (menelaus_read_reg(MENELAUS_INT_STATUS2)
> > +				& ~menelaus->mask2) << 8;
> > +		isr |= menelaus_read_reg(MENELAUS_INT_STATUS1)
> > +				& ~menelaus->mask1;
> > +		if (!isr)
> > +			break;
> > +
> > +		while (isr) {
> > +			int irq = fls(isr) - 1;
> > +			isr &= ~(1 << irq);
> > +
> > +			mutex_lock(&menelaus->lock);
> > +			menelaus_disable_irq(irq);
> > +			menelaus_ack_irq(irq);
> > +			handler = menelaus->handlers[irq];
> > +			if (handler)
> > +				handler(menelaus);
> > +			menelaus_enable_irq(irq);
> > +			mutex_unlock(&menelaus->lock);
> > +		}
> > +	}
> > +	enable_irq(menelaus->client->irq);
> 
> This can do an enable_irq() of an already-enabled IRQ.  I don't know if
> that will cause runtime problems, but it doesn't seem desirable.

How could it do that?


> > +}
> > +
> > +/*
> > + * We cannot use I2C in interrupt context, so we just schedule work.
> > + */
> > +static irqreturn_t menelaus_irq(int irq, void *_menelaus)
> > +{
> > +	struct menelaus_chip *menelaus = _menelaus;
> > +
> > +	disable_irq_nosync(irq);
> 
> I guess the reader of this code will wonder why the nosync variant was
> used.  A comment would explain that.

Right.  ISTR that the "sync" version waits for any active
IRQ handler to complete.  That is, it's specified to cause
a self-deadlock in this call context (wait for self) ...


> In fact the reader might wonder why the heck we use a workqueue at all,
> rather than just doing the work in interrupt context as drivers normally
> do.
> 
> Perhaps that was all explained somewhere and I missed it.  If not, I'd
> suggest that this design decision should be described in a code comment
> somewhere.

Evidently the "we cannot use I2C in interrupt context" comment was
excessively subtle.  ;)

The whole I2C stack is synchronous; *EVERY* request to perform I/O
requires a can-sleep task context.  It's not like USB or SPI, where
the IRQ handler can submit I/O requests which will complete later.

Which is why every I2C driver that needs to handle an IRQ will need
to arrange some task context ... ergo the workqueue.  It's something
far more common in embedded systems than in the original "sensors"
context from which the I2C stack evolved.


> > +	int			err = 0;
> > +	struct menelaus_platform_data *menelaus_pdata =
> > +					client->dev.platform_data;
> > +
> > +	if (the_menelaus) {
> > +		dev_dbg(&client->dev, "only one %s for now\n",
> > +				DRIVER_NAME);
> > +		return -ENODEV;
> 
> I doubt if this can happen?

It's just paranoia.  If it ever *did* happen there would be
extreme confusion; it's easy to prevent, and useful to be
very explicit about this rule.


-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ